diff options
1592 files changed, 49370 insertions, 35709 deletions
diff --git a/.clang-format b/.clang-format index eda00dd8dd..a6822dc2cd 100644 --- a/.clang-format +++ b/.clang-format @@ -1,6 +1,6 @@ # 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 19.1.0). BasedOnStyle: LLVM AccessModifierOffset: -4 AlignAfterOpenBracket: DontAlign @@ -37,7 +37,29 @@ AlignAfterOpenBracket: DontAlign # Enabled: false # AcrossEmptyLines: false # AcrossComments: false +# AlignCaseArrows: false # AlignCaseColons: false +# AlignConsecutiveTableGenBreakingDAGArgColons: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCompound: false +# AlignFunctionPointers: false +# PadOperators: false +# AlignConsecutiveTableGenCondOperatorColons: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCompound: false +# AlignFunctionPointers: false +# PadOperators: false +# AlignConsecutiveTableGenDefinitionColons: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCompound: false +# AlignFunctionPointers: false +# PadOperators: false # AlignEscapedNewlines: Right AlignOperands: DontAlign AlignTrailingComments: @@ -47,6 +69,7 @@ AlignTrailingComments: AllowAllParametersOfDeclarationOnNextLine: false # AllowBreakBeforeNoexceptSpecifier: Never # AllowShortBlocksOnASingleLine: Never +# AllowShortCaseExpressionOnASingleLine: true # AllowShortCaseLabelsOnASingleLine: false # AllowShortCompoundRequirementOnASingleLine: true # AllowShortEnumsOnASingleLine: true @@ -54,9 +77,7 @@ AllowAllParametersOfDeclarationOnNextLine: false # AllowShortIfStatementsOnASingleLine: Never # AllowShortLambdasOnASingleLine: All # AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterReturnType: None # AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations: MultiLine # AttributeMacros: # - __capability # BinPackArguments: true @@ -84,6 +105,7 @@ AllowAllParametersOfDeclarationOnNextLine: false # BreakAdjacentStringLiterals: true # BreakAfterAttributes: Leave # BreakAfterJavaFieldAnnotations: false +# BreakAfterReturnType: None # BreakArrays: true # BreakBeforeBinaryOperators: None # BreakBeforeBraces: Attach @@ -91,8 +113,10 @@ AllowAllParametersOfDeclarationOnNextLine: false # BreakBeforeInlineASMColon: OnlyMultiline # BreakBeforeTernaryOperators: true BreakConstructorInitializers: AfterColon +# BreakFunctionDefinitionParameters: false # BreakInheritanceList: BeforeColon # BreakStringLiterals: true +# BreakTemplateDeclarations: MultiLine ColumnLimit: 0 # CommentPragmas: '^ IWYU pragma:' # CompactNamespaces: false @@ -150,13 +174,16 @@ JavaImportGroups: - javax # JavaScriptQuotes: Leave # JavaScriptWrapImports: true -# KeepEmptyLinesAtEOF: false -KeepEmptyLinesAtTheStartOfBlocks: false +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: false + AtStartOfFile: false # LambdaBodyIndentation: Signature # Language: Cpp # LineEnding: DeriveLF # MacroBlockBegin: '' # MacroBlockEnd: '' +# MainIncludeChar: Quote # MaxEmptyLinesToKeep: 1 # NamespaceIndentation: None # ObjCBinPackProtocolList: Auto @@ -183,7 +210,7 @@ PackConstructorInitializers: NextLine # ReflowComments: true # RemoveBracesLLVM: false # RemoveParentheses: Leave -# RemoveSemicolon: false +RemoveSemicolon: true # RequiresClausePosition: OwnLine # RequiresExpressionIndentation: OuterScope # SeparateDefinitionBlocks: Leave @@ -219,25 +246,25 @@ PackConstructorInitializers: NextLine # SpacesBeforeTrailingComments: 1 # SpacesInAngles: Never # SpacesInContainerLiterals: true -## Godot TODO: We'll want to use a min of 1, but we need to see how to fix -## our comment capitalization at the same time. SpacesInLineCommentPrefix: - Minimum: 0 + Minimum: 0 # We want a minimum of 1 for comments, but allow 0 for disabled code. Maximum: -1 # SpacesInParens: Never # SpacesInParensOptions: +# ExceptDoubleParentheses: false # InConditionalStatements: false # InCStyleCasts: false # InEmptyParentheses: false # Other: false # SpacesInSquareBrackets: false -Standard: c++17 +Standard: c++20 # StatementAttributeLikeMacros: # - Q_EMIT # StatementMacros: # - Q_UNUSED # - QT_REQUIRE_VERSION TabWidth: 4 +# TableGenBreakInsideDAGArg: DontBreak UseTab: Always # VerilogBreakBetweenInstancePorts: true # WhitespaceSensitiveMacros: diff --git a/.clang-tidy b/.clang-tidy index 366781cc82..1eb974f3f8 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,14 +1,12 @@ ---- -Checks: >- - -*, - cppcoreguidelines-pro-type-member-init, - modernize-redundant-void-arg, - modernize-use-bool-literals, - modernize-use-default-member-init, - modernize-use-nullptr, - readability-braces-around-statements, - readability-redundant-member-init -WarningsAsErrors: '' +Checks: + - -* + - cppcoreguidelines-pro-type-member-init + - modernize-redundant-void-arg + - modernize-use-bool-literals + - modernize-use-default-member-init + - modernize-use-nullptr + - readability-braces-around-statements + - readability-redundant-member-init 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)/ @@ -19,4 +17,3 @@ CheckOptions: modernize-use-bool-literals.IgnoreMacros: false modernize-use-default-member-init.IgnoreMacros: false modernize-use-default-member-init.UseAssignment: true -... diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 1c78dde7a4..f149078d5d 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -57,3 +57,9 @@ df61dc4b2bd54a5a40c515493c76f5a458e5b541 # Style: Apply new `clang-format` fixes b37fc1014abf7adda70dc30b0822d775b3a4433f + +# Set clang-format `RemoveSemicolon` rule to `true` +0d350e71086fffce0553811739aae9f6ad66136c + +# Style: Apply clang-tidy fixes (superficial) +bb5f390fb9b466be35a5df7651323d7e66afca31 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 68bd4bc4ce..713c982123 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,6 +1,6 @@ # 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 +# Owners can be @users, @org/teams or emails. # Buildsystem (Before everything to be overwritten) @@ -77,14 +77,12 @@ /modules/ @godotengine/_engine /modules/**/doc_classes/ @godotengine/_engine @godotengine/documentation -/modules/**/editor/ @godotengine/_engine @godotengine/_editor /modules/**/icons/ @godotengine/_engine @godotengine/usability /modules/**/tests/ @godotengine/_engine @godotengine/tests ## 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/minimp3/ @godotengine/audio /modules/minimp3/doc_classes/ @godotengine/audio @godotengine/documentation /modules/ogg/ @godotengine/audio @@ -104,10 +102,8 @@ /modules/etcpak/ @godotengine/import /modules/fbx/ @godotengine/import /modules/fbx/doc_classes/ @godotengine/import @godotengine/documentation -/modules/fbx/editor/ @godotengine/import @godotengine/_editor /modules/gltf/ @godotengine/import /modules/gltf/doc_classes/ @godotengine/import @godotengine/documentation -/modules/gltf/editor/ @godotengine/import @godotengine/_editor /modules/gltf/tests/ @godotengine/import @godotengine/tests /modules/hdr/ @godotengine/import /modules/jpg/ @godotengine/import @@ -125,14 +121,13 @@ /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 @@ -149,14 +144,12 @@ ## Scripting /modules/gdscript/ @godotengine/gdscript /modules/gdscript/doc_classes/ @godotengine/gdscript @godotengine/documentation -/modules/gdscript/editor/ @godotengine/gdscript @godotengine/_editor /modules/gdscript/icons/ @godotengine/gdscript @godotengine/usability /modules/gdscript/tests/ @godotengine/gdscript @godotengine/tests /modules/jsonrpc/ @godotengine/gdscript @godotengine/network -/modules/jsonrpc/tests @godotengine/gdscript @godotengine/network @godotengine/tests +/modules/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/_editor /modules/mono/icons/ @godotengine/dotnet @godotengine/usability ## Text @@ -173,24 +166,19 @@ /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/csg/ @godotengine/3d-nodes /modules/csg/doc_classes/ @godotengine/3d-nodes @godotengine/documentation -/modules/csg/editor/ @godotengine/3d-nodes @godotengine/_editor /modules/csg/icons/ @godotengine/3d-nodes @godotengine/usability /modules/gridmap/ @godotengine/3d-nodes /modules/gridmap/doc_classes/ @godotengine/3d-nodes @godotengine/documentation -/modules/gridmap/editor/ @godotengine/3d-nodes @godotengine/_editor /modules/gridmap/icons/ @godotengine/3d-nodes @godotengine/usability /modules/navigation/ @godotengine/navigation -/modules/navigation/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/icons/ @godotengine/core @godotengine/usability /modules/noise/tests/ @godotengine/core @godotengine/tests /modules/regex/ @godotengine/core @@ -238,15 +226,23 @@ # Servers /servers/ @godotengine/_systems -/servers/**/audio* @godotengine/audio -/servers/**/camera* @godotengine/xr -/servers/**/debugger* @godotengine/debugger -/servers/**/display* @godotengine/_platforms -/servers/**/navigation* @godotengine/navigation -/servers/**/physics* @godotengine/physics -/servers/**/rendering* @godotengine/rendering -/servers/**/text* @godotengine/gui-nodes -/servers/**/xr* @godotengine/xr +/servers/**/audio_* @godotengine/audio +/servers/**/camera_* @godotengine/xr +/servers/**/debugger_* @godotengine/debugger +/servers/**/display_* @godotengine/_platforms +/servers/**/navigation_* @godotengine/navigation +/servers/**/physics_* @godotengine/physics +/servers/**/rendering_* @godotengine/rendering +/servers/**/text_* @godotengine/gui-nodes +/servers/**/xr_* @godotengine/xr +/servers/audio/ @godotengine/audio +/servers/camera/ @godotengine/xr +/servers/debugger/ @godotengine/debugger +/servers/display/ @godotengine/_platforms +/servers/navigation/ @godotengine/navigation +/servers/rendering/ @godotengine/rendering +/servers/text/ @godotengine/gui-nodes +/servers/xr/ @godotengine/xr # Tests diff --git a/.github/actions/godot-build/action.yml b/.github/actions/godot-build/action.yml index 93d6f076b7..ebc301dd0f 100644 --- a/.github/actions/godot-build/action.yml +++ b/.github/actions/godot-build/action.yml @@ -18,12 +18,12 @@ inputs: required: false scons-cache: description: The SCons cache path. - default: ${{ github.workspace }}/.scons-cache/ + default: ${{ github.workspace }}/.scons_cache/ scons-cache-limit: description: The SCons cache size limit. # actions/cache has 10 GiB limit, and GitHub runners have a 14 GiB disk. # Limit to 7 GiB to avoid having the extracted cache fill the disk. - default: 7168 + default: 7 runs: using: composite @@ -32,10 +32,8 @@ runs: shell: sh env: SCONSFLAGS: ${{ inputs.sconsflags }} - SCONS_CACHE: ${{ inputs.scons-cache }} - SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }} run: | - echo "Building with flags:" platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }} + echo "Building with flags:" platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }} "cache_path=${{ inputs.scons-cache }}" cache_limit=${{ inputs.scons-cache-limit }} if [ "${{ inputs.target }}" != "editor" ]; then # Ensure we don't include editor code in export template builds. @@ -49,5 +47,5 @@ runs: export BUILD_NAME="gh" fi - scons platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }} + scons platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }} "cache_path=${{ inputs.scons-cache }}" cache_limit=${{ inputs.scons-cache-limit }} ls -l bin/ diff --git a/.github/actions/godot-cache-restore/action.yml b/.github/actions/godot-cache-restore/action.yml index 7abec20a28..e2a1b97019 100644 --- a/.github/actions/godot-cache-restore/action.yml +++ b/.github/actions/godot-cache-restore/action.yml @@ -6,7 +6,7 @@ inputs: default: ${{ github.job }} scons-cache: description: The SCons cache path. - default: ${{ github.workspace }}/.scons-cache/ + default: ${{ github.workspace }}/.scons_cache/ runs: using: composite @@ -29,7 +29,6 @@ runs: # 4. A partial match for the same base branch only (not ideal, matches any PR with the same base branch). restore-keys: | - ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }} ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-refs/heads/${{ env.GODOT_BASE_BRANCH }} ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }} diff --git a/.github/actions/godot-cache-save/action.yml b/.github/actions/godot-cache-save/action.yml index df877cec67..42aa836406 100644 --- a/.github/actions/godot-cache-save/action.yml +++ b/.github/actions/godot-cache-save/action.yml @@ -6,7 +6,7 @@ inputs: default: ${{ github.job }} scons-cache: description: The SCons cache path. - default: ${{ github.workspace }}/.scons-cache/ + default: ${{ github.workspace }}/.scons_cache/ runs: using: composite diff --git a/.github/actions/godot-deps/action.yml b/.github/actions/godot-deps/action.yml index eb9bdef1e7..bd9a1f55ed 100644 --- a/.github/actions/godot-deps/action.yml +++ b/.github/actions/godot-deps/action.yml @@ -27,6 +27,5 @@ runs: shell: bash run: | python -c "import sys; print(sys.version)" - python -m pip install wheel python -m pip install scons==${{ inputs.scons-version }} scons --version diff --git a/.github/workflows/android_builds.yml b/.github/workflows/android_builds.yml index 7ff5502137..950e1e51cc 100644 --- a/.github/workflows/android_builds.yml +++ b/.github/workflows/android_builds.yml @@ -14,7 +14,7 @@ concurrency: jobs: build-android: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 name: ${{ matrix.name }} strategy: fail-fast: false @@ -24,19 +24,19 @@ jobs: cache-name: android-editor target: editor tests: false - sconsflags: arch=arm64 production=yes + sconsflags: arch=arm64 production=yes swappy=yes - name: Template arm32 (target=template_release, arch=arm32) cache-name: android-template-arm32 target: template_release tests: false - sconsflags: arch=arm32 + sconsflags: arch=arm32 swappy=yes - name: Template arm64 (target=template_release, arch=arm64) cache-name: android-template-arm64 target: template_release tests: false - sconsflags: arch=arm64 + sconsflags: arch=arm64 swappy=yes steps: - name: Checkout @@ -59,6 +59,17 @@ jobs: - name: Setup Python and SCons uses: ./.github/actions/godot-deps + - name: Download pre-built Android Swappy Frame Pacing Library + uses: dsaltares/fetch-gh-release-asset@1.1.2 + with: + repo: darksylinc/godot-swappy + version: tags/v2023.3.0.0 + file: godot-swappy.7z + target: swappy/godot-swappy.7z + + - name: Extract pre-built Android Swappy Frame Pacing Library + run: 7za x -y swappy/godot-swappy.7z -o${{github.workspace}}/thirdparty/swappy-frame-pacing + - name: Compilation uses: ./.github/actions/godot-build with: diff --git a/.github/workflows/godot_cpp_test.yml b/.github/workflows/godot_cpp_test.yml index e26c109d75..af99a4b035 100644 --- a/.github/workflows/godot_cpp_test.yml +++ b/.github/workflows/godot_cpp_test.yml @@ -15,7 +15,7 @@ concurrency: jobs: godot-cpp-tests: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 name: Build and test Godot CPP steps: - name: Checkout @@ -52,9 +52,6 @@ jobs: # continue-on-error: true - name: Build godot-cpp test extension - env: # Keep synced with godot-build. - SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ - SCONS_CACHE_LIMIT: 7168 run: scons --directory=./godot-cpp/test target=template_debug dev_build=yes verbose=yes # - name: Save Godot build cache diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index dc3d9f3786..bd4e2856e3 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -17,7 +17,8 @@ concurrency: jobs: build-linux: - runs-on: ubuntu-20.04 + # Stay one LTS before latest to increase portability of Linux artifacts. + runs-on: ubuntu-22.04 name: ${{ matrix.name }} strategy: fail-fast: false @@ -100,7 +101,7 @@ jobs: run: | sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EB8B81E14DA65431D7504EA8F63F0F2B90935439 - sudo add-apt-repository "deb https://ppa.launchpadcontent.net/kisak/turtle/ubuntu focal main" + sudo add-apt-repository "deb https://ppa.launchpadcontent.net/kisak/turtle/ubuntu ${{ matrix.os == 'ubuntu-20.04' && 'focal' || 'jammy' }} main" sudo apt-get install -qq mesa-vulkan-drivers # TODO: Figure out somehow how to embed this one. @@ -129,8 +130,8 @@ jobs: uses: ./.github/actions/godot-deps with: # Sync with Ensure*Version in SConstruct. - python-version: 3.6 - scons-version: 3.1.2 + python-version: 3.8 + scons-version: 4.0 - name: Setup GCC problem matcher uses: ammaraskar/gcc-problem-matcher@master diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index ff102a06cc..9b326cb43e 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -9,7 +9,7 @@ concurrency: jobs: static-checks: name: Code style, file formatting, and docs - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/web_builds.yml b/.github/workflows/web_builds.yml index 8e30c99fbc..9ed8475769 100644 --- a/.github/workflows/web_builds.yml +++ b/.github/workflows/web_builds.yml @@ -8,7 +8,6 @@ env: GODOT_BASE_BRANCH: master SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no use_closure_compiler=yes strict_checks=yes EM_VERSION: 3.1.64 - EM_CACHE_FOLDER: emsdk-cache concurrency: group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-web @@ -16,7 +15,7 @@ concurrency: jobs: web-template: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 name: ${{ matrix.name }} strategy: fail-fast: false @@ -46,8 +45,7 @@ jobs: uses: mymindstorm/setup-emsdk@v14 with: version: ${{ env.EM_VERSION }} - actions-cache-folder: ${{ env.EM_CACHE_FOLDER }} - cache-key: emsdk-${{ matrix.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} + no-cache: true - name: Verify Emscripten setup run: | diff --git a/.gitignore b/.gitignore index 32a43b8c63..f72ea1ac51 100644 --- a/.gitignore +++ b/.gitignore @@ -36,8 +36,8 @@ compile_commands.json platform/windows/godot_res.res # Ninja build files -build.ninja -.ninja +*.ninja +.ninja/ run_ninja_env.bat # Generated by Godot binary @@ -77,6 +77,9 @@ venv __pycache__/ *.pyc +# Python modules +.*_cache/ + # Documentation doc/_build/ @@ -164,9 +167,6 @@ gmon.out # Kdevelop *.kdev4 -# Mypy -.mypy_cache - # Qt Creator *.config *.creator diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 572eaf6791..56f64ad079 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,10 +9,20 @@ exclude: | repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v19.1.0 + rev: v19.1.3 hooks: - id: clang-format - files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java|glsl)$ + files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java)$ + types_or: [text] + exclude: | + (?x)^( + tests/python_build/.*| + platform/android/java/editor/src/main/java/com/android/.*| + platform/android/java/lib/src/com/.* + ) + - id: clang-format + name: clang-format-glsl + files: \.glsl$ types_or: [text] exclude: | (?x)^( @@ -20,6 +30,7 @@ repos: platform/android/java/editor/src/main/java/com/android/.*| platform/android/java/lib/src/com/.* ) + args: ['-style=file:misc/utility/.clang-format-glsl'] - repo: https://github.com/pocc/pre-commit-hooks rev: v1.3.5 @@ -34,19 +45,19 @@ repos: platform/android/java/editor/src/main/java/com/android/.*| platform/android/java/lib/src/com/.* ) - additional_dependencies: [clang-tidy==18.1.1] + additional_dependencies: [clang-tidy==19.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.6.6 + rev: v0.7.3 hooks: - id: ruff args: [--fix] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.2 + rev: v1.13.0 hooks: - id: mypy files: \.py$ @@ -176,7 +187,8 @@ repos: modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment\.notest\.gd$| modules/gdscript/tests/scripts/parser/warnings/empty_file_newline\.notest\.gd$| platform/android/java/editor/src/main/java/com/android/.*| - platform/android/java/lib/src/com/google/.* + platform/android/java/lib/src/com/google/.*| + tests/data/.*\.bin$ ) - id: dotnet-format diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 6d227d6615..2ece06eebb 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -341,7 +341,7 @@ License: Apache-2.0 Files: ./thirdparty/meshoptimizer/ Comment: meshoptimizer -Copyright: 2016-2023, Arseny Kapoulkine +Copyright: 2016-2024, Arseny Kapoulkine License: Expat Files: ./thirdparty/mingw-std-threads/ @@ -432,7 +432,7 @@ License: BSD-3-clause Files: ./thirdparty/misc/smolv.cpp ./thirdparty/misc/smolv.h Comment: SMOL-V -Copyright: 2016-2020, Aras Pranckevicius +Copyright: 2016-2024, Aras Pranckevicius License: public-domain or Unlicense or Expat Files: ./thirdparty/misc/stb_rect_pack.h @@ -575,6 +575,196 @@ License: BSD-3-clause License: Apache-2.0 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + . + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + . + 1. Definitions. + . + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + . + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + . + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + . + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + . + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + . + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + . + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + . + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + . + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + . + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + . + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + . + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + . + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + . + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + . + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + . + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + . + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + . + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + . + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + . + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + . + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + . + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + . + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + . + END OF TERMS AND CONDITIONS + . + APPENDIX: How to apply the Apache License to your work. + . + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + . + Copyright [yyyy] [name of copyright owner] + . Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/SConstruct b/SConstruct index 63cff4fe16..fa324b2aa0 100644 --- a/SConstruct +++ b/SConstruct @@ -1,8 +1,8 @@ #!/usr/bin/env python from misc.utility.scons_hints import * -EnsureSConsVersion(3, 1, 2) -EnsurePythonVersion(3, 6) +EnsureSConsVersion(4, 0) +EnsurePythonVersion(3, 8) # System import atexit @@ -59,7 +59,7 @@ import glsl_builders import methods import scu_builders from methods import print_error, print_warning -from platform_methods import architecture_aliases, architectures +from platform_methods import architecture_aliases, architectures, compatibility_platform_aliases if ARGUMENTS.get("target", "editor") == "editor": _helper_module("editor.editor_builders", "editor/editor_builders.py") @@ -149,13 +149,11 @@ env.PrependENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) if "TERM" in os.environ: # Used for colored output. env["ENV"]["TERM"] = os.environ["TERM"] -env.disabled_modules = [] +env.disabled_modules = set() env.module_version_string = "" env.msvc = False env.scons_version = env._get_major_minor_revision(scons_raw_version) -env.__class__.disable_module = methods.disable_module - env.__class__.add_module_version_string = methods.add_module_version_string env.__class__.add_source_files = methods.add_source_files @@ -272,6 +270,8 @@ 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)) opts.Add(BoolVariable("steamapi", "Enable minimal SteamAPI integration for usage time tracking (editor only)", False)) +opts.Add("cache_path", "Path to a directory where SCons cache files will be stored. No value disables the cache.", "") +opts.Add("cache_limit", "Max size (in GiB) for the SCons cache. 0 means no limit.", "0") # Thirdparty libraries opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True)) @@ -322,6 +322,9 @@ opts.Add("rcflags", "Custom flags for Windows resource compiler") # in following code (especially platform and custom_modules). opts.Update(env) +# Setup caching logic early to catch everything. +methods.prepare_cache(env) + # Copy custom environment variables if set. if env["import_env_vars"]: for env_var in str(env["import_env_vars"]).split(","): @@ -351,27 +354,18 @@ if env["platform"] == "": if env["platform"] != "": print(f'Automatically detected platform: {env["platform"]}') -if env["platform"] == "osx": - # Deprecated alias kept for compatibility. - print_warning('Platform "osx" has been renamed to "macos" in Godot 4. Building for platform "macos".') - env["platform"] = "macos" - -if env["platform"] == "iphone": - # Deprecated alias kept for compatibility. - print_warning('Platform "iphone" has been renamed to "ios" in Godot 4. Building for platform "ios".') - env["platform"] = "ios" - -if env["platform"] in ["linux", "bsd", "x11"]: - if env["platform"] == "x11": - # Deprecated alias kept for compatibility. - print_warning('Platform "x11" has been renamed to "linuxbsd" in Godot 4. Building for platform "linuxbsd".') - # Alias for convenience. - env["platform"] = "linuxbsd" +# Deprecated aliases kept for compatibility. +if env["platform"] in compatibility_platform_aliases: + alias = env["platform"] + platform = compatibility_platform_aliases[alias] + print_warning( + f'Platform "{alias}" has been renamed to "{platform}" in Godot 4. Building for platform "{platform}".' + ) + env["platform"] = platform -if env["platform"] == "javascript": - # Deprecated alias kept for compatibility. - print_warning('Platform "javascript" has been renamed to "web" in Godot 4. Building for platform "web".') - env["platform"] = "web" +# Alias for convenience. +if env["platform"] in ["linux", "bsd"]: + env["platform"] = "linuxbsd" if env["platform"] not in platform_list: text = "The following platforms are available:\n\t{}\n".format("\n\t".join(platform_list)) @@ -388,8 +382,7 @@ if env["platform"] not in platform_list: # Add platform-specific options. if env["platform"] in platform_opts: - for opt in platform_opts[env["platform"]]: - opts.Add(opt) + opts.AddVariables(*platform_opts[env["platform"]]) # Platform-specific flags. # These can sometimes override default options, so they need to be processed @@ -445,12 +438,11 @@ for name, path in modules_detected.items(): else: enabled = False - opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled)) + opts.Add(BoolVariable(f"module_{name}_enabled", f"Enable module '{name}'", enabled)) # Add module-specific options. try: - for opt in config.get_opts(env["platform"]): - opts.Add(opt) + opts.AddVariables(*config.get_opts(env["platform"])) except AttributeError: pass @@ -585,7 +577,7 @@ env.Append(RCFLAGS=env.get("rcflags", "").split()) # Feature build profile env.disabled_classes = [] if env["build_profile"] != "": - print('Using feature build profile: "{}"'.format(env["build_profile"])) + print(f'Using feature build profile: "{env["build_profile"]}"') import json try: @@ -597,7 +589,7 @@ if env["build_profile"] != "": for c in dbo: env[c] = dbo[c] except json.JSONDecodeError: - print_error('Failed to open feature build profile: "{}"'.format(env["build_profile"])) + 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 @@ -611,6 +603,8 @@ if env["dev_mode"]: if env["production"]: env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True) env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False) + if platform_arg == "android": + env["swappy"] = methods.get_cmdline_bool("swappy", True) # LTO "auto" means we handle the preferred option in each platform detect.py. env["lto"] = ARGUMENTS.get("lto", "auto") @@ -666,40 +660,32 @@ elif methods.using_gcc(env): "to switch to posix threads." ) Exit(255) - if env["debug_paths_relative"] and cc_version_major < 8: - print_warning("GCC < 8 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") - env["debug_paths_relative"] = False elif methods.using_clang(env): # Apple LLVM versions differ from upstream LLVM version \o/, compare # in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions - if env["platform"] == "macos" or env["platform"] == "ios": - vanilla = methods.is_vanilla_clang(env) - if vanilla and cc_version_major < 6: - print_error( - "Detected Clang version older than 6, which does not fully support " - "C++17. Supported versions are Clang 6 and later." - ) - Exit(255) - elif not vanilla and cc_version_major < 10: + if methods.is_apple_clang(env): + if cc_version_major < 10: print_error( "Detected Apple Clang version older than 10, which does not fully " "support C++17. Supported versions are Apple Clang 10 and later." ) Exit(255) - if env["debug_paths_relative"] and not vanilla and cc_version_major < 12: + 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 - elif cc_version_major < 6: - print_error( - "Detected Clang version older than 6, which does not fully support " - "C++17. Supported versions are Clang 6 and later." - ) - Exit(255) - if env["debug_paths_relative"] and cc_version_major < 10: - print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") - env["debug_paths_relative"] = False + else: + if cc_version_major < 6: + print_error( + "Detected Clang version older than 6, which does not fully support " + "C++17. Supported versions are Clang 6 and later." + ) + Exit(255) + elif env["debug_paths_relative"] and cc_version_major < 10: + print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") + env["debug_paths_relative"] = False + elif env.msvc: # Ensure latest minor builds of Visual Studio 2017/2019. # https://github.com/godotengine/godot/pull/94995#issuecomment-2336464574 @@ -763,7 +749,7 @@ else: project_path = Dir("#").abspath env.Append(CCFLAGS=[f"-ffile-prefix-map={project_path}=."]) else: - if methods.using_clang(env) and not methods.is_vanilla_clang(env): + if methods.is_apple_clang(env): # Apple Clang, its linker doesn't like -s. env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"]) else: @@ -799,8 +785,8 @@ if env["lto"] != "none": # This needs to come after `configure`, otherwise we don't have env.msvc. if not env.msvc: # Specifying GNU extensions support explicitly, which are supported by - # both GCC and Clang. Both currently default to gnu11 and gnu++17. - env.Prepend(CFLAGS=["-std=gnu11"]) + # both GCC and Clang. Both currently default to gnu17 and gnu++17. + env.Prepend(CFLAGS=["-std=gnu17"]) env.Prepend(CXXFLAGS=["-std=gnu++17"]) else: # MSVC started offering C standard support with Visual Studio 2019 16.8, which covers all @@ -809,7 +795,7 @@ else: if cc_version_major < 16: print_warning("Visual Studio 2017 cannot specify a C-Standard.") else: - env.Prepend(CFLAGS=["/std:c11"]) + env.Prepend(CFLAGS=["/std:c17"]) # MSVC is non-conforming with the C++ standard by default, so we enable more conformance. # Note that this is still not complete conformance, as certain Windows-related headers # don't compile under complete conformance. @@ -850,6 +836,7 @@ if env.msvc and not methods.using_clang(env): # MSVC "/wd4245", "/wd4267", "/wd4305", # C4305 (truncation): double to float or real_t, too hard to avoid. + "/wd4324", # C4820 (structure was padded due to alignment specifier) "/wd4514", # C4514 (unreferenced inline function has been removed) "/wd4714", # C4714 (function marked as __forceinline not inlined) "/wd4820", # C4820 (padding added after construct) @@ -864,8 +851,6 @@ else: # GCC, Clang if methods.using_gcc(env): common_warnings += ["-Wshadow", "-Wno-misleading-indentation"] - if cc_version_major == 7: # Bogus warning fixed in 8+. - common_warnings += ["-Wno-strict-overflow"] if cc_version_major < 11: # Regression in GCC 9/10, spams so much in our variadic templates # that we need to outright disable it. @@ -941,7 +926,7 @@ env.module_icons_paths = [] env.doc_class_path = platform_doc_class_path for name, path in modules_detected.items(): - if not env["module_" + name + "_enabled"]: + if not env[f"module_{name}_enabled"]: continue sys.path.insert(0, path) env.current_module = name @@ -1048,35 +1033,19 @@ GLSL_BUILDERS = { } env.Append(BUILDERS=GLSL_BUILDERS) -scons_cache_path = os.environ.get("SCONS_CACHE") -if scons_cache_path is not None: - CacheDir(scons_cache_path) - print("Scons cache enabled... (path: '" + scons_cache_path + "')") - -if env["vsproj"]: - env.vs_incs = [] - env.vs_srcs = [] - if env["compiledb"]: - if env.scons_version < (4, 0, 0): - # Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later. - print_error( - "The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version - ) - Exit(255) - env.Tool("compilation_db") env.Alias("compiledb", env.CompilationDatabase()) if env["ninja"]: if env.scons_version < (4, 2, 0): - print_error("The `ninja=yes` option requires SCons 4.2 or later, but your version is %s." % scons_raw_version) + print_error(f"The `ninja=yes` option requires SCons 4.2 or later, but your version is {scons_raw_version}.") Exit(255) SetOption("experimental", "ninja") env["NINJA_FILE_NAME"] = env["ninja_file"] env["NINJA_DISABLE_AUTO_RUN"] = not env["ninja_auto_run"] - env.Tool("ninja", "build.ninja") + env.Tool("ninja", env["ninja_file"]) # Threads if env["threads"]: @@ -1138,7 +1107,7 @@ atexit.register(print_elapsed_time) def purge_flaky_files(): - paths_to_keep = ["build.ninja"] + paths_to_keep = [env["ninja_file"]] for build_failure in GetBuildFailures(): path = build_failure.node.path if os.path.isfile(path) and path not in paths_to_keep: @@ -1146,5 +1115,3 @@ def purge_flaky_files(): atexit.register(purge_flaky_files) - -methods.clean_cache(env) diff --git a/core/config/engine.cpp b/core/config/engine.cpp index d77c913314..aac048e93f 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -36,6 +36,7 @@ #include "core/license.gen.h" #include "core/variant/typed_array.h" #include "core/version.h" +#include "servers/rendering/rendering_device.h" 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."); @@ -68,6 +69,11 @@ double Engine::get_physics_jitter_fix() const { void Engine::set_max_fps(int p_fps) { _max_fps = p_fps > 0 ? p_fps : 0; + + RenderingDevice *rd = RenderingDevice::get_singleton(); + if (rd) { + rd->_set_max_fps(_max_fps); + } } int Engine::get_max_fps() const { @@ -110,6 +116,10 @@ void Engine::set_time_scale(double p_scale) { } double Engine::get_time_scale() const { + return freeze_time_scale ? 0 : _time_scale; +} + +double Engine::get_unfrozen_time_scale() const { return _time_scale; } @@ -267,6 +277,12 @@ bool Engine::is_extra_gpu_memory_tracking_enabled() const { return extra_gpu_memory_tracking; } +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) +bool Engine::is_accurate_breadcrumbs_enabled() const { + return accurate_breadcrumbs; +} +#endif + void Engine::set_print_to_stdout(bool p_enabled) { CoreGlobals::print_line_enabled = p_enabled; } @@ -392,6 +408,10 @@ bool Engine::notify_frame_server_synced() { return server_syncs > SERVER_SYNC_FRAME_COUNT_WARNING; } +void Engine::set_freeze_time_scale(bool p_frozen) { + freeze_time_scale = p_frozen; +} + Engine::Engine() { singleton = this; } diff --git a/core/config/engine.h b/core/config/engine.h index a0b1ffa981..b38412308a 100644 --- a/core/config/engine.h +++ b/core/config/engine.h @@ -73,6 +73,9 @@ private: bool use_validation_layers = false; bool generate_spirv_debug_info = false; bool extra_gpu_memory_tracking = false; +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) + bool accurate_breadcrumbs = false; +#endif int32_t gpu_idx = -1; uint64_t _process_frames = 0; @@ -96,6 +99,8 @@ private: int server_syncs = 0; bool frame_server_synced = false; + bool freeze_time_scale = false; + public: static Engine *get_singleton(); @@ -127,6 +132,7 @@ public: void set_time_scale(double p_scale); double get_time_scale() const; + double get_unfrozen_time_scale() const; void set_print_to_stdout(bool p_enabled); bool is_printing_to_stdout() const; @@ -186,11 +192,16 @@ public: bool is_validation_layers_enabled() const; bool is_generate_spirv_debug_info_enabled() const; bool is_extra_gpu_memory_tracking_enabled() const; +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) + bool is_accurate_breadcrumbs_enabled() const; +#endif int32_t get_gpu_index() const; void increment_frames_drawn(); bool notify_frame_server_synced(); + void set_freeze_time_scale(bool p_frozen); + Engine(); virtual ~Engine(); }; diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 01f15f9c8e..6c28b00f48 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -194,7 +194,7 @@ String ProjectSettings::localize_path(const String &p_path) const { return cwd.replace_first(res_path, "res://"); } else { - int sep = path.rfind("/"); + int sep = path.rfind_char('/'); if (sep == -1) { return "res://" + path; } @@ -214,36 +214,36 @@ String ProjectSettings::localize_path(const String &p_path) const { } void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); // Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value. props[p_name].initial = p_value.duplicate(); } void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); props[p_name].restart_if_changed = p_restart; } void ProjectSettings::set_as_basic(const String &p_name, bool p_basic) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); props[p_name].basic = p_basic; } void ProjectSettings::set_as_internal(const String &p_name, bool p_internal) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); props[p_name].internal = p_internal; } void ProjectSettings::set_ignore_value_in_docs(const String &p_name, bool p_ignore) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); #ifdef DEBUG_METHODS_ENABLED props[p_name].ignore_value_in_docs = p_ignore; #endif } bool ProjectSettings::get_ignore_value_in_docs(const String &p_name) const { - ERR_FAIL_COND_V_MSG(!props.has(p_name), false, "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_V_MSG(!props.has(p_name), false, vformat("Request for nonexistent project setting: '%s'.", p_name)); #ifdef DEBUG_METHODS_ENABLED return props[p_name].ignore_value_in_docs; #else @@ -262,6 +262,12 @@ String ProjectSettings::globalize_path(const String &p_path) const { return p_path.replace("res:/", resource_path); } return p_path.replace("res://", ""); + } else if (p_path.begins_with("uid://")) { + const String path = ResourceUID::uid_to_path(p_path); + if (!resource_path.is_empty()) { + return path.replace("res:/", resource_path); + } + return path.replace("res://", ""); } else if (p_path.begins_with("user://")) { String data_dir = OS::get_singleton()->get_user_data_dir(); if (!data_dir.is_empty()) { @@ -300,7 +306,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { } { // Feature overrides. - int dot = p_name.operator String().find("."); + int dot = p_name.operator String().find_char('.'); if (dot != -1) { Vector<String> s = p_name.operator String().split("."); @@ -371,7 +377,7 @@ Variant ProjectSettings::get_setting_with_override(const StringName &p_name) con } if (!props.has(name)) { - WARN_PRINT("Property not found: " + String(name)); + WARN_PRINT(vformat("Property not found: '%s'.", String(name))); return Variant(); } return props[name].variant; @@ -435,7 +441,7 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const { for (const _VCSort &E : vclist) { String prop_info_name = E.name; - int dot = prop_info_name.find("."); + 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); } @@ -494,6 +500,7 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_f } void ProjectSettings::_convert_to_last_version(int p_from_version) { +#ifndef DISABLE_DEPRECATED if (p_from_version <= 3) { // Converts the actions from array to dictionary (array of events to dictionary with deadzone + events) for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) { @@ -507,6 +514,25 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) { } } } + if (p_from_version == 5) { + // Converts the device in events from -3 to -1. + // -3 was introduced in GH-97707 as a way to prevent a clash in device IDs, but as reported in GH-99243, this leads to problems. + // -3 was used during dev-releases, so this conversion helps to revert such affected projects. + // This conversion doesn't affect any other projects, since -3 is not used otherwise. + for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) { + if (String(E.key).begins_with("input/")) { + Dictionary action = E.value.variant; + Array events = action["events"]; + for (int i = 0; i < events.size(); i++) { + Ref<InputEvent> ev = events[i]; + if (ev.is_valid() && ev->get_device() == -3) { + ev->set_device(-1); + } + } + } + } + } +#endif // DISABLE_DEPRECATED } /* @@ -548,7 +574,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b if (!p_main_pack.is_empty()) { bool ok = _load_resource_pack(p_main_pack); - ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, "Cannot open resource pack '" + p_main_pack + "'."); + 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"); if (err == OK && !p_ignore_override) { @@ -627,7 +653,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b // or, if requested (`p_upwards`) in parent directories. Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V_MSG(d.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(d.is_null(), ERR_CANT_CREATE, vformat("Cannot create DirAccess for path '%s'.", p_path)); d->change_dir(p_path); String current_dir = d->get_current_dir(); @@ -731,7 +757,7 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) { f->get_buffer(d.ptrw(), vlen); Variant value; err = decode_variant(value, d.ptr(), d.size(), nullptr, true); - ERR_CONTINUE_MSG(err != OK, "Error decoding property: " + key + "."); + ERR_CONTINUE_MSG(err != OK, vformat("Error decoding property: '%s'.", key)); set(key, value); } @@ -773,7 +799,7 @@ Error ProjectSettings::_load_settings_text(const String &p_path) { last_save_time = FileAccess::get_modified_time(get_resource_path().path_join("project.godot")); return OK; } - ERR_FAIL_COND_V_MSG(err != OK, err, "Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error parsing '%s' at line %d: %s File might be corrupted.", p_path, lines, error_text)); if (!assign.is_empty()) { if (section.is_empty() && assign == "config_version") { @@ -799,7 +825,7 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path, return OK; } else if (err != ERR_FILE_NOT_FOUND) { // If the file exists but can't be loaded, we want to know it. - ERR_PRINT("Couldn't load file '" + p_bin_path + "', error code " + itos(err) + "."); + ERR_PRINT(vformat("Couldn't load file '%s', error code %d.", p_bin_path, err)); } // Fallback to text-based project.godot file if binary was not found. @@ -807,7 +833,7 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path, if (err == OK) { return OK; } else if (err != ERR_FILE_NOT_FOUND) { - ERR_PRINT("Couldn't load file '" + p_text_path + "', error code " + itos(err) + "."); + ERR_PRINT(vformat("Couldn't load file '%s', error code %d.", p_text_path, err)); } return err; @@ -821,17 +847,17 @@ Error ProjectSettings::load_custom(const String &p_path) { } int ProjectSettings::get_order(const String &p_name) const { - ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, vformat("Request for nonexistent project setting: '%s'.", p_name)); return props[p_name].order; } void ProjectSettings::set_order(const String &p_name, int p_order) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); props[p_name].order = p_order; } void ProjectSettings::set_builtin_order(const String &p_name) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); if (props[p_name].order >= NO_BUILTIN_ORDER_BASE) { props[p_name].order = last_builtin_order++; } @@ -839,12 +865,12 @@ void ProjectSettings::set_builtin_order(const String &p_name) { bool ProjectSettings::is_builtin_setting(const String &p_name) const { // Return true because a false negative is worse than a false positive. - ERR_FAIL_COND_V_MSG(!props.has(p_name), true, "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_V_MSG(!props.has(p_name), true, vformat("Request for nonexistent project setting: '%s'.", p_name)); return props[p_name].order < NO_BUILTIN_ORDER_BASE; } void ProjectSettings::clear(const String &p_name) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name)); props.erase(p_name); } @@ -859,7 +885,7 @@ Error ProjectSettings::save() { Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<String, List<String>> &p_props, const CustomMap &p_custom, const String &p_custom_features) { Error err; Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.binary at " + p_file + "."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Couldn't save project.binary at '%s'.", p_file)); uint8_t hdr[4] = { 'E', 'C', 'F', 'G' }; file->store_buffer(hdr, 4); @@ -929,7 +955,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const RBMap<Str Error err; Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.godot - " + p_file + "."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Couldn't save project.godot - %s.", p_file)); file->store_line("; Engine configuration file."); file->store_line("; It's best edited using the editor UI and not directly,"); @@ -1075,7 +1101,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust String category = E.name; String name = E.name; - int div = category.find("/"); + int div = category.find_char('/'); if (div < 0) { category = ""; @@ -1102,7 +1128,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust } else if (p_path.ends_with(".binary")) { return _save_settings_binary(p_path, save_props, p_custom, save_features); } else { - ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unknown config file format: " + p_path); + ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Unknown config file format: '%s'.", p_path)); } } @@ -1391,7 +1417,7 @@ void ProjectSettings::_add_builtin_input_map() { } Dictionary action; - action["deadzone"] = Variant(0.2f); + action["deadzone"] = Variant(InputMap::DEFAULT_DEADZONE); action["events"] = events; String action_name = "input/" + E.key; @@ -1460,6 +1486,7 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("display/window/size/transparent", false); GLOBAL_DEF("display/window/size/extend_to_title", false); GLOBAL_DEF("display/window/size/no_focus", false); + GLOBAL_DEF("display/window/size/sharp_corners", false); 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 @@ -1485,6 +1512,10 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("display/window/subwindows/embed_subwindows", true); // 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); + GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/frame_pacing/android/swappy_mode", PROPERTY_HINT_ENUM, "pipeline_forced_on,auto_fps_pipeline_forced_on,auto_fps_auto_pipeline"), 2); + custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded"); GLOBAL_DEF("physics/2d/run_on_separate_thread", false); GLOBAL_DEF("physics/3d/run_on_separate_thread", false); diff --git a/core/core_bind.compat.inc b/core/core_bind.compat.inc index 3e8ac3c5de..22c78623da 100644 --- a/core/core_bind.compat.inc +++ b/core/core_bind.compat.inc @@ -44,11 +44,16 @@ void Semaphore::_bind_compatibility_methods() { // OS +String OS::_read_string_from_stdin_bind_compat_91201() { + return read_string_from_stdin(1024); +} + Dictionary OS::_execute_with_pipe_bind_compat_94434(const String &p_path, const Vector<String> &p_arguments) { return execute_with_pipe(p_path, p_arguments, true); } void OS::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("read_string_from_stdin"), &OS::_read_string_from_stdin_bind_compat_91201); ClassDB::bind_compatibility_method(D_METHOD("execute_with_pipe", "path", "arguments"), &OS::_execute_with_pipe_bind_compat_94434); } diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 891e3a28c9..925551d933 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -75,7 +75,7 @@ Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hi Error err = OK; Ref<Resource> ret = ::ResourceLoader::load(p_path, p_type_hint, ResourceFormatLoader::CacheMode(p_cache_mode), &err); - ERR_FAIL_COND_V_MSG(err != OK, ret, "Error loading resource: '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, ret, vformat("Error loading resource: '%s'.", p_path)); return ret; } @@ -132,6 +132,10 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) { return ::ResourceLoader::get_resource_uid(p_path); } +Vector<String> ResourceLoader::list_directory(const String &p_directory) { + return ::ResourceLoader::list_directory(p_directory); +} + void ResourceLoader::_bind_methods() { ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads", "cache_mode"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE)); ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL_ARRAY); @@ -147,6 +151,7 @@ void ResourceLoader::_bind_methods() { ClassDB::bind_method(D_METHOD("get_cached_ref", "path"), &ResourceLoader::get_cached_ref); ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &ResourceLoader::exists, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_resource_uid", "path"), &ResourceLoader::get_resource_uid); + ClassDB::bind_method(D_METHOD("list_directory", "directory_path"), &ResourceLoader::list_directory); BIND_ENUM_CONSTANT(THREAD_LOAD_INVALID_RESOURCE); BIND_ENUM_CONSTANT(THREAD_LOAD_IN_PROGRESS); @@ -303,8 +308,24 @@ Error OS::shell_show_in_file_manager(const String &p_path, bool p_open_folder) { return ::OS::get_singleton()->shell_show_in_file_manager(p_path, p_open_folder); } -String OS::read_string_from_stdin() { - return ::OS::get_singleton()->get_stdin_string(); +String OS::read_string_from_stdin(int64_t p_buffer_size) { + return ::OS::get_singleton()->get_stdin_string(p_buffer_size); +} + +PackedByteArray OS::read_buffer_from_stdin(int64_t p_buffer_size) { + return ::OS::get_singleton()->get_stdin_buffer(p_buffer_size); +} + +OS::StdHandleType OS::get_stdin_type() const { + return (OS::StdHandleType)::OS::get_singleton()->get_stdin_type(); +} + +OS::StdHandleType OS::get_stdout_type() const { + return (OS::StdHandleType)::OS::get_singleton()->get_stdout_type(); +} + +OS::StdHandleType OS::get_stderr_type() const { + return (OS::StdHandleType)::OS::get_singleton()->get_stderr_type(); } int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r_output, bool p_read_stderr, bool p_open_console) { @@ -468,11 +489,11 @@ Error OS::set_thread_name(const String &p_name) { ::Thread::ID OS::get_thread_caller_id() const { return ::Thread::get_caller_id(); -}; +} ::Thread::ID OS::get_main_thread_id() const { return ::Thread::get_main_id(); -}; +} bool OS::has_feature(const String &p_feature) const { const bool *value_ptr = feature_cache.getptr(p_feature); @@ -628,7 +649,13 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_system_font_path", "font_name", "weight", "stretch", "italic"), &OS::get_system_font_path, DEFVAL(400), DEFVAL(100), DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path); - ClassDB::bind_method(D_METHOD("read_string_from_stdin"), &OS::read_string_from_stdin); + + ClassDB::bind_method(D_METHOD("read_string_from_stdin", "buffer_size"), &OS::read_string_from_stdin); + ClassDB::bind_method(D_METHOD("read_buffer_from_stdin", "buffer_size"), &OS::read_buffer_from_stdin); + ClassDB::bind_method(D_METHOD("get_stdin_type"), &OS::get_stdin_type); + ClassDB::bind_method(D_METHOD("get_stdout_type"), &OS::get_stdout_type); + ClassDB::bind_method(D_METHOD("get_stderr_type"), &OS::get_stderr_type); + ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL_ARRAY, DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("execute_with_pipe", "path", "arguments", "blocking"), &OS::execute_with_pipe, DEFVAL(true)); ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false)); @@ -720,6 +747,12 @@ void OS::_bind_methods() { BIND_ENUM_CONSTANT(SYSTEM_DIR_MUSIC); BIND_ENUM_CONSTANT(SYSTEM_DIR_PICTURES); BIND_ENUM_CONSTANT(SYSTEM_DIR_RINGTONES); + + BIND_ENUM_CONSTANT(STD_HANDLE_INVALID); + BIND_ENUM_CONSTANT(STD_HANDLE_CONSOLE); + BIND_ENUM_CONSTANT(STD_HANDLE_FILE); + BIND_ENUM_CONSTANT(STD_HANDLE_PIPE); + BIND_ENUM_CONSTANT(STD_HANDLE_UNKNOWN); } ////// Geometry2D ////// @@ -920,6 +953,19 @@ Dictionary Geometry2D::make_atlas(const Vector<Size2> &p_rects) { return ret; } +TypedArray<Point2i> Geometry2D::bresenham_line(const Point2i &p_from, const Point2i &p_to) { + Vector<Point2i> points = ::Geometry2D::bresenham_line(p_from, p_to); + + TypedArray<Point2i> result; + result.resize(points.size()); + + for (int i = 0; i < points.size(); i++) { + result[i] = points[i]; + } + + return result; +} + void Geometry2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &Geometry2D::is_point_in_circle); ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &Geometry2D::segment_intersects_circle); @@ -954,6 +1000,8 @@ void Geometry2D::_bind_methods() { ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &Geometry2D::make_atlas); + ClassDB::bind_method(D_METHOD("bresenham_line", "from", "to"), &Geometry2D::bresenham_line); + BIND_ENUM_CONSTANT(OPERATION_UNION); BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE); BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); @@ -1300,7 +1348,7 @@ void Thread::_start_func(void *ud) { } if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_MSG("Could not call function '" + func_name + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce) + "."); + ERR_FAIL_MSG(vformat("Could not call function '%s' to start thread %d: %s.", func_name, t->get_id(), Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce))); } } @@ -1525,7 +1573,7 @@ TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class, return ret; } -Variant ClassDB::class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) { +Variant ClassDB::class_call_static(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) { if (p_argcount < 2) { r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; return Variant::NIL; @@ -1666,7 +1714,7 @@ void ClassDB::_bind_methods() { ::ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &ClassDB::class_get_method_list, DEFVAL(false)); - ::ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "class_call_static_method", &ClassDB::class_call_static_method, MethodInfo("class_call_static_method", PropertyInfo(Variant::STRING_NAME, "class"), PropertyInfo(Variant::STRING_NAME, "method"))); + ::ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "class_call_static", &ClassDB::class_call_static, MethodInfo("class_call_static", PropertyInfo(Variant::STRING_NAME, "class"), PropertyInfo(Variant::STRING_NAME, "method"))); ::ClassDB::bind_method(D_METHOD("class_get_integer_constant_list", "class", "no_inheritance"), &ClassDB::class_get_integer_constant_list, DEFVAL(false)); @@ -1799,8 +1847,8 @@ Object *Engine::get_singleton_object(const StringName &p_name) const { } void Engine::register_singleton(const StringName &p_name, Object *p_object) { - ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name)); - ERR_FAIL_COND_MSG(!String(p_name).is_valid_ascii_identifier(), "Singleton name is not a valid identifier: " + p_name); + ERR_FAIL_COND_MSG(has_singleton(p_name), vformat("Singleton already registered: '%s'.", String(p_name))); + ERR_FAIL_COND_MSG(!String(p_name).is_valid_ascii_identifier(), vformat("Singleton name is not a valid identifier: '%s'.", p_name)); ::Engine::Singleton s; s.class_name = p_name; s.name = p_name; @@ -1810,8 +1858,8 @@ void Engine::register_singleton(const StringName &p_name, Object *p_object) { } void Engine::unregister_singleton(const StringName &p_name) { - ERR_FAIL_COND_MSG(!has_singleton(p_name), "Attempt to remove unregistered singleton: " + String(p_name)); - ERR_FAIL_COND_MSG(!::Engine::get_singleton()->is_singleton_user_created(p_name), "Attempt to remove non-user created singleton: " + String(p_name)); + ERR_FAIL_COND_MSG(!has_singleton(p_name), vformat("Attempt to remove unregistered singleton: '%s'.", String(p_name))); + ERR_FAIL_COND_MSG(!::Engine::get_singleton()->is_singleton_user_created(p_name), vformat("Attempt to remove non-user created singleton: '%s'.", String(p_name))); ::Engine::get_singleton()->remove_singleton(p_name); } @@ -1955,14 +2003,14 @@ bool EngineDebugger::is_active() { void EngineDebugger::register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler) { ERR_FAIL_COND(p_profiler.is_null()); ERR_FAIL_COND_MSG(p_profiler->is_bound(), "Profiler already registered."); - ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler name already in use: " + p_name); + ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), vformat("Profiler name already in use: '%s'.", p_name)); Error err = p_profiler->bind(p_name); - ERR_FAIL_COND_MSG(err != OK, "Profiler failed to register with error: " + itos(err)); + ERR_FAIL_COND_MSG(err != OK, vformat("Profiler failed to register with error: %d.", err)); profilers.insert(p_name, p_profiler); } void EngineDebugger::unregister_profiler(const StringName &p_name) { - ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name); + ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Profiler not registered: '%s'.", p_name)); profilers[p_name]->unbind(); profilers.erase(p_name); } @@ -1986,7 +2034,7 @@ void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, c } void EngineDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) { - ERR_FAIL_COND_MSG(captures.has(p_name) || has_capture(p_name), "Capture already registered: " + p_name); + ERR_FAIL_COND_MSG(captures.has(p_name) || has_capture(p_name), vformat("Capture already registered: '%s'.", p_name)); captures.insert(p_name, p_callable); Callable &c = captures[p_name]; ::EngineDebugger::Capture capture(&c, &EngineDebugger::call_capture); @@ -1994,7 +2042,7 @@ void EngineDebugger::register_message_capture(const StringName &p_name, const Ca } void EngineDebugger::unregister_message_capture(const StringName &p_name) { - ERR_FAIL_COND_MSG(!captures.has(p_name), "Capture not registered: " + p_name); + ERR_FAIL_COND_MSG(!captures.has(p_name), vformat("Capture not registered: '%s'.", p_name)); ::EngineDebugger::unregister_message_capture(p_name); captures.erase(p_name); } @@ -2028,8 +2076,8 @@ Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Arra Variant retval; Callable::CallError err; capture.callp(args, 2, retval, err); - ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, FAILED, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(capture, args, 2, err)); - ERR_FAIL_COND_V_MSG(retval.get_type() != Variant::BOOL, FAILED, "Error calling 'capture' to callable: " + String(capture) + ". Return type is not bool."); + ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, FAILED, vformat("Error calling 'capture' to callable: %s.", Variant::get_callable_error_text(capture, args, 2, err))); + ERR_FAIL_COND_V_MSG(retval.get_type() != Variant::BOOL, FAILED, vformat("Error calling 'capture' to callable: '%s'. Return type is not bool.", String(capture))); r_captured = retval; return OK; } diff --git a/core/core_bind.h b/core/core_bind.h index ce0bde3c05..d013e348bd 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -32,7 +32,6 @@ #define CORE_BIND_H #include "core/debugger/engine_profiler.h" -#include "core/io/image.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/object/script_language.h" @@ -87,6 +86,8 @@ public: bool exists(const String &p_path, const String &p_type_hint = ""); ResourceUID::ID get_resource_uid(const String &p_path); + Vector<String> list_directory(const String &p_directory); + ResourceLoader() { singleton = this; } }; @@ -133,6 +134,7 @@ protected: #ifndef DISABLE_DEPRECATED Dictionary _execute_with_pipe_bind_compat_94434(const String &p_path, const Vector<String> &p_arguments); + String _read_string_from_stdin_bind_compat_91201(); static void _bind_compatibility_methods(); #endif @@ -147,6 +149,14 @@ public: PackedByteArray get_entropy(int p_bytes); String get_system_ca_certificates(); + enum StdHandleType { + STD_HANDLE_INVALID, + STD_HANDLE_CONSOLE, + STD_HANDLE_FILE, + STD_HANDLE_PIPE, + STD_HANDLE_UNKNOWN, + }; + virtual PackedStringArray get_connected_midi_inputs(); virtual void open_midi_inputs(); virtual void close_midi_inputs(); @@ -167,7 +177,13 @@ public: String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const; Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const; String get_executable_path() const; - String read_string_from_stdin(); + + String read_string_from_stdin(int64_t p_buffer_size = 1024); + PackedByteArray read_buffer_from_stdin(int64_t p_buffer_size = 1024); + StdHandleType get_stdin_type() const; + StdHandleType get_stdout_type() const; + StdHandleType get_stderr_type() const; + int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = ClassDB::default_array_arg, bool p_read_stderr = false, bool p_open_console = false); Dictionary execute_with_pipe(const String &p_path, const Vector<String> &p_arguments, bool p_blocking = true); int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false); @@ -325,6 +341,8 @@ public: Dictionary make_atlas(const Vector<Size2> &p_rects); + TypedArray<Point2i> bresenham_line(const Point2i &p_from, const Point2i &p_to); + Geometry2D() { singleton = this; } }; @@ -483,7 +501,7 @@ public: int class_get_method_argument_count(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const; TypedArray<Dictionary> class_get_method_list(const StringName &p_class, bool p_no_inheritance = false) const; - Variant class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error); + Variant class_call_static(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error); PackedStringArray class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const; bool class_has_integer_constant(const StringName &p_class, const StringName &p_name) const; @@ -641,6 +659,7 @@ VARIANT_BITFIELD_CAST(core_bind::ResourceSaver::SaverFlags); VARIANT_ENUM_CAST(core_bind::OS::RenderingDriver); VARIANT_ENUM_CAST(core_bind::OS::SystemDir); +VARIANT_ENUM_CAST(core_bind::OS::StdHandleType); VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyBooleanOperation); VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyJoinType); diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 25da49fa5c..cdb4f2c800 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -678,6 +678,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_HIDE_QUATERNION_EDIT); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TOOL_BUTTON); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ONESHOT); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX); BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NONE); diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index 62bacadf91..30003e4ea8 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -240,7 +240,7 @@ Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const Str } else { ERR_FAIL_V(ERR_INVALID_PARAMETER); } - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Crypto resource to file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot save Crypto resource to file '%s'.", p_path)); return OK; } diff --git a/core/crypto/crypto_core.cpp b/core/crypto/crypto_core.cpp index 69a83284cc..13852d5177 100644 --- a/core/crypto/crypto_core.cpp +++ b/core/crypto/crypto_core.cpp @@ -70,7 +70,7 @@ int CryptoCore::RandomGenerator::_entropy_poll(void *p_data, unsigned char *r_bu Error CryptoCore::RandomGenerator::init() { int ret = mbedtls_ctr_drbg_seed((mbedtls_ctr_drbg_context *)ctx, mbedtls_entropy_func, (mbedtls_entropy_context *)entropy, nullptr, 0); if (ret) { - ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n ! mbedtls_ctr_drbg_seed returned an error" + itos(ret)); + ERR_FAIL_COND_V_MSG(ret, FAILED, vformat(" failed\n ! mbedtls_ctr_drbg_seed returned an error %d.", ret)); } return OK; } @@ -78,7 +78,7 @@ Error CryptoCore::RandomGenerator::init() { Error CryptoCore::RandomGenerator::get_random_bytes(uint8_t *r_buffer, size_t p_bytes) { ERR_FAIL_NULL_V(ctx, ERR_UNCONFIGURED); int ret = mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *)ctx, r_buffer, p_bytes); - ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n ! mbedtls_ctr_drbg_seed returned an error" + itos(ret)); + ERR_FAIL_COND_V_MSG(ret, FAILED, vformat(" failed\n ! mbedtls_ctr_drbg_seed returned an error %d.", ret)); return OK; } diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp index f4283e0ea9..cc36ca4816 100644 --- a/core/debugger/debugger_marshalls.cpp +++ b/core/debugger/debugger_marshalls.cpp @@ -147,3 +147,37 @@ bool DebuggerMarshalls::OutputError::deserialize(const Array &p_arr) { CHECK_END(p_arr, idx, "OutputError"); return true; } + +Array DebuggerMarshalls::serialize_key_shortcut(const Ref<Shortcut> &p_shortcut) { + ERR_FAIL_COND_V(p_shortcut.is_null(), Array()); + Array keys; + for (const Ref<InputEvent> ev : p_shortcut->get_events()) { + const Ref<InputEventKey> kev = ev; + ERR_CONTINUE(kev.is_null()); + if (kev->get_physical_keycode() != Key::NONE) { + keys.push_back(true); + keys.push_back(kev->get_physical_keycode_with_modifiers()); + } else { + keys.push_back(false); + keys.push_back(kev->get_keycode_with_modifiers()); + } + } + return keys; +} + +Ref<Shortcut> DebuggerMarshalls::deserialize_key_shortcut(const Array &p_keys) { + Array key_events; + ERR_FAIL_COND_V(p_keys.size() % 2 != 0, Ref<Shortcut>()); + for (int i = 0; i < p_keys.size(); i += 2) { + ERR_CONTINUE(p_keys[i].get_type() != Variant::BOOL); + ERR_CONTINUE(p_keys[i + 1].get_type() != Variant::INT); + key_events.push_back(InputEventKey::create_reference((Key)p_keys[i + 1].operator int(), p_keys[i].operator bool())); + } + if (key_events.is_empty()) { + return Ref<Shortcut>(); + } + Ref<Shortcut> shortcut; + shortcut.instantiate(); + shortcut->set_events(key_events); + return shortcut; +} diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h index 1b81623688..1072ddaeb7 100644 --- a/core/debugger/debugger_marshalls.h +++ b/core/debugger/debugger_marshalls.h @@ -31,6 +31,7 @@ #ifndef DEBUGGER_MARSHALLS_H #define DEBUGGER_MARSHALLS_H +#include "core/input/shortcut.h" #include "core/object/script_language.h" struct DebuggerMarshalls { @@ -68,6 +69,9 @@ struct DebuggerMarshalls { Array serialize(); bool deserialize(const Array &p_arr); }; + + static Array serialize_key_shortcut(const Ref<Shortcut> &p_shortcut); + static Ref<Shortcut> deserialize_key_shortcut(const Array &p_keys); }; #endif // DEBUGGER_MARSHALLS_H diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 97a020e4c3..a9f87ad825 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -46,12 +46,12 @@ HashMap<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols; void (*EngineDebugger::allow_focus_steal_fn)(); void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) { - ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name); + ERR_FAIL_COND_MSG(profilers.has(p_name), vformat("Profiler already registered: '%s'.", p_name)); profilers.insert(p_name, p_func); } void EngineDebugger::unregister_profiler(const StringName &p_name) { - ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name); + ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Profiler not registered: '%s'.", p_name)); Profiler &p = profilers[p_name]; if (p.active && p.toggle) { p.toggle(p.data, false, Array()); @@ -61,22 +61,22 @@ void EngineDebugger::unregister_profiler(const StringName &p_name) { } void EngineDebugger::register_message_capture(const StringName &p_name, Capture p_func) { - ERR_FAIL_COND_MSG(captures.has(p_name), "Capture already registered: " + p_name); + ERR_FAIL_COND_MSG(captures.has(p_name), vformat("Capture already registered: '%s'.", p_name)); captures.insert(p_name, p_func); } void EngineDebugger::unregister_message_capture(const StringName &p_name) { - ERR_FAIL_COND_MSG(!captures.has(p_name), "Capture not registered: " + p_name); + ERR_FAIL_COND_MSG(!captures.has(p_name), vformat("Capture not registered: '%s'.", p_name)); captures.erase(p_name); } void EngineDebugger::register_uri_handler(const String &p_protocol, CreatePeerFunc p_func) { - ERR_FAIL_COND_MSG(protocols.has(p_protocol), "Protocol handler already registered: " + p_protocol); + ERR_FAIL_COND_MSG(protocols.has(p_protocol), vformat("Protocol handler already registered: '%s'.", p_protocol)); protocols.insert(p_protocol, p_func); } void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) { - ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't change profiler state, no profiler: " + p_name); + ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Can't change profiler state, no profiler: '%s'.", p_name)); Profiler &p = profilers[p_name]; if (p.toggle) { p.toggle(p.data, p_enabled, p_opts); @@ -85,7 +85,7 @@ void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, c } void EngineDebugger::profiler_add_frame_data(const StringName &p_name, const Array &p_data) { - ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't add frame data, no profiler: " + p_name); + ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Can't add frame data, no profiler: '%s'.", p_name)); Profiler &p = profilers[p_name]; if (p.add) { p.add(p.data, p_data); @@ -106,7 +106,7 @@ bool EngineDebugger::has_capture(const StringName &p_name) { Error EngineDebugger::capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured) { r_captured = false; - ERR_FAIL_COND_V_MSG(!captures.has(p_name), ERR_UNCONFIGURED, "Capture not registered: " + p_name); + ERR_FAIL_COND_V_MSG(!captures.has(p_name), ERR_UNCONFIGURED, vformat("Capture not registered: '%s'.", p_name)); const Capture &cap = captures[p_name]; return cap.capture(cap.data, p_msg, p_args, r_captured); } @@ -163,8 +163,8 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, co for (int i = 0; i < p_breakpoints.size(); i++) { const String &bp = p_breakpoints[i]; - int sp = bp.rfind(":"); - ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format."); + int sp = bp.rfind_char(':'); + ERR_CONTINUE_MSG(sp == -1, vformat("Invalid breakpoint: '%s', expected file:line format.", bp)); singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp)); } diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index 16050778aa..3c4ac87408 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -106,7 +106,7 @@ public: _FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; } _FORCE_INLINE_ static bool is_active() { return singleton != nullptr && script_debugger != nullptr; } - _FORCE_INLINE_ static ScriptDebugger *get_script_debugger() { return script_debugger; }; + _FORCE_INLINE_ static ScriptDebugger *get_script_debugger() { return script_debugger; } static void initialize(const String &p_uri, bool p_skip_breakpoints, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()); static void deinitialize(); diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index dc46ffc307..a5d807f66b 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -171,7 +171,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else { String key_value = line.get_slicec(' ', 1); - int value_pos = key_value.find("="); + int value_pos = key_value.find_char('='); if (value_pos < 0) { print_line("Error: Invalid set format. Use: set key=value"); @@ -208,10 +208,10 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { print_variables(members, values, variable_prefix); } else if (line.begins_with("p") || line.begins_with("print")) { - if (line.get_slice_count(" ") <= 1) { - print_line("Usage: print <expre>"); + if (line.find_char(' ') < 0) { + print_line("Usage: print <expression>"); } else { - String expr = line.get_slicec(' ', 2); + String expr = line.split(" ", true, 1)[1]; String res = script_lang->debug_parse_stack_level_expression(current_frame, expr); print_line(res); } @@ -344,7 +344,7 @@ Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) { String breakpoint_part = p_line.get_slicec(' ', 1); Pair<String, int> breakpoint; - int last_colon = breakpoint_part.rfind(":"); + int last_colon = breakpoint_part.rfind_char(':'); if (last_colon < 0) { print_line("Error: Invalid breakpoint format. Expected [source:line]"); return breakpoint; diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index fc1b7b74f9..f8e42e6d92 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -79,7 +79,7 @@ public: for (int i = 0; i < custom_monitor_names.size(); i++) { Variant monitor_value = performance->call("get_custom_monitor", custom_monitor_names[i]); if (!monitor_value.is_num()) { - ERR_PRINT("Value of custom monitor '" + String(custom_monitor_names[i]) + "' is not a number"); + ERR_PRINT(vformat("Value of custom monitor '%s' is not a number.", String(custom_monitor_names[i]))); arr[i + max] = Variant(); } else { arr[i + max] = monitor_value; @@ -338,7 +338,7 @@ void RemoteDebugger::_send_stack_vars(List<String> &p_names, List<Variant> &p_va } Error RemoteDebugger::_try_capture(const String &p_msg, const Array &p_data, bool &r_captured) { - const int idx = p_msg.find(":"); + const int idx = p_msg.find_char(':'); r_captured = false; if (idx < 0) { // No prefix, unknown message. return OK; @@ -569,7 +569,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { bool captured = false; ERR_CONTINUE(_try_capture(command, data, captured) != OK); if (!captured) { - WARN_PRINT("Unknown message received from debugger: " + command); + WARN_PRINT(vformat("Unknown message received from debugger: %s.", command)); } } } else { @@ -610,7 +610,7 @@ void RemoteDebugger::poll_events(bool p_is_idle) { ERR_CONTINUE(arr[1].get_type() != Variant::ARRAY); const String cmd = arr[0]; - const int idx = cmd.find(":"); + const int idx = cmd.find_char(':'); bool parsed = false; if (idx < 0) { // Not prefix, use scripts capture. capture_parse("core", cmd, arr[1], parsed); diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index 9dca47a0b4..d38fbc8d91 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -178,7 +178,7 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po } if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) { - ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + "."); + ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num(tcp_client->get_status()))); return FAILED; } connected = true; @@ -224,7 +224,7 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) { uint16_t debug_port = 6007; if (debug_host.contains(":")) { - int sep_pos = debug_host.rfind(":"); + int sep_pos = debug_host.rfind_char(':'); debug_port = debug_host.substr(sep_pos + 1).to_int(); debug_host = debug_host.substr(0, sep_pos); } diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp index 813ee7684f..a2369992e6 100644 --- a/core/error/error_macros.cpp +++ b/core/error/error_macros.cpp @@ -107,6 +107,28 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co _global_unlock(); } +// 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) { + if (OS::get_singleton()) { + 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. + 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, p_error.utf8().get_data(), "", false, p_type); + l = l->next; + } + + _global_unlock(); +} + // Errors with message. (All combinations of p_error and p_message as String or char*.) void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) { _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_type); diff --git a/core/error/error_macros.h b/core/error/error_macros.h index 19c16667d0..752fd605e0 100644 --- a/core/error/error_macros.h +++ b/core/error/error_macros.h @@ -68,6 +68,7 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); +void _err_print_error_asap(const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR); void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false); void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false); void _err_flush_stdout(); diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index c5f7502c12..7263cafdf3 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -1363,7 +1363,7 @@ static bool compare_dict_array(const Dictionary &p_old_api, const Dictionary &p_ return true; // May just not have this array and its still good. Probably added recently. } bool failed = false; - ERR_FAIL_COND_V_MSG(!p_new_api.has(p_base_array), false, "New API lacks base array: " + p_base_array); + ERR_FAIL_COND_V_MSG(!p_new_api.has(p_base_array), false, vformat("New API lacks base array: %s", p_base_array)); Array new_api = p_new_api[p_base_array]; HashMap<String, Dictionary> new_api_assoc; @@ -1371,6 +1371,9 @@ static bool compare_dict_array(const Dictionary &p_old_api, const Dictionary &p_ Dictionary elem = var; ERR_FAIL_COND_V_MSG(!elem.has(p_name_field), false, vformat("Validate extension JSON: Element of base_array '%s' is missing field '%s'. This is a bug.", base_array, p_name_field)); String name = elem[p_name_field]; + if (name.is_valid_float()) { + name = name.trim_suffix(".0"); // Make "integers" stringified as integers. + } if (p_compare_operators && elem.has("right_type")) { name += " " + String(elem["right_type"]); } @@ -1386,6 +1389,9 @@ static bool compare_dict_array(const Dictionary &p_old_api, const Dictionary &p_ continue; } String name = old_elem[p_name_field]; + if (name.is_valid_float()) { + name = name.trim_suffix(".0"); // Make "integers" stringified as integers. + } if (p_compare_operators && old_elem.has("right_type")) { name += " " + String(old_elem["right_type"]); } @@ -1515,7 +1521,7 @@ static bool compare_sub_dict_array(HashSet<String> &r_removed_classes_registered return true; // May just not have this array and its still good. Probably added recently or optional. } bool failed = false; - ERR_FAIL_COND_V_MSG(!p_new_api.has(p_outer), false, "New API lacks base array: " + p_outer); + ERR_FAIL_COND_V_MSG(!p_new_api.has(p_outer), false, vformat("New API lacks base array: %s", p_outer)); Array new_api = p_new_api[p_outer]; HashMap<String, Dictionary> new_api_assoc; diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 7cba5cb161..258b01542e 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -154,7 +154,7 @@ public: } virtual bool is_vararg() const override { - return false; + return vararg; } #ifdef TOOLS_ENABLED @@ -355,8 +355,8 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name); - ERR_FAIL_COND_MSG(!String(class_name).is_valid_unicode_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier."); - ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered."); + ERR_FAIL_COND_MSG(!String(class_name).is_valid_unicode_identifier(), vformat("Attempt to register extension class '%s', which is not a valid class identifier.", class_name)); + ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), vformat("Attempt to register extension class '%s', which appears to be already registered.", class_name)); Extension *parent_extension = nullptr; @@ -370,7 +370,7 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr //inheriting from engine class } } else { - ERR_FAIL_MSG("Attempt to register an extension class '" + String(class_name) + "' using non-existing parent class '" + String(parent_class_name) + "'."); + ERR_FAIL_MSG(vformat("Attempt to register an extension class '%s' using non-existing parent class '%s'.", String(class_name), String(parent_class_name))); } #ifdef TOOLS_ENABLED @@ -463,7 +463,7 @@ void GDExtension::_register_extension_class_method(GDExtensionClassLibraryPtr p_ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name); - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension method '%s' for unexisting class '%s'.", String(method_name), class_name)); #ifdef TOOLS_ENABLED Extension *extension = &self->extension_classes[class_name]; @@ -513,7 +513,7 @@ void GDExtension::_register_extension_class_integer_constant(GDExtensionClassLib StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name); StringName constant_name = *reinterpret_cast<const StringName *>(p_constant_name); - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + constant_name + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension constant '%s' for unexisting class '%s'.", constant_name, class_name)); #ifdef TOOLS_ENABLED // If the extension is still marked as reloading, that means it failed to register again. @@ -537,7 +537,7 @@ void GDExtension::_register_extension_class_property_indexed(GDExtensionClassLib StringName setter = *reinterpret_cast<const StringName *>(p_setter); StringName getter = *reinterpret_cast<const StringName *>(p_getter); String property_name = *reinterpret_cast<const StringName *>(p_info->name); - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class property '%s' for unexisting class '%s'.", property_name, class_name)); #ifdef TOOLS_ENABLED // If the extension is still marked as reloading, that means it failed to register again. @@ -558,7 +558,7 @@ void GDExtension::_register_extension_class_property_group(GDExtensionClassLibra StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); String group_name = *reinterpret_cast<const String *>(p_group_name); String prefix = *reinterpret_cast<const String *>(p_prefix); - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + group_name + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class property group '%s' for unexisting class '%s'.", group_name, class_name)); #ifdef TOOLS_ENABLED // If the extension is still marked as reloading, that means it failed to register again. @@ -577,7 +577,7 @@ void GDExtension::_register_extension_class_property_subgroup(GDExtensionClassLi StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name); String prefix = *reinterpret_cast<const String *>(p_prefix); - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + subgroup_name + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class property subgroup '%s' for unexisting class '%s'.", subgroup_name, class_name)); #ifdef TOOLS_ENABLED // If the extension is still marked as reloading, that means it failed to register again. @@ -595,7 +595,7 @@ void GDExtension::_register_extension_class_signal(GDExtensionClassLibraryPtr p_ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name); - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + signal_name + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class signal '%s' for unexisting class '%s'.", signal_name, class_name)); #ifdef TOOLS_ENABLED // If the extension is still marked as reloading, that means it failed to register again. @@ -618,7 +618,7 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to unregister unexisting extension class '%s'.", class_name)); Extension *ext = &self->extension_classes[class_name]; #ifdef TOOLS_ENABLED @@ -626,7 +626,7 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra self->_clear_extension(ext); } #endif - ERR_FAIL_COND_MSG(ext->gdextension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it."); + ERR_FAIL_COND_MSG(ext->gdextension.children.size(), vformat("Attempt to unregister class '%s' while other extension classes inherit from it.", class_name)); #ifdef TOOLS_ENABLED ClassDB::unregister_extension_class(class_name, !ext->is_reloading); @@ -664,13 +664,13 @@ void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExte 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), "Attempt to register interface function '" + p_function_name + "', which appears to be already registered."); + 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)); gdextension_interface_functions.insert(p_function_name, p_function_pointer); } GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(const StringName &p_function_name) { GDExtensionInterfaceFunctionPtr *function = gdextension_interface_functions.getptr(p_function_name); - ERR_FAIL_NULL_V_MSG(function, nullptr, "Attempt to get non-existent interface function: " + String(p_function_name) + "."); + ERR_FAIL_NULL_V_MSG(function, nullptr, vformat("Attempt to get non-existent interface function: '%s'.", String(p_function_name))); return *function; } @@ -680,8 +680,8 @@ Error GDExtension::open_library(const String &p_path, const Ref<GDExtensionLoade Error err = loader->open_library(p_path); - ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + p_path); - ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + p_path); + ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, vformat("GDExtension dynamic library not found: '%s'.", p_path)); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Can't open GDExtension dynamic library: '%s'.", p_path)); err = loader->initialize(&gdextension_get_proc_address, this, &initialization); diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index 66b0161160..203f7960dc 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -34,6 +34,7 @@ #include "core/extension/gdextension.h" #include "core/extension/gdextension_compat_hashes.h" #include "core/io/file_access.h" +#include "core/io/image.h" #include "core/io/xml_parser.h" #include "core/object/class_db.h" #include "core/object/script_language_extension.h" @@ -1525,7 +1526,7 @@ static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionC #endif if (!mb && exists) { - ERR_PRINT("Method '" + classname + "." + methodname + "' has changed and no compatibility fallback has been provided. Please open an issue."); + ERR_PRINT(vformat("Method '%s.%s' has changed and no compatibility fallback has been provided. Please open an issue.", classname, methodname)); return nullptr; } ERR_FAIL_NULL_V(mb, nullptr); diff --git a/core/extension/gdextension_library_loader.cpp b/core/extension/gdextension_library_loader.cpp index d5f2eb668f..17200916ba 100644 --- a/core/extension/gdextension_library_loader.cpp +++ b/core/extension/gdextension_library_loader.cpp @@ -219,7 +219,7 @@ Error GDExtensionLibraryLoader::initialize(GDExtensionInterfaceGetProcAddress p_ Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, entry_symbol, entry_funcptr, false); if (err != OK) { - ERR_PRINT("GDExtension entry point '" + entry_symbol + "' not found in library " + library_path); + ERR_PRINT(vformat("GDExtension entry point '%s' not found in library %s.", entry_symbol, library_path)); return err; } @@ -230,7 +230,7 @@ Error GDExtensionLibraryLoader::initialize(GDExtensionInterfaceGetProcAddress p_ if (ret) { return OK; } else { - ERR_PRINT("GDExtension initialization function '" + entry_symbol + "' returned an error."); + ERR_PRINT(vformat("GDExtension initialization function '%s' returned an error.", entry_symbol)); return FAILED; } } @@ -272,12 +272,12 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) { Error err = config->load(p_path); if (err != OK) { - ERR_PRINT("Error loading GDExtension configuration file: " + p_path); + ERR_PRINT(vformat("Error loading GDExtension configuration file: '%s'.", p_path)); return err; } if (!config->has_section_key("configuration", "entry_symbol")) { - ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path); + ERR_PRINT(vformat("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: '%s'.", p_path)); return ERR_INVALID_DATA; } @@ -296,7 +296,7 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) { } } } else { - ERR_PRINT("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: " + p_path); + ERR_PRINT(vformat("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: '%s'.", p_path)); return ERR_INVALID_DATA; } diff --git a/core/extension/gdextension_manager.cpp b/core/extension/gdextension_manager.cpp index fff938858f..0dc13cf375 100644 --- a/core/extension/gdextension_manager.cpp +++ b/core/extension/gdextension_manager.cpp @@ -258,7 +258,7 @@ void GDExtensionManager::load_extensions() { String s = f->get_line().strip_edges(); if (!s.is_empty()) { LoadStatus err = load_extension(s); - ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, "Error loading extension: " + s); + ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, vformat("Error loading extension: '%s'.", s)); } } diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 7150911e75..50a7db5efd 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -3,6 +3,7 @@ # Windows 03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows, +03000000fa190000918d000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows, 03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, 03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, 03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, @@ -19,6 +20,7 @@ 03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +05000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows, 03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows, @@ -72,6 +74,8 @@ 03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001d30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, @@ -108,13 +112,14 @@ 03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows, 03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows, 03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, +03000000380800001889000000000000,AtGames Legends Gamer Pro,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b14,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000008a3500000102000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows, 030000008a3500000201000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows, 030000008a3500000302000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows, @@ -124,7 +129,7 @@ 03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, 030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows, 030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, @@ -141,8 +146,8 @@ 030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, @@ -224,7 +229,7 @@ 030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 0300000047530000616d000000000000,GameStop,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows, 030000008f0e00001411000000000000,Gamo2 Divaller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, @@ -258,7 +263,7 @@ 030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006201000000000000,Hori Fighting Commander Octa,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006401000000000000,Hori Fighting Commander Octa,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,start:b7,x:b2,y:b3,platform:Windows, @@ -266,7 +271,7 @@ 030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f00008800000000000000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -030000000d0f00008700000000000000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008700000000000000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, @@ -276,8 +281,8 @@ 030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows, -030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -311,18 +316,20 @@ 030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006e00000000000000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000c100000000000000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00009601000000000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b15,paddle2:b5,paddle3:b19,paddle4:b18,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows, 03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows, 03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows, 03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows, +03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, 03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows, 03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, 03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, @@ -377,22 +384,22 @@ 03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, 030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, @@ -405,6 +412,7 @@ 03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, 0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000242e0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows, 03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows, 03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows, 030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, @@ -436,11 +444,12 @@ 03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows, 03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows, +030000006f0e00001311000000000000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Windows, 030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 0300000085320000170d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 0300000085320000190d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, -030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 03000000eb0300000000000000000000,NeGcon Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows, @@ -475,6 +484,7 @@ 03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008901000000000000,PDP Realmz Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows, 03000000666600006706000000000000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows, 03000000e30500009605000000000000,PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, @@ -483,11 +493,13 @@ 03000000f0250000c183000000000000,PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000d620000013a7000000000000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d62000002640000000000000,PowerA OPS Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000d62000003340000000000000,PowerA OPS Pro Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000d620000014a7000000000000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -521,28 +533,28 @@ 030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, 030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows, -03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, -030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000004c0500005f0e000000000000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, @@ -557,7 +569,7 @@ 03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, 03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, 03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows, 03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, 03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, @@ -585,10 +597,11 @@ 030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, 030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, 030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +03000000790000008f18000000000000,Rapoo Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, 03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows, 03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, @@ -596,7 +609,7 @@ 03000000321500000a10000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows, 03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, @@ -653,7 +666,7 @@ 03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows, 03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, 03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, @@ -663,7 +676,7 @@ 03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, 030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows, 03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, 0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, 03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, @@ -678,7 +691,7 @@ 03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, 03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, @@ -738,10 +751,11 @@ 03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, 03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000882800000305000000000000,V5 Game Pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,x:b2,y:b3,platform:Windows, 03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows, 03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, @@ -769,7 +783,6 @@ 03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows, -03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, @@ -778,7 +791,6 @@ 030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, @@ -812,6 +824,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X, 03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Mac OS X, 03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, @@ -853,6 +866,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001d30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, @@ -871,18 +886,19 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, 03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, +03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X, 03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X, 03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X, 030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X, 030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X, 030000008a3500000402000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000008a3500000302000000010000,Backbone One PlayStationÆ Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X, +030000008a3500000302000000010000,Backbone One PlayStation Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X, 03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, 03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, @@ -897,7 +913,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X, 030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -906,13 +922,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00008800000000010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X, 030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -920,7 +936,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000000d0f00000002000017010000,Hori Split Pad Fit,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00000002000015010000,Hori Switch Split Pad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f0000c100000072050000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -943,8 +959,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006d04000018c2000000010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X, 03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, @@ -988,10 +1004,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, 030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, 030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 0300004b4c0500005f0e000000010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, @@ -1004,10 +1020,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000009b2800008000000022020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Mac OS X, 030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000321500000104000000010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000104000000010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 03000000321500000010000000010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000321500000011000000010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000011000000010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -1031,8 +1047,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, 030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X, -030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, @@ -1062,8 +1078,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, 03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X, -030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, 050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, 030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -1078,7 +1094,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, -030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, 030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, @@ -1088,7 +1104,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000022050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -1096,10 +1114,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, # Linux 03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000631000000010000,8BitDo Adapter 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, 03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Linux, 03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, @@ -1107,11 +1127,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000a20000000020000,8BitDo M30 Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, 03000000c82d00002090000011010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, 03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00006928000011010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux, 05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux, 05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, @@ -1133,6 +1155,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux, +03000000c82d00000060000011010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, @@ -1151,12 +1174,16 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000a31000014010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000631000010010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00000631000014010000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1164,7 +1191,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -050000005e040000e002000030110000,8BitDo Zero 2,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, 05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1201,7 +1227,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000008a3500000302000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000008a3500000402000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1209,14 +1235,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux, 030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux, 03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux, 03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +030000005e0400008e02000002010000,Data Frog S80,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, 03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, @@ -1260,17 +1287,16 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, 03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, 030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux, 030000000d0f00008800000011010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, 030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1286,7 +1312,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000000d0f00008501000017010000,Hori Split Pad Fit,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f0000c100000011010000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1337,12 +1363,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000380700006652000025010000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700008532000010010000,Mad Catz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, 03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008483000011010000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008483000011010000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000380700001888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700003888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700001647000010040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1385,6 +1411,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b000001050000,Microsoft Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, 03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, @@ -1398,9 +1425,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux, +030000006f0e00001311000011010000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Linux, 030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000853200000706000012010000,Nacon GC-100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux, @@ -1461,7 +1492,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d620000011a7000011010000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1476,7 +1507,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000b20000001010000,PowerA Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000250900000017000010010000,PS/SS/N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux, 03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, @@ -1492,18 +1525,18 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, 060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 0300004b4c0500005f0e000011010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, @@ -1515,25 +1548,29 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, 03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +03000000222c00001220000011010000,Qanba Drone 2 Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick (PS5),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux, 03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, 030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux, +0300132d9b2800006500000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, +0300132d9b2800006500000001010000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux, 03000000f8270000bf0b000011010000,Razer Kishi,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000321500000010000011010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000011000011010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000011000011010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1541,6 +1578,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f0000c100000072056800,Retro Bit Legacy16,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:+a4,misc1:b11,rightshoulder:b10,righttrigger:+a5,start:b6,x:b3,y:b2,platform:Linux, 03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux, 0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, 190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, @@ -1567,6 +1606,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000a306000020f6000011010000,Saitek PS2700 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 05000000e804000000a000001b010000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux, +03000000952e00004b43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000952e00004d43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000952e00004e43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, 03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux, 03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux, 03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, @@ -1578,7 +1620,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000bc2000000055000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004b2900000430000011000000,Snakebyte Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, 03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1648,8 +1691,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, 03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, -030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, @@ -1660,6 +1703,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000a102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000a102000030060000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001503000000020000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400008e02000000010000,Xbox 360 EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, @@ -1679,12 +1723,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000ea02000016050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000015050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1696,10 +1742,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000130b000017050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -060000005e040000120b00000d050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b000014050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000130b000017050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +060000005e040000120b00000d050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000200b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1712,181 +1758,184 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000120c0000101e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, # Android -38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, -64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, -34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, -38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, +34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, +38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android, +38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android, -32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android, -38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android, -64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android, -66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android, -66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android, -38426974446f204d6963726f2067616d,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, -61653365323561356263373333643266,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, -62613137616239666338343866326336,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, -33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, -38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, +32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android, +38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android, +64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android, +66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android, +66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android, +38426974446f204d6963726f2067616d,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, +61653365323561356263373333643266,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, +62613137616239666338343866326336,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, +33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, +38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, 05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38323035343766666239373834336637,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, -38426974446f204e3634204d6f646b69,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, -32363135613966656338666638666237,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35363534633333373639386466346631,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f204e454f47454f204750,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39383963623932353561633733306334,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38323035343766666239373834336637,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, +38426974446f204e3634204d6f646b69,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, +32363135613966656338666638666237,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35363534633333373639386466346631,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f204e454f47454f204750,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39383963623932353561633733306334,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android, -38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Android, -38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android, +38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +61333362366131643730353063616330,8BitDo Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Android, +38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android, +38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android, 61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android, 05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, -38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android, 33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, 38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, 05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, -63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, -4c696e757820342e31392e3137322077,Anbernic Gamepad,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android, +33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +4c696e757820342e31392e3137322077,Anbernic Gamepad,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android, 417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, -35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,start:b6,platform:Android, -32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,start:b6,platform:Android, +32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4f64696e20436f6e74726f6c6c657200,AYN Odin,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b14,dpright:b13,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:+a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, -4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, -30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android, +34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android, 05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, 05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android, -66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -484f524920434f2e2c4c544420205041,Hori Gem Pad 3,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, -65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b18,platform:Android, -31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -32656664353964393561366362333636,Hori Switch Split Pad Pro,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -30306539356238653637313730656134,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +484f524920434f2e2c4c544420205041,Hori Gem Pad 3,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, +65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b18,platform:Android, +31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +32656664353964393561366362333636,Hori Switch Split Pad Pro,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +30306539356238653637313730656134,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, 48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, 62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, -31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, -5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, 0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android, -5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android, +5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android, 64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android, -532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android, -65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, -33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, -64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, -6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android, -436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, -65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, -37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, -4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, -535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, -30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, -39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android, +532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android, +65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, +33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android, +436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android, 31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, -37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, -64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android, -33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, +37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b9,x:b2,y:b3,platform:Android, +33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, 30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, -32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4d4f42415041442050726f2d48440000,Mobapad Chitu HD,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4d4f42415041442050726f2d48440000,Mobapad Chitu HD,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android, 050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android, 34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android, -36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, -4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, -534e455320436f6e74726f6c6c657200,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -64623863346133633561626136366634,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android, +36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, +4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, +534e455320436f6e74726f6c6c657200,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +64623863346133633561626136366634,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, 050000005509000003720000cf7f3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005509000010720000ffff3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005509000014720000df7f3f00,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, 050000005509000014720000df7f3f80,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android, -37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, 4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, -506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, +506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, 62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, -536f6e7920496e746572616374697665,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -576972656c65737320436f6e74726f6c,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android, -32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android, +536f6e7920496e746572616374697665,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +576972656c65737320436f6e74726f6c,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android, +32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android, 050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -1895,89 +1944,89 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30303839663330346632363232623138,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, -31326235383662333266633463653332,PS4 Controller,a:b1,b:b16,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android, -31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -31663838336334393132303338353963,PS4 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -34613139376634626133336530386430,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, -37626233336235343937333961353732,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -37626464343430636562316661643863,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38393161636261653636653532386639,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -63313733393535663339656564343962,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -63393662363836383439353064663939,PS4 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +30303839663330346632363232623138,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +31326235383662333266633463653332,PS4 Controller,a:b1,b:b16,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android, +31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +31663838336334393132303338353963,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34613139376634626133336530386430,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +37626233336235343937333961353732,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +37626464343430636562316661643863,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38393161636261653636653532386639,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +63313733393535663339656564343962,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +63393662363836383439353064663939,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, 050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, -050000004c050000e60c0000fffe3f80,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000004c050000e60c0000fffe3f80,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b2,y:b17,platform:Android, 050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, -36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000f8270000bf0b0000ffff3f00,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, -5a6869587520526574726f2042697420,Retro Bit Saturn Controller,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b26,rightshoulder:b27,righttrigger:b28,start:b30,x:b23,y:b24,platform:Android, +5a6869587520526574726f2042697420,Retro Bit Saturn Controller,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b26,rightshoulder:b27,righttrigger:b28,start:b30,x:b23,y:b24,platform:Android, 32417865732031314b6579732047616d,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, 36313938306539326233393732613361,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android, -61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android, -526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android, +526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android, +61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android, +526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b6,platform:Android, 37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, 5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, 526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, 64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, -37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, -36363537303435333566386638366333,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -53616d73756e672047616d6520506164,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, +36363537303435333566386638366333,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +53616d73756e672047616d6520506164,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android, -32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, 38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, -61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, -30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, -66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, 5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, -5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, -63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, -476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, +63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, +476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 5374616469614e3848532d6532633400,Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, -0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android, +0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android, 35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android, 33313930373536613937326534303931,Taito Egret II Mini Control Panel,a:b25,b:b23,back:b27,guide:b30,leftx:a0,lefty:a1,rightshoulder:b21,righttrigger:b22,start:b28,x:b29,y:b24,platform:Android, -54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android, 38346162326232346533316164363336,THEGamepad,a:b23,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b24,y:b21,platform:Android, 050000004f0400000ed00000fffe3f00,ThrustMaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, -30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, -33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, +30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, 050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -58626f782033363020576972656c6573,Xbox 360 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +58626f782033363020576972656c6573,Xbox 360 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 65353331386662343338643939643636,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 65613532386633373963616462363038,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -47656e6572696320582d426f78207061,Xbox Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4d6963726f736f667420582d426f7820,Xbox Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -64633436313965656664373634323364,Xbox Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +47656e6572696320582d426f78207061,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4d6963726f736f667420582d426f7820,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64633436313965656664373634323364,Xbox Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e04000091020000ff073f00,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 050000005e04000091020000ff073f80,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e040000e00200000ffe3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, @@ -1985,11 +2034,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000e0020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, 050000005e040000e0020000ffff3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android, 050000005e040000fd020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, -35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, +35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 050000005e040000000b000000783f80,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e040000050b0000ffff3f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -1998,8 +2047,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 050000005e040000120b000000783f80,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000001727000044310000ffff3f00,XiaoMi Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, # iOS diff --git a/core/input/input.cpp b/core/input/input.cpp index eba7ded267..a0c00d7716 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -87,11 +87,50 @@ Input *Input::get_singleton() { void Input::set_mouse_mode(MouseMode p_mode) { ERR_FAIL_INDEX((int)p_mode, 5); + + if (p_mode == mouse_mode) { + return; + } + + // Allow to be set even if overridden, to see if the platform allows the mode. set_mouse_mode_func(p_mode); + mouse_mode = get_mouse_mode_func(); + + if (mouse_mode_override_enabled) { + set_mouse_mode_func(mouse_mode_override); + } } Input::MouseMode Input::get_mouse_mode() const { - return get_mouse_mode_func(); + return mouse_mode; +} + +void Input::set_mouse_mode_override_enabled(bool p_enabled) { + if (p_enabled == mouse_mode_override_enabled) { + return; + } + + mouse_mode_override_enabled = p_enabled; + + if (p_enabled) { + set_mouse_mode_func(mouse_mode_override); + mouse_mode_override = get_mouse_mode_func(); + } else { + set_mouse_mode_func(mouse_mode); + } +} + +void Input::set_mouse_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX((int)p_mode, 5); + + if (p_mode == mouse_mode_override) { + return; + } + + if (mouse_mode_override_enabled) { + set_mouse_mode_func(p_mode); + mouse_mode_override = get_mouse_mode_func(); + } } void Input::_bind_methods() { @@ -197,7 +236,7 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S continue; } - String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); + String name = pi.name.substr(pi.name.find_char('/') + 1, pi.name.length()); r_options->push_back(name.quote()); } } @@ -252,6 +291,10 @@ Input::VelocityTrack::VelocityTrack() { bool Input::is_anything_pressed() const { _THREAD_SAFE_METHOD_ + if (disable_input) { + return false; + } + if (!keys_pressed.is_empty() || !joy_buttons_pressed.is_empty() || !mouse_button_mask.is_empty()) { return true; } @@ -267,21 +310,41 @@ bool Input::is_anything_pressed() const { bool Input::is_key_pressed(Key p_keycode) const { _THREAD_SAFE_METHOD_ + + if (disable_input) { + return false; + } + return keys_pressed.has(p_keycode); } bool Input::is_physical_key_pressed(Key p_keycode) const { _THREAD_SAFE_METHOD_ + + if (disable_input) { + return false; + } + return physical_keys_pressed.has(p_keycode); } bool Input::is_key_label_pressed(Key p_keycode) const { _THREAD_SAFE_METHOD_ + + if (disable_input) { + return false; + } + return key_label_pressed.has(p_keycode); } bool Input::is_mouse_button_pressed(MouseButton p_button) const { _THREAD_SAFE_METHOD_ + + if (disable_input) { + return false; + } + return mouse_button_mask.has_flag(mouse_button_to_mask(p_button)); } @@ -295,11 +358,21 @@ static JoyButton _combine_device(JoyButton p_value, int p_device) { bool Input::is_joy_button_pressed(int p_device, JoyButton p_button) const { _THREAD_SAFE_METHOD_ + + if (disable_input) { + return false; + } + return joy_buttons_pressed.has(_combine_device(p_button, p_device)); } bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action)); + + if (disable_input) { + return false; + } + HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action); if (!E) { return false; @@ -310,6 +383,11 @@ bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const { bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action)); + + if (disable_input) { + return false; + } + HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action); if (!E) { return false; @@ -331,6 +409,11 @@ bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) con bool Input::is_action_just_released(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action)); + + if (disable_input) { + return false; + } + HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action); if (!E) { return false; @@ -352,6 +435,11 @@ bool Input::is_action_just_released(const StringName &p_action, bool p_exact) co float Input::get_action_strength(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), 0.0, InputMap::get_singleton()->suggest_actions(p_action)); + + if (disable_input) { + return 0.0f; + } + HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action); if (!E) { return 0.0f; @@ -366,6 +454,11 @@ float Input::get_action_strength(const StringName &p_action, bool p_exact) const float Input::get_action_raw_strength(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), 0.0, InputMap::get_singleton()->suggest_actions(p_action)); + + if (disable_input) { + return 0.0f; + } + HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action); if (!E) { return 0.0f; @@ -410,6 +503,11 @@ Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_po float Input::get_joy_axis(int p_device, JoyAxis p_axis) const { _THREAD_SAFE_METHOD_ + + if (disable_input) { + return 0; + } + JoyAxis c = _combine_device(p_axis, p_device); if (_joy_axis.has(c)) { return _joy_axis[c]; @@ -690,6 +788,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em button_event->set_canceled(st->is_canceled()); button_event->set_button_index(MouseButton::LEFT); button_event->set_double_click(st->is_double_tap()); + button_event->set_window_id(st->get_window_id()); BitField<MouseButtonMask> ev_bm = mouse_button_mask; if (st->is_pressed()) { @@ -727,6 +826,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em motion_event->set_velocity(sd->get_velocity()); motion_event->set_screen_velocity(sd->get_screen_velocity()); motion_event->set_button_mask(mouse_button_mask); + motion_event->set_window_id(sd->get_window_id()); _parse_input_event_impl(motion_event, true); } @@ -934,7 +1034,7 @@ void Input::action_release(const StringName &p_action) { // Create or retrieve existing action. ActionState &action_state = action_states[p_action]; - action_state.cache.pressed = 0; + action_state.cache.pressed = false; action_state.cache.strength = 0.0; action_state.cache.raw_strength = 0.0; // As input may come in part way through a physics tick, the earliest we can react to it is the next physics tick. @@ -1662,6 +1762,14 @@ int Input::get_unused_joy_id() { return -1; } +void Input::set_disable_input(bool p_disable) { + disable_input = p_disable; +} + +bool Input::is_input_disabled() const { + return disable_input; +} + Input::Input() { singleton = this; diff --git a/core/input/input.h b/core/input/input.h index 95dd623cc0..a189ae7d9a 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -103,6 +103,11 @@ private: Vector2 mouse_pos; int64_t mouse_window = 0; bool legacy_just_pressed_behavior = false; + bool disable_input = false; + + MouseMode mouse_mode = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; struct ActionState { uint64_t pressed_physics_frame = UINT64_MAX; @@ -279,6 +284,8 @@ protected: public: void set_mouse_mode(MouseMode p_mode); MouseMode get_mouse_mode() const; + void set_mouse_mode_override_enabled(bool p_enabled); + void set_mouse_mode_override(MouseMode p_mode); #ifdef TOOLS_ENABLED void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; @@ -380,6 +387,9 @@ public: void set_event_dispatch_function(EventDispatchFunc p_function); + void set_disable_input(bool p_disable); + bool is_input_disabled() const; + Input(); ~Input(); }; diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 905526bbbd..045ac83cd8 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -1100,7 +1100,7 @@ JoyAxis InputEventJoypadMotion::get_axis() const { void InputEventJoypadMotion::set_axis_value(float p_value) { axis_value = p_value; - pressed = Math::abs(axis_value) >= 0.5f; + pressed = Math::abs(axis_value) >= InputMap::DEFAULT_DEADZONE; emit_changed(); } diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 27a50c79f6..abd2c80ce1 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -44,7 +44,7 @@ int InputMap::ALL_DEVICES = -1; void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action); ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions); - ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(0.2f)); + ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(DEFAULT_DEADZONE)); ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action); ClassDB::bind_method(D_METHOD("action_set_deadzone", "action", "deadzone"), &InputMap::action_set_deadzone); @@ -106,7 +106,7 @@ void InputMap::get_argument_options(const StringName &p_function, int p_idx, Lis continue; } - String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); + String name = pi.name.substr(pi.name.find_char('/') + 1, pi.name.length()); r_options->push_back(name.quote()); } } @@ -116,7 +116,7 @@ void InputMap::get_argument_options(const StringName &p_function, int p_idx, Lis #endif void InputMap::add_action(const StringName &p_action, float p_deadzone) { - ERR_FAIL_COND_MSG(input_map.has(p_action), "InputMap already has action \"" + String(p_action) + "\"."); + ERR_FAIL_COND_MSG(input_map.has(p_action), vformat("InputMap already has action \"%s\".", String(p_action))); input_map[p_action] = Action(); static int last_id = 1; input_map[p_action].id = last_id; @@ -304,10 +304,10 @@ void InputMap::load_from_project_settings() { continue; } - String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); + String name = pi.name.substr(pi.name.find_char('/') + 1, pi.name.length()); Dictionary action = GLOBAL_GET(pi.name); - float deadzone = action.has("deadzone") ? (float)action["deadzone"] : 0.2f; + float deadzone = action.has("deadzone") ? (float)action["deadzone"] : DEFAULT_DEADZONE; Array events = action["events"]; add_action(name, deadzone); diff --git a/core/input/input_map.h b/core/input/input_map.h index b29687d144..0479d45c57 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -54,6 +54,8 @@ public: List<Ref<InputEvent>> inputs; }; + static constexpr float DEFAULT_DEADZONE = 0.2f; + private: static InputMap *singleton; @@ -79,7 +81,7 @@ public: bool has_action(const StringName &p_action) const; List<StringName> get_actions() const; - void add_action(const StringName &p_action, float p_deadzone = 0.2); + void add_action(const StringName &p_action, float p_deadzone = DEFAULT_DEADZONE); void erase_action(const StringName &p_action); float action_get_deadzone(const StringName &p_action); diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index 2f3fe4deeb..14588923cb 100644 --- a/core/io/dir_access.cpp +++ b/core/io/dir_access.cpp @@ -155,9 +155,9 @@ Error DirAccess::make_dir_recursive(const String &p_dir) { } else if (full_dir.begins_with("user://")) { base = "user://"; } else if (full_dir.is_network_share_path()) { - int pos = full_dir.find("/", 2); + int pos = full_dir.find_char('/', 2); ERR_FAIL_COND_V(pos < 0, ERR_INVALID_PARAMETER); - pos = full_dir.find("/", pos + 1); + pos = full_dir.find_char('/', pos + 1); ERR_FAIL_COND_V(pos < 0, ERR_INVALID_PARAMETER); base = full_dir.substr(0, pos + 1); } else if (full_dir.begins_with("/")) { @@ -177,7 +177,7 @@ Error DirAccess::make_dir_recursive(const String &p_dir) { curpath = curpath.path_join(subdirs[i]); Error err = make_dir(curpath); if (err != OK && err != ERR_ALREADY_EXISTS) { - ERR_FAIL_V_MSG(err, "Could not create directory: " + curpath); + ERR_FAIL_V_MSG(err, vformat("Could not create directory: '%s'.", curpath)); } } @@ -239,7 +239,7 @@ Ref<DirAccess> DirAccess::create_for_path(const String &p_path) { Ref<DirAccess> DirAccess::open(const String &p_path, Error *r_error) { Ref<DirAccess> da = create_for_path(p_path); - ERR_FAIL_COND_V_MSG(da.is_null(), nullptr, "Cannot create DirAccess for path '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(da.is_null(), nullptr, vformat("Cannot create DirAccess for path '%s'.", p_path)); Error err = da->change_dir(p_path); if (r_error) { *r_error = err; @@ -345,10 +345,10 @@ Error DirAccess::copy(const String &p_from, const String &p_to, int p_chmod_flag Error err; { Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Failed to open '%s'.", p_from)); Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Failed to open '%s'.", p_to)); const size_t copy_buffer_limit = 65536; // 64 KB @@ -444,11 +444,11 @@ Error DirAccess::_copy_dir(Ref<DirAccess> &p_target_da, const String &p_to, int String target_dir = p_to + rel_path; if (!p_target_da->dir_exists(target_dir)) { Error err = p_target_da->make_dir(target_dir); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + target_dir + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot create directory '%s'.", target_dir)); } Error err = change_dir(rel_path); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + rel_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot change current directory to '%s'.", rel_path)); err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags, p_copy_links); if (err) { @@ -466,11 +466,11 @@ Error DirAccess::copy_dir(const String &p_from, String p_to, int p_chmod_flags, ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist."); Ref<DirAccess> target_da = DirAccess::create_for_path(p_to); - ERR_FAIL_COND_V_MSG(target_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'."); + ERR_FAIL_COND_V_MSG(target_da.is_null(), ERR_CANT_CREATE, vformat("Cannot create DirAccess for path '%s'.", p_to)); if (!target_da->dir_exists(p_to)) { Error err = target_da->make_dir_recursive(p_to); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot create directory '%s'.", p_to)); } if (!p_to.ends_with("/")) { diff --git a/core/io/dir_access.h b/core/io/dir_access.h index e9c864c56b..2392944f76 100644 --- a/core/io/dir_access.h +++ b/core/io/dir_access.h @@ -96,8 +96,8 @@ public: virtual bool file_exists(String p_file) = 0; virtual bool dir_exists(String p_dir) = 0; - virtual bool is_readable(String p_dir) { return true; }; - virtual bool is_writable(String p_dir) { return true; }; + virtual bool is_readable(String p_dir) { return true; } + virtual bool is_writable(String p_dir) { return true; } static bool exists(const String &p_dir); virtual uint64_t get_space_left() = 0; @@ -116,10 +116,10 @@ public: Ref<DirAccess> da = create(ACCESS_FILESYSTEM); if (da->file_exists(p_path)) { if (da->remove(p_path) != OK) { - ERR_FAIL_MSG("Cannot remove file or directory: " + p_path); + ERR_FAIL_MSG(vformat("Cannot remove file or directory: '%s'.", p_path)); } } else { - ERR_FAIL_MSG("Cannot remove non-existent file or directory: " + p_path); + ERR_FAIL_MSG(vformat("Cannot remove non-existent file or directory: '%s'.", p_path)); } } diff --git a/core/io/file_access.compat.inc b/core/io/file_access.compat.inc new file mode 100644 index 0000000000..ed16050126 --- /dev/null +++ b/core/io/file_access.compat.inc @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* file_access.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +Ref<FileAccess> FileAccess::_open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) { + return open_encrypted(p_path, p_mode_flags, p_key, Vector<uint8_t>()); +} + +void FileAccess::_bind_compatibility_methods() { + ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918); +} + +#endif // DISABLE_DEPRECATED diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index d919243e6b..29027cade1 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "file_access.h" +#include "file_access.compat.inc" #include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" @@ -70,7 +71,7 @@ void FileAccess::_set_access_type(AccessType p_access) { Ref<FileAccess> FileAccess::create_for_path(const String &p_path) { Ref<FileAccess> ret; - if (p_path.begins_with("res://")) { + if (p_path.begins_with("res://") || p_path.begins_with("uid://")) { ret = create(ACCESS_RESOURCES); } else if (p_path.begins_with("user://")) { ret = create(ACCESS_USERDATA); @@ -124,7 +125,7 @@ Ref<FileAccess> FileAccess::_open(const String &p_path, ModeFlags p_mode_flags) return fa; } -Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) { +Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv) { Ref<FileAccess> fa = _open(p_path, p_mode_flags); if (fa.is_null()) { return fa; @@ -132,7 +133,7 @@ Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mod Ref<FileAccessEncrypted> fae; fae.instantiate(); - Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ); + Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ, true, p_iv); last_file_open_error = err; if (err) { return Ref<FileAccess>(); @@ -182,13 +183,17 @@ FileAccess::AccessType FileAccess::get_access_type() const { } String FileAccess::fix_path(const String &p_path) const { - //helper used by file accesses that use a single filesystem + // Helper used by file accesses that use a single filesystem. String r_path = p_path.replace("\\", "/"); switch (_access_type) { case ACCESS_RESOURCES: { if (ProjectSettings::get_singleton()) { + if (r_path.begins_with("uid://")) { + r_path = ResourceUID::uid_to_path(r_path); + } + if (r_path.begins_with("res://")) { String resource_path = ProjectSettings::get_singleton()->get_resource_path(); if (!resource_path.is_empty()) { @@ -263,6 +268,10 @@ uint64_t FileAccess::get_64() const { return data; } +float FileAccess::get_half() const { + return Math::half_to_float(get_16()); +} + float FileAccess::get_float() const { MarshallFloat m; m.i = get_32(); @@ -459,7 +468,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const { } Error err = data.resize(p_length); - ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements."); + ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length)); uint8_t *w = data.ptrw(); int64_t len = get_buffer(w, p_length); @@ -522,6 +531,10 @@ void FileAccess::store_real(real_t p_real) { } } +void FileAccess::store_half(float p_dest) { + store_16(Math::make_half_float(p_dest)); +} + void FileAccess::store_float(float p_dest) { MarshallFloat m; m.f = p_dest; @@ -540,7 +553,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) { } Ref<FileAccess> fa = create_for_path(p_file); - ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file)); uint64_t mt = fa->_get_modified_time(p_file); return mt; @@ -552,7 +565,7 @@ BitField<FileAccess::UnixPermissionFlags> FileAccess::get_unix_permissions(const } Ref<FileAccess> fa = create_for_path(p_file); - ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file)); return fa->_get_unix_permissions(p_file); } @@ -563,7 +576,7 @@ Error FileAccess::set_unix_permissions(const String &p_file, BitField<FileAccess } Ref<FileAccess> fa = create_for_path(p_file); - ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file)); Error err = fa->_set_unix_permissions(p_file, p_permissions); return err; @@ -575,7 +588,7 @@ bool FileAccess::get_hidden_attribute(const String &p_file) { } Ref<FileAccess> fa = create_for_path(p_file); - ERR_FAIL_COND_V_MSG(fa.is_null(), false, "Cannot create FileAccess for path '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("Cannot create FileAccess for path '%s'.", p_file)); return fa->_get_hidden_attribute(p_file); } @@ -586,7 +599,7 @@ Error FileAccess::set_hidden_attribute(const String &p_file, bool p_hidden) { } Ref<FileAccess> fa = create_for_path(p_file); - ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file)); Error err = fa->_set_hidden_attribute(p_file, p_hidden); return err; @@ -598,7 +611,7 @@ bool FileAccess::get_read_only_attribute(const String &p_file) { } Ref<FileAccess> fa = create_for_path(p_file); - ERR_FAIL_COND_V_MSG(fa.is_null(), false, "Cannot create FileAccess for path '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("Cannot create FileAccess for path '%s'.", p_file)); return fa->_get_read_only_attribute(p_file); } @@ -609,7 +622,7 @@ Error FileAccess::set_read_only_attribute(const String &p_file, bool p_ro) { } Ref<FileAccess> fa = create_for_path(p_file); - ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file)); Error err = fa->_set_read_only_attribute(p_file, p_ro); return err; @@ -697,7 +710,7 @@ Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_err if (r_error) { // if error requested, do not throw error return Vector<uint8_t>(); } - ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path '" + String(p_path) + "'."); + ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path))); } Vector<uint8_t> data; data.resize(f->get_length()); @@ -715,7 +728,7 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) { if (r_error) { return String(); } - ERR_FAIL_V_MSG(String(), "Can't get file as string from path '" + String(p_path) + "'."); + ERR_FAIL_V_MSG(String(), vformat("Can't get file as string from path '%s'.", String(p_path))); } String ret; @@ -806,7 +819,7 @@ String FileAccess::get_sha256(const String &p_file) { void FileAccess::_bind_methods() { ClassDB::bind_static_method("FileAccess", D_METHOD("open", "path", "flags"), &FileAccess::_open); - ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::open_encrypted); + ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key", "iv"), &FileAccess::open_encrypted, DEFVAL(Vector<uint8_t>())); ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &FileAccess::open_encrypted_pass); ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0)); ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error); @@ -828,6 +841,7 @@ void FileAccess::_bind_methods() { ClassDB::bind_method(D_METHOD("get_16"), &FileAccess::get_16); ClassDB::bind_method(D_METHOD("get_32"), &FileAccess::get_32); ClassDB::bind_method(D_METHOD("get_64"), &FileAccess::get_64); + ClassDB::bind_method(D_METHOD("get_half"), &FileAccess::get_half); ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float); ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double); ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real); @@ -846,6 +860,7 @@ void FileAccess::_bind_methods() { ClassDB::bind_method(D_METHOD("store_16", "value"), &FileAccess::store_16); ClassDB::bind_method(D_METHOD("store_32", "value"), &FileAccess::store_32); ClassDB::bind_method(D_METHOD("store_64", "value"), &FileAccess::store_64); + ClassDB::bind_method(D_METHOD("store_half", "value"), &FileAccess::store_half); ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float); ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double); ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real); diff --git a/core/io/file_access.h b/core/io/file_access.h index 2f4d1a8604..48984c6c1b 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -109,6 +109,12 @@ protected: static FileCloseFailNotify close_fail_notify; +#ifndef DISABLE_DEPRECATED + static Ref<FileAccess> _open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key); + + static void _bind_compatibility_methods(); +#endif + private: static bool backup_save; thread_local static Error last_file_open_error; @@ -142,6 +148,7 @@ public: virtual uint32_t get_32() const; ///< get 32 bits uint virtual uint64_t get_64() const; ///< get 64 bits uint + virtual float get_half() const; virtual float get_float() const; virtual double get_double() const; virtual real_t get_real() const; @@ -173,6 +180,7 @@ public: virtual void store_32(uint32_t p_dest); ///< store 32 bits uint virtual void store_64(uint64_t p_dest); ///< store 64 bits uint + virtual void store_half(float p_dest); virtual void store_float(float p_dest); virtual void store_double(double p_dest); virtual void store_real(real_t p_real); @@ -199,7 +207,7 @@ public: static Ref<FileAccess> create_for_path(const String &p_path); static Ref<FileAccess> open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files. - static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key); + static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv = Vector<uint8_t>()); static Ref<FileAccess> open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass); static Ref<FileAccess> open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ); static Error get_open_error(); @@ -215,8 +223,8 @@ public: static bool get_read_only_attribute(const String &p_file); static Error set_read_only_attribute(const String &p_file, bool p_ro); - static void set_backup_save(bool p_enable) { backup_save = p_enable; }; - static bool is_backup_save_enabled() { return backup_save; }; + static void set_backup_save(bool p_enable) { backup_save = p_enable; } + static bool is_backup_save_enabled() { return backup_save; } static String get_md5(const String &p_file); static String get_sha256(const String &p_file); diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 3602baf8c5..f7f2852e0a 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -58,7 +58,7 @@ Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) { block_size = f->get_32(); if (block_size == 0) { f.unref(); - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, vformat("Can't open compressed file '%s' with block size 0, it is corrupted.", p_base->get_path())); } read_total = f->get_32(); uint32_t bc = (read_total / block_size) + 1; diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 13d1e0c8fc..ba26f2e07b 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -36,8 +36,8 @@ #include <stdio.h> -Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) { - ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open."); +Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic, const Vector<uint8_t> &p_iv) { + ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, vformat("Can't open file while another file from path '%s' is open.", file->get_path_absolute())); ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER); pos = 0; @@ -49,6 +49,16 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u writing = true; file = p_base; key = p_key; + if (p_iv.is_empty()) { + iv.resize(16); + CryptoCore::RandomGenerator rng; + ERR_FAIL_COND_V_MSG(rng.init(), FAILED, "Failed to initialize random number generator."); + Error err = rng.get_random_bytes(iv.ptrw(), 16); + ERR_FAIL_COND_V(err != OK, err); + } else { + ERR_FAIL_COND_V(p_iv.size() != 16, ERR_INVALID_PARAMETER); + iv = p_iv; + } } else if (p_mode == MODE_READ) { writing = false; @@ -63,10 +73,8 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u p_base->get_buffer(md5d, 16); length = p_base->get_64(); - unsigned char iv[16]; - for (int i = 0; i < 16; i++) { - iv[i] = p_base->get_8(); - } + iv.resize(16); + p_base->get_buffer(iv.ptrw(), 16); base = p_base->get_position(); ERR_FAIL_COND_V(p_base->get_length() < base + length, ERR_FILE_CORRUPT); @@ -83,7 +91,7 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u CryptoCore::AESContext ctx; ctx.set_encode_key(key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption! - ctx.decrypt_cfb(ds, iv, data.ptrw(), data.ptrw()); + ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw()); } data.resize(length); @@ -145,14 +153,9 @@ void FileAccessEncrypted::_close() { file->store_buffer(hash, 16); file->store_64(data.size()); + file->store_buffer(iv.ptr(), 16); - unsigned char iv[16]; - for (int i = 0; i < 16; i++) { - iv[i] = Math::rand() % 256; - file->store_8(iv[i]); - } - - ctx.encrypt_cfb(len, iv, compressed.ptrw(), compressed.ptrw()); + ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptrw(), compressed.ptrw()); file->store_buffer(compressed.ptr(), compressed.size()); data.clear(); diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index 5f8c803d60..63a8cab145 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -44,6 +44,7 @@ public: }; private: + Vector<uint8_t> iv; Vector<uint8_t> key; bool writing = false; Ref<FileAccess> file; @@ -57,9 +58,11 @@ private: void _close(); public: - Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true); + Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true, const Vector<uint8_t> &p_iv = Vector<uint8_t>()); Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode); + Vector<uint8_t> get_iv() const { return iv; } + virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file virtual bool is_open() const override; ///< true when file is open diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index 1541a5ed4a..8d74011632 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -85,7 +85,7 @@ Error FileAccessMemory::open_internal(const String &p_path, int p_mode_flags) { //name = DirAccess::normalize_path(name); HashMap<String, Vector<uint8_t>>::Iterator E = files->find(name); - ERR_FAIL_COND_V_MSG(!E, ERR_FILE_NOT_FOUND, "Can't find file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(!E, ERR_FILE_NOT_FOUND, vformat("Can't find file '%s'.", p_path)); data = E->value.ptrw(); length = E->value.size(); diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 1340382eaa..8b6b445cea 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -48,7 +48,7 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t } void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) { - String simplified_path = p_path.simplify_path(); + String simplified_path = p_path.simplify_path().trim_prefix("res://"); PathMD5 pmd5(simplified_path.md5_buffer()); bool exists = files.has(pmd5); @@ -68,13 +68,11 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64 } if (!exists) { - //search for dir - String p = simplified_path.replace_first("res://", ""); + // Search for directory. PackedDir *cd = root; - if (p.contains("/")) { //in a subdir - - Vector<String> ds = p.get_base_dir().split("/"); + if (simplified_path.contains("/")) { // In a subdirectory. + Vector<String> ds = simplified_path.get_base_dir().split("/"); for (int j = 0; j < ds.size(); j++) { if (!cd->subdirs.has(ds[j])) { @@ -89,13 +87,40 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64 } } String filename = simplified_path.get_file(); - // Don't add as a file if the path points to a directory + // Don't add as a file if the path points to a directory. if (!filename.is_empty()) { cd->files.insert(filename); } } } +void PackedData::remove_path(const String &p_path) { + String simplified_path = p_path.simplify_path().trim_prefix("res://"); + PathMD5 pmd5(simplified_path.md5_buffer()); + if (!files.has(pmd5)) { + return; + } + + // Search for directory. + PackedDir *cd = root; + + if (simplified_path.contains("/")) { // In a subdirectory. + Vector<String> ds = simplified_path.get_base_dir().split("/"); + + for (int j = 0; j < ds.size(); j++) { + if (!cd->subdirs.has(ds[j])) { + return; // Subdirectory does not exist, do not bother creating. + } else { + cd = cd->subdirs[ds[j]]; + } + } + } + + cd->files.erase(simplified_path.get_file()); + + files.erase(pmd5); +} + void PackedData::add_pack_source(PackSource *p_source) { if (p_source != nullptr) { sources.push_back(p_source); @@ -103,15 +128,32 @@ void PackedData::add_pack_source(PackSource *p_source) { } uint8_t *PackedData::get_file_hash(const String &p_path) { - PathMD5 pmd5(p_path.md5_buffer()); + String simplified_path = p_path.simplify_path().trim_prefix("res://"); + PathMD5 pmd5(simplified_path.md5_buffer()); HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5); - if (!E || E->value.offset == 0) { + if (!E) { return nullptr; } return E->value.md5; } +HashSet<String> PackedData::get_file_paths() const { + HashSet<String> file_paths; + _get_file_paths(root, root->name, file_paths); + return file_paths; +} + +void PackedData::_get_file_paths(PackedDir *p_dir, const String &p_parent_dir, HashSet<String> &r_paths) const { + for (const String &E : p_dir->files) { + r_paths.insert(p_parent_dir.path_join(E)); + } + + for (const KeyValue<String, PackedDir *> &E : p_dir->subdirs) { + _get_file_paths(E.value, p_parent_dir.path_join(E.key), r_paths); + } +} + void PackedData::clear() { files.clear(); _free_packed_dirs(root); @@ -223,8 +265,8 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint32_t ver_minor = f->get_32(); f->get_32(); // patch number, not used for validation. - ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, "Pack version unsupported: " + itos(version) + "."); - ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + "."); + ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, vformat("Pack version unsupported: %d.", version)); + ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.", ver_major, ver_minor)); uint32_t pack_flags = f->get_32(); uint64_t file_base = f->get_64(); @@ -269,13 +311,17 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, String path; path.parse_utf8(cs.ptr()); - uint64_t ofs = file_base + f->get_64(); + uint64_t ofs = f->get_64(); uint64_t size = f->get_64(); uint8_t md5[16]; f->get_buffer(md5, 16); uint32_t flags = f->get_32(); - PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED)); + if (flags & PACK_FILE_REMOVAL) { // The file was removed. + PackedData::get_singleton()->remove_path(path); + } else { + PackedData::get_singleton()->add_path(p_path, path, file_base + ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED)); + } } return true; @@ -386,7 +432,7 @@ void FileAccessPack::close() { FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) : pf(p_file), f(FileAccess::open(pf.pack, FileAccess::READ)) { - ERR_FAIL_COND_MSG(f.is_null(), "Can't open pack-referenced file '" + String(pf.pack) + "'."); + ERR_FAIL_COND_MSG(f.is_null(), vformat("Can't open pack-referenced file '%s'.", String(pf.pack))); f->seek(pf.offset); off = pf.offset; @@ -394,7 +440,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil if (pf.encrypted) { Ref<FileAccessEncrypted> fae; fae.instantiate(); - ERR_FAIL_COND_MSG(fae.is_null(), "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'."); + ERR_FAIL_COND_MSG(fae.is_null(), vformat("Can't open encrypted pack-referenced file '%s'.", String(pf.pack))); Vector<uint8_t> key; key.resize(32); @@ -403,7 +449,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil } Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false); - ERR_FAIL_COND_MSG(err, "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'."); + ERR_FAIL_COND_MSG(err, vformat("Can't open encrypted pack-referenced file '%s'.", String(pf.pack))); f = fae; off = 0; } @@ -544,8 +590,6 @@ String DirAccessPack::get_current_dir(bool p_include_drive) const { } bool DirAccessPack::file_exists(String p_file) { - p_file = fix_path(p_file); - PackedData::PackedDir *pd = _find_dir(p_file.get_base_dir()); if (!pd) { return false; @@ -554,8 +598,6 @@ bool DirAccessPack::file_exists(String p_file) { } bool DirAccessPack::dir_exists(String p_dir) { - p_dir = fix_path(p_dir); - return _find_dir(p_dir) != nullptr; } diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 57b7a5f87f..b957a43de2 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -49,7 +49,8 @@ enum PackFlags { }; enum PackFileFlags { - PACK_FILE_ENCRYPTED = 1 << 0 + PACK_FILE_ENCRYPTED = 1 << 0, + PACK_FILE_REMOVAL = 1 << 1, }; class PackSource; @@ -107,11 +108,14 @@ private: bool disabled = false; void _free_packed_dirs(PackedDir *p_dir); + void _get_file_paths(PackedDir *p_dir, const String &p_parent_dir, HashSet<String> &r_paths) const; public: void add_pack_source(PackSource *p_source); void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource + void remove_path(const String &p_path); uint8_t *get_file_hash(const String &p_path); + HashSet<String> get_file_paths() const; void set_disabled(bool p_disabled) { disabled = p_disabled; } _FORCE_INLINE_ bool is_disabled() const { return disabled; } @@ -190,21 +194,18 @@ public: }; Ref<FileAccess> PackedData::try_open_path(const String &p_path) { - String simplified_path = p_path.simplify_path(); + String simplified_path = p_path.simplify_path().trim_prefix("res://"); PathMD5 pmd5(simplified_path.md5_buffer()); HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5); if (!E) { - return nullptr; //not found - } - if (E->value.offset == 0) { - return nullptr; //was erased + return nullptr; // Not found. } return E->value.src->get_file(p_path, &E->value); } bool PackedData::has_path(const String &p_path) { - return files.has(PathMD5(p_path.simplify_path().md5_buffer())); + return files.has(PathMD5(p_path.simplify_path().trim_prefix("res://").md5_buffer())); } bool PackedData::has_directory(const String &p_path) { diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index b33b7b35c3..41907d1a3f 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -116,7 +116,7 @@ void ZipArchive::close_handle(unzFile p_file) const { } unzFile ZipArchive::get_file_handle(const String &p_file) const { - ERR_FAIL_COND_V_MSG(!file_exists(p_file), nullptr, "File '" + p_file + " doesn't exist."); + ERR_FAIL_COND_V_MSG(!file_exists(p_file), nullptr, vformat("File '%s' doesn't exist.", p_file)); File file = files[p_file]; zlib_filefunc_def io; @@ -136,7 +136,7 @@ unzFile ZipArchive::get_file_handle(const String &p_file) const { io.free_mem = godot_free; unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io); - ERR_FAIL_NULL_V_MSG(pkg, nullptr, "Cannot open file '" + packages[file.package].filename + "'."); + ERR_FAIL_NULL_V_MSG(pkg, nullptr, vformat("Cannot open file '%s'.", packages[file.package].filename)); int unz_err = unzGoToFilePos(pkg, &file.file_pos); if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) { unzClose(pkg); diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index fc91341bed..b7a324e710 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -100,9 +100,9 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) { Error HTTPClient::verify_headers(const Vector<String> &p_headers) { for (int i = 0; i < p_headers.size(); i++) { String sanitized = p_headers[i].strip_edges(); - ERR_FAIL_COND_V_MSG(sanitized.is_empty(), ERR_INVALID_PARAMETER, "Invalid HTTP header at index " + itos(i) + ": empty."); - ERR_FAIL_COND_V_MSG(sanitized.find(":") < 1, ERR_INVALID_PARAMETER, - "Invalid HTTP header at index " + itos(i) + ": String must contain header-value pair, delimited by ':', but was: " + p_headers[i]); + ERR_FAIL_COND_V_MSG(sanitized.is_empty(), ERR_INVALID_PARAMETER, vformat("Invalid HTTP header at index %d: empty.", i)); + ERR_FAIL_COND_V_MSG(sanitized.find_char(':') < 1, ERR_INVALID_PARAMETER, + vformat("Invalid HTTP header at index %d: String must contain header-value pair, delimited by ':', but was: '%s'.", i, p_headers[i])); } return OK; @@ -113,7 +113,7 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() { get_response_headers(&rh); Dictionary ret; for (const String &s : rh) { - int sp = s.find(":"); + int sp = s.find_char(':'); if (sp == -1) { continue; } diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp index 70fcad543a..1382aecb38 100644 --- a/core/io/http_client_tcp.cpp +++ b/core/io/http_client_tcp.cpp @@ -508,11 +508,11 @@ Error HTTPClientTCP::poll() { continue; } if (s.begins_with("content-length:")) { - body_size = s.substr(s.find(":") + 1, s.length()).strip_edges().to_int(); + body_size = s.substr(s.find_char(':') + 1, s.length()).strip_edges().to_int(); body_left = body_size; } else if (s.begins_with("transfer-encoding:")) { - String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges(); + String encoding = header.substr(header.find_char(':') + 1, header.length()).strip_edges(); if (encoding == "chunked") { chunked = true; } @@ -662,15 +662,16 @@ PackedByteArray HTTPClientTCP::read_response_body_chunk() { chunk_left -= rec; if (chunk_left == 0) { - if (chunk[chunk.size() - 2] != '\r' || chunk[chunk.size() - 1] != '\n') { + const int chunk_size = chunk.size(); + if (chunk[chunk_size - 2] != '\r' || chunk[chunk_size - 1] != '\n') { ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)"); status = STATUS_CONNECTION_ERROR; break; } - ret.resize(chunk.size() - 2); + ret.resize(chunk_size - 2); uint8_t *w = ret.ptrw(); - memcpy(w, chunk.ptr(), chunk.size() - 2); + memcpy(w, chunk.ptr(), chunk_size - 2); chunk.clear(); } diff --git a/core/io/image.cpp b/core/io/image.cpp index d782af931f..128bbf3e6f 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -44,24 +44,24 @@ #include <cmath> const char *Image::format_names[Image::FORMAT_MAX] = { - "Lum8", //luminance - "LumAlpha8", //luminance-alpha + "Lum8", + "LumAlpha8", "Red8", "RedGreen", "RGB8", "RGBA8", "RGBA4444", - "RGBA5551", - "RFloat", //float + "RGBA5551", // Actually RGB565, kept as RGBA5551 for compatibility. + "RFloat", "RGFloat", "RGBFloat", "RGBAFloat", - "RHalf", //half float + "RHalf", "RGHalf", "RGBHalf", "RGBAHalf", "RGBE9995", - "DXT1 RGB8", //s3tc + "DXT1 RGB8", "DXT3 RGBA8", "DXT5 RGBA8", "RGTC Red8", @@ -69,9 +69,9 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "BPTC_RGBA", "BPTC_RGBF", "BPTC_RGBFU", - "ETC", //etc1 - "ETC2_R11", //etc2 - "ETC2_R11S", //signed", NOT srgb. + "ETC", + "ETC2_R11", + "ETC2_R11S", "ETC2_RG11", "ETC2_RG11S", "ETC2_RGB8", @@ -85,17 +85,60 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "ASTC_8x8_HDR", }; +// External saver function pointers. + SavePNGFunc Image::save_png_func = nullptr; SaveJPGFunc Image::save_jpg_func = nullptr; SaveEXRFunc Image::save_exr_func = nullptr; +SaveWebPFunc Image::save_webp_func = nullptr; SavePNGBufferFunc Image::save_png_buffer_func = nullptr; -SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr; SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr; - -SaveWebPFunc Image::save_webp_func = nullptr; +SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr; SaveWebPBufferFunc Image::save_webp_buffer_func = nullptr; +// External loader function pointers. + +ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_png_mem_unpacker_func = nullptr; +ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; +ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr; + +// External VRAM compression function pointers. + +void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_etc1_func)(Image *) = nullptr; +void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr; + +Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr; +Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr; + +// External VRAM decompression function pointers. + +void (*Image::_image_decompress_bc)(Image *) = nullptr; +void (*Image::_image_decompress_bptc)(Image *) = nullptr; +void (*Image::_image_decompress_etc1)(Image *) = nullptr; +void (*Image::_image_decompress_etc2)(Image *) = nullptr; +void (*Image::_image_decompress_astc)(Image *) = nullptr; + +// External packer function pointers. + +Vector<uint8_t> (*Image::webp_lossy_packer)(const Ref<Image> &, float) = nullptr; +Vector<uint8_t> (*Image::webp_lossless_packer)(const Ref<Image> &) = nullptr; +Vector<uint8_t> (*Image::png_packer)(const Ref<Image> &) = nullptr; +Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = nullptr; + +Ref<Image> (*Image::webp_unpacker)(const Vector<uint8_t> &) = nullptr; +Ref<Image> (*Image::png_unpacker)(const Vector<uint8_t> &) = nullptr; +Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr; +Ref<Image> (*Image::basis_universal_unpacker_ptr)(const uint8_t *, int) = nullptr; + void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel) { uint32_t ofs = (p_y * width + p_x) * p_pixel_size; memcpy(p_data + ofs, p_pixel, p_pixel_size); @@ -109,9 +152,9 @@ void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t * int Image::get_format_pixel_size(Format p_format) { switch (p_format) { case FORMAT_L8: - return 1; //luminance + return 1; case FORMAT_LA8: - return 2; //luminance-alpha + return 2; case FORMAT_R8: return 1; case FORMAT_RG8: @@ -125,7 +168,7 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RGB565: return 2; case FORMAT_RF: - return 4; //float + return 4; case FORMAT_RGF: return 8; case FORMAT_RGBF: @@ -133,7 +176,7 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RGBAF: return 16; case FORMAT_RH: - return 2; //half float + return 2; case FORMAT_RGH: return 4; case FORMAT_RGBH: @@ -143,27 +186,27 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RGBE9995: return 4; case FORMAT_DXT1: - return 1; //s3tc bc1 + return 1; case FORMAT_DXT3: - return 1; //bc2 + return 1; case FORMAT_DXT5: - return 1; //bc3 + return 1; case FORMAT_RGTC_R: - return 1; //bc4 + return 1; case FORMAT_RGTC_RG: - return 1; //bc5 + return 1; case FORMAT_BPTC_RGBA: - return 1; //btpc bc6h + return 1; case FORMAT_BPTC_RGBF: - return 1; //float / + return 1; case FORMAT_BPTC_RGBFU: - return 1; //unsigned float + return 1; case FORMAT_ETC: - return 1; //etc1 + return 1; case FORMAT_ETC2_R11: - return 1; //etc2 + return 1; case FORMAT_ETC2_R11S: - return 1; //signed: return 1; NOT srgb. + return 1; case FORMAT_ETC2_RG11: return 1; case FORMAT_ETC2_RG11S: @@ -194,12 +237,11 @@ int Image::get_format_pixel_size(Format p_format) { void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { switch (p_format) { - case FORMAT_DXT1: //s3tc bc1 - case FORMAT_DXT3: //bc2 - case FORMAT_DXT5: //bc3 - case FORMAT_RGTC_R: //bc4 - case FORMAT_RGTC_RG: { //bc5 case case FORMAT_DXT1: - + case FORMAT_DXT1: + case FORMAT_DXT3: + case FORMAT_DXT5: + case FORMAT_RGTC_R: + case FORMAT_RGTC_RG: { r_w = 4; r_h = 4; } break; @@ -213,8 +255,8 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { r_w = 4; r_h = 4; } break; - case FORMAT_ETC2_R11: //etc2 - case FORMAT_ETC2_R11S: //signed: NOT srgb. + case FORMAT_ETC2_R11: + case FORMAT_ETC2_R11S: case FORMAT_ETC2_RG11: case FORMAT_ETC2_RG11S: case FORMAT_ETC2_RGB8: @@ -224,19 +266,16 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { case FORMAT_DXT5_RA_AS_RG: { r_w = 4; r_h = 4; - } break; case FORMAT_ASTC_4x4: case FORMAT_ASTC_4x4_HDR: { r_w = 4; r_h = 4; - } break; case FORMAT_ASTC_8x8: case FORMAT_ASTC_8x8_HDR: { r_w = 8; r_h = 8; - } break; default: { r_w = 1; @@ -257,12 +296,11 @@ int Image::get_format_pixel_rshift(Format p_format) { int Image::get_format_block_size(Format p_format) { switch (p_format) { - case FORMAT_DXT1: //s3tc bc1 - case FORMAT_DXT3: //bc2 - case FORMAT_DXT5: //bc3 - case FORMAT_RGTC_R: //bc4 - case FORMAT_RGTC_RG: { //bc5 case case FORMAT_DXT1: - + case FORMAT_DXT1: + case FORMAT_DXT3: + case FORMAT_DXT5: + case FORMAT_RGTC_R: + case FORMAT_RGTC_RG: { return 4; } case FORMAT_ETC: { @@ -273,17 +311,15 @@ int Image::get_format_block_size(Format p_format) { case FORMAT_BPTC_RGBFU: { return 4; } - case FORMAT_ETC2_R11: //etc2 - case FORMAT_ETC2_R11S: //signed: NOT srgb. + case FORMAT_ETC2_R11: + case FORMAT_ETC2_R11S: case FORMAT_ETC2_RG11: case FORMAT_ETC2_RG11S: case FORMAT_ETC2_RGB8: case FORMAT_ETC2_RGBA8: case FORMAT_ETC2_RGB8A1: - case FORMAT_ETC2_RA_AS_RG: //used to make basis universal happy - case FORMAT_DXT5_RA_AS_RG: //used to make basis universal happy - - { + case FORMAT_ETC2_RA_AS_RG: + case FORMAT_DXT5_RA_AS_RG: { return 4; } case FORMAT_ASTC_4x4: @@ -459,7 +495,7 @@ int Image::get_mipmap_count() const { } } -//using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers +// Using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers. template <uint32_t read_bytes, bool read_alpha, uint32_t write_bytes, bool write_alpha, bool read_gray, bool write_gray> static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p_dst) { constexpr uint32_t max_bytes = MAX(read_bytes, write_bytes); @@ -535,7 +571,7 @@ static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_for } void Image::convert(Format p_new_format) { - ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, "The Image format specified (" + itos(p_new_format) + ") is out of range. See Image's Format enum."); + ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_new_format)); if (data.size() == 0) { return; } @@ -551,7 +587,7 @@ void Image::convert(Format p_new_format) { ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); } else if (!_are_formats_compatible(format, p_new_format)) { - //use put/set pixel which is slower but works with non byte formats + // Use put/set pixel which is slower but works with non-byte formats. Image new_img(width, height, mipmaps, p_new_format); for (int mip = 0; mip < mipmap_count; mip++) { @@ -1132,9 +1168,9 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0."); ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0."); - ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); - ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); - ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); + ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, vformat("Image width cannot be greater than %d pixels.", MAX_WIDTH)); + ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, vformat("Image height cannot be greater than %d pixels.", MAX_HEIGHT)); + ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, vformat("Too many pixels for image, maximum is %d pixels.", MAX_PIXELS)); if (p_width == width && p_height == height) { return; @@ -1435,8 +1471,8 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { ERR_FAIL_COND_MSG(p_y < 0, "Start y position cannot be smaller than 0."); ERR_FAIL_COND_MSG(p_width <= 0, "Width of image must be greater than 0."); ERR_FAIL_COND_MSG(p_height <= 0, "Height of image must be greater than 0."); - ERR_FAIL_COND_MSG(p_x + p_width > MAX_WIDTH, "End x position cannot be greater than " + itos(MAX_WIDTH) + "."); - ERR_FAIL_COND_MSG(p_y + p_height > MAX_HEIGHT, "End y position cannot be greater than " + itos(MAX_HEIGHT) + "."); + ERR_FAIL_COND_MSG(p_x + p_width > MAX_WIDTH, vformat("End x position cannot be greater than %d.", MAX_WIDTH)); + ERR_FAIL_COND_MSG(p_y + p_height > MAX_HEIGHT, vformat("End y position cannot be greater than %d.", MAX_HEIGHT)); /* to save memory, cropping should be done in-place, however, since this function will most likely either not be used much, or in critical areas, for now it won't, because @@ -1484,8 +1520,8 @@ void Image::crop(int p_width, int p_height) { void Image::rotate_90(ClockDirection p_direction) { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); - ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels."); - ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width)); + ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height)); bool used_mipmaps = has_mipmaps(); if (used_mipmaps) { @@ -1602,8 +1638,8 @@ void Image::rotate_90(ClockDirection p_direction) { void Image::rotate_180() { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); - ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels."); - ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width)); + ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height)); bool used_mipmaps = has_mipmaps(); if (used_mipmaps) { @@ -1694,7 +1730,7 @@ void Image::flip_x() { } } -/// Get mipmap size and offset. +// Get mipmap size and offset. int64_t Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps, int *r_mm_width, int *r_mm_height) { // Data offset in mipmaps (including the original texture). int64_t size = 0; @@ -2249,15 +2285,15 @@ void Image::set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_for } void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { - ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels."); - ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(p_width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", p_width)); + ERR_FAIL_COND_MSG(p_height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", p_height)); ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, - "The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + "pixels."); + vformat("The Image width specified (%d pixels) cannot be greater than %d pixels.", p_width, MAX_WIDTH)); ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, - "The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + "pixels."); + vformat("The Image height specified (%d pixels) cannot be greater than %d pixels.", p_height, MAX_HEIGHT)); ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, - "Too many pixels for Image. Maximum is " + itos(MAX_WIDTH) + "x" + itos(MAX_HEIGHT) + " = " + itos(MAX_PIXELS) + "pixels."); - ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum."); + vformat("Too many pixels for Image. Maximum is %dx%d = %d pixels.", MAX_WIDTH, MAX_HEIGHT, MAX_PIXELS)); + ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_format)); int mm = 0; int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); @@ -2275,15 +2311,15 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma } void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { - ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels."); - ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(p_width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", p_width)); + ERR_FAIL_COND_MSG(p_height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", p_height)); ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, - "The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + " pixels."); + vformat("The Image width specified (%d pixels) cannot be greater than %d pixels.", p_width, MAX_WIDTH)); ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, - "The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + " pixels."); + vformat("The Image height specified (%d pixels) cannot be greater than %d pixels.", p_height, MAX_HEIGHT)); ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, - "Too many pixels for Image. Maximum is " + itos(MAX_WIDTH) + "x" + itos(MAX_HEIGHT) + " = " + itos(MAX_PIXELS) + "pixels ."); - ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum."); + vformat("Too many pixels for Image. Maximum is %dx%d = %d pixels.", MAX_WIDTH, MAX_HEIGHT, MAX_PIXELS)); + ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_format)); int mm; int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); @@ -2575,23 +2611,25 @@ Image::AlphaMode Image::detect_alpha() const { } Error Image::load(const String &p_path) { + String path = ResourceUID::ensure_path(p_path); #ifdef DEBUG_ENABLED - if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) { - WARN_PRINT("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource."); + if (path.begins_with("res://") && ResourceLoader::exists(path)) { + WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", path)); } #endif - return ImageLoader::load_image(p_path, this); + return ImageLoader::load_image(path, this); } Ref<Image> Image::load_from_file(const String &p_path) { + String path = ResourceUID::ensure_path(p_path); #ifdef DEBUG_ENABLED - if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) { - WARN_PRINT("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource."); + if (path.begins_with("res://") && ResourceLoader::exists(path)) { + WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", path)); } #endif Ref<Image> image; image.instantiate(); - Error err = ImageLoader::load_image(p_path, image); + Error err = ImageLoader::load_image(path, image); if (err != OK) { ERR_FAIL_V_MSG(Ref<Image>(), vformat("Failed to load image. Error %d", err)); } @@ -2649,7 +2687,7 @@ Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_q if (save_webp_func == nullptr) { return ERR_UNAVAILABLE; } - ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), ERR_INVALID_PARAMETER, "The WebP lossy quality was set to " + rtos(p_quality) + ", which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive)."); + ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), ERR_INVALID_PARAMETER, vformat("The WebP lossy quality was set to %f, which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).", p_quality)); return save_webp_func(p_path, Ref<Image>((Image *)this), p_lossy, p_quality); } @@ -2658,7 +2696,7 @@ Vector<uint8_t> Image::save_webp_to_buffer(const bool p_lossy, const float p_qua if (save_webp_buffer_func == nullptr) { return Vector<uint8_t>(); } - ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), Vector<uint8_t>(), "The WebP lossy quality was set to " + rtos(p_quality) + ", which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive)."); + ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), Vector<uint8_t>(), vformat("The WebP lossy quality was set to %f, which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).", p_quality)); return save_webp_buffer_func(Ref<Image>((Image *)this), p_lossy, p_quality); } @@ -3134,37 +3172,6 @@ void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) { } } -ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_png_mem_unpacker_func = nullptr; -ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; -ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr; - -void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_etc1_func)(Image *) = nullptr; -void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr; -Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr; -Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_decompress_bc)(Image *) = nullptr; -void (*Image::_image_decompress_bptc)(Image *) = nullptr; -void (*Image::_image_decompress_etc1)(Image *) = nullptr; -void (*Image::_image_decompress_etc2)(Image *) = nullptr; -void (*Image::_image_decompress_astc)(Image *) = nullptr; - -Vector<uint8_t> (*Image::webp_lossy_packer)(const Ref<Image> &, float) = nullptr; -Vector<uint8_t> (*Image::webp_lossless_packer)(const Ref<Image> &) = nullptr; -Ref<Image> (*Image::webp_unpacker)(const Vector<uint8_t> &) = nullptr; -Vector<uint8_t> (*Image::png_packer)(const Ref<Image> &) = nullptr; -Ref<Image> (*Image::png_unpacker)(const Vector<uint8_t> &) = nullptr; -Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = nullptr; -Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr; -Ref<Image> (*Image::basis_universal_unpacker_ptr)(const uint8_t *, int) = nullptr; - void Image::_set_data(const Dictionary &p_data) { ERR_FAIL_COND(!p_data.has("width")); ERR_FAIL_COND(!p_data.has("height")); @@ -3204,6 +3211,14 @@ Color Image::get_pixelv(const Point2i &p_point) const { return get_pixel(p_point.x, p_point.y); } +void Image::_copy_internals_from(const Image &p_image) { + format = p_image.format; + width = p_image.width; + height = p_image.height; + mipmaps = p_image.mipmaps; + data = p_image.data; +} + Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { switch (format) { case FORMAT_L8: { @@ -3643,34 +3658,34 @@ void Image::_bind_methods() { BIND_CONSTANT(MAX_WIDTH); BIND_CONSTANT(MAX_HEIGHT); - BIND_ENUM_CONSTANT(FORMAT_L8); //luminance - BIND_ENUM_CONSTANT(FORMAT_LA8); //luminance-alpha + BIND_ENUM_CONSTANT(FORMAT_L8); + BIND_ENUM_CONSTANT(FORMAT_LA8); BIND_ENUM_CONSTANT(FORMAT_R8); BIND_ENUM_CONSTANT(FORMAT_RG8); BIND_ENUM_CONSTANT(FORMAT_RGB8); BIND_ENUM_CONSTANT(FORMAT_RGBA8); BIND_ENUM_CONSTANT(FORMAT_RGBA4444); BIND_ENUM_CONSTANT(FORMAT_RGB565); - BIND_ENUM_CONSTANT(FORMAT_RF); //float + BIND_ENUM_CONSTANT(FORMAT_RF); BIND_ENUM_CONSTANT(FORMAT_RGF); BIND_ENUM_CONSTANT(FORMAT_RGBF); BIND_ENUM_CONSTANT(FORMAT_RGBAF); - BIND_ENUM_CONSTANT(FORMAT_RH); //half float + BIND_ENUM_CONSTANT(FORMAT_RH); BIND_ENUM_CONSTANT(FORMAT_RGH); BIND_ENUM_CONSTANT(FORMAT_RGBH); BIND_ENUM_CONSTANT(FORMAT_RGBAH); BIND_ENUM_CONSTANT(FORMAT_RGBE9995); - BIND_ENUM_CONSTANT(FORMAT_DXT1); //s3tc bc1 - BIND_ENUM_CONSTANT(FORMAT_DXT3); //bc2 - BIND_ENUM_CONSTANT(FORMAT_DXT5); //bc3 + BIND_ENUM_CONSTANT(FORMAT_DXT1); + BIND_ENUM_CONSTANT(FORMAT_DXT3); + BIND_ENUM_CONSTANT(FORMAT_DXT5); BIND_ENUM_CONSTANT(FORMAT_RGTC_R); BIND_ENUM_CONSTANT(FORMAT_RGTC_RG); - BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBA); //btpc bc6h - BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBF); //float / - BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBFU); //unsigned float - BIND_ENUM_CONSTANT(FORMAT_ETC); //etc1 - BIND_ENUM_CONSTANT(FORMAT_ETC2_R11); //etc2 - BIND_ENUM_CONSTANT(FORMAT_ETC2_R11S); //signed ); NOT srgb. + BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBA); + BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBF); + BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBFU); + BIND_ENUM_CONSTANT(FORMAT_ETC); + BIND_ENUM_CONSTANT(FORMAT_ETC2_R11); + BIND_ENUM_CONSTANT(FORMAT_ETC2_R11S); BIND_ENUM_CONSTANT(FORMAT_ETC2_RG11); BIND_ENUM_CONSTANT(FORMAT_ETC2_RG11S); BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8); @@ -4177,7 +4192,7 @@ void Image::renormalize_half(uint16_t *p_rgb) { } void Image::renormalize_rgbe9995(uint32_t *p_rgb) { - // Never used + // Never used. } Image::Image(const uint8_t *p_mem_png_jpg, int p_len) { @@ -4210,6 +4225,15 @@ void Image::set_as_black() { memset(data.ptrw(), 0, data.size()); } +void Image::copy_internals_from(const Ref<Image> &p_image) { + ERR_FAIL_COND_MSG(p_image.is_null(), "Cannot copy image internals: invalid Image object."); + format = p_image->format; + width = p_image->width; + height = p_image->height; + mipmaps = p_image->mipmaps; + data = p_image->data; +} + Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool p_luma_metric) { // https://github.com/richgel999/bc7enc_rdo/blob/master/LICENSE // @@ -4250,8 +4274,6 @@ Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool } ERR_FAIL_COND_V(err != OK, result); - ERR_FAIL_COND_V(err != OK, result); - ERR_FAIL_COND_V_MSG((compared_image->get_format() >= Image::FORMAT_RH) && (compared_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported."); ERR_FAIL_COND_V_MSG((source_image->get_format() >= Image::FORMAT_RH) && (source_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported."); diff --git a/core/io/image.h b/core/io/image.h index 78757246e0..3149314ad8 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -43,12 +43,17 @@ class Image; +// Function pointer prototypes. + typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img); typedef Vector<uint8_t> (*SavePNGBufferFunc)(const Ref<Image> &p_img); + typedef Error (*SaveJPGFunc)(const String &p_path, const Ref<Image> &p_img, float p_quality); typedef Vector<uint8_t> (*SaveJPGBufferFunc)(const Ref<Image> &p_img, float p_quality); + typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size); typedef Ref<Image> (*ScalableImageMemLoadFunc)(const uint8_t *p_data, int p_size, float p_scale); + typedef Error (*SaveWebPFunc)(const String &p_path, const Ref<Image> &p_img, const bool p_lossy, const float p_quality); typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const bool p_lossy, const float p_quality); @@ -59,57 +64,48 @@ class Image : public Resource { GDCLASS(Image, Resource); public: - static SavePNGFunc save_png_func; - static SaveJPGFunc save_jpg_func; - static SaveEXRFunc save_exr_func; - static SavePNGBufferFunc save_png_buffer_func; - static SaveEXRBufferFunc save_exr_buffer_func; - static SaveJPGBufferFunc save_jpg_buffer_func; - static SaveWebPFunc save_webp_func; - static SaveWebPBufferFunc save_webp_buffer_func; - enum { - MAX_WIDTH = (1 << 24), // force a limit somehow - MAX_HEIGHT = (1 << 24), // force a limit somehow - MAX_PIXELS = 268435456 + MAX_WIDTH = (1 << 24), // Force a limit somehow. + MAX_HEIGHT = (1 << 24), // Force a limit somehow. + MAX_PIXELS = 268435456 // 16384 ^ 2 }; enum Format { - FORMAT_L8, //luminance - FORMAT_LA8, //luminance-alpha + FORMAT_L8, // Luminance + FORMAT_LA8, // Luminance-Alpha FORMAT_R8, FORMAT_RG8, FORMAT_RGB8, FORMAT_RGBA8, FORMAT_RGBA4444, FORMAT_RGB565, - FORMAT_RF, //float + FORMAT_RF, // Float FORMAT_RGF, FORMAT_RGBF, FORMAT_RGBAF, - FORMAT_RH, //half float + FORMAT_RH, // Half FORMAT_RGH, FORMAT_RGBH, FORMAT_RGBAH, FORMAT_RGBE9995, - FORMAT_DXT1, //s3tc bc1 - FORMAT_DXT3, //bc2 - FORMAT_DXT5, //bc3 - FORMAT_RGTC_R, - FORMAT_RGTC_RG, - FORMAT_BPTC_RGBA, //btpc bc7 - FORMAT_BPTC_RGBF, //float bc6h - FORMAT_BPTC_RGBFU, //unsigned float bc6hu - FORMAT_ETC, //etc1 - FORMAT_ETC2_R11, //etc2 - FORMAT_ETC2_R11S, //signed, NOT srgb. + FORMAT_DXT1, // BC1 + FORMAT_DXT3, // BC2 + FORMAT_DXT5, // BC3 + FORMAT_RGTC_R, // BC4 + FORMAT_RGTC_RG, // BC5 + FORMAT_BPTC_RGBA, // BC7 + FORMAT_BPTC_RGBF, // BC6 Signed + FORMAT_BPTC_RGBFU, // BC6 Unsigned + FORMAT_ETC, // ETC1 + FORMAT_ETC2_R11, + FORMAT_ETC2_R11S, // Signed, NOT srgb. FORMAT_ETC2_RG11, - FORMAT_ETC2_RG11S, + FORMAT_ETC2_RG11S, // Signed, NOT srgb. FORMAT_ETC2_RGB8, FORMAT_ETC2_RGBA8, FORMAT_ETC2_RGB8A1, - FORMAT_ETC2_RA_AS_RG, //used to make basis universal happy - FORMAT_DXT5_RA_AS_RG, //used to make basis universal happy + FORMAT_ETC2_RA_AS_RG, // ETC2 RGBA with a RA-RG swizzle for normal maps. + FORMAT_DXT5_RA_AS_RG, // BC3 with a RA-RG swizzle for normal maps. FORMAT_ASTC_4x4, FORMAT_ASTC_4x4_HDR, FORMAT_ASTC_8x8, @@ -118,17 +114,18 @@ public: }; static const char *format_names[FORMAT_MAX]; + enum Interpolation { INTERPOLATE_NEAREST, INTERPOLATE_BILINEAR, INTERPOLATE_CUBIC, INTERPOLATE_TRILINEAR, INTERPOLATE_LANCZOS, - /* INTERPOLATE_TRICUBIC, */ - /* INTERPOLATE GAUSS */ + // INTERPOLATE_TRICUBIC, + // INTERPOLATE_GAUSS }; - //this is used for compression + // Used for obtaining optimal compression quality. enum UsedChannels { USED_CHANNELS_L, USED_CHANNELS_LA, @@ -137,13 +134,66 @@ public: USED_CHANNELS_RGB, USED_CHANNELS_RGBA, }; - //some functions provided by something else + // ASTC supports block formats other than 4x4. enum ASTCFormat { ASTC_FORMAT_4x4, ASTC_FORMAT_8x8, }; + enum RoughnessChannel { + ROUGHNESS_CHANNEL_R, + ROUGHNESS_CHANNEL_G, + ROUGHNESS_CHANNEL_B, + ROUGHNESS_CHANNEL_A, + ROUGHNESS_CHANNEL_L, + }; + + enum Image3DValidateError { + VALIDATE_3D_OK, + VALIDATE_3D_ERR_IMAGE_EMPTY, + VALIDATE_3D_ERR_MISSING_IMAGES, + VALIDATE_3D_ERR_EXTRA_IMAGES, + VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH, + VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH, + VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS, + }; + + enum CompressMode { + COMPRESS_S3TC, + COMPRESS_ETC, + COMPRESS_ETC2, + COMPRESS_BPTC, + COMPRESS_ASTC, + COMPRESS_MAX, + }; + + enum CompressSource { + COMPRESS_SOURCE_GENERIC, + COMPRESS_SOURCE_SRGB, + COMPRESS_SOURCE_NORMAL, + COMPRESS_SOURCE_MAX, + }; + + enum AlphaMode { + ALPHA_NONE, + ALPHA_BIT, + ALPHA_BLEND + }; + + // External saver function pointers. + + static SavePNGFunc save_png_func; + static SaveJPGFunc save_jpg_func; + static SaveEXRFunc save_exr_func; + static SaveWebPFunc save_webp_func; + static SavePNGBufferFunc save_png_buffer_func; + static SaveEXRBufferFunc save_exr_buffer_func; + static SaveJPGBufferFunc save_jpg_buffer_func; + static SaveWebPBufferFunc save_webp_buffer_func; + + // External loader function pointers. + static ImageMemLoadFunc _png_mem_loader_func; static ImageMemLoadFunc _png_mem_unpacker_func; static ImageMemLoadFunc _jpg_mem_loader_func; @@ -153,6 +203,8 @@ public: static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func; static ImageMemLoadFunc _ktx_mem_loader_func; + // External VRAM compression function pointers. + static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels); static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels); static void (*_image_compress_etc1_func)(Image *); @@ -162,24 +214,26 @@ public: static Error (*_image_compress_bptc_rd_func)(Image *, UsedChannels p_channels); static Error (*_image_compress_bc_rd_func)(Image *, UsedChannels p_channels); + // External VRAM decompression function pointers. + static void (*_image_decompress_bc)(Image *); static void (*_image_decompress_bptc)(Image *); static void (*_image_decompress_etc1)(Image *); static void (*_image_decompress_etc2)(Image *); static void (*_image_decompress_astc)(Image *); + // External packer function pointers. + static Vector<uint8_t> (*webp_lossy_packer)(const Ref<Image> &p_image, float p_quality); static Vector<uint8_t> (*webp_lossless_packer)(const Ref<Image> &p_image); - static Ref<Image> (*webp_unpacker)(const Vector<uint8_t> &p_buffer); static Vector<uint8_t> (*png_packer)(const Ref<Image> &p_image); - static Ref<Image> (*png_unpacker)(const Vector<uint8_t> &p_buffer); static Vector<uint8_t> (*basis_universal_packer)(const Ref<Image> &p_image, UsedChannels p_channels); + + static Ref<Image> (*webp_unpacker)(const Vector<uint8_t> &p_buffer); + static Ref<Image> (*png_unpacker)(const Vector<uint8_t> &p_buffer); static Ref<Image> (*basis_universal_unpacker)(const Vector<uint8_t> &p_buffer); static Ref<Image> (*basis_universal_unpacker_ptr)(const uint8_t *p_data, int p_size); - _FORCE_INLINE_ Color _get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const; - _FORCE_INLINE_ void _set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color); - protected: static void _bind_methods(); @@ -190,15 +244,12 @@ private: int height = 0; bool mipmaps = false; - void _copy_internals_from(const Image &p_image) { - format = p_image.format; - width = p_image.width; - height = p_image.height; - mipmaps = p_image.mipmaps; - data = p_image.data; - } + void _copy_internals_from(const Image &p_image); + + _FORCE_INLINE_ Color _get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const; + _FORCE_INLINE_ void _set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color); - _FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data + _FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const; // Get where the mipmap begins in data. static int64_t _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = nullptr, int *r_mm_height = nullptr); bool _can_modify(Format p_format) const; @@ -225,52 +276,32 @@ private: static void renormalize_rgbe9995(uint32_t *p_rgb); public: - int get_width() const; ///< Get image width - int get_height() const; ///< Get image height + int get_width() const; + int get_height() const; Size2i get_size() const; bool has_mipmaps() const; int get_mipmap_count() const; - /** - * Convert the image to another format, conversion only to raw byte format - */ + // Convert the image to another format, conversion only to raw byte format. void convert(Format p_new_format); - /** - * Get the current image format. - */ Format get_format() const; - /** - * Get where the mipmap begins in data. - */ + // Get where the mipmap begins in data. int64_t get_mipmap_offset(int p_mipmap) const; void get_mipmap_offset_and_size(int p_mipmap, int64_t &r_ofs, int64_t &r_size) const; void get_mipmap_offset_size_and_dimensions(int p_mipmap, int64_t &r_ofs, int64_t &r_size, int &w, int &h) const; - enum Image3DValidateError { - VALIDATE_3D_OK, - VALIDATE_3D_ERR_IMAGE_EMPTY, - VALIDATE_3D_ERR_MISSING_IMAGES, - VALIDATE_3D_ERR_EXTRA_IMAGES, - VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH, - VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH, - VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS, - }; - static Image3DValidateError validate_3d_image(Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_images); static String get_3d_image_validation_error_text(Image3DValidateError p_error); - /** - * Resize the image, using the preferred interpolation method. - */ + // Resize the image, using the preferred interpolation method. void resize_to_po2(bool p_square = false, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void shrink_x2(); bool is_size_po2() const; - /** - * Crop the image to a specific size, if larger, then the image is filled by black - */ + + // Crop the image to a specific size, if larger, then the image is filled by black. void crop_from_point(int p_x, int p_y, int p_width, int p_height); void crop(int p_width, int p_height); @@ -280,34 +311,20 @@ public: void flip_x(); void flip_y(); - /** - * Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1) - */ + // Generate a mipmap chain of an image (creates an image 1/4 the size, with averaging of 4->1). Error generate_mipmaps(bool p_renormalize = false); - enum RoughnessChannel { - ROUGHNESS_CHANNEL_R, - ROUGHNESS_CHANNEL_G, - ROUGHNESS_CHANNEL_B, - ROUGHNESS_CHANNEL_A, - ROUGHNESS_CHANNEL_L, - }; - Error generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map); void clear_mipmaps(); - void normalize(); //for normal maps + void normalize(); - /** - * Creates new internal image data of a given size and format. Current image will be lost. - */ + // Creates new internal image data of a given size and format. Current image will be lost. void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format); void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); void initialize_data(const char **p_xpm); - /** - * returns true when the image is empty (0,0) in size - */ + // Returns true when the image is empty (0,0) in size. bool is_empty() const; Vector<uint8_t> get_data() const; @@ -327,27 +344,14 @@ public: static Ref<Image> create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); void set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); - /** - * create an empty image - */ - Image() {} - /** - * create an empty image of a specific size and format - */ - Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format); - /** - * import an image of a specific size and format from a pointer - */ - Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data); + Image() = default; // Create an empty image. + Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format); // Create an empty image of a specific size and format. + Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data); // Import an image of a specific size and format from a byte vector. + Image(const uint8_t *p_mem_png_jpg, int p_len = -1); // Import either a png or jpg from a pointer. + Image(const char **p_xpm); // Import an XPM image. ~Image() {} - enum AlphaMode { - ALPHA_NONE, - ALPHA_BIT, - ALPHA_BLEND - }; - AlphaMode detect_alpha() const; bool is_invisible() const; @@ -362,21 +366,6 @@ public: static int64_t get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap); static int64_t get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h); - enum CompressMode { - COMPRESS_S3TC, - COMPRESS_ETC, - COMPRESS_ETC2, - COMPRESS_BPTC, - COMPRESS_ASTC, - COMPRESS_MAX, - }; - enum CompressSource { - COMPRESS_SOURCE_GENERIC, - COMPRESS_SOURCE_SRGB, - COMPRESS_SOURCE_NORMAL, - COMPRESS_SOURCE_MAX, - }; - Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); Error decompress(); @@ -422,9 +411,6 @@ public: void convert_ra_rgba8_to_rg(); void convert_rgba8_to_bgra8(); - Image(const uint8_t *p_mem_png_jpg, int p_len = -1); - Image(const char **p_xpm); - virtual Ref<Resource> duplicate(bool p_subresources = false) const override; UsedChannels detect_used_channels(CompressSource p_source = COMPRESS_SOURCE_GENERIC) const; @@ -443,14 +429,7 @@ public: void set_as_black(); - void copy_internals_from(const Ref<Image> &p_image) { - ERR_FAIL_COND_MSG(p_image.is_null(), "Cannot copy image internals: invalid Image object."); - format = p_image->format; - width = p_image->width; - height = p_image->height; - mipmaps = p_image->mipmaps; - data = p_image->data; - } + void copy_internals_from(const Ref<Image> &p_image); Dictionary compute_image_metrics(const Ref<Image> p_compared_image, bool p_luma_metric = true); }; diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 92c690dc2a..58e63a4cc9 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -82,15 +82,16 @@ void ImageFormatLoaderExtension::_bind_methods() { Error ImageLoader::load_image(const String &p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) { ERR_FAIL_COND_V_MSG(p_image.is_null(), ERR_INVALID_PARAMETER, "Can't load an image: invalid Image object."); + const String file = ResourceUID::ensure_path(p_file); Ref<FileAccess> f = p_custom; if (f.is_null()) { Error err; - f = FileAccess::open(p_file, FileAccess::READ, &err); - ERR_FAIL_COND_V_MSG(f.is_null(), err, "Error opening file '" + p_file + "'."); + f = FileAccess::open(file, FileAccess::READ, &err); + ERR_FAIL_COND_V_MSG(f.is_null(), err, vformat("Error opening file '%s'.", file)); } - String extension = p_file.get_extension(); + String extension = file.get_extension(); for (int i = 0; i < loader.size(); i++) { if (!loader[i]->recognize(extension)) { @@ -98,7 +99,7 @@ Error ImageLoader::load_image(const String &p_file, Ref<Image> p_image, Ref<File } Error err = loader.write[i]->load_image(p_image, f, p_flags, p_scale); if (err != OK) { - ERR_PRINT("Error loading image: " + p_file); + ERR_PRINT(vformat("Error loading image: '%s'.", file)); } if (err != ERR_FILE_UNRECOGNIZED) { diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 38c71b19fa..3c67a8f894 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -51,7 +51,7 @@ struct _IP_ResolverPrivate { response.clear(); type = IP::TYPE_NONE; hostname = ""; - }; + } QueueItem() { clear(); @@ -201,7 +201,7 @@ IPAddress IP::get_resolve_item_address(ResolverID p_id) const { MutexLock lock(resolver->mutex); if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) { - ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); + ERR_PRINT(vformat("Resolve of '%s' didn't complete yet.", resolver->queue[p_id].hostname)); return IPAddress(); } @@ -220,7 +220,7 @@ Array IP::get_resolve_item_addresses(ResolverID p_id) const { MutexLock lock(resolver->mutex); if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) { - ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); + ERR_PRINT(vformat("Resolve of '%s' didn't complete yet.", resolver->queue[p_id].hostname)); return Array(); } diff --git a/core/io/json.cpp b/core/io/json.cpp index 664ff7857b..e73677be9c 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -121,7 +121,7 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_ d.get_key_list(&keys); if (p_sort_keys) { - keys.sort(); + keys.sort_custom<StringLikeVariantOrder>(); } bool first_key = true; @@ -1402,7 +1402,7 @@ Error ResourceFormatSaverJSON::save(const Ref<Resource> &p_resource, const Strin Error err; Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err, err, "Cannot save json '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err, err, vformat("Cannot save json '%s'.", p_path)); file->store_string(source); if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 67469de5cc..d9664e7370 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -33,8 +33,6 @@ #include "core/io/resource_loader.h" #include "core/object/ref_counted.h" #include "core/object/script_language.h" -#include "core/os/keyboard.h" -#include "core/string/print_string.h" #include <limits.h> #include <stdio.h> @@ -69,10 +67,31 @@ ObjectID EncodedObjectAsID::get_object_id() const { // For `Variant::ARRAY`. // Occupies bits 16 and 17. #define HEADER_DATA_FIELD_TYPED_ARRAY_MASK (0b11 << 16) -#define HEADER_DATA_FIELD_TYPED_ARRAY_NONE (0b00 << 16) -#define HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN (0b01 << 16) -#define HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME (0b10 << 16) -#define HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT (0b11 << 16) +#define HEADER_DATA_FIELD_TYPED_ARRAY_SHIFT 16 + +// For `Variant::DICTIONARY`. +// Occupies bits 16 and 17. +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_MASK (0b11 << 16) +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_SHIFT 16 +// Occupies bits 18 and 19. +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_MASK (0b11 << 18) +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_SHIFT 18 + +enum ContainerTypeKind { + CONTAINER_TYPE_KIND_NONE = 0b00, + CONTAINER_TYPE_KIND_BUILTIN = 0b01, + CONTAINER_TYPE_KIND_CLASS_NAME = 0b10, + CONTAINER_TYPE_KIND_SCRIPT = 0b11, +}; + +struct ContainerType { + Variant::Type builtin_type = Variant::NIL; + StringName class_name; + Ref<Script> script; +}; + +#define GET_CONTAINER_TYPE_KIND(m_header, m_field) \ + ((ContainerTypeKind)(((m_header) & HEADER_DATA_FIELD_##m_field##_MASK) >> HEADER_DATA_FIELD_##m_field##_SHIFT)) static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); @@ -80,7 +99,7 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r int32_t strlen = decode_uint32(buf); int32_t pad = 0; - // Handle padding + // Handle padding. if (strlen % 4) { pad = 4 - strlen % 4; } @@ -88,7 +107,7 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r buf += 4; len -= 4; - // Ensure buffer is big enough + // Ensure buffer is big enough. ERR_FAIL_ADD_OF(strlen, pad, ERR_FILE_EOF); ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF); @@ -96,10 +115,10 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA); r_string = str; - // Add padding + // Add padding. strlen += pad; - // Update buffer pos, left data count, and return size + // Update buffer pos, left data count, and return size. buf += strlen; len -= strlen; if (r_len) { @@ -109,6 +128,65 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r return OK; } +static Error _decode_container_type(const uint8_t *&buf, int &len, int *r_len, bool p_allow_objects, ContainerTypeKind p_type_kind, ContainerType &r_type) { + switch (p_type_kind) { + case CONTAINER_TYPE_KIND_NONE: { + return OK; + } break; + case CONTAINER_TYPE_KIND_BUILTIN: { + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + + int32_t bt = decode_uint32(buf); + buf += 4; + len -= 4; + if (r_len) { + (*r_len) += 4; + } + + ERR_FAIL_INDEX_V(bt, Variant::VARIANT_MAX, ERR_INVALID_DATA); + r_type.builtin_type = (Variant::Type)bt; + if (!p_allow_objects && r_type.builtin_type == Variant::OBJECT) { + r_type.class_name = EncodedObjectAsID::get_class_static(); + } + return OK; + } break; + case CONTAINER_TYPE_KIND_CLASS_NAME: { + String str; + Error err = _decode_string(buf, len, r_len, str); + if (err) { + return err; + } + + r_type.builtin_type = Variant::OBJECT; + if (p_allow_objects) { + r_type.class_name = str; + } else { + r_type.class_name = EncodedObjectAsID::get_class_static(); + } + return OK; + } break; + case CONTAINER_TYPE_KIND_SCRIPT: { + String path; + Error err = _decode_string(buf, len, r_len, path); + if (err) { + return err; + } + + r_type.builtin_type = Variant::OBJECT; + if (p_allow_objects) { + ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path \"%s\".", path)); + r_type.script = ResourceLoader::load(path, "Script"); + ERR_FAIL_COND_V_MSG(r_type.script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path \"%s\".", path)); + r_type.class_name = r_type.script->get_instance_base_type(); + } else { + r_type.class_name = EncodedObjectAsID::get_class_static(); + } + return OK; + } break; + } + ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Invalid container type kind."); // Future proofing. +} + Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_objects, int p_depth) { ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Variant is too deep. Bailing."); const uint8_t *buf = p_buffer; @@ -126,7 +204,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = 4; } - // Note: We cannot use sizeof(real_t) for decoding, in case a different size is encoded. + // NOTE: We cannot use `sizeof(real_t)` for decoding, in case a different size is encoded. // Decoding math types always checks for the encoded size, while encoding always uses compilation setting. // This does lead to some code duplication for decoding, but compatibility is the priority. switch (header & HEADER_TYPE_MASK) { @@ -188,7 +266,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; - // math types + // Math types. case Variant::VECTOR2: { Vector2 val; if (header & HEADER_DATA_FLAG_64) { @@ -539,7 +617,8 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = val; } break; - // misc types + + // Misc types. case Variant::COLOR: { ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); Color val; @@ -568,7 +647,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int int32_t strlen = decode_uint32(buf); if (strlen & 0x80000000) { - //new format + // New format. ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA); Vector<StringName> names; Vector<StringName> subnames; @@ -607,8 +686,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = NodePath(names, subnames, np_flags & 1); } else { - //old format, just a string - + // Old format, just a string. ERR_FAIL_V(ERR_INVALID_DATA); } @@ -698,9 +776,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (str == "script" && value.get_type() != Variant::NIL) { ERR_FAIL_COND_V_MSG(value.get_type() != Variant::STRING, ERR_INVALID_DATA, "Invalid value for \"script\" property, expected script path as String."); String path = value; - ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, "Invalid script path: '" + path + "'."); + ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path \"%s\".", path)); Ref<Script> script = ResourceLoader::load(path, "Script"); - ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, "Can't load script at path: '" + path + "'."); + ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path \"%s\".", path)); obj->set_script(script); } else { obj->set(str, value); @@ -731,9 +809,30 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = Signal(id, StringName(name)); } break; case Variant::DICTIONARY: { + ContainerType key_type; + + { + ContainerTypeKind key_type_kind = GET_CONTAINER_TYPE_KIND(header, TYPED_DICTIONARY_KEY); + Error err = _decode_container_type(buf, len, r_len, p_allow_objects, key_type_kind, key_type); + if (err) { + return err; + } + } + + ContainerType value_type; + + { + ContainerTypeKind value_type_kind = GET_CONTAINER_TYPE_KIND(header, TYPED_DICTIONARY_VALUE); + Error err = _decode_container_type(buf, len, r_len, p_allow_objects, value_type_kind, value_type); + if (err) { + return err; + } + } + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t count = decode_uint32(buf); - // bool shared = count&0x80000000; + //bool shared = count & 0x80000000; count &= 0x7FFFFFFF; buf += 4; @@ -743,7 +842,10 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int (*r_len) += 4; // Size of count number. } - Dictionary d; + Dictionary dict; + if (key_type.builtin_type != Variant::NIL || value_type.builtin_type != Variant::NIL) { + dict.set_typed(key_type.builtin_type, key_type.class_name, key_type.script, value_type.builtin_type, value_type.class_name, value_type.script); + } for (int i = 0; i < count; i++) { Variant key, value; @@ -767,75 +869,27 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int (*r_len) += used; } - d[key] = value; + dict[key] = value; } - r_variant = d; + r_variant = dict; } break; case Variant::ARRAY: { - Variant::Type builtin_type = Variant::VARIANT_MAX; - StringName class_name; - Ref<Script> script; - - switch (header & HEADER_DATA_FIELD_TYPED_ARRAY_MASK) { - case HEADER_DATA_FIELD_TYPED_ARRAY_NONE: - break; // Untyped array. - case HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); - - int32_t bt = decode_uint32(buf); - buf += 4; - len -= 4; - if (r_len) { - (*r_len) += 4; - } + ContainerType type; - ERR_FAIL_INDEX_V(bt, Variant::VARIANT_MAX, ERR_INVALID_DATA); - builtin_type = (Variant::Type)bt; - if (!p_allow_objects && builtin_type == Variant::OBJECT) { - class_name = EncodedObjectAsID::get_class_static(); - } - } break; - case HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME: { - String str; - Error err = _decode_string(buf, len, r_len, str); - if (err) { - return err; - } - - builtin_type = Variant::OBJECT; - if (p_allow_objects) { - class_name = str; - } else { - class_name = EncodedObjectAsID::get_class_static(); - } - } break; - case HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT: { - String path; - Error err = _decode_string(buf, len, r_len, path); - if (err) { - return err; - } - - builtin_type = Variant::OBJECT; - if (p_allow_objects) { - ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, "Invalid script path: '" + path + "'."); - script = ResourceLoader::load(path, "Script"); - ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, "Can't load script at path: '" + path + "'."); - class_name = script->get_instance_base_type(); - } else { - class_name = EncodedObjectAsID::get_class_static(); - } - } break; - default: - ERR_FAIL_V(ERR_INVALID_DATA); // Future proofing. + { + ContainerTypeKind type_kind = GET_CONTAINER_TYPE_KIND(header, TYPED_ARRAY); + Error err = _decode_container_type(buf, len, r_len, p_allow_objects, type_kind, type); + if (err) { + return err; + } } ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); - // bool shared = count&0x80000000; + //bool shared = count & 0x80000000; count &= 0x7FFFFFFF; buf += 4; @@ -845,29 +899,29 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int (*r_len) += 4; // Size of count number. } - Array varr; - if (builtin_type != Variant::VARIANT_MAX) { - varr.set_typed(builtin_type, class_name, script); + Array array; + if (type.builtin_type != Variant::NIL) { + array.set_typed(type.builtin_type, type.class_name, type.script); } for (int i = 0; i < count; i++) { int used = 0; - Variant v; - Error err = decode_variant(v, buf, len, &used, p_allow_objects, p_depth + 1); + Variant elem; + Error err = decode_variant(elem, buf, len, &used, p_allow_objects, p_depth + 1); ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant."); buf += used; len -= used; - varr.push_back(v); + array.push_back(elem); if (r_len) { (*r_len) += used; } } - r_variant = varr; + r_variant = array; } break; - // arrays + // Packed arrays. case Variant::PACKED_BYTE_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -906,7 +960,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Vector<int32_t> data; if (count) { - //const int*rbuf=(const int*)buf; + //const int *rbuf = (const int *)buf; data.resize(count); int32_t *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -930,7 +984,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Vector<int64_t> data; if (count) { - //const int*rbuf=(const int*)buf; + //const int *rbuf = (const int *)buf; data.resize(count); int64_t *w = data.ptrw(); for (int64_t i = 0; i < count; i++) { @@ -954,7 +1008,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Vector<float> data; if (count) { - //const float*rbuf=(const float*)buf; + //const float *rbuf = (const float *)buf; data.resize(count); float *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -1265,13 +1319,50 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) { r_len += 4 + utf8.length(); while (r_len % 4) { - r_len++; //pad + r_len++; // Pad. if (buf) { *(buf++) = 0; } } } +static void _encode_container_type_header(const ContainerType &p_type, uint32_t &header, uint32_t p_shift, bool p_full_objects) { + if (p_type.builtin_type != Variant::NIL) { + if (p_type.script.is_valid()) { + header |= (p_full_objects ? CONTAINER_TYPE_KIND_SCRIPT : CONTAINER_TYPE_KIND_CLASS_NAME) << p_shift; + } else if (p_type.class_name != StringName()) { + header |= CONTAINER_TYPE_KIND_CLASS_NAME << p_shift; + } else { + // No need to check `p_full_objects` since `class_name` should be non-empty for `builtin_type == Variant::OBJECT`. + header |= CONTAINER_TYPE_KIND_BUILTIN << p_shift; + } + } +} + +static Error _encode_container_type(const ContainerType &p_type, uint8_t *&buf, int &r_len, bool p_full_objects) { + if (p_type.builtin_type != Variant::NIL) { + if (p_type.script.is_valid()) { + if (p_full_objects) { + String path = p_type.script->get_path(); + ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://"), ERR_UNAVAILABLE, "Failed to encode a path to a custom script for a container type."); + _encode_string(path, buf, r_len); + } else { + _encode_string(EncodedObjectAsID::get_class_static(), buf, r_len); + } + } else if (p_type.class_name != StringName()) { + _encode_string(p_full_objects ? p_type.class_name.operator String() : EncodedObjectAsID::get_class_static(), buf, r_len); + } else { + // No need to check `p_full_objects` since `class_name` should be non-empty for `builtin_type == Variant::OBJECT`. + if (buf) { + encode_uint32(p_type.builtin_type, buf); + buf += 4; + } + r_len += 4; + } + } + return OK; +} + Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects, int p_depth) { ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Potential infinite recursion detected. Bailing."); uint8_t *buf = r_buffer; @@ -1310,20 +1401,32 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo header |= HEADER_DATA_FLAG_OBJECT_AS_ID; } } break; + case Variant::DICTIONARY: { + Dictionary dict = p_variant; + + ContainerType key_type; + key_type.builtin_type = (Variant::Type)dict.get_typed_key_builtin(); + key_type.class_name = dict.get_typed_key_class_name(); + key_type.script = dict.get_typed_key_script(); + + _encode_container_type_header(key_type, header, HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_SHIFT, p_full_objects); + + ContainerType value_type; + value_type.builtin_type = (Variant::Type)dict.get_typed_value_builtin(); + value_type.class_name = dict.get_typed_value_class_name(); + value_type.script = dict.get_typed_value_script(); + + _encode_container_type_header(value_type, header, HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_SHIFT, p_full_objects); + } break; case Variant::ARRAY: { Array array = p_variant; - if (array.is_typed()) { - Ref<Script> script = array.get_typed_script(); - if (script.is_valid()) { - header |= p_full_objects ? HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT : HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME; - } else if (array.get_typed_class_name() != StringName()) { - header |= HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME; - } else { - // No need to check `p_full_objects` since for `Variant::OBJECT` - // `array.get_typed_class_name()` should be non-empty. - header |= HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN; - } - } + + ContainerType type; + type.builtin_type = (Variant::Type)array.get_typed_builtin(); + type.class_name = array.get_typed_class_name(); + type.script = array.get_typed_script(); + + _encode_container_type_header(type, header, HEADER_DATA_FIELD_TYPED_ARRAY_SHIFT, p_full_objects); } break; #ifdef REAL_T_IS_DOUBLE case Variant::VECTOR2: @@ -1344,7 +1447,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; #endif // REAL_T_IS_DOUBLE default: { - } // nothing to do at this stage + // Nothing to do at this stage. + } break; } if (buf) { @@ -1355,7 +1459,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo switch (p_variant.get_type()) { case Variant::NIL: { - //nothing to do + // Nothing to do. } break; case Variant::BOOL: { if (buf) { @@ -1367,7 +1471,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::INT: { if (header & HEADER_DATA_FLAG_64) { - //64 bits + // 64 bits. if (buf) { encode_uint64(p_variant.operator int64_t(), buf); } @@ -1401,7 +1505,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo case Variant::NODE_PATH: { NodePath np = p_variant; if (buf) { - encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format + encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); // For compatibility with the old format. encode_uint32(np.get_subname_count(), buf + 4); uint32_t np_flags = 0; if (np.is_absolute()) { @@ -1451,7 +1555,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; - // math types + // Math types. case Variant::VECTOR2: { if (buf) { Vector2 v2 = p_variant; @@ -1635,7 +1739,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; - // misc types + // Misc types. case Variant::COLOR: { if (buf) { Color c = p_variant; @@ -1746,29 +1850,53 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 8; } break; case Variant::DICTIONARY: { - Dictionary d = p_variant; + Dictionary dict = p_variant; + + { + ContainerType key_type; + key_type.builtin_type = (Variant::Type)dict.get_typed_key_builtin(); + key_type.class_name = dict.get_typed_key_class_name(); + key_type.script = dict.get_typed_key_script(); + + Error err = _encode_container_type(key_type, buf, r_len, p_full_objects); + if (err) { + return err; + } + } + + { + ContainerType value_type; + value_type.builtin_type = (Variant::Type)dict.get_typed_value_builtin(); + value_type.class_name = dict.get_typed_value_class_name(); + value_type.script = dict.get_typed_value_script(); + + Error err = _encode_container_type(value_type, buf, r_len, p_full_objects); + if (err) { + return err; + } + } if (buf) { - encode_uint32(uint32_t(d.size()), buf); + encode_uint32(uint32_t(dict.size()), buf); buf += 4; } r_len += 4; List<Variant> keys; - d.get_key_list(&keys); + dict.get_key_list(&keys); - for (const Variant &E : keys) { + for (const Variant &key : keys) { int len; - Error err = encode_variant(E, buf, len, p_full_objects, p_depth + 1); + Error err = encode_variant(key, buf, len, p_full_objects, p_depth + 1); ERR_FAIL_COND_V(err, err); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; if (buf) { buf += len; } - Variant *v = d.getptr(E); - ERR_FAIL_NULL_V(v, ERR_BUG); - err = encode_variant(*v, buf, len, p_full_objects, p_depth + 1); + Variant *value = dict.getptr(key); + ERR_FAIL_NULL_V(value, ERR_BUG); + err = encode_variant(*value, buf, len, p_full_objects, p_depth + 1); ERR_FAIL_COND_V(err, err); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; @@ -1781,27 +1909,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo case Variant::ARRAY: { Array array = p_variant; - if (array.is_typed()) { - Variant variant = array.get_typed_script(); - Ref<Script> script = variant; - if (script.is_valid()) { - if (p_full_objects) { - String path = script->get_path(); - ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://"), ERR_UNAVAILABLE, "Failed to encode a path to a custom script for an array type."); - _encode_string(path, buf, r_len); - } else { - _encode_string(EncodedObjectAsID::get_class_static(), buf, r_len); - } - } else if (array.get_typed_class_name() != StringName()) { - _encode_string(p_full_objects ? array.get_typed_class_name().operator String() : EncodedObjectAsID::get_class_static(), buf, r_len); - } else { - // No need to check `p_full_objects` since for `Variant::OBJECT` - // `array.get_typed_class_name()` should be non-empty. - if (buf) { - encode_uint32(array.get_typed_builtin(), buf); - buf += 4; - } - r_len += 4; + { + ContainerType type; + type.builtin_type = (Variant::Type)array.get_typed_builtin(); + type.class_name = array.get_typed_class_name(); + type.script = array.get_typed_script(); + + Error err = _encode_container_type(type, buf, r_len, p_full_objects); + if (err) { + return err; } } @@ -1811,9 +1927,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } r_len += 4; - for (const Variant &var : array) { + for (const Variant &elem : array) { int len; - Error err = encode_variant(var, buf, len, p_full_objects, p_depth + 1); + Error err = encode_variant(elem, buf, len, p_full_objects, p_depth + 1); ERR_FAIL_COND_V(err, err); ERR_FAIL_COND_V(len % 4, ERR_BUG); if (buf) { @@ -1823,7 +1939,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; - // arrays + + // Packed arrays. case Variant::PACKED_BYTE_ARRAY: { Vector<uint8_t> data = p_variant; int datalen = data.size(); @@ -1939,7 +2056,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 + utf8.length() + 1; while (r_len % 4) { - r_len++; //pad + r_len++; // Pad. if (buf) { *(buf++) = 0; } @@ -2057,9 +2174,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } Vector<float> vector3_to_float32_array(const Vector3 *vecs, size_t count) { - // We always allocate a new array, and we don't memcpy. - // We also don't consider returning a pointer to the passed vectors when sizeof(real_t) == 4. - // One reason is that we could decide to put a 4th component in Vector3 for SIMD/mobile performance, + // We always allocate a new array, and we don't `memcpy()`. + // We also don't consider returning a pointer to the passed vectors when `sizeof(real_t) == 4`. + // One reason is that we could decide to put a 4th component in `Vector3` for SIMD/mobile performance, // which would cause trouble with these optimizations. Vector<float> floats; if (count == 0) { diff --git a/core/io/marshalls.h b/core/io/marshalls.h index 6f015ac386..82c760c28d 100644 --- a/core/io/marshalls.h +++ b/core/io/marshalls.h @@ -84,6 +84,12 @@ static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) { return sizeof(uint32_t); } +static inline unsigned int encode_half(float p_float, uint8_t *p_arr) { + encode_uint16(Math::make_half_float(p_float), p_arr); + + return sizeof(uint16_t); +} + static inline unsigned int encode_float(float p_float, uint8_t *p_arr) { MarshallFloat mf; mf.f = p_float; @@ -172,6 +178,10 @@ static inline uint32_t decode_uint32(const uint8_t *p_arr) { return u; } +static inline float decode_half(const uint8_t *p_arr) { + return Math::half_to_float(decode_uint16(p_arr)); +} + static inline float decode_float(const uint8_t *p_arr) { MarshallFloat mf; mf.i = decode_uint32(p_arr); diff --git a/core/io/missing_resource.cpp b/core/io/missing_resource.cpp index c78195bc46..1c15cc7dd3 100644 --- a/core/io/missing_resource.cpp +++ b/core/io/missing_resource.cpp @@ -74,6 +74,10 @@ bool MissingResource::is_recording_properties() const { return recording_properties; } +String MissingResource::get_save_class() const { + return original_class; +} + void MissingResource::_bind_methods() { ClassDB::bind_method(D_METHOD("set_original_class", "name"), &MissingResource::set_original_class); ClassDB::bind_method(D_METHOD("get_original_class"), &MissingResource::get_original_class); diff --git a/core/io/missing_resource.h b/core/io/missing_resource.h index f32d818ccb..4cded5ca24 100644 --- a/core/io/missing_resource.h +++ b/core/io/missing_resource.h @@ -57,6 +57,8 @@ public: void set_recording_properties(bool p_enable); bool is_recording_properties() const; + virtual String get_save_class() const override; + MissingResource(); }; diff --git a/core/io/net_socket.h b/core/io/net_socket.h index 120ad5e85b..c12bab622a 100644 --- a/core/io/net_socket.h +++ b/core/io/net_socket.h @@ -76,6 +76,8 @@ public: virtual void set_reuse_address_enabled(bool p_enabled) = 0; virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) = 0; virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) = 0; + + virtual ~NetSocket() {} }; #endif // NET_SOCKET_H diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index fae3de2a98..08e5353174 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -105,6 +105,19 @@ Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { return ERR_UNAVAILABLE; } +/* Bogus GCC warning here: + * In member function 'int RingBuffer<T>::read(T*, int, bool) [with T = unsigned char]', + * inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:112:9, + * inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:99:7: + * Error: ./core/ring_buffer.h:68:46: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=] + * 68 | p_buf[dst++] = read[pos + i]; + * | ~~~~~~~~~~~~~^~~~~~~ + */ +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wstringop-overflow=0" +#endif + uint32_t size = 0; uint8_t ipv6[16] = {}; rb.read(ipv6, 16, true); @@ -115,6 +128,11 @@ Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { --queue_count; *r_buffer = packet_buffer; r_buffer_size = size; + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + return OK; } diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 93179d9a11..c832ef5700 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -48,7 +48,8 @@ static int _get_pad(int p_alignment, int p_n) { void PCKPacker::_bind_methods() { ClassDB::bind_method(D_METHOD("pck_start", "pck_path", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_file", "target_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_file_removal", "target_path"), &PCKPacker::add_file_removal); ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false)); } @@ -84,7 +85,7 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri enc_dir = p_encrypt_directory; file = FileAccess::open(p_pck_path, FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_pck_path) + "."); + ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, vformat("Can't open file to write: '%s'.", String(p_pck_path))); alignment = p_alignment; @@ -106,23 +107,42 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri return OK; } -Error PCKPacker::add_file(const String &p_pck_path, const String &p_src, bool p_encrypt) { +Error PCKPacker::add_file_removal(const String &p_target_path) { ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use."); - Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ); + File pf; + // Simplify path here and on every 'files' access so that paths that have extra '/' + // symbols or 'res://' in them still match the MD5 hash for the saved path. + pf.path = p_target_path.simplify_path().trim_prefix("res://"); + pf.ofs = ofs; + pf.size = 0; + pf.removal = true; + + pf.md5.resize(16); + pf.md5.fill(0); + + files.push_back(pf); + + return OK; +} + +Error PCKPacker::add_file(const String &p_target_path, const String &p_source_path, bool p_encrypt) { + ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use."); + + Ref<FileAccess> f = FileAccess::open(p_source_path, FileAccess::READ); if (f.is_null()) { return ERR_FILE_CANT_OPEN; } File pf; // Simplify path here and on every 'files' access so that paths that have extra '/' - // symbols in them still match to the MD5 hash for the saved path. - pf.path = p_pck_path.simplify_path(); - pf.src_path = p_src; + // symbols or 'res://' in them still match the MD5 hash for the saved path. + pf.path = p_target_path.simplify_path().trim_prefix("res://"); + pf.src_path = p_source_path; pf.ofs = ofs; pf.size = f->get_length(); - Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_src); + Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_source_path); { unsigned char hash[16]; CryptoCore::md5(data.ptr(), data.size(), hash); @@ -195,6 +215,9 @@ Error PCKPacker::flush(bool p_verbose) { if (files[i].encrypted) { flags |= PACK_FILE_ENCRYPTED; } + if (files[i].removal) { + flags |= PACK_FILE_REMOVAL; + } fhead->store_32(flags); } @@ -218,6 +241,10 @@ Error PCKPacker::flush(bool p_verbose) { int count = 0; for (int i = 0; i < files.size(); i++) { + if (files[i].removal) { + continue; + } + Ref<FileAccess> src = FileAccess::open(files[i].src_path, FileAccess::READ); uint64_t to_write = files[i].size; diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h index 5aac833532..043a1dbdb8 100644 --- a/core/io/pck_packer.h +++ b/core/io/pck_packer.h @@ -53,13 +53,15 @@ class PCKPacker : public RefCounted { uint64_t ofs = 0; uint64_t size = 0; bool encrypted = false; + bool removal = false; Vector<uint8_t> md5; }; Vector<File> files; public: Error pck_start(const String &p_pck_path, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false); - Error add_file(const String &p_pck_path, const String &p_src, bool p_encrypt = false); + Error add_file(const String &p_target_path, const String &p_source_path, bool p_encrypt = false); + Error add_file_removal(const String &p_target_path); Error flush(bool p_verbose = false); PCKPacker() {} diff --git a/core/io/plist.cpp b/core/io/plist.cpp index 8d91e6dec2..26b8c39495 100644 --- a/core/io/plist.cpp +++ b/core/io/plist.cpp @@ -450,7 +450,7 @@ PList::PList() { PList::PList(const String &p_string) { String err_str; bool ok = load_string(p_string, err_str); - ERR_FAIL_COND_MSG(!ok, "PList: " + err_str); + ERR_FAIL_COND_MSG(!ok, vformat("PList: %s.", err_str)); } uint64_t PList::read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size) { @@ -661,12 +661,12 @@ bool PList::load_string(const String &p_string, String &r_err_out) { List<Ref<PListNode>> stack; String key; while (pos >= 0) { - int open_token_s = p_string.find("<", pos); + int open_token_s = p_string.find_char('<', pos); if (open_token_s == -1) { r_err_out = "Unexpected end of data. No tags found."; return false; } - int open_token_e = p_string.find(">", open_token_s); + int open_token_e = p_string.find_char('>', open_token_s); pos = open_token_e; String token = p_string.substr(open_token_s + 1, open_token_e - open_token_s - 1); @@ -676,7 +676,7 @@ bool PList::load_string(const String &p_string, String &r_err_out) { } String value; if (token[0] == '?' || token[0] == '!') { // Skip <?xml ... ?> and <!DOCTYPE ... > - int end_token_e = p_string.find(">", open_token_s); + int end_token_e = p_string.find_char('>', open_token_s); pos = end_token_e; continue; } @@ -769,7 +769,7 @@ bool PList::load_string(const String &p_string, String &r_err_out) { r_err_out = vformat("Mismatched <%s> tag.", token); return false; } - int end_token_e = p_string.find(">", end_token_s); + int end_token_e = p_string.find_char('>', end_token_s); pos = end_token_e; String end_token = p_string.substr(end_token_s + 2, end_token_e - end_token_s - 2); if (end_token != token) { diff --git a/core/io/remote_filesystem_client.cpp b/core/io/remote_filesystem_client.cpp index 1198810441..c3f9a0016c 100644 --- a/core/io/remote_filesystem_client.cpp +++ b/core/io/remote_filesystem_client.cpp @@ -96,7 +96,7 @@ Error RemoteFilesystemClient::_store_file(const String &p_path, const LocalVecto } Ref<FileAccess> f = FileAccess::open(full_path, FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Unable to open file for writing to remote filesystem cache: " + p_path); + ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, vformat("Unable to open file for writing to remote filesystem cache: '%s'.", p_path)); f->store_buffer(p_file.ptr(), p_file.size()); Error err = f->get_error(); if (err) { @@ -115,10 +115,10 @@ Error RemoteFilesystemClient::_store_cache_file(const Vector<FileCache> &p_cache String full_path = cache_path.path_join(FILES_CACHE_FILE); String base_file_dir = full_path.get_base_dir(); Error err = DirAccess::make_dir_recursive_absolute(base_file_dir); - ERR_FAIL_COND_V_MSG(err != OK && err != ERR_ALREADY_EXISTS, err, "Unable to create base directory to store cache file: " + base_file_dir); + ERR_FAIL_COND_V_MSG(err != OK && err != ERR_ALREADY_EXISTS, err, vformat("Unable to create base directory to store cache file: '%s'.", base_file_dir)); Ref<FileAccess> f = FileAccess::open(full_path, FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Unable to open the remote cache file for writing: " + full_path); + ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, vformat("Unable to open the remote cache file for writing: '%s'.", full_path)); f->store_line(itos(FILESYSTEM_CACHE_VERSION)); for (int i = 0; i < p_cache.size(); i++) { String l = p_cache[i].path + "::" + itos(p_cache[i].server_modified_time) + "::" + itos(p_cache[i].modified_time); @@ -151,10 +151,10 @@ Error RemoteFilesystemClient::_synchronize_with_server(const String &p_host, int tcp_client.instantiate(); IPAddress ip = p_host.is_valid_ip_address() ? IPAddress(p_host) : IP::get_singleton()->resolve_hostname(p_host); - ERR_FAIL_COND_V_MSG(!ip.is_valid(), ERR_INVALID_PARAMETER, "Unable to resolve remote filesystem server hostname: " + p_host); + ERR_FAIL_COND_V_MSG(!ip.is_valid(), ERR_INVALID_PARAMETER, vformat("Unable to resolve remote filesystem server hostname: '%s'.", p_host)); print_verbose(vformat("Remote Filesystem: Connecting to host %s, port %d.", ip, p_port)); Error err = tcp_client->connect_to_host(ip, p_port); - ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to open connection to remote file server (" + String(p_host) + ", port " + itos(p_port) + ") failed."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Unable to open connection to remote file server (%s, port %d) failed.", String(p_host), p_port)); while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTING) { tcp_client->poll(); @@ -162,7 +162,7 @@ Error RemoteFilesystemClient::_synchronize_with_server(const String &p_host, int } if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) { - ERR_FAIL_V_MSG(ERR_CANT_CONNECT, "Connection to remote file server (" + String(p_host) + ", port " + itos(p_port) + ") failed."); + ERR_FAIL_V_MSG(ERR_CANT_CONNECT, vformat("Connection to remote file server (%s, port %d) failed.", String(p_host), p_port)); } // Connection OK, now send the current file state. @@ -280,7 +280,7 @@ Error RemoteFilesystemClient::_synchronize_with_server(const String &p_host, int err = tcp_client->get_data(file_buffer.ptr(), file_size); if (err != OK) { - ERR_PRINT("Error retrieving file from remote filesystem: " + file); + ERR_PRINT(vformat("Error retrieving file from remote filesystem: '%s'.", file)); server_disconnected = true; } diff --git a/core/io/resource.cpp b/core/io/resource.cpp index 0ff4fbe490..c65484b6c6 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -76,7 +76,7 @@ void Resource::set_path(const String &p_path, bool p_take_over) { existing->path_cache = String(); ResourceCache::resources.erase(p_path); } else { - ERR_FAIL_MSG("Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion)."); + ERR_FAIL_MSG(vformat("Another resource is loaded from path '%s' (possible cyclic resource inclusion).", p_path)); } } diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 109999d612..ed11f96d03 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -411,7 +411,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { //always use internal cache for loading internal resources if (!internal_index_cache.has(path)) { - WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data()); + WARN_PRINT(vformat("Couldn't load resource (no cache): %s.", path)); r_v = Variant(); } else { r_v = internal_index_cache[path]; @@ -435,7 +435,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { Ref<Resource> res = ResourceLoader::load(path, exttype, cache_mode_for_external); if (res.is_null()) { - WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); + WARN_PRINT(vformat("Couldn't load resource: %s.", path)); } r_v = res; @@ -458,7 +458,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { ResourceLoader::notify_dependency_error(local_path, external_resources[erindex].path, external_resources[erindex].type); } else { error = ERR_FILE_MISSING_DEPENDENCIES; - ERR_FAIL_V_MSG(error, "Can't load dependency: " + external_resources[erindex].path + "."); + ERR_FAIL_V_MSG(error, vformat("Can't load dependency: '%s'.", external_resources[erindex].path)); } } } else { @@ -704,7 +704,7 @@ Error ResourceLoaderBinary::load() { ResourceLoader::notify_dependency_error(local_path, path, external_resources[i].type); } else { error = ERR_FILE_MISSING_DEPENDENCIES; - ERR_FAIL_V_MSG(error, "Can't load dependency: " + path + "."); + ERR_FAIL_V_MSG(error, vformat("Can't load dependency: '%s'.", path)); } } } @@ -780,7 +780,7 @@ Error ResourceLoaderBinary::load() { obj = missing_resource; } else { error = ERR_FILE_CORRUPT; - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + "."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, vformat("'%s': Resource of unrecognized type in file: '%s'.", local_path, t)); } } @@ -789,7 +789,7 @@ Error ResourceLoaderBinary::load() { String obj_class = obj->get_class(); error = ERR_FILE_CORRUPT; memdelete(obj); //bye - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + "."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, vformat("'%s': Resource type in resource field not a resource, type is: %s.", local_path, obj_class)); } res = Ref<Resource>(r); @@ -833,7 +833,7 @@ Error ResourceLoaderBinary::load() { } bool set_valid = true; - if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) { + if (value.get_type() == Variant::OBJECT && missing_resource == nullptr && ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) { // If the property being set is a missing resource (and the parent is not), // then setting it will most likely not work. // Instead, save it as metadata. @@ -999,7 +999,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p error = fac->open_after_magic(f); if (error != OK) { f.unref(); - ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + "."); + ERR_FAIL_MSG(vformat("Failed to open binary resource file: '%s'.", local_path)); } f = fac; @@ -1007,7 +1007,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p // Not normal. error = ERR_FILE_UNRECOGNIZED; f.unref(); - ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + "."); + ERR_FAIL_MSG(vformat("Unrecognized binary resource file: '%s'.", local_path)); } bool big_endian = f->get_32(); @@ -1093,10 +1093,10 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p #ifdef TOOLS_ENABLED // Silence a warning that can happen during the initial filesystem scan due to cache being regenerated. if (ResourceLoader::get_resource_uid(res_path) != er.uid) { - WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data()); + WARN_PRINT(vformat("'%s': In external resource #%d, invalid UID: '%s' - using text path instead: '%s'.", res_path, i, ResourceUID::get_singleton()->id_to_text(er.uid), er.path)); } #else - WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data()); + WARN_PRINT(vformat("'%s': In external resource #%d, invalid UID: '%s' - using text path instead: '%s'.", res_path, i, ResourceUID::get_singleton()->id_to_text(er.uid), er.path)); #endif } } @@ -1120,7 +1120,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p if (f->eof_reached()) { error = ERR_FILE_CORRUPT; f.unref(); - ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + "."); + ERR_FAIL_MSG(vformat("Premature end of file (EOF): '%s'.", local_path)); } } @@ -1224,7 +1224,7 @@ Ref<Resource> ResourceFormatLoaderBinary::load(const String &p_path, const Strin Error err; Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); - ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), vformat("Cannot open file '%s'.", p_path)); ResourceLoaderBinary loader; switch (p_cache_mode) { @@ -1268,6 +1268,11 @@ void ResourceFormatLoaderBinary::get_recognized_extensions_for_type(const String return; } + // res files not supported for GDExtension. + if (p_type == "GDExtension") { + return; + } + List<String> extensions; ClassDB::get_extensions_for_type(p_type, &extensions); @@ -1296,7 +1301,7 @@ bool ResourceFormatLoaderBinary::handles_type(const String &p_type) const { void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_MSG(f.is_null(), vformat("Cannot open file '%s'.", p_path)); ResourceLoaderBinary loader; loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); @@ -1306,7 +1311,7 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Cannot open file '%s'.", p_path)); Ref<FileAccess> fw; @@ -1319,23 +1324,23 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons Ref<FileAccessCompressed> fac; fac.instantiate(); Error err = fac->open_after_magic(f); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot open file '%s'.", p_path)); f = fac; Ref<FileAccessCompressed> facw; facw.instantiate(); facw->configure("RSCC"); err = facw->open_internal(p_path + ".depren", FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'."); + ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, vformat("Cannot create file '%s.depren'.", p_path)); fw = facw; } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') { // Not normal. - ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'."); + ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Unrecognized binary resource file '%s'.", local_path)); } else { fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".depren'."); + ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, vformat("Cannot create file '%s.depren'.", p_path)); uint8_t magic[4] = { 'R', 'S', 'R', 'C' }; fw->store_buffer(magic, 4); @@ -1367,12 +1372,12 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons // Use the old approach. - WARN_PRINT("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'."); + WARN_PRINT(vformat("This file is old, so it can't refactor dependencies, opening and resaving '%s'.", p_path)); Error err; f = FileAccess::open(p_path, FileAccess::READ, &err); - ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_OPEN, "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_OPEN, vformat("Cannot open file '%s'.", p_path)); ResourceLoaderBinary loader; loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); @@ -1518,7 +1523,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons void ResourceFormatLoaderBinary::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_MSG(f.is_null(), vformat("Cannot open file '%s'.", p_path)); ResourceLoaderBinary loader; loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); @@ -1572,6 +1577,10 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat return loader.uid; } +bool ResourceFormatLoaderBinary::has_custom_uid_support() const { + return true; +} + /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// @@ -2022,7 +2031,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant if (!p_main && (!bundle_resources) && !res->is_built_in()) { if (res->get_path() == path) { - ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); + ERR_PRINT(vformat("Circular reference to resource being saved found: '%s' will be null next time it's loaded.", local_path)); return; } int idx = external_resources.size(); @@ -2148,7 +2157,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re f = FileAccess::open(p_path, FileAccess::WRITE, &err); } - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot create file '%s'.", p_path)); relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS; skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES; @@ -2220,10 +2229,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re List<ResourceData> resources; - Dictionary missing_resource_properties = p_resource->get_meta(META_MISSING_RESOURCES, Dictionary()); - { for (const Ref<Resource> &E : saved_resources) { + Dictionary missing_resource_properties = E->get_meta(META_MISSING_RESOURCES, Dictionary()); + ResourceData &rd = resources.push_back(ResourceData())->get(); rd.type = _resource_get_class(E); @@ -2238,7 +2247,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re continue; } - if ((F.usage & PROPERTY_USAGE_STORAGE)) { + if ((F.usage & PROPERTY_USAGE_STORAGE) || missing_resource_properties.has(F.name)) { Property p; p.name_idx = get_string_index(F.name); @@ -2253,7 +2262,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re p.value = E->get(F.name); } - if (p.pi.type == Variant::OBJECT && missing_resource_properties.has(F.name)) { + if (F.type == Variant::OBJECT && missing_resource_properties.has(F.name)) { // Was this missing resource overridden? If so do not save the old value. Ref<Resource> res = p.value; if (res.is_null()) { @@ -2379,7 +2388,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceUID::ID p_uid) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Cannot open file '%s'.", p_path)); Ref<FileAccess> fw; @@ -2392,14 +2401,14 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU Ref<FileAccessCompressed> fac; fac.instantiate(); Error err = fac->open_after_magic(f); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot open file '%s'.", p_path)); f = fac; Ref<FileAccessCompressed> facw; facw.instantiate(); facw->configure("RSCC"); err = facw->open_internal(p_path + ".uidren", FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".uidren'."); + ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, vformat("Cannot create file '%s.uidren'.", p_path)); fw = facw; @@ -2408,7 +2417,7 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU return ERR_FILE_UNRECOGNIZED; } else { fw = FileAccess::open(p_path + ".uidren", FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".uidren'."); + ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, vformat("Cannot create file '%s.uidren'.", p_path)); uint8_t magich[4] = { 'R', 'S', 'R', 'C' }; fw->store_buffer(magich, 4); @@ -2439,7 +2448,7 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU // Use the old approach. - WARN_PRINT("This file is old, so it does not support UIDs, opening and resaving '" + p_path + "'."); + WARN_PRINT(vformat("This file is old, so it does not support UIDs, opening and resaving '%s'.", p_path)); return ERR_UNAVAILABLE; } diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 222e633e58..ec8d7ead5d 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -118,6 +118,7 @@ public: virtual String get_resource_script_class(const String &p_path) const override; virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override; virtual ResourceUID::ID get_resource_uid(const String &p_path) const override; + virtual bool has_custom_uid_support() const override; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override; virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) override; }; diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 1ae50d2d0d..b7a14f2b88 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -75,7 +75,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy if (err == ERR_FILE_EOF) { return OK; } else if (err != OK) { - ERR_PRINT("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text); + ERR_PRINT(vformat("ResourceFormatImporter::load - %s.import:%d error: %s.", p_path, lines, error_text)); return err; } @@ -335,7 +335,7 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat if (err == ERR_FILE_EOF) { return; } else if (err != OK) { - ERR_PRINT("ResourceFormatImporter::get_internal_resource_path_list - " + p_path + ".import:" + itos(lines) + " error: " + error_text); + ERR_PRINT(vformat("ResourceFormatImporter::get_internal_resource_path_list - %s.import:%d error: %s.", p_path, lines, error_text)); return; } @@ -387,6 +387,10 @@ ResourceUID::ID ResourceFormatImporter::get_resource_uid(const String &p_path) c return pat.uid; } +bool ResourceFormatImporter::has_custom_uid_support() const { + return true; +} + Error ResourceFormatImporter::get_resource_import_info(const String &p_path, StringName &r_type, ResourceUID::ID &r_uid, String &r_import_group_file) const { PathAndType pat; Error err = _get_path_and_type(p_path, pat); diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 221f38494b..c3d3c4b67e 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -70,6 +70,7 @@ public: virtual bool handles_type(const String &p_type) const override; virtual String get_resource_type(const String &p_path) const override; virtual ResourceUID::ID get_resource_uid(const String &p_path) const override; + virtual bool has_custom_uid_support() const override; virtual Variant get_resource_metadata(const String &p_path) const; virtual bool is_import_valid(const String &p_path) const override; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override; @@ -147,8 +148,8 @@ public: virtual void handle_compatibility_options(HashMap<StringName, Variant> &p_import_params) const {} virtual String get_option_group_file() const { return String(); } - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) = 0; - virtual bool can_import_threaded() const { return true; } + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) = 0; + virtual bool can_import_threaded() const { return false; } virtual void import_threaded_begin() {} virtual void import_threaded_end() {} diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index f026d5416c..1615f145db 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/core_bind.h" +#include "core/io/dir_access.h" #include "core/io/file_access.h" #include "core/io/resource_importer.h" #include "core/object/script_language.h" @@ -40,6 +41,7 @@ #include "core/os/safe_binary_mutex.h" #include "core/string/print_string.h" #include "core/string/translation_server.h" +#include "core/templates/rb_set.h" #include "core/variant/variant_parser.h" #include "servers/rendering_server.h" @@ -112,10 +114,21 @@ String ResourceFormatLoader::get_resource_script_class(const String &p_path) con ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const { int64_t uid = ResourceUID::INVALID_ID; - GDVIRTUAL_CALL(_get_resource_uid, p_path, uid); + if (has_custom_uid_support()) { + GDVIRTUAL_CALL(_get_resource_uid, p_path, uid); + } else { + Ref<FileAccess> file = FileAccess::open(p_path + ".uid", FileAccess::READ); + if (file.is_valid()) { + uid = ResourceUID::get_singleton()->text_to_id(file->get_line()); + } + } return uid; } +bool ResourceFormatLoader::has_custom_uid_support() const { + return GDVIRTUAL_IS_OVERRIDDEN(_get_resource_uid); +} + void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const { if (p_type.is_empty() || handles_type(p_type)) { get_recognized_extensions(p_extensions); @@ -162,7 +175,7 @@ Ref<Resource> ResourceFormatLoader::load(const String &p_path, const String &p_o } } - ERR_FAIL_V_MSG(Ref<Resource>(), "Failed to load resource '" + p_path + "'. ResourceFormatLoader::load was not implemented for this resource type."); + ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Failed to load resource '%s'. ResourceFormatLoader::load was not implemented for this resource type.", p_path)); } void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { @@ -1150,6 +1163,21 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) { return ResourceUID::INVALID_ID; } +bool ResourceLoader::has_custom_uid_support(const String &p_path) { + String local_path = _validate_local_path(p_path); + + for (int i = 0; i < loader_count; i++) { + if (!loader[i]->recognize_path(local_path)) { + continue; + } + if (loader[i]->has_custom_uid_support()) { + return true; + } + } + + return false; +} + String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_remapped) { String new_path = p_path; @@ -1163,13 +1191,13 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem // An extra remap may still be necessary afterwards due to the text -> binary converter on export. String locale = TranslationServer::get_singleton()->get_locale(); - ERR_FAIL_COND_V_MSG(locale.length() < 2, p_path, "Could not remap path '" + p_path + "' for translation as configured locale '" + locale + "' is invalid."); + ERR_FAIL_COND_V_MSG(locale.length() < 2, p_path, vformat("Could not remap path '%s' for translation as configured locale '%s' is invalid.", p_path, locale)); Vector<String> &res_remaps = *translation_remaps.getptr(new_path); int best_score = 0; for (int i = 0; i < res_remaps.size(); i++) { - int split = res_remaps[i].rfind(":"); + int split = res_remaps[i].rfind_char(':'); if (split == -1) { continue; } @@ -1222,7 +1250,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem if (err == ERR_FILE_EOF) { break; } else if (err != OK) { - ERR_PRINT("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text + "."); + ERR_PRINT(vformat("Parse error: %s.remap:%d error: %s.", p_path, lines, error_text)); break; } @@ -1439,6 +1467,60 @@ bool ResourceLoader::is_cleaning_tasks() { return cleaning_tasks; } +Vector<String> ResourceLoader::list_directory(const String &p_directory) { + RBSet<String> files_found; + Ref<DirAccess> dir = DirAccess::open(p_directory); + if (dir.is_null()) { + return Vector<String>(); + } + + Error err = dir->list_dir_begin(); + if (err != OK) { + return Vector<String>(); + } + + String d = dir->get_next(); + while (!d.is_empty()) { + bool recognized = false; + if (dir->current_is_dir()) { + if (d != "." && d != "..") { + d += "/"; + recognized = true; + } + } else { + if (d.ends_with(".import") || d.ends_with(".remap") || d.ends_with(".uid")) { + d = d.substr(0, d.rfind_char('.')); + } + + if (d.ends_with(".gdc")) { + d = d.substr(0, d.rfind_char('.')); + d += ".gd"; + } + + const String full_path = p_directory.path_join(d); + // Try all loaders and pick the first match for the type hint. + for (int i = 0; i < loader_count; i++) { + if (loader[i]->recognize_path(full_path)) { + recognized = true; + break; + } + } + } + + if (recognized) { + files_found.insert(d); + } + d = dir->get_next(); + } + + Vector<String> ret; + for (const String &f : files_found) { + ret.push_back(f); + } + + return ret; +} + void ResourceLoader::initialize() {} void ResourceLoader::finalize() {} diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index caaf9f8f45..ebd6024033 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -81,6 +81,7 @@ public: virtual String get_resource_type(const String &p_path) const; virtual String get_resource_script_class(const String &p_path) const; virtual ResourceUID::ID get_resource_uid(const String &p_path) const; + virtual bool has_custom_uid_support() const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map); virtual bool is_import_valid(const String &p_path) const { return true; } @@ -222,7 +223,7 @@ public: static ThreadLoadStatus load_threaded_get_status(const String &p_path, float *r_progress = nullptr); static Ref<Resource> load_threaded_get(const String &p_path, Error *r_error = nullptr); - static bool is_within_load() { return load_nesting > 0; }; + static bool is_within_load() { return load_nesting > 0; } static void resource_changed_connect(Resource *p_source, const Callable &p_callable, uint32_t p_flags); static void resource_changed_disconnect(Resource *p_source, const Callable &p_callable); @@ -238,6 +239,7 @@ public: static String get_resource_type(const String &p_path); static String get_resource_script_class(const String &p_path); static ResourceUID::ID get_resource_uid(const String &p_path); + static bool has_custom_uid_support(const String &p_path); static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); static Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map); static bool is_import_valid(const String &p_path); @@ -302,6 +304,8 @@ public: static bool is_cleaning_tasks(); + static Vector<String> list_directory(const String &p_directory); + static void initialize(); static void finalize(); }; diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 1dc1245355..d49037dbe0 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -98,7 +98,7 @@ void ResourceFormatSaver::_bind_methods() { } Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { - ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, vformat("Can't save empty resource to path '%s'.", p_path)); String path = p_path; if (path.is_empty()) { path = p_resource->get_path(); diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp index c14121a53b..946bc524e5 100644 --- a/core/io/resource_uid.cpp +++ b/core/io/resource_uid.cpp @@ -34,6 +34,7 @@ #include "core/crypto/crypto_core.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" +#include "core/io/resource_loader.h" // These constants are off by 1, causing the 'z' and '9' characters never to be used. // This cannot be fixed without breaking compatibility; see GH-83843. @@ -139,6 +140,21 @@ void ResourceUID::remove_id(ID p_id) { unique_ids.erase(p_id); } +String ResourceUID::uid_to_path(const String &p_uid) { + return singleton->get_id_path(singleton->text_to_id(p_uid)); +} + +String ResourceUID::path_to_uid(const String &p_path) { + return singleton->id_to_text(ResourceLoader::get_resource_uid(p_path)); +} + +String ResourceUID::ensure_path(const String &p_uid_or_path) { + if (p_uid_or_path.begins_with("uid://")) { + return uid_to_path(p_uid_or_path); + } + return p_uid_or_path; +} + Error ResourceUID::save_to_cache() { String cache_file = get_cache_file(); if (!FileAccess::exists(cache_file)) { diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h index e56b89f603..7b735d296a 100644 --- a/core/io/resource_uid.h +++ b/core/io/resource_uid.h @@ -73,6 +73,10 @@ public: String get_id_path(ID p_id) const; void remove_id(ID p_id); + static String uid_to_path(const String &p_uid); + static String path_to_uid(const String &p_path); + static String ensure_path(const String &p_uid_or_path); + Error load_from_cache(bool p_reset); Error save_to_cache(); Error update_cache(); diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index c49e15a3a0..045904fb5d 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -178,6 +178,18 @@ void StreamPeer::put_64(int64_t p_val) { put_data(buf, 8); } +void StreamPeer::put_half(float p_val) { + uint8_t buf[2]; + + encode_half(p_val, buf); + uint16_t *p16 = (uint16_t *)buf; + if (big_endian) { + *p16 = BSWAP16(*p16); + } + + put_data(buf, 2); +} + void StreamPeer::put_float(float p_val) { uint8_t buf[4]; @@ -223,13 +235,13 @@ void StreamPeer::put_var(const Variant &p_variant, bool p_full_objects) { } uint8_t StreamPeer::get_u8() { - uint8_t buf[1]; + uint8_t buf[1] = {}; get_data(buf, 1); return buf[0]; } int8_t StreamPeer::get_8() { - uint8_t buf[1]; + uint8_t buf[1] = {}; get_data(buf, 1); return buf[0]; } @@ -294,6 +306,18 @@ int64_t StreamPeer::get_64() { return r; } +float StreamPeer::get_half() { + uint8_t buf[2]; + get_data(buf, 2); + + uint16_t *p16 = (uint16_t *)buf; + if (big_endian) { + *p16 = BSWAP16(*p16); + } + + return decode_half(buf); +} + float StreamPeer::get_float() { uint8_t buf[4]; get_data(buf, 4); @@ -385,6 +409,7 @@ void StreamPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("put_u32", "value"), &StreamPeer::put_u32); ClassDB::bind_method(D_METHOD("put_64", "value"), &StreamPeer::put_64); ClassDB::bind_method(D_METHOD("put_u64", "value"), &StreamPeer::put_u64); + ClassDB::bind_method(D_METHOD("put_half", "value"), &StreamPeer::put_half); ClassDB::bind_method(D_METHOD("put_float", "value"), &StreamPeer::put_float); ClassDB::bind_method(D_METHOD("put_double", "value"), &StreamPeer::put_double); ClassDB::bind_method(D_METHOD("put_string", "value"), &StreamPeer::put_string); @@ -399,6 +424,7 @@ void StreamPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_u32"), &StreamPeer::get_u32); ClassDB::bind_method(D_METHOD("get_64"), &StreamPeer::get_64); ClassDB::bind_method(D_METHOD("get_u64"), &StreamPeer::get_u64); + ClassDB::bind_method(D_METHOD("get_half"), &StreamPeer::get_half); ClassDB::bind_method(D_METHOD("get_float"), &StreamPeer::get_float); ClassDB::bind_method(D_METHOD("get_double"), &StreamPeer::get_double); ClassDB::bind_method(D_METHOD("get_string", "bytes"), &StreamPeer::get_string, DEFVAL(-1)); diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 29cdb82615..44bbfbf1d5 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -73,6 +73,7 @@ public: void put_u32(uint32_t p_val); void put_64(int64_t p_val); void put_u64(uint64_t p_val); + void put_half(float p_val); void put_float(float p_val); void put_double(double p_val); void put_string(const String &p_string); @@ -87,6 +88,7 @@ public: int32_t get_32(); uint64_t get_u64(); int64_t get_64(); + float get_half(); float get_float(); double get_double(); String get_string(int p_bytes = -1); diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index f2b3d5e56a..d69d1f1b29 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -112,7 +112,7 @@ Ref<StreamPeerTCP> TCPServer::take_connection() { return conn; } - conn = Ref<StreamPeerTCP>(memnew(StreamPeerTCP)); + conn.instantiate(); conn->accept_socket(ns, ip, port); return conn; } diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index 578cd91c52..1761d6fa23 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -31,7 +31,6 @@ #include "translation_loader_po.h" #include "core/io/file_access.h" -#include "core/string/translation.h" #include "core/string/translation_po.h" Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) { @@ -109,7 +108,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ // Record plural rule. int p_start = config.find("Plural-Forms"); if (p_start != -1) { - int p_end = config.find("\n", p_start); + int p_end = config.find_char('\n', p_start); translation->set_plural_rule(config.substr(p_start, p_end - p_start)); } } else { @@ -170,14 +169,14 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ // If we reached last line and it's not a content line, break, otherwise let processing that last loop if (is_eof && l.is_empty()) { if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) { - ERR_FAIL_V_MSG(Ref<Resource>(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line)); + ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Unexpected EOF while reading PO file at: %s:%d.", path, line)); } else { break; } } if (l.begins_with("msgctxt")) { - ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, Ref<Resource>(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, Ref<Resource>(), vformat("Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: %s:%d.", path, line)); // In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read // and set "entered_context" to true to prevent adding twice. @@ -185,7 +184,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ if (status == STATUS_READING_STRING) { translation->add_message(msg_id, msg_str, msg_context); } else if (status == STATUS_READING_PLURAL) { - ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), vformat("Number of 'msgstr[]' doesn't match with number of plural forms: %s:%d.", path, line)); translation->add_plural_message(msg_id, msgs_plural, msg_context); } } @@ -197,9 +196,9 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ if (l.begins_with("msgid_plural")) { if (plural_forms == 0) { - ERR_FAIL_V_MSG(Ref<Resource>(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line)); + ERR_FAIL_V_MSG(Ref<Resource>(), vformat("PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: %s:%d.", path, line)); } else if (status != STATUS_READING_ID) { - ERR_FAIL_V_MSG(Ref<Resource>(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line)); + ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: %s:%d.", path, line)); } // We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already. // We just have to reset variables related to plurals for "msgstr[]" later on. @@ -209,14 +208,14 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ msgs_plural.resize(plural_forms); status = STATUS_READING_PLURAL; } else if (l.begins_with("msgid")) { - ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, Ref<Resource>(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, Ref<Resource>(), vformat("Unexpected 'msgid', was expecting 'msgstr' while parsing: %s:%d.", path, line)); if (!msg_id.is_empty()) { if (!skip_this && !entered_context) { if (status == STATUS_READING_STRING) { translation->add_message(msg_id, msg_str, msg_context); } else if (status == STATUS_READING_PLURAL) { - ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), vformat("Number of 'msgstr[]' doesn't match with number of plural forms: %s:%d.", path, line)); translation->add_plural_message(msg_id, msgs_plural, msg_context); } } @@ -225,7 +224,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ // Record plural rule. int p_start = config.find("Plural-Forms"); if (p_start != -1) { - int p_end = config.find("\n", p_start); + int p_end = config.find_char('\n', p_start); translation->set_plural_rule(config.substr(p_start, p_end - p_start)); plural_forms = translation->get_plural_forms(); } @@ -245,11 +244,11 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ } if (l.begins_with("msgstr[")) { - ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, Ref<Resource>(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, Ref<Resource>(), vformat("Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: %s:%d.", path, line)); plural_index++; // Increment to add to the next slot in vector msgs_plural. l = l.substr(9, l.length()).strip_edges(); } else if (l.begins_with("msgstr")) { - ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, Ref<Resource>(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, Ref<Resource>(), vformat("Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: %s:%d.", path, line)); l = l.substr(6, l.length()).strip_edges(); status = STATUS_READING_STRING; } @@ -262,7 +261,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ continue; // Nothing to read or comment. } - ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, Ref<Resource>(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, Ref<Resource>(), vformat("Invalid line '%s' while parsing: %s:%d.", l, path, line)); l = l.substr(1, l.length()); // Find final quote, ignoring escaped ones (\"). @@ -284,7 +283,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ escape_next = false; } - ERR_FAIL_COND_V_MSG(end_pos == -1, Ref<Resource>(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(end_pos == -1, Ref<Resource>(), vformat("Expected '\"' at end of message while parsing: %s:%d.", path, line)); l = l.substr(0, end_pos); l = l.c_unescape(); @@ -296,7 +295,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ } else if (status == STATUS_READING_CONTEXT) { msg_context += l; } else if (status == STATUS_READING_PLURAL && plural_index >= 0) { - ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, Ref<Resource>(), "Unexpected plural form while parsing: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, Ref<Resource>(), vformat("Unexpected plural form while parsing: %s:%d.", path, line)); msgs_plural.write[plural_index] = msgs_plural[plural_index] + l; } @@ -314,18 +313,18 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_ } } else if (status == STATUS_READING_PLURAL) { if (!skip_this && !msg_id.is_empty()) { - ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line)); + ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), vformat("Number of 'msgstr[]' doesn't match with number of plural forms: %s:%d.", path, line)); translation->add_plural_message(msg_id, msgs_plural, msg_context); } } } - ERR_FAIL_COND_V_MSG(config.is_empty(), Ref<Resource>(), "No config found in file: " + path + "."); + ERR_FAIL_COND_V_MSG(config.is_empty(), Ref<Resource>(), vformat("No config found in file: '%s'.", path)); Vector<String> configs = config.split("\n"); for (int i = 0; i < configs.size(); i++) { String c = configs[i].strip_edges(); - int p = c.find(":"); + int p = c.find_char(':'); if (p == -1) { continue; } @@ -350,7 +349,7 @@ Ref<Resource> TranslationLoaderPO::load(const String &p_path, const String &p_or } Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(f.is_null(), Ref<Resource>(), "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(f.is_null(), Ref<Resource>(), vformat("Cannot open file '%s'.", p_path)); return load_translation(f, r_error); } @@ -361,7 +360,7 @@ void TranslationLoaderPO::get_recognized_extensions(List<String> *p_extensions) } bool TranslationLoaderPO::handles_type(const String &p_type) const { - return (p_type == "Translation"); + return (p_type == "Translation") || (p_type == "TranslationPO"); } String TranslationLoaderPO::get_resource_type(const String &p_path) const { diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 06888c7cda..6923ca1269 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -429,7 +429,7 @@ String XMLParser::get_named_attribute_value(const String &p_name) const { } } - ERR_FAIL_COND_V_MSG(idx < 0, "", "Attribute not found: " + p_name + "."); + ERR_FAIL_COND_V_MSG(idx < 0, "", vformat("Attribute not found: '%s'.", p_name)); return attributes[idx].value; } @@ -493,7 +493,7 @@ Error XMLParser::open(const String &p_path) { Error err; Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot open file '%s'.", p_path)); length = file->get_length(); ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT); diff --git a/core/math/basis.h b/core/math/basis.h index 236d666103..2d4994de19 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -223,7 +223,7 @@ struct [[nodiscard]] Basis { static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false); - Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }; + Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); } Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); } Basis(const Vector3 &p_axis, real_t p_angle) { set_axis_angle(p_axis, p_angle); } diff --git a/core/math/bvh_logic.inc b/core/math/bvh_logic.inc index dd3b135bb5..aaa91bc9d3 100644 --- a/core/math/bvh_logic.inc +++ b/core/math/bvh_logic.inc @@ -1,4 +1,3 @@ - // for slow incremental optimization, we will periodically remove each // item from the tree and reinsert, to give it a chance to find a better position void _logic_item_remove_and_reinsert(uint32_t p_ref_id) { diff --git a/core/math/bvh_misc.inc b/core/math/bvh_misc.inc index 9b35a1d36d..ef1261a759 100644 --- a/core/math/bvh_misc.inc +++ b/core/math/bvh_misc.inc @@ -1,4 +1,3 @@ - int _handle_get_tree_id(BVHHandle p_handle) const { if (USE_PAIRS) { return _extra[p_handle.id()].tree_id; diff --git a/core/math/bvh_structs.inc b/core/math/bvh_structs.inc index d40c631ce2..6326cd63ef 100644 --- a/core/math/bvh_structs.inc +++ b/core/math/bvh_structs.inc @@ -1,4 +1,3 @@ - public: struct ItemRef { uint32_t tnode_id; // -1 is invalid diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 0692ece1e6..35303fe9ac 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1491,7 +1491,7 @@ Error Expression::parse(const String &p_expression, const Vector<String> &p_inpu } Variant Expression::execute(const Array &p_inputs, Object *p_base, bool p_show_error, bool p_const_calls_only) { - ERR_FAIL_COND_V_MSG(error_set, Variant(), "There was previously a parse error: " + error_str + "."); + ERR_FAIL_COND_V_MSG(error_set, Variant(), vformat("There was previously a parse error: %s.", error_str)); execution_error = false; Variant output; diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp index a49826958a..376d5d0b43 100644 --- a/core/math/geometry_2d.cpp +++ b/core/math/geometry_2d.cpp @@ -76,7 +76,7 @@ struct _AtlasWorkRect { Size2i s; Point2i p; int idx = 0; - _FORCE_INLINE_ bool operator<(const _AtlasWorkRect &p_r) const { return s.width > p_r.s.width; }; + _FORCE_INLINE_ bool operator<(const _AtlasWorkRect &p_r) const { return s.width > p_r.s.width; } }; struct _AtlasWorkRectResult { diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h index 83ebdc5a84..abd395d8df 100644 --- a/core/math/geometry_2d.h +++ b/core/math/geometry_2d.h @@ -451,17 +451,17 @@ public: return H; } - static Vector<Point2i> bresenham_line(const Point2i &p_start, const Point2i &p_end) { + static Vector<Point2i> bresenham_line(const Point2i &p_from, const Point2i &p_to) { Vector<Point2i> points; - Vector2i delta = (p_end - p_start).abs() * 2; - Vector2i step = (p_end - p_start).sign(); - Vector2i current = p_start; + Vector2i delta = (p_to - p_from).abs() * 2; + Vector2i step = (p_to - p_from).sign(); + Vector2i current = p_from; if (delta.x > delta.y) { int err = delta.x / 2; - for (; current.x != p_end.x; current.x += step.x) { + for (; current.x != p_to.x; current.x += step.x) { points.push_back(current); err -= delta.y; @@ -473,7 +473,7 @@ public: } else { int err = delta.y / 2; - for (; current.y != p_end.y; current.y += step.y) { + for (; current.y != p_to.y; current.y += step.y) { points.push_back(current); err -= delta.x; diff --git a/core/math/plane.h b/core/math/plane.h index 6529fea60a..65783ff4cf 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -40,7 +40,7 @@ struct [[nodiscard]] Plane { real_t d = 0; void set_normal(const Vector3 &p_normal); - _FORCE_INLINE_ Vector3 get_normal() const { return normal; }; + _FORCE_INLINE_ Vector3 get_normal() const { return normal; } void normalize(); Plane normalized() const; diff --git a/core/math/projection.cpp b/core/math/projection.cpp index d0ca7c5684..4a0faef08f 100644 --- a/core/math/projection.cpp +++ b/core/math/projection.cpp @@ -596,101 +596,229 @@ Projection Projection::inverse() const { } void Projection::invert() { - int i, j, k; - int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */ - real_t pvt_val; /* Value of current pivot element */ - real_t hold; /* Temporary storage */ - real_t determinant = 1.0f; - for (k = 0; k < 4; k++) { - /** Locate k'th pivot element **/ - pvt_val = columns[k][k]; /** Initialize for search **/ - pvt_i[k] = k; - pvt_j[k] = k; - for (i = k; i < 4; i++) { - for (j = k; j < 4; j++) { - if (Math::abs(columns[i][j]) > Math::abs(pvt_val)) { - pvt_i[k] = i; - pvt_j[k] = j; - pvt_val = columns[i][j]; - } - } - } - - /** Product of pivots, gives determinant when finished **/ - determinant *= pvt_val; - if (Math::is_zero_approx(determinant)) { - return; /** Matrix is singular (zero determinant). **/ - } - - /** "Interchange" rows (with sign change stuff) **/ - i = pvt_i[k]; - if (i != k) { /** If rows are different **/ - for (j = 0; j < 4; j++) { - hold = -columns[k][j]; - columns[k][j] = columns[i][j]; - columns[i][j] = hold; - } - } - - /** "Interchange" columns **/ - j = pvt_j[k]; - if (j != k) { /** If columns are different **/ - for (i = 0; i < 4; i++) { - hold = -columns[i][k]; - columns[i][k] = columns[i][j]; - columns[i][j] = hold; - } - } - - /** Divide column by minus pivot value **/ - for (i = 0; i < 4; i++) { - if (i != k) { - columns[i][k] /= (-pvt_val); - } - } - - /** Reduce the matrix **/ - for (i = 0; i < 4; i++) { - hold = columns[i][k]; - for (j = 0; j < 4; j++) { - if (i != k && j != k) { - columns[i][j] += hold * columns[k][j]; - } - } - } - - /** Divide row by pivot **/ - for (j = 0; j < 4; j++) { - if (j != k) { - columns[k][j] /= pvt_val; - } - } - - /** Replace pivot by reciprocal (at last we can touch it). **/ - columns[k][k] = 1.0 / pvt_val; + // Adapted from Mesa's `src/util/u_math.c` `util_invert_mat4x4`. + // MIT licensed. Copyright 2008 VMware, Inc. Authored by Jacques Leroy. + Projection temp; + real_t *out = (real_t *)temp.columns; + real_t *m = (real_t *)columns; + + real_t wtmp[4][8]; + real_t m0, m1, m2, m3, s; + real_t *r0, *r1, *r2, *r3; + +#define MAT(m, r, c) (m)[(c) * 4 + (r)] + + r0 = wtmp[0]; + r1 = wtmp[1]; + r2 = wtmp[2]; + r3 = wtmp[3]; + + r0[0] = MAT(m, 0, 0); + r0[1] = MAT(m, 0, 1); + r0[2] = MAT(m, 0, 2); + r0[3] = MAT(m, 0, 3); + r0[4] = 1.0; + r0[5] = 0.0; + r0[6] = 0.0; + r0[7] = 0.0; + + r1[0] = MAT(m, 1, 0); + r1[1] = MAT(m, 1, 1); + r1[2] = MAT(m, 1, 2); + r1[3] = MAT(m, 1, 3); + r1[5] = 1.0; + r1[4] = 0.0; + r1[6] = 0.0; + r1[7] = 0.0; + + r2[0] = MAT(m, 2, 0); + r2[1] = MAT(m, 2, 1); + r2[2] = MAT(m, 2, 2); + r2[3] = MAT(m, 2, 3); + r2[6] = 1.0; + r2[4] = 0.0; + r2[5] = 0.0; + r2[7] = 0.0; + + r3[0] = MAT(m, 3, 0); + r3[1] = MAT(m, 3, 1); + r3[2] = MAT(m, 3, 2); + r3[3] = MAT(m, 3, 3); + + r3[7] = 1.0; + r3[4] = 0.0; + r3[5] = 0.0; + r3[6] = 0.0; + + /* choose pivot - or die */ + if (Math::abs(r3[0]) > Math::abs(r2[0])) { + SWAP(r3, r2); + } + if (Math::abs(r2[0]) > Math::abs(r1[0])) { + SWAP(r2, r1); + } + if (Math::abs(r1[0]) > Math::abs(r0[0])) { + SWAP(r1, r0); + } + ERR_FAIL_COND(0.0 == r0[0]); + + /* eliminate first variable */ + m1 = r1[0] / r0[0]; + m2 = r2[0] / r0[0]; + m3 = r3[0] / r0[0]; + s = r0[1]; + r1[1] -= m1 * s; + r2[1] -= m2 * s; + r3[1] -= m3 * s; + s = r0[2]; + r1[2] -= m1 * s; + r2[2] -= m2 * s; + r3[2] -= m3 * s; + s = r0[3]; + r1[3] -= m1 * s; + r2[3] -= m2 * s; + r3[3] -= m3 * s; + s = r0[4]; + if (s != 0.0) { + r1[4] -= m1 * s; + r2[4] -= m2 * s; + r3[4] -= m3 * s; + } + s = r0[5]; + if (s != 0.0) { + r1[5] -= m1 * s; + r2[5] -= m2 * s; + r3[5] -= m3 * s; + } + s = r0[6]; + if (s != 0.0) { + r1[6] -= m1 * s; + r2[6] -= m2 * s; + r3[6] -= m3 * s; + } + s = r0[7]; + if (s != 0.0) { + r1[7] -= m1 * s; + r2[7] -= m2 * s; + r3[7] -= m3 * s; } - /* That was most of the work, one final pass of row/column interchange */ - /* to finish */ - for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/ - i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */ - if (i != k) { /* If rows are different */ - for (j = 0; j < 4; j++) { - hold = columns[k][j]; - columns[k][j] = -columns[i][j]; - columns[i][j] = hold; - } - } + /* choose pivot - or die */ + if (Math::abs(r3[1]) > Math::abs(r2[1])) { + SWAP(r3, r2); + } + if (Math::abs(r2[1]) > Math::abs(r1[1])) { + SWAP(r2, r1); + } + ERR_FAIL_COND(0.0 == r1[1]); + + /* eliminate second variable */ + m2 = r2[1] / r1[1]; + m3 = r3[1] / r1[1]; + r2[2] -= m2 * r1[2]; + r3[2] -= m3 * r1[2]; + r2[3] -= m2 * r1[3]; + r3[3] -= m3 * r1[3]; + s = r1[4]; + if (0.0 != s) { + r2[4] -= m2 * s; + r3[4] -= m3 * s; + } + s = r1[5]; + if (0.0 != s) { + r2[5] -= m2 * s; + r3[5] -= m3 * s; + } + s = r1[6]; + if (0.0 != s) { + r2[6] -= m2 * s; + r3[6] -= m3 * s; + } + s = r1[7]; + if (0.0 != s) { + r2[7] -= m2 * s; + r3[7] -= m3 * s; + } - j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */ - if (j != k) { /* If columns are different */ - for (i = 0; i < 4; i++) { - hold = columns[i][k]; - columns[i][k] = -columns[i][j]; - columns[i][j] = hold; - } - } + /* choose pivot - or die */ + if (Math::abs(r3[2]) > Math::abs(r2[2])) { + SWAP(r3, r2); } + ERR_FAIL_COND(0.0 == r2[2]); + + /* eliminate third variable */ + m3 = r3[2] / r2[2]; + r3[3] -= m3 * r2[3]; + r3[4] -= m3 * r2[4]; + r3[5] -= m3 * r2[5]; + r3[6] -= m3 * r2[6]; + r3[7] -= m3 * r2[7]; + + /* last check */ + ERR_FAIL_COND(0.0 == r3[3]); + + s = 1.0 / r3[3]; /* now back substitute row 3 */ + r3[4] *= s; + r3[5] *= s; + r3[6] *= s; + r3[7] *= s; + + m2 = r2[3]; /* now back substitute row 2 */ + s = 1.0 / r2[2]; + r2[4] = s * (r2[4] - r3[4] * m2); + r2[5] = s * (r2[5] - r3[5] * m2); + r2[6] = s * (r2[6] - r3[6] * m2); + r2[7] = s * (r2[7] - r3[7] * m2); + m1 = r1[3]; + r1[4] -= r3[4] * m1; + r1[5] -= r3[5] * m1; + r1[6] -= r3[6] * m1; + r1[7] -= r3[7] * m1; + m0 = r0[3]; + r0[4] -= r3[4] * m0; + r0[5] -= r3[5] * m0; + r0[6] -= r3[6] * m0; + r0[7] -= r3[7] * m0; + + m1 = r1[2]; /* now back substitute row 1 */ + s = 1.0 / r1[1]; + r1[4] = s * (r1[4] - r2[4] * m1); + r1[5] = s * (r1[5] - r2[5] * m1), + r1[6] = s * (r1[6] - r2[6] * m1); + r1[7] = s * (r1[7] - r2[7] * m1); + m0 = r0[2]; + r0[4] -= r2[4] * m0; + r0[5] -= r2[5] * m0; + r0[6] -= r2[6] * m0; + r0[7] -= r2[7] * m0; + + m0 = r0[1]; /* now back substitute row 0 */ + s = 1.0 / r0[0]; + r0[4] = s * (r0[4] - r1[4] * m0); + r0[5] = s * (r0[5] - r1[5] * m0), + r0[6] = s * (r0[6] - r1[6] * m0); + r0[7] = s * (r0[7] - r1[7] * m0); + + MAT(out, 0, 0) = r0[4]; + MAT(out, 0, 1) = r0[5]; + MAT(out, 0, 2) = r0[6]; + MAT(out, 0, 3) = r0[7]; + MAT(out, 1, 0) = r1[4]; + MAT(out, 1, 1) = r1[5]; + MAT(out, 1, 2) = r1[6]; + MAT(out, 1, 3) = r1[7]; + MAT(out, 2, 0) = r2[4]; + MAT(out, 2, 1) = r2[5]; + MAT(out, 2, 2) = r2[6]; + MAT(out, 2, 3) = r2[7]; + MAT(out, 3, 0) = r3[4]; + MAT(out, 3, 1) = r3[5]; + MAT(out, 3, 2) = r3[6]; + MAT(out, 3, 3) = r3[7]; + +#undef MAT + + *this = temp; } void Projection::flip_y() { diff --git a/core/math/rect2.cpp b/core/math/rect2.cpp index c55226a57e..7f77b0786c 100644 --- a/core/math/rect2.cpp +++ b/core/math/rect2.cpp @@ -283,7 +283,7 @@ next4: } Rect2::operator String() const { - return "[P: " + position.operator String() + ", S: " + size + "]"; + return "[P: " + position.operator String() + ", S: " + size.operator String() + "]"; } Rect2::operator Rect2i() const { diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index e86b97d6a8..0590ee8a37 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -203,7 +203,7 @@ bool Vector2::is_finite() const { } Vector2::operator String() const { - return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")"; + return "(" + String::num_real(x, true) + ", " + String::num_real(y, true) + ")"; } Vector2::operator Vector2i() const { diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 1e90002665..e18ac3b011 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -165,7 +165,7 @@ bool Vector3::is_finite() const { } Vector3::operator String() const { - return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")"; + return "(" + String::num_real(x, true) + ", " + String::num_real(y, true) + ", " + String::num_real(z, true) + ")"; } Vector3::operator Vector3i() const { diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 9826d73a9d..d48e1a3622 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -352,7 +352,7 @@ StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) StringName ClassDB::_get_parent_class(const StringName &p_class) { ClassInfo *ti = classes.getptr(p_class); - ERR_FAIL_NULL_V_MSG(ti, StringName(), "Cannot get class '" + String(p_class) + "'."); + ERR_FAIL_NULL_V_MSG(ti, StringName(), vformat("Cannot get class '%s'.", String(p_class))); return ti->inherits; } @@ -367,7 +367,7 @@ ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { ClassInfo *ti = classes.getptr(p_class); - ERR_FAIL_NULL_V_MSG(ti, API_NONE, "Cannot get class '" + String(p_class) + "'."); + ERR_FAIL_NULL_V_MSG(ti, API_NONE, vformat("Cannot get class '%s'.", String(p_class))); return ti->api; } @@ -390,7 +390,7 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { for (const StringName &E : class_list) { ClassInfo *t = classes.getptr(E); - ERR_FAIL_NULL_V_MSG(t, 0, "Cannot get class '" + String(E) + "'."); + ERR_FAIL_NULL_V_MSG(t, 0, vformat("Cannot get class '%s'.", String(E))); if (t->api != p_api || !t->exposed) { continue; } @@ -547,14 +547,14 @@ Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require ti = classes.getptr(compat_classes[p_class]); } } - ERR_FAIL_NULL_V_MSG(ti, nullptr, "Cannot get class '" + String(p_class) + "'."); - ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, "Class '" + String(p_class) + "' is disabled."); - ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, "Class '" + String(p_class) + "' or its base class cannot be instantiated."); + ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class))); + ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class))); + ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, vformat("Class '%s' or its base class cannot be instantiated.", String(p_class))); } #ifdef TOOLS_ENABLED if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) { - ERR_PRINT("Class '" + String(p_class) + "' can only be instantiated by editor."); + ERR_PRINT(vformat("Class '%s' can only be instantiated by editor.", String(p_class))); return nullptr; } #endif @@ -653,8 +653,8 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class) ti = classes.getptr(compat_classes[p_class]); } } - ERR_FAIL_NULL_V_MSG(ti, nullptr, "Cannot get class '" + String(p_class) + "'."); - ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, "Class '" + String(p_class) + "' is disabled."); + ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class))); + ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class))); } // Make a "fake" extension to act as a placeholder. @@ -734,9 +734,9 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName & ti = classes.getptr(compat_classes[p_class]); } } - ERR_FAIL_NULL_MSG(ti, "Cannot get class '" + String(p_class) + "'."); - ERR_FAIL_COND_MSG(ti->disabled, "Class '" + String(p_class) + "' is disabled."); - ERR_FAIL_NULL_MSG(ti->gdextension, "Class '" + String(p_class) + "' has no native extension."); + ERR_FAIL_NULL_MSG(ti, vformat("Cannot get class '%s'.", String(p_class))); + ERR_FAIL_COND_MSG(ti->disabled, vformat("Class '%s' is disabled.", String(p_class))); + ERR_FAIL_NULL_MSG(ti->gdextension, vformat("Class '%s' has no native extension.", String(p_class))); } p_object->_extension = ti->gdextension; @@ -750,69 +750,87 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName & } bool ClassDB::can_instantiate(const StringName &p_class) { - OBJTYPE_RLOCK; + String script_path; + { + OBJTYPE_RLOCK; - ClassInfo *ti = classes.getptr(p_class); - if (!ti) { - if (!ScriptServer::is_global_class(p_class)) { - ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'."); + ClassInfo *ti = classes.getptr(p_class); + if (!ti) { + if (!ScriptServer::is_global_class(p_class)) { + ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class))); + } + script_path = ScriptServer::get_global_class_path(p_class); + goto use_script; // Open the lock for resource loading. } - String path = ScriptServer::get_global_class_path(p_class); - Ref<Script> scr = ResourceLoader::load(path); - return scr.is_valid() && scr->is_valid() && !scr->is_abstract(); - } #ifdef TOOLS_ENABLED - if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) { - return false; - } + if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) { + return false; + } #endif - return _can_instantiate(ti); + return _can_instantiate(ti); + } + +use_script: + Ref<Script> scr = ResourceLoader::load(script_path); + return scr.is_valid() && scr->is_valid() && !scr->is_abstract(); } bool ClassDB::is_abstract(const StringName &p_class) { - OBJTYPE_RLOCK; + String script_path; + { + OBJTYPE_RLOCK; - ClassInfo *ti = classes.getptr(p_class); - if (!ti) { - if (!ScriptServer::is_global_class(p_class)) { - ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'."); + ClassInfo *ti = classes.getptr(p_class); + if (!ti) { + if (!ScriptServer::is_global_class(p_class)) { + ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class))); + } + script_path = ScriptServer::get_global_class_path(p_class); + goto use_script; // Open the lock for resource loading. } - String path = ScriptServer::get_global_class_path(p_class); - Ref<Script> scr = ResourceLoader::load(path); - return scr.is_valid() && scr->is_valid() && scr->is_abstract(); - } - if (ti->creation_func != nullptr) { - return false; - } - if (!ti->gdextension) { - return true; - } + if (ti->creation_func != nullptr) { + return false; + } + if (!ti->gdextension) { + return true; + } #ifndef DISABLE_DEPRECATED - return ti->gdextension->create_instance2 == nullptr && ti->gdextension->create_instance == nullptr; + return ti->gdextension->create_instance2 == nullptr && ti->gdextension->create_instance == nullptr; #else - return ti->gdextension->create_instance2 == nullptr; + return ti->gdextension->create_instance2 == nullptr; #endif // DISABLE_DEPRECATED + } + +use_script: + Ref<Script> scr = ResourceLoader::load(script_path); + return scr.is_valid() && scr->is_valid() && scr->is_abstract(); } bool ClassDB::is_virtual(const StringName &p_class) { - OBJTYPE_RLOCK; + String script_path; + { + OBJTYPE_RLOCK; - ClassInfo *ti = classes.getptr(p_class); - if (!ti) { - if (!ScriptServer::is_global_class(p_class)) { - ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'."); + ClassInfo *ti = classes.getptr(p_class); + if (!ti) { + if (!ScriptServer::is_global_class(p_class)) { + ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class))); + } + script_path = ScriptServer::get_global_class_path(p_class); + goto use_script; // Open the lock for resource loading. } - String path = ScriptServer::get_global_class_path(p_class); - Ref<Script> scr = ResourceLoader::load(path); - return scr.is_valid() && scr->is_valid() && scr->is_abstract(); - } #ifdef TOOLS_ENABLED - if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) { - return false; - } + if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) { + return false; + } #endif - return (_can_instantiate(ti) && ti->is_virtual); + return (_can_instantiate(ti) && ti->is_virtual); + } + +use_script: + Ref<Script> scr = ResourceLoader::load(script_path); + return scr.is_valid() && scr->is_valid() && scr->is_abstract(); } void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) { @@ -820,7 +838,7 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit const StringName &name = p_class; - ERR_FAIL_COND_MSG(classes.has(name), "Class '" + String(p_class) + "' already exists."); + ERR_FAIL_COND_MSG(classes.has(name), vformat("Class '%s' already exists.", String(p_class))); classes[name] = ClassInfo(); ClassInfo &ti = classes[name]; @@ -1328,7 +1346,7 @@ void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) #ifdef DEBUG_METHODS_ENABLED ClassInfo *check = type; while (check) { - ERR_FAIL_COND_MSG(check->signal_map.has(sname), "Class '" + String(p_class) + "' already has signal '" + String(sname) + "'."); + ERR_FAIL_COND_MSG(check->signal_map.has(sname), vformat("Class '%s' already has signal '%s'.", String(p_class), String(sname))); check = check->inherits_ptr; } #endif @@ -1442,10 +1460,10 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf mb_set = get_method(p_class, p_setter); #ifdef DEBUG_METHODS_ENABLED - ERR_FAIL_NULL_MSG(mb_set, "Invalid setter '" + p_class + "::" + p_setter + "' for property '" + p_pinfo.name + "'."); + ERR_FAIL_NULL_MSG(mb_set, vformat("Invalid setter '%s::%s' for property '%s'.", p_class, p_setter, p_pinfo.name)); int exp_args = 1 + (p_index >= 0 ? 1 : 0); - ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, "Invalid function for setter '" + p_class + "::" + p_setter + " for property '" + p_pinfo.name + "'."); + ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, vformat("Invalid function for setter '%s::%s' for property '%s'.", p_class, p_setter, p_pinfo.name)); #endif } @@ -1454,15 +1472,15 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf mb_get = get_method(p_class, p_getter); #ifdef DEBUG_METHODS_ENABLED - ERR_FAIL_NULL_MSG(mb_get, "Invalid getter '" + p_class + "::" + p_getter + "' for property '" + p_pinfo.name + "'."); + ERR_FAIL_NULL_MSG(mb_get, vformat("Invalid getter '%s::%s' for property '%s'.", p_class, p_getter, p_pinfo.name)); int exp_args = 0 + (p_index >= 0 ? 1 : 0); - ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, "Invalid function for getter '" + p_class + "::" + p_getter + "' for property: '" + p_pinfo.name + "'."); + ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, vformat("Invalid function for getter '%s::%s' for property '%s'.", p_class, p_getter, p_pinfo.name)); #endif } #ifdef DEBUG_METHODS_ENABLED - ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), "Object '" + p_class + "' already has property '" + p_pinfo.name + "'."); + ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), vformat("Object '%s' already has property '%s'.", p_class, p_pinfo.name)); #endif OBJTYPE_WLOCK @@ -1847,7 +1865,7 @@ void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_metho ClassInfo *type = classes.getptr(p_class); if (!type) { - ERR_FAIL_MSG("Couldn't bind custom method '" + p_method->get_name() + "' for instance '" + p_class + "'."); + ERR_FAIL_MSG(vformat("Couldn't bind custom method '%s' for instance '%s'.", p_method->get_name(), p_class)); } if (p_compatibility) { @@ -1857,7 +1875,7 @@ void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_metho if (type->method_map.has(p_method->get_name())) { // overloading not supported - ERR_FAIL_MSG("Method already bound '" + p_class + "::" + p_method->get_name() + "'."); + ERR_FAIL_MSG(vformat("Method already bound '%s::%s'.", p_class, p_method->get_name())); } #ifdef DEBUG_METHODS_ENABLED @@ -1888,7 +1906,7 @@ MethodBind *ClassDB::_bind_vararg_method(MethodBind *p_bind, const StringName &p if (type->method_map.has(p_name)) { memdelete(bind); // Overloading not supported - ERR_FAIL_V_MSG(nullptr, "Method already bound: " + instance_type + "::" + p_name + "."); + ERR_FAIL_V_MSG(nullptr, vformat("Method already bound: '%s::%s'.", instance_type, p_name)); } type->method_map[p_name] = bind; #ifdef DEBUG_METHODS_ENABLED @@ -1916,26 +1934,26 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_ #ifdef DEBUG_ENABLED - ERR_FAIL_COND_V_MSG(!p_compatibility && has_method(instance_type, mdname), nullptr, "Class " + String(instance_type) + " already has a method " + String(mdname) + "."); + ERR_FAIL_COND_V_MSG(!p_compatibility && has_method(instance_type, mdname), nullptr, vformat("Class '%s' already has a method '%s'.", String(instance_type), String(mdname))); #endif ClassInfo *type = classes.getptr(instance_type); if (!type) { memdelete(p_bind); - ERR_FAIL_V_MSG(nullptr, "Couldn't bind method '" + mdname + "' for instance '" + instance_type + "'."); + ERR_FAIL_V_MSG(nullptr, vformat("Couldn't bind method '%s' for instance '%s'.", mdname, instance_type)); } if (!p_compatibility && type->method_map.has(mdname)) { memdelete(p_bind); // overloading not supported - ERR_FAIL_V_MSG(nullptr, "Method already bound '" + instance_type + "::" + mdname + "'."); + ERR_FAIL_V_MSG(nullptr, vformat("Method already bound '%s::%s'.", instance_type, mdname)); } #ifdef DEBUG_METHODS_ENABLED if (method_name.args.size() > p_bind->get_argument_count()) { memdelete(p_bind); - ERR_FAIL_V_MSG(nullptr, "Method definition provides more arguments than the method actually has '" + instance_type + "::" + mdname + "'."); + ERR_FAIL_V_MSG(nullptr, vformat("Method definition provides more arguments than the method actually has '%s::%s'.", instance_type, mdname)); } p_bind->set_argument_names(method_name.args); @@ -1964,7 +1982,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_ } void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) { - ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'."); + ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class)); OBJTYPE_WLOCK; @@ -1979,7 +1997,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_ if (!p_object_core) { if (p_arg_names.size() != mi.arguments.size()) { - WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name); + WARN_PRINT(vformat("Mismatch argument name count for virtual method: '%s::%s'.", String(p_class), p_method.name)); } else { List<PropertyInfo>::Iterator itr = mi.arguments.begin(); for (int i = 0; i < p_arg_names.size(); ++itr, ++i) { @@ -1990,7 +2008,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_ if (classes[p_class].virtual_methods_map.has(p_method.name)) { // overloading not supported - ERR_FAIL_MSG("Virtual method already bound '" + String(p_class) + "::" + p_method.name + "'."); + ERR_FAIL_MSG(vformat("Virtual method already bound '%s::%s'.", String(p_class), p_method.name)); } classes[p_class].virtual_methods.push_back(mi); classes[p_class].virtual_methods_map[p_method.name] = mi; @@ -1999,7 +2017,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_ } void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance) { - ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'."); + ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class)); #ifdef DEBUG_METHODS_ENABLED @@ -2020,7 +2038,7 @@ void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p } void ClassDB::add_extension_class_virtual_method(const StringName &p_class, const GDExtensionClassVirtualMethodInfo *p_method_info) { - ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'."); + ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class)); #ifdef DEBUG_METHODS_ENABLED PackedStringArray arg_names; @@ -2044,7 +2062,7 @@ void ClassDB::add_extension_class_virtual_method(const StringName &p_class, cons void ClassDB::set_class_enabled(const StringName &p_class, bool p_enable) { OBJTYPE_WLOCK; - ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'."); + ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class)); classes[p_class].disabled = !p_enable; } @@ -2058,7 +2076,7 @@ bool ClassDB::is_class_enabled(const StringName &p_class) { } } - ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'."); + ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class))); return !ti->disabled; } @@ -2066,7 +2084,7 @@ bool ClassDB::is_class_exposed(const StringName &p_class) { OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); - ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'."); + ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class))); return ti->exposed; } @@ -2074,7 +2092,7 @@ bool ClassDB::is_class_reloadable(const StringName &p_class) { OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); - ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'."); + ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class))); return ti->reloadable; } @@ -2082,7 +2100,7 @@ bool ClassDB::is_class_runtime(const StringName &p_class) { OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); - ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'."); + ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class))); return ti->is_runtime; } @@ -2192,14 +2210,14 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con void ClassDB::register_extension_class(ObjectGDExtension *p_extension) { GLOBAL_LOCK_FUNCTION; - ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name)); - ERR_FAIL_COND_MSG(!classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name)); + ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), vformat("Class already registered: '%s'.", String(p_extension->class_name))); + ERR_FAIL_COND_MSG(!classes.has(p_extension->parent_class_name), vformat("Parent class name for extension class not found: '%s'.", String(p_extension->parent_class_name))); ClassInfo *parent = classes.getptr(p_extension->parent_class_name); #ifdef TOOLS_ENABLED // @todo This is a limitation of the current implementation, but it should be possible to remove. - ERR_FAIL_COND_MSG(p_extension->is_runtime && parent->gdextension && !parent->is_runtime, "Extension runtime class " + String(p_extension->class_name) + " cannot descend from " + parent->name + " which isn't also a runtime class"); + ERR_FAIL_COND_MSG(p_extension->is_runtime && parent->gdextension && !parent->is_runtime, vformat("Extension runtime class '%s' cannot descend from '%s' which isn't also a runtime class.", String(p_extension->class_name), parent->name)); #endif ClassInfo c; @@ -2215,7 +2233,7 @@ void ClassDB::register_extension_class(ObjectGDExtension *p_extension) { concrete_ancestor->gdextension != nullptr) { concrete_ancestor = concrete_ancestor->inherits_ptr; } - ERR_FAIL_NULL_MSG(concrete_ancestor->creation_func, "Extension class " + String(p_extension->class_name) + " cannot extend native abstract class " + String(concrete_ancestor->name)); + ERR_FAIL_NULL_MSG(concrete_ancestor->creation_func, vformat("Extension class '%s' cannot extend native abstract class '%s'.", String(p_extension->class_name), String(concrete_ancestor->name))); c.creation_func = concrete_ancestor->creation_func; } c.inherits = parent->name; @@ -2239,7 +2257,7 @@ void ClassDB::register_extension_class(ObjectGDExtension *p_extension) { void ClassDB::unregister_extension_class(const StringName &p_class, bool p_free_method_binds) { ClassInfo *c = classes.getptr(p_class); - ERR_FAIL_NULL_MSG(c, "Class '" + String(p_class) + "' does not exist."); + ERR_FAIL_NULL_MSG(c, vformat("Class '%s' does not exist.", String(p_class))); if (p_free_method_binds) { for (KeyValue<StringName, MethodBind *> &F : c->method_map) { memdelete(F.value); diff --git a/core/object/message_queue.h b/core/object/message_queue.h index 673eb3845b..64e244bda8 100644 --- a/core/object/message_queue.h +++ b/core/object/message_queue.h @@ -153,7 +153,7 @@ public: bool is_flushing() const; int get_max_buffer_usage() const; - CallQueue(Allocator *p_custom_allocator = 0, uint32_t p_max_pages = 8192, const String &p_error_text = String()); + CallQueue(Allocator *p_custom_allocator = nullptr, uint32_t p_max_pages = 8192, const String &p_error_text = String()); virtual ~CallQueue(); }; diff --git a/core/object/method_bind.h b/core/object/method_bind.h index 2f9a2d1679..e06eb1f8fa 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -109,7 +109,7 @@ public: _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } _FORCE_INLINE_ void set_instance_class(const StringName &p_class) { instance_class = p_class; } - _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; + _FORCE_INLINE_ int get_argument_count() const { return argument_count; } #ifdef TOOLS_ENABLED virtual bool is_valid() const { return true; } diff --git a/core/object/object.cpp b/core/object/object.cpp index b3a4ec6e2e..ef1ca8132c 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -750,7 +750,7 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) { Callable::CallError ce; const Variant ret = callp(p_method, argptrs, p_args.size(), ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(Variant(), "Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + "."); + ERR_FAIL_V_MSG(Variant(), vformat("Error calling method from 'callv': %s.", Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce))); } return ret; } @@ -999,7 +999,7 @@ void Object::set_meta(const StringName &p_name, const Variant &p_value) { if (E) { E->value = p_value; } else { - ERR_FAIL_COND_MSG(!p_name.operator String().is_valid_ascii_identifier(), "Invalid metadata identifier: '" + p_name + "'."); + ERR_FAIL_COND_MSG(!p_name.operator String().is_valid_ascii_identifier(), vformat("Invalid metadata identifier: '%s'.", p_name)); Variant *V = &metadata.insert(p_name, p_value)->value; const String &sname = p_name; @@ -1015,7 +1015,7 @@ Variant Object::get_meta(const StringName &p_name, const Variant &p_default) con if (p_default != Variant()) { return p_default; } else { - ERR_FAIL_V_MSG(Variant(), "The object does not have any 'meta' values with the key '" + p_name + "'."); + ERR_FAIL_V_MSG(Variant(), vformat("The object does not have any 'meta' values with the key '%s'.", p_name)); } } return metadata[p_name]; @@ -1071,8 +1071,8 @@ void Object::get_meta_list(List<StringName> *p_list) const { void Object::add_user_signal(const MethodInfo &p_signal) { ERR_FAIL_COND_MSG(p_signal.name.is_empty(), "Signal name cannot be empty."); - ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), "User signal's name conflicts with a built-in signal of '" + get_class_name() + "'."); - ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), "Trying to add already existing signal '" + p_signal.name + "'."); + ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), vformat("User signal's name conflicts with a built-in signal of '%s'.", get_class_name())); + ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), vformat("Trying to add already existing signal '%s'.", p_signal.name)); SignalData s; s.user = p_signal; signal_map[p_signal.name] = s; @@ -1137,7 +1137,7 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int #ifdef DEBUG_ENABLED bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_name); //check in script - ERR_FAIL_COND_V_MSG(!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name), ERR_UNAVAILABLE, "Can't emit non-existing signal " + String("\"") + p_name + "\"."); + ERR_FAIL_COND_V_MSG(!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name), ERR_UNAVAILABLE, vformat("Can't emit non-existing signal \"%s\".", p_name)); #endif //not connected? just return return ERR_UNAVAILABLE; @@ -1210,7 +1210,7 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD && target && !ClassDB::class_exists(target->get_class_name())) { //most likely object is not initialized yet, do not throw error. } else { - ERR_PRINT("Error calling from signal '" + String(p_name) + "' to callable: " + Variant::get_callable_error_text(callable, args, argc, ce) + "."); + ERR_PRINT(vformat("Error calling from signal '%s' to callable: %s.", String(p_name), Variant::get_callable_error_text(callable, args, argc, ce))); err = ERR_METHOD_NOT_FOUND; } } @@ -1371,15 +1371,15 @@ void Object::get_signals_connected_to_this(List<Connection> *p_connections) cons } Error Object::connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags) { - ERR_FAIL_COND_V_MSG(p_callable.is_null(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "': the provided callable is null."); + ERR_FAIL_COND_V_MSG(p_callable.is_null(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s': the provided callable is null.", p_signal)); if (p_callable.is_standard()) { // FIXME: This branch should probably removed in favor of the `is_valid()` branch, but there exist some classes // that call `connect()` before they are fully registered with ClassDB. Until all such classes can be found // and registered soon enough this branch is needed to allow `connect()` to succeed. - ERR_FAIL_NULL_V_MSG(p_callable.get_object(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "' to callable '" + p_callable + "': the callable object is null."); + ERR_FAIL_NULL_V_MSG(p_callable.get_object(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s' to callable '%s': the callable object is null.", p_signal, p_callable)); } else { - ERR_FAIL_COND_V_MSG(!p_callable.is_valid(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "': the provided callable is not valid: " + p_callable); + ERR_FAIL_COND_V_MSG(!p_callable.is_valid(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s': the provided callable is not valid: '%s'.", p_signal, p_callable)); } SignalData *s = signal_map.getptr(p_signal); @@ -1400,7 +1400,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui #endif } - ERR_FAIL_COND_V_MSG(!signal_is_valid, ERR_INVALID_PARAMETER, "In Object of type '" + String(get_class()) + "': Attempt to connect nonexistent signal '" + p_signal + "' to callable '" + p_callable + "'."); + ERR_FAIL_COND_V_MSG(!signal_is_valid, ERR_INVALID_PARAMETER, vformat("In Object of type '%s': Attempt to connect nonexistent signal '%s' to callable '%s'.", String(get_class()), p_signal, p_callable)); signal_map[p_signal] = SignalData(); s = &signal_map[p_signal]; @@ -1412,7 +1412,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui s->slot_map[*p_callable.get_base_comparator()].reference_count++; return OK; } else { - ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Signal '" + p_signal + "' is already connected to given callable '" + p_callable + "' in that object."); + ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("Signal '%s' is already connected to given callable '%s' in that object.", p_signal, p_callable)); } } @@ -1439,7 +1439,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui } bool Object::is_connected(const StringName &p_signal, const Callable &p_callable) const { - ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, "Cannot determine if connected to '" + p_signal + "': the provided callable is null."); // Should use `is_null`, see note in `connect` about the use of `is_valid`. + ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, vformat("Cannot determine if connected to '%s': the provided callable is null.", p_signal)); // Should use `is_null`, see note in `connect` about the use of `is_valid`. const SignalData *s = signal_map.getptr(p_signal); if (!s) { bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal); @@ -1451,7 +1451,7 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable return false; } - ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + "."); + ERR_FAIL_V_MSG(false, vformat("Nonexistent signal: '%s'.", p_signal)); } return s->slot_map.has(*p_callable.get_base_comparator()); @@ -1469,7 +1469,7 @@ bool Object::has_connections(const StringName &p_signal) const { return false; } - ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + "."); + ERR_FAIL_V_MSG(false, vformat("Nonexistent signal: '%s'.", p_signal)); } return !s->slot_map.is_empty(); @@ -1480,17 +1480,17 @@ void Object::disconnect(const StringName &p_signal, const Callable &p_callable) } bool Object::_disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force) { - ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, "Cannot disconnect from '" + p_signal + "': the provided callable is null."); // Should use `is_null`, see note in `connect` about the use of `is_valid`. + ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, vformat("Cannot disconnect from '%s': the provided callable is null.", p_signal)); // Should use `is_null`, see note in `connect` about the use of `is_valid`. SignalData *s = signal_map.getptr(p_signal); if (!s) { bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) || (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)); - ERR_FAIL_COND_V_MSG(signal_is_valid, false, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. Signal: '" + p_signal + "', callable: '" + p_callable + "'."); + ERR_FAIL_COND_V_MSG(signal_is_valid, false, vformat("Attempt to disconnect a nonexistent connection from '%s'. Signal: '%s', callable: '%s'.", to_string(), p_signal, p_callable)); } - ERR_FAIL_NULL_V_MSG(s, false, vformat("Disconnecting nonexistent signal '%s' in %s.", p_signal, to_string())); + ERR_FAIL_NULL_V_MSG(s, false, vformat("Disconnecting nonexistent signal '%s' in '%s'.", p_signal, to_string())); - ERR_FAIL_COND_V_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), false, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. Signal: '" + p_signal + "', callable: '" + p_callable + "'."); + ERR_FAIL_COND_V_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), false, vformat("Attempt to disconnect a nonexistent connection from '%s'. Signal: '%s', callable: '%s'.", to_string(), p_signal, p_callable)); SignalData::Slot *slot = &s->slot_map[*p_callable.get_base_comparator()]; @@ -2128,7 +2128,7 @@ Object::~Object() { if (_emitting) { //@todo this may need to actually reach the debugger prioritarily somehow because it may crash before - ERR_PRINT("Object " + to_string() + " was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes."); + ERR_PRINT(vformat("Object '%s' was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes.", to_string())); } // Drop all connections to the signals of this object. diff --git a/core/object/object.h b/core/object/object.h index 110d2790c5..11b94a7fbf 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -88,6 +88,7 @@ enum PropertyHint { PROPERTY_HINT_LAYERS_AVOIDANCE, PROPERTY_HINT_DICTIONARY_TYPE, PROPERTY_HINT_TOOL_BUTTON, + PROPERTY_HINT_ONESHOT, ///< the property will be changed by self after setting, such as AudioStreamPlayer.playing, Particles.emitting. PROPERTY_HINT_MAX, }; @@ -685,22 +686,22 @@ protected: _ALWAYS_INLINE_ const ObjectGDExtension *_get_extension() const { return _extension; } _ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance() const { return _extension_instance; } virtual void _initialize_classv() { initialize_class(); } - virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; }; - virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; }; - virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const {}; - virtual void _validate_propertyv(PropertyInfo &p_property) const {}; - virtual bool _property_can_revertv(const StringName &p_name) const { return false; }; - virtual bool _property_get_revertv(const StringName &p_name, Variant &r_property) const { return false; }; + virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; } + virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; } + virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const {} + virtual void _validate_propertyv(PropertyInfo &p_property) const {} + virtual bool _property_can_revertv(const StringName &p_name) const { return false; } + virtual bool _property_get_revertv(const StringName &p_name, Variant &r_property) const { return false; } virtual void _notificationv(int p_notification, bool p_reversed) {} static void _bind_methods(); static void _bind_compatibility_methods() {} - bool _set(const StringName &p_name, const Variant &p_property) { return false; }; - bool _get(const StringName &p_name, Variant &r_property) const { return false; }; - void _get_property_list(List<PropertyInfo> *p_list) const {}; - void _validate_property(PropertyInfo &p_property) const {}; - bool _property_can_revert(const StringName &p_name) const { return false; }; - bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; }; + bool _set(const StringName &p_name, const Variant &p_property) { return false; } + bool _get(const StringName &p_name, Variant &r_property) const { return false; } + void _get_property_list(List<PropertyInfo> *p_list) const {} + void _validate_property(PropertyInfo &p_property) const {} + bool _property_can_revert(const StringName &p_name) const { return false; } + bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; } void _notification(int p_notification) {} _FORCE_INLINE_ static void (*_get_bind_methods())() { diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index c5856a8a81..542cb2b24d 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -239,9 +239,9 @@ Error ScriptServer::register_language(ScriptLanguage *p_language) { ERR_FAIL_COND_V_MSG(_language_count >= MAX_LANGUAGES, ERR_UNAVAILABLE, "Script languages limit has been reach, cannot register more."); for (int i = 0; i < _language_count; i++) { const ScriptLanguage *other_language = _languages[i]; - ERR_FAIL_COND_V_MSG(other_language->get_extension() == p_language->get_extension(), ERR_ALREADY_EXISTS, "A script language with extension '" + p_language->get_extension() + "' is already registered."); - ERR_FAIL_COND_V_MSG(other_language->get_name() == p_language->get_name(), ERR_ALREADY_EXISTS, "A script language with name '" + p_language->get_name() + "' is already registered."); - ERR_FAIL_COND_V_MSG(other_language->get_type() == p_language->get_type(), ERR_ALREADY_EXISTS, "A script language with type '" + p_language->get_type() + "' is already registered."); + ERR_FAIL_COND_V_MSG(other_language->get_extension() == p_language->get_extension(), ERR_ALREADY_EXISTS, vformat("A script language with extension '%s' is already registered.", p_language->get_extension())); + ERR_FAIL_COND_V_MSG(other_language->get_name() == p_language->get_name(), ERR_ALREADY_EXISTS, vformat("A script language with name '%s' is already registered.", p_language->get_name())); + ERR_FAIL_COND_V_MSG(other_language->get_type() == p_language->get_type(), ERR_ALREADY_EXISTS, vformat("A script language with type '%s' is already registered.", p_language->get_type())); } _languages[_language_count++] = p_language; return OK; diff --git a/core/object/script_language.h b/core/object/script_language.h index 3ddfbb3e7d..31d6638e58 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -446,8 +446,8 @@ public: virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override; virtual void validate_property(PropertyInfo &p_property) const override {} - virtual bool property_can_revert(const StringName &p_name) const override { return false; }; - virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override { return false; }; + virtual bool property_can_revert(const StringName &p_name) const override { return false; } + virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override { return false; } virtual void get_method_list(List<MethodInfo> *p_list) const override; virtual bool has_method(const StringName &p_method) const override; diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp index 03537dbeb1..7126852a5a 100644 --- a/core/object/undo_redo.cpp +++ b/core/object/undo_redo.cpp @@ -364,7 +364,7 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E, bool p_execu Variant ret; op.callable.callp(nullptr, 0, ret, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT("Error calling UndoRedo method operation '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, nullptr, 0, ce)); + ERR_PRINT(vformat("Error calling UndoRedo method operation '%s': %s.", String(op.name), Variant::get_call_error_text(obj, op.name, nullptr, 0, ce))); } #ifdef TOOLS_ENABLED Resource *res = Object::cast_to<Resource>(obj); diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h index 62296ac040..58e86e3e48 100644 --- a/core/object/worker_thread_pool.h +++ b/core/object/worker_thread_pool.h @@ -258,7 +258,13 @@ public: bool is_group_task_completed(GroupID p_group) const; void wait_for_group_task_completion(GroupID p_group); - _FORCE_INLINE_ int get_thread_count() const { return threads.size(); } + _FORCE_INLINE_ int get_thread_count() const { +#ifdef THREADS_ENABLED + return threads.size(); +#else + return 1; +#endif + } static WorkerThreadPool *get_singleton() { return singleton; } static int get_thread_index(); diff --git a/core/os/os.cpp b/core/os/os.cpp index 642de11a9f..59a0579ce3 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -352,7 +352,7 @@ void OS::ensure_user_data_dir() { Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Error err = da->make_dir_recursive(dd); - ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + "."); + ERR_FAIL_COND_MSG(err != OK, vformat("Error attempting to create data dir: %s.", dd)); } String OS::get_model_name() const { @@ -439,6 +439,11 @@ bool OS::has_feature(const String &p_feature) { } #if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64) #if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) +#if defined(MACOS_ENABLED) + if (p_feature == "universal") { + return true; + } +#endif if (p_feature == "x86_64") { return true; } @@ -452,6 +457,11 @@ bool OS::has_feature(const String &p_feature) { } #elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) #if defined(__aarch64__) || defined(_M_ARM64) +#if defined(MACOS_ENABLED) + if (p_feature == "universal") { + return true; + } +#endif if (p_feature == "arm64") { return true; } diff --git a/core/os/os.h b/core/os/os.h index 30d2a4266f..ffdb905aba 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -32,7 +32,6 @@ #define OS_H #include "core/config/engine.h" -#include "core/io/image.h" #include "core/io/logger.h" #include "core/io/remote_filesystem_client.h" #include "core/os/time_enums.h" @@ -95,7 +94,15 @@ public: enum RenderThreadMode { RENDER_THREAD_UNSAFE, RENDER_THREAD_SAFE, - RENDER_SEPARATE_THREAD + RENDER_SEPARATE_THREAD, + }; + + enum StdHandleType { + STD_HANDLE_INVALID, + STD_HANDLE_CONSOLE, + STD_HANDLE_FILE, + STD_HANDLE_PIPE, + STD_HANDLE_UNKNOWN, }; protected: @@ -147,7 +154,12 @@ public: void print_rich(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; - virtual String get_stdin_string() = 0; + virtual String get_stdin_string(int64_t p_buffer_size = 1024) = 0; + virtual PackedByteArray get_stdin_buffer(int64_t p_buffer_size = 1024) = 0; + + virtual StdHandleType get_stdin_type() const { return STD_HANDLE_UNKNOWN; } + virtual StdHandleType get_stdout_type() const { return STD_HANDLE_UNKNOWN; } + virtual StdHandleType get_stderr_type() const { return STD_HANDLE_UNKNOWN; } virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) = 0; // Should return cryptographically-safe random bytes. virtual String get_system_ca_certificates() { return ""; } // Concatenated certificates in PEM format. @@ -177,14 +189,14 @@ public: void set_delta_smoothing(bool p_enabled); bool is_delta_smoothing_enabled() const; - virtual Vector<String> get_system_fonts() const { return Vector<String>(); }; - virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return String(); }; - virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return Vector<String>(); }; + virtual Vector<String> get_system_fonts() const { return Vector<String>(); } + virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return String(); } + virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return Vector<String>(); } virtual String get_executable_path() const; virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) = 0; virtual Dictionary execute_with_pipe(const String &p_path, const List<String> &p_arguments, bool p_blocking = true) { return Dictionary(); } virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) = 0; - virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) { return create_process(get_executable_path(), p_arguments, r_child_id); }; + virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) { return create_process(get_executable_path(), p_arguments, r_child_id); } virtual Error kill(const ProcessID &p_pid) = 0; virtual int get_process_id() const; virtual bool is_process_running(const ProcessID &p_pid) const = 0; diff --git a/core/os/spin_lock.h b/core/os/spin_lock.h index d386cd5890..8c2d5667ff 100644 --- a/core/os/spin_lock.h +++ b/core/os/spin_lock.h @@ -33,6 +33,10 @@ #include "core/typedefs.h" +#ifdef _MSC_VER +#include <intrin.h> +#endif + #if defined(__APPLE__) #include <os/lock.h> @@ -52,19 +56,52 @@ public: #else +#include "core/os/thread.h" + #include <atomic> -class SpinLock { - mutable std::atomic_flag locked = ATOMIC_FLAG_INIT; +_ALWAYS_INLINE_ static void _cpu_pause() { +#if defined(_MSC_VER) +// ----- MSVC. +#if defined(_M_ARM) || defined(_M_ARM64) // ARM. + __yield(); +#elif defined(_M_IX86) || defined(_M_X64) // x86. + _mm_pause(); +#endif +#elif defined(__GNUC__) || defined(__clang__) +// ----- GCC/Clang. +#if defined(__i386__) || defined(__x86_64__) // x86. + __builtin_ia32_pause(); +#elif defined(__arm__) || defined(__aarch64__) // ARM. + asm volatile("yield"); +#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) // PowerPC. + asm volatile("or 27,27,27"); +#elif defined(__riscv) // RISC-V. + asm volatile(".insn i 0x0F, 0, x0, x0, 0x010"); +#endif +#endif +} + +static_assert(std::atomic_bool::is_always_lock_free); + +class alignas(Thread::CACHE_LINE_BYTES) SpinLock { + mutable std::atomic<bool> locked = ATOMIC_VAR_INIT(false); public: _ALWAYS_INLINE_ void lock() const { - while (locked.test_and_set(std::memory_order_acquire)) { - // Continue. + while (true) { + bool expected = false; + if (locked.compare_exchange_weak(expected, true, std::memory_order_acquire, std::memory_order_relaxed)) { + break; + } + do { + _cpu_pause(); + } while (locked.load(std::memory_order_relaxed)); } } + _ALWAYS_INLINE_ void unlock() const { - locked.clear(std::memory_order_release); + locked.store(false, std::memory_order_release); } }; diff --git a/core/os/thread.h b/core/os/thread.h index a0ecc24c91..1c442b41f6 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -42,6 +42,8 @@ #include "core/templates/safe_refcount.h" #include "core/typedefs.h" +#include <new> + #ifdef MINGW_ENABLED #define MINGW_STDTHREAD_REDUNDANCY_WARNING #include "thirdparty/mingw-std-threads/mingw.thread.h" @@ -85,6 +87,20 @@ public: void (*term)() = nullptr; }; +#if defined(__cpp_lib_hardware_interference_size) && !defined(ANDROID_ENABLED) // This would be OK with NDK >= 26. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winterference-size" +#endif + static constexpr size_t CACHE_LINE_BYTES = std::hardware_destructive_interference_size; +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif +#else + // At a negligible memory cost, we use a conservatively high value. + static constexpr size_t CACHE_LINE_BYTES = 128; +#endif + private: friend class Main; @@ -135,6 +151,8 @@ public: typedef uint64_t ID; + static constexpr size_t CACHE_LINE_BYTES = sizeof(void *); + enum : ID { UNASSIGNED_ID = 0, MAIN_ID = 1 diff --git a/core/string/char_range.inc b/core/string/char_range.inc index 2b081b96de..efae757802 100644 --- a/core/string/char_range.inc +++ b/core/string/char_range.inc @@ -33,14 +33,17 @@ #include "core/typedefs.h" +// Unicode Derived Core Properties +// Source: https://www.unicode.org/Public/16.0.0/ucd/DerivedCoreProperties.txt + struct CharRange { char32_t start; char32_t end; }; -inline constexpr CharRange xid_start[] = { +constexpr inline CharRange xid_start[] = { { 0x41, 0x5a }, - { 0x5f, 0x5f }, + { 0x5f, 0x5f }, // Underscore technically isn't in XID_Start, but for our purposes it's included. { 0x61, 0x7a }, { 0xaa, 0xaa }, { 0xb5, 0xb5 }, @@ -54,7 +57,7 @@ inline constexpr CharRange xid_start[] = { { 0x2ee, 0x2ee }, { 0x370, 0x374 }, { 0x376, 0x377 }, - { 0x37a, 0x37d }, + { 0x37b, 0x37d }, { 0x37f, 0x37f }, { 0x386, 0x386 }, { 0x388, 0x38a }, @@ -182,7 +185,7 @@ inline constexpr CharRange xid_start[] = { { 0xdbd, 0xdbd }, { 0xdc0, 0xdc6 }, { 0xe01, 0xe30 }, - { 0xe32, 0xe33 }, + { 0xe32, 0xe32 }, { 0xe40, 0xe46 }, { 0xe81, 0xe82 }, { 0xe84, 0xe84 }, @@ -190,7 +193,7 @@ inline constexpr CharRange xid_start[] = { { 0xe8c, 0xea3 }, { 0xea5, 0xea5 }, { 0xea7, 0xeb0 }, - { 0xeb2, 0xeb3 }, + { 0xeb2, 0xeb2 }, { 0xebd, 0xebd }, { 0xec0, 0xec4 }, { 0xec6, 0xec6 }, @@ -245,8 +248,7 @@ inline constexpr CharRange xid_start[] = { { 0x17d7, 0x17d7 }, { 0x17dc, 0x17dc }, { 0x1820, 0x1878 }, - { 0x1880, 0x1884 }, - { 0x1887, 0x18a8 }, + { 0x1880, 0x18a8 }, { 0x18aa, 0x18aa }, { 0x18b0, 0x18f5 }, { 0x1900, 0x191e }, @@ -265,7 +267,7 @@ inline constexpr CharRange xid_start[] = { { 0x1c00, 0x1c23 }, { 0x1c4d, 0x1c4f }, { 0x1c5a, 0x1c7d }, - { 0x1c80, 0x1c88 }, + { 0x1c80, 0x1c8a }, { 0x1c90, 0x1cba }, { 0x1cbd, 0x1cbf }, { 0x1ce9, 0x1cec }, @@ -330,7 +332,7 @@ inline constexpr CharRange xid_start[] = { { 0x3031, 0x3035 }, { 0x3038, 0x303c }, { 0x3041, 0x3096 }, - { 0x309b, 0x309f }, + { 0x309d, 0x309f }, { 0x30a1, 0x30fa }, { 0x30fc, 0x30ff }, { 0x3105, 0x312f }, @@ -348,10 +350,10 @@ inline constexpr CharRange xid_start[] = { { 0xa6a0, 0xa6ef }, { 0xa717, 0xa71f }, { 0xa722, 0xa788 }, - { 0xa78b, 0xa7ca }, + { 0xa78b, 0xa7cd }, { 0xa7d0, 0xa7d1 }, { 0xa7d3, 0xa7d3 }, - { 0xa7d5, 0xa7d9 }, + { 0xa7d5, 0xa7dc }, { 0xa7f2, 0xa801 }, { 0xa803, 0xa805 }, { 0xa807, 0xa80a }, @@ -406,15 +408,22 @@ inline constexpr CharRange xid_start[] = { { 0xfb40, 0xfb41 }, { 0xfb43, 0xfb44 }, { 0xfb46, 0xfbb1 }, - { 0xfbd3, 0xfd3d }, + { 0xfbd3, 0xfc5d }, + { 0xfc64, 0xfd3d }, { 0xfd50, 0xfd8f }, { 0xfd92, 0xfdc7 }, - { 0xfdf0, 0xfdfb }, - { 0xfe70, 0xfe74 }, - { 0xfe76, 0xfefc }, + { 0xfdf0, 0xfdf9 }, + { 0xfe71, 0xfe71 }, + { 0xfe73, 0xfe73 }, + { 0xfe77, 0xfe77 }, + { 0xfe79, 0xfe79 }, + { 0xfe7b, 0xfe7b }, + { 0xfe7d, 0xfe7d }, + { 0xfe7f, 0xfefc }, { 0xff21, 0xff3a }, { 0xff41, 0xff5a }, - { 0xff66, 0xffbe }, + { 0xff66, 0xff9d }, + { 0xffa0, 0xffbe }, { 0xffc2, 0xffc7 }, { 0xffca, 0xffcf }, { 0xffd2, 0xffd7 }, @@ -449,6 +458,7 @@ inline constexpr CharRange xid_start[] = { { 0x105a3, 0x105b1 }, { 0x105b3, 0x105b9 }, { 0x105bb, 0x105bc }, + { 0x105c0, 0x105f3 }, { 0x10600, 0x10736 }, { 0x10740, 0x10755 }, { 0x10760, 0x10767 }, @@ -485,8 +495,11 @@ inline constexpr CharRange xid_start[] = { { 0x10c80, 0x10cb2 }, { 0x10cc0, 0x10cf2 }, { 0x10d00, 0x10d23 }, + { 0x10d4a, 0x10d65 }, + { 0x10d6f, 0x10d85 }, { 0x10e80, 0x10ea9 }, { 0x10eb0, 0x10eb1 }, + { 0x10ec2, 0x10ec4 }, { 0x10f00, 0x10f1c }, { 0x10f27, 0x10f27 }, { 0x10f30, 0x10f45 }, @@ -509,6 +522,7 @@ inline constexpr CharRange xid_start[] = { { 0x111dc, 0x111dc }, { 0x11200, 0x11211 }, { 0x11213, 0x1122b }, + { 0x1123f, 0x11240 }, { 0x11280, 0x11286 }, { 0x11288, 0x11288 }, { 0x1128a, 0x1128d }, @@ -524,6 +538,13 @@ inline constexpr CharRange xid_start[] = { { 0x1133d, 0x1133d }, { 0x11350, 0x11350 }, { 0x1135d, 0x11361 }, + { 0x11380, 0x11389 }, + { 0x1138b, 0x1138b }, + { 0x1138e, 0x1138e }, + { 0x11390, 0x113b5 }, + { 0x113b7, 0x113b7 }, + { 0x113d1, 0x113d1 }, + { 0x113d3, 0x113d3 }, { 0x11400, 0x11434 }, { 0x11447, 0x1144a }, { 0x1145f, 0x11461 }, @@ -558,6 +579,7 @@ inline constexpr CharRange xid_start[] = { { 0x11a5c, 0x11a89 }, { 0x11a9d, 0x11a9d }, { 0x11ab0, 0x11af8 }, + { 0x11bc0, 0x11be0 }, { 0x11c00, 0x11c08 }, { 0x11c0a, 0x11c2e }, { 0x11c40, 0x11c40 }, @@ -571,13 +593,19 @@ inline constexpr CharRange xid_start[] = { { 0x11d6a, 0x11d89 }, { 0x11d98, 0x11d98 }, { 0x11ee0, 0x11ef2 }, + { 0x11f02, 0x11f02 }, + { 0x11f04, 0x11f10 }, + { 0x11f12, 0x11f33 }, { 0x11fb0, 0x11fb0 }, { 0x12000, 0x12399 }, { 0x12400, 0x1246e }, { 0x12480, 0x12543 }, { 0x12f90, 0x12ff0 }, - { 0x13000, 0x1342e }, + { 0x13000, 0x1342f }, + { 0x13441, 0x13446 }, + { 0x13460, 0x143fa }, { 0x14400, 0x14646 }, + { 0x16100, 0x1611d }, { 0x16800, 0x16a38 }, { 0x16a40, 0x16a5e }, { 0x16a70, 0x16abe }, @@ -586,6 +614,7 @@ inline constexpr CharRange xid_start[] = { { 0x16b40, 0x16b43 }, { 0x16b63, 0x16b77 }, { 0x16b7d, 0x16b8f }, + { 0x16d40, 0x16d6c }, { 0x16e40, 0x16e7f }, { 0x16f00, 0x16f4a }, { 0x16f50, 0x16f50 }, @@ -594,12 +623,14 @@ inline constexpr CharRange xid_start[] = { { 0x16fe3, 0x16fe3 }, { 0x17000, 0x187f7 }, { 0x18800, 0x18cd5 }, - { 0x18d00, 0x18d08 }, + { 0x18cff, 0x18d08 }, { 0x1aff0, 0x1aff3 }, { 0x1aff5, 0x1affb }, { 0x1affd, 0x1affe }, { 0x1b000, 0x1b122 }, + { 0x1b132, 0x1b132 }, { 0x1b150, 0x1b152 }, + { 0x1b155, 0x1b155 }, { 0x1b164, 0x1b167 }, { 0x1b170, 0x1b2fb }, { 0x1bc00, 0x1bc6a }, @@ -637,11 +668,16 @@ inline constexpr CharRange xid_start[] = { { 0x1d7aa, 0x1d7c2 }, { 0x1d7c4, 0x1d7cb }, { 0x1df00, 0x1df1e }, + { 0x1df25, 0x1df2a }, + { 0x1e030, 0x1e06d }, { 0x1e100, 0x1e12c }, { 0x1e137, 0x1e13d }, { 0x1e14e, 0x1e14e }, { 0x1e290, 0x1e2ad }, { 0x1e2c0, 0x1e2eb }, + { 0x1e4d0, 0x1e4eb }, + { 0x1e5d0, 0x1e5ed }, + { 0x1e5f0, 0x1e5f0 }, { 0x1e7e0, 0x1e7e6 }, { 0x1e7e8, 0x1e7eb }, { 0x1e7ed, 0x1e7ee }, @@ -683,15 +719,17 @@ inline constexpr CharRange xid_start[] = { { 0x1eea5, 0x1eea9 }, { 0x1eeab, 0x1eebb }, { 0x20000, 0x2a6df }, - { 0x2a700, 0x2b738 }, + { 0x2a700, 0x2b739 }, { 0x2b740, 0x2b81d }, { 0x2b820, 0x2cea1 }, { 0x2ceb0, 0x2ebe0 }, + { 0x2ebf0, 0x2ee5d }, { 0x2f800, 0x2fa1d }, { 0x30000, 0x3134a }, + { 0x31350, 0x323af }, }; -inline constexpr CharRange xid_continue[] = { +constexpr inline CharRange xid_continue[] = { { 0x30, 0x39 }, { 0x41, 0x5a }, { 0x5f, 0x5f }, @@ -709,7 +747,7 @@ inline constexpr CharRange xid_continue[] = { { 0x2ee, 0x2ee }, { 0x300, 0x374 }, { 0x376, 0x377 }, - { 0x37a, 0x37d }, + { 0x37b, 0x37d }, { 0x37f, 0x37f }, { 0x386, 0x38a }, { 0x38c, 0x38c }, @@ -745,7 +783,7 @@ inline constexpr CharRange xid_continue[] = { { 0x860, 0x86a }, { 0x870, 0x887 }, { 0x889, 0x88e }, - { 0x898, 0x8e1 }, + { 0x897, 0x8e1 }, { 0x8e3, 0x963 }, { 0x966, 0x96f }, { 0x971, 0x983 }, @@ -850,7 +888,7 @@ inline constexpr CharRange xid_continue[] = { { 0xcdd, 0xcde }, { 0xce0, 0xce3 }, { 0xce6, 0xcef }, - { 0xcf1, 0xcf2 }, + { 0xcf1, 0xcf3 }, { 0xd00, 0xd0c }, { 0xd0e, 0xd10 }, { 0xd12, 0xd44 }, @@ -883,7 +921,7 @@ inline constexpr CharRange xid_continue[] = { { 0xea7, 0xebd }, { 0xec0, 0xec4 }, { 0xec6, 0xec6 }, - { 0xec8, 0xecd }, + { 0xec8, 0xece }, { 0xed0, 0xed9 }, { 0xedc, 0xedf }, { 0xf00, 0xf00 }, @@ -921,8 +959,7 @@ inline constexpr CharRange xid_continue[] = { { 0x1312, 0x1315 }, { 0x1318, 0x135a }, { 0x135d, 0x135f }, - { 0x1369, 0x1369 }, - { 0x1371, 0x1371 }, + { 0x1369, 0x1371 }, { 0x1380, 0x138f }, { 0x13a0, 0x13f5 }, { 0x13f8, 0x13fd }, @@ -969,7 +1006,7 @@ inline constexpr CharRange xid_continue[] = { { 0x1c00, 0x1c37 }, { 0x1c40, 0x1c49 }, { 0x1c4d, 0x1c7d }, - { 0x1c80, 0x1c88 }, + { 0x1c80, 0x1c8a }, { 0x1c90, 0x1cba }, { 0x1cbd, 0x1cbf }, { 0x1cd0, 0x1cd2 }, @@ -993,6 +1030,7 @@ inline constexpr CharRange xid_continue[] = { { 0x1fe0, 0x1fec }, { 0x1ff2, 0x1ff4 }, { 0x1ff6, 0x1ffc }, + { 0x200c, 0x200d }, { 0x203f, 0x2040 }, { 0x2054, 0x2054 }, { 0x2071, 0x2071 }, @@ -1036,9 +1074,9 @@ inline constexpr CharRange xid_continue[] = { { 0x3031, 0x3035 }, { 0x3038, 0x303c }, { 0x3041, 0x3096 }, - { 0x3099, 0x309f }, - { 0x30a1, 0x30fa }, - { 0x30fc, 0x30ff }, + { 0x3099, 0x309a }, + { 0x309d, 0x309f }, + { 0x30a1, 0x30ff }, { 0x3105, 0x312f }, { 0x3131, 0x318e }, { 0x31a0, 0x31bf }, @@ -1053,10 +1091,10 @@ inline constexpr CharRange xid_continue[] = { { 0xa67f, 0xa6f1 }, { 0xa717, 0xa71f }, { 0xa722, 0xa788 }, - { 0xa78b, 0xa7ca }, + { 0xa78b, 0xa7cd }, { 0xa7d0, 0xa7d1 }, { 0xa7d3, 0xa7d3 }, - { 0xa7d5, 0xa7d9 }, + { 0xa7d5, 0xa7dc }, { 0xa7f2, 0xa827 }, { 0xa82c, 0xa82c }, { 0xa840, 0xa873 }, @@ -1102,21 +1140,27 @@ inline constexpr CharRange xid_continue[] = { { 0xfb40, 0xfb41 }, { 0xfb43, 0xfb44 }, { 0xfb46, 0xfbb1 }, - { 0xfbd3, 0xfd3d }, + { 0xfbd3, 0xfc5d }, + { 0xfc64, 0xfd3d }, { 0xfd50, 0xfd8f }, { 0xfd92, 0xfdc7 }, - { 0xfdf0, 0xfdfb }, + { 0xfdf0, 0xfdf9 }, { 0xfe00, 0xfe0f }, { 0xfe20, 0xfe2f }, { 0xfe33, 0xfe34 }, { 0xfe4d, 0xfe4f }, - { 0xfe70, 0xfe74 }, - { 0xfe76, 0xfefc }, + { 0xfe71, 0xfe71 }, + { 0xfe73, 0xfe73 }, + { 0xfe77, 0xfe77 }, + { 0xfe79, 0xfe79 }, + { 0xfe7b, 0xfe7b }, + { 0xfe7d, 0xfe7d }, + { 0xfe7f, 0xfefc }, { 0xff10, 0xff19 }, { 0xff21, 0xff3a }, { 0xff3f, 0xff3f }, { 0xff41, 0xff5a }, - { 0xff66, 0xffbe }, + { 0xff65, 0xffbe }, { 0xffc2, 0xffc7 }, { 0xffca, 0xffcf }, { 0xffd2, 0xffd7 }, @@ -1154,6 +1198,7 @@ inline constexpr CharRange xid_continue[] = { { 0x105a3, 0x105b1 }, { 0x105b3, 0x105b9 }, { 0x105bb, 0x105bc }, + { 0x105c0, 0x105f3 }, { 0x10600, 0x10736 }, { 0x10740, 0x10755 }, { 0x10760, 0x10767 }, @@ -1194,10 +1239,14 @@ inline constexpr CharRange xid_continue[] = { { 0x10cc0, 0x10cf2 }, { 0x10d00, 0x10d27 }, { 0x10d30, 0x10d39 }, + { 0x10d40, 0x10d65 }, + { 0x10d69, 0x10d6d }, + { 0x10d6f, 0x10d85 }, { 0x10e80, 0x10ea9 }, { 0x10eab, 0x10eac }, { 0x10eb0, 0x10eb1 }, - { 0x10f00, 0x10f1c }, + { 0x10ec2, 0x10ec4 }, + { 0x10efc, 0x10f1c }, { 0x10f27, 0x10f27 }, { 0x10f30, 0x10f50 }, { 0x10f70, 0x10f85 }, @@ -1220,7 +1269,7 @@ inline constexpr CharRange xid_continue[] = { { 0x111dc, 0x111dc }, { 0x11200, 0x11211 }, { 0x11213, 0x11237 }, - { 0x1123e, 0x1123e }, + { 0x1123e, 0x11241 }, { 0x11280, 0x11286 }, { 0x11288, 0x11288 }, { 0x1128a, 0x1128d }, @@ -1243,6 +1292,16 @@ inline constexpr CharRange xid_continue[] = { { 0x1135d, 0x11363 }, { 0x11366, 0x1136c }, { 0x11370, 0x11374 }, + { 0x11380, 0x11389 }, + { 0x1138b, 0x1138b }, + { 0x1138e, 0x1138e }, + { 0x11390, 0x113b5 }, + { 0x113b7, 0x113c0 }, + { 0x113c2, 0x113c2 }, + { 0x113c5, 0x113c5 }, + { 0x113c7, 0x113ca }, + { 0x113cc, 0x113d3 }, + { 0x113e1, 0x113e2 }, { 0x11400, 0x1144a }, { 0x11450, 0x11459 }, { 0x1145e, 0x11461 }, @@ -1257,6 +1316,7 @@ inline constexpr CharRange xid_continue[] = { { 0x11650, 0x11659 }, { 0x11680, 0x116b8 }, { 0x116c0, 0x116c9 }, + { 0x116d0, 0x116e3 }, { 0x11700, 0x1171a }, { 0x1171d, 0x1172b }, { 0x11730, 0x11739 }, @@ -1280,6 +1340,8 @@ inline constexpr CharRange xid_continue[] = { { 0x11a50, 0x11a99 }, { 0x11a9d, 0x11a9d }, { 0x11ab0, 0x11af8 }, + { 0x11bc0, 0x11be0 }, + { 0x11bf0, 0x11bf9 }, { 0x11c00, 0x11c08 }, { 0x11c0a, 0x11c36 }, { 0x11c38, 0x11c40 }, @@ -1301,13 +1363,20 @@ inline constexpr CharRange xid_continue[] = { { 0x11d93, 0x11d98 }, { 0x11da0, 0x11da9 }, { 0x11ee0, 0x11ef6 }, + { 0x11f00, 0x11f10 }, + { 0x11f12, 0x11f3a }, + { 0x11f3e, 0x11f42 }, + { 0x11f50, 0x11f5a }, { 0x11fb0, 0x11fb0 }, { 0x12000, 0x12399 }, { 0x12400, 0x1246e }, { 0x12480, 0x12543 }, { 0x12f90, 0x12ff0 }, - { 0x13000, 0x1342e }, + { 0x13000, 0x1342f }, + { 0x13440, 0x13455 }, + { 0x13460, 0x143fa }, { 0x14400, 0x14646 }, + { 0x16100, 0x16139 }, { 0x16800, 0x16a38 }, { 0x16a40, 0x16a5e }, { 0x16a60, 0x16a69 }, @@ -1320,6 +1389,8 @@ inline constexpr CharRange xid_continue[] = { { 0x16b50, 0x16b59 }, { 0x16b63, 0x16b77 }, { 0x16b7d, 0x16b8f }, + { 0x16d40, 0x16d6c }, + { 0x16d70, 0x16d79 }, { 0x16e40, 0x16e7f }, { 0x16f00, 0x16f4a }, { 0x16f4f, 0x16f87 }, @@ -1329,12 +1400,14 @@ inline constexpr CharRange xid_continue[] = { { 0x16ff0, 0x16ff1 }, { 0x17000, 0x187f7 }, { 0x18800, 0x18cd5 }, - { 0x18d00, 0x18d08 }, + { 0x18cff, 0x18d08 }, { 0x1aff0, 0x1aff3 }, { 0x1aff5, 0x1affb }, { 0x1affd, 0x1affe }, { 0x1b000, 0x1b122 }, + { 0x1b132, 0x1b132 }, { 0x1b150, 0x1b152 }, + { 0x1b155, 0x1b155 }, { 0x1b164, 0x1b167 }, { 0x1b170, 0x1b2fb }, { 0x1bc00, 0x1bc6a }, @@ -1342,6 +1415,7 @@ inline constexpr CharRange xid_continue[] = { { 0x1bc80, 0x1bc88 }, { 0x1bc90, 0x1bc99 }, { 0x1bc9d, 0x1bc9e }, + { 0x1ccf0, 0x1ccf9 }, { 0x1cf00, 0x1cf2d }, { 0x1cf30, 0x1cf46 }, { 0x1d165, 0x1d169 }, @@ -1388,17 +1462,22 @@ inline constexpr CharRange xid_continue[] = { { 0x1da9b, 0x1da9f }, { 0x1daa1, 0x1daaf }, { 0x1df00, 0x1df1e }, + { 0x1df25, 0x1df2a }, { 0x1e000, 0x1e006 }, { 0x1e008, 0x1e018 }, { 0x1e01b, 0x1e021 }, { 0x1e023, 0x1e024 }, { 0x1e026, 0x1e02a }, + { 0x1e030, 0x1e06d }, + { 0x1e08f, 0x1e08f }, { 0x1e100, 0x1e12c }, { 0x1e130, 0x1e13d }, { 0x1e140, 0x1e149 }, { 0x1e14e, 0x1e14e }, { 0x1e290, 0x1e2ae }, { 0x1e2c0, 0x1e2f9 }, + { 0x1e4d0, 0x1e4f9 }, + { 0x1e5d0, 0x1e5fa }, { 0x1e7e0, 0x1e7e6 }, { 0x1e7e8, 0x1e7eb }, { 0x1e7ed, 0x1e7ee }, @@ -1442,16 +1521,18 @@ inline constexpr CharRange xid_continue[] = { { 0x1eeab, 0x1eebb }, { 0x1fbf0, 0x1fbf9 }, { 0x20000, 0x2a6df }, - { 0x2a700, 0x2b738 }, + { 0x2a700, 0x2b739 }, { 0x2b740, 0x2b81d }, { 0x2b820, 0x2cea1 }, { 0x2ceb0, 0x2ebe0 }, + { 0x2ebf0, 0x2ee5d }, { 0x2f800, 0x2fa1d }, { 0x30000, 0x3134a }, + { 0x31350, 0x323af }, { 0xe0100, 0xe01ef }, }; -inline constexpr CharRange uppercase_letter[] = { +constexpr inline CharRange uppercase_letter[] = { { 0x41, 0x5a }, { 0xc0, 0xd6 }, { 0xd8, 0xde }, @@ -1728,6 +1809,7 @@ inline constexpr CharRange uppercase_letter[] = { { 0x10c7, 0x10c7 }, { 0x10cd, 0x10cd }, { 0x13a0, 0x13f5 }, + { 0x1c89, 0x1c89 }, { 0x1c90, 0x1cba }, { 0x1cbd, 0x1cbf }, { 0x1e00, 0x1e00 }, @@ -1882,7 +1964,9 @@ inline constexpr CharRange uppercase_letter[] = { { 0x2130, 0x2133 }, { 0x213e, 0x213f }, { 0x2145, 0x2145 }, + { 0x2160, 0x216f }, { 0x2183, 0x2183 }, + { 0x24b6, 0x24cf }, { 0x2c00, 0x2c2f }, { 0x2c60, 0x2c60 }, { 0x2c62, 0x2c64 }, @@ -2052,9 +2136,12 @@ inline constexpr CharRange uppercase_letter[] = { { 0xa7c2, 0xa7c2 }, { 0xa7c4, 0xa7c7 }, { 0xa7c9, 0xa7c9 }, + { 0xa7cb, 0xa7cc }, { 0xa7d0, 0xa7d0 }, { 0xa7d6, 0xa7d6 }, { 0xa7d8, 0xa7d8 }, + { 0xa7da, 0xa7da }, + { 0xa7dc, 0xa7dc }, { 0xa7f5, 0xa7f5 }, { 0xff21, 0xff3a }, { 0x10400, 0x10427 }, @@ -2064,6 +2151,7 @@ inline constexpr CharRange uppercase_letter[] = { { 0x1058c, 0x10592 }, { 0x10594, 0x10595 }, { 0x10c80, 0x10cb2 }, + { 0x10d50, 0x10d65 }, { 0x118a0, 0x118bf }, { 0x16e40, 0x16e5f }, { 0x1d400, 0x1d419 }, @@ -2098,11 +2186,16 @@ inline constexpr CharRange uppercase_letter[] = { { 0x1d790, 0x1d7a8 }, { 0x1d7ca, 0x1d7ca }, { 0x1e900, 0x1e921 }, + { 0x1f130, 0x1f149 }, + { 0x1f150, 0x1f169 }, + { 0x1f170, 0x1f189 }, }; -inline constexpr CharRange lowercase_letter[] = { +constexpr inline CharRange lowercase_letter[] = { { 0x61, 0x7a }, + { 0xaa, 0xaa }, { 0xb5, 0xb5 }, + { 0xba, 0xba }, { 0xdf, 0xf6 }, { 0xf8, 0xff }, { 0x101, 0x101 }, @@ -2246,11 +2339,14 @@ inline constexpr CharRange lowercase_letter[] = { { 0x24b, 0x24b }, { 0x24d, 0x24d }, { 0x24f, 0x293 }, - { 0x295, 0x2af }, + { 0x295, 0x2b8 }, + { 0x2c0, 0x2c1 }, + { 0x2e0, 0x2e4 }, + { 0x345, 0x345 }, { 0x371, 0x371 }, { 0x373, 0x373 }, { 0x377, 0x377 }, - { 0x37b, 0x37d }, + { 0x37a, 0x37d }, { 0x390, 0x390 }, { 0x3ac, 0x3ce }, { 0x3d0, 0x3d1 }, @@ -2372,12 +2468,11 @@ inline constexpr CharRange lowercase_letter[] = { { 0x52f, 0x52f }, { 0x560, 0x588 }, { 0x10d0, 0x10fa }, - { 0x10fd, 0x10ff }, + { 0x10fc, 0x10ff }, { 0x13f8, 0x13fd }, { 0x1c80, 0x1c88 }, - { 0x1d00, 0x1d2b }, - { 0x1d6b, 0x1d77 }, - { 0x1d79, 0x1d9a }, + { 0x1c8a, 0x1c8a }, + { 0x1d00, 0x1dbf }, { 0x1e01, 0x1e01 }, { 0x1e03, 0x1e03 }, { 0x1e05, 0x1e05 }, @@ -2522,6 +2617,9 @@ inline constexpr CharRange lowercase_letter[] = { { 0x1fe0, 0x1fe7 }, { 0x1ff2, 0x1ff4 }, { 0x1ff6, 0x1ff7 }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, { 0x210a, 0x210a }, { 0x210e, 0x210f }, { 0x2113, 0x2113 }, @@ -2531,7 +2629,9 @@ inline constexpr CharRange lowercase_letter[] = { { 0x213c, 0x213d }, { 0x2146, 0x2149 }, { 0x214e, 0x214e }, + { 0x2170, 0x217f }, { 0x2184, 0x2184 }, + { 0x24d0, 0x24e9 }, { 0x2c30, 0x2c5f }, { 0x2c61, 0x2c61 }, { 0x2c65, 0x2c66 }, @@ -2540,7 +2640,7 @@ inline constexpr CharRange lowercase_letter[] = { { 0x2c6c, 0x2c6c }, { 0x2c71, 0x2c71 }, { 0x2c73, 0x2c74 }, - { 0x2c76, 0x2c7b }, + { 0x2c76, 0x2c7d }, { 0x2c81, 0x2c81 }, { 0x2c83, 0x2c83 }, { 0x2c85, 0x2c85 }, @@ -2633,7 +2733,7 @@ inline constexpr CharRange lowercase_letter[] = { { 0xa695, 0xa695 }, { 0xa697, 0xa697 }, { 0xa699, 0xa699 }, - { 0xa69b, 0xa69b }, + { 0xa69b, 0xa69d }, { 0xa723, 0xa723 }, { 0xa725, 0xa725 }, { 0xa727, 0xa727 }, @@ -2671,8 +2771,7 @@ inline constexpr CharRange lowercase_letter[] = { { 0xa769, 0xa769 }, { 0xa76b, 0xa76b }, { 0xa76d, 0xa76d }, - { 0xa76f, 0xa76f }, - { 0xa771, 0xa778 }, + { 0xa76f, 0xa778 }, { 0xa77a, 0xa77a }, { 0xa77c, 0xa77c }, { 0xa77f, 0xa77f }, @@ -2705,15 +2804,18 @@ inline constexpr CharRange lowercase_letter[] = { { 0xa7c3, 0xa7c3 }, { 0xa7c8, 0xa7c8 }, { 0xa7ca, 0xa7ca }, + { 0xa7cd, 0xa7cd }, { 0xa7d1, 0xa7d1 }, { 0xa7d3, 0xa7d3 }, { 0xa7d5, 0xa7d5 }, { 0xa7d7, 0xa7d7 }, { 0xa7d9, 0xa7d9 }, + { 0xa7db, 0xa7db }, + { 0xa7f2, 0xa7f4 }, { 0xa7f6, 0xa7f6 }, - { 0xa7fa, 0xa7fa }, + { 0xa7f8, 0xa7fa }, { 0xab30, 0xab5a }, - { 0xab60, 0xab68 }, + { 0xab5c, 0xab69 }, { 0xab70, 0xabbf }, { 0xfb00, 0xfb06 }, { 0xfb13, 0xfb17 }, @@ -2724,7 +2826,12 @@ inline constexpr CharRange lowercase_letter[] = { { 0x105a3, 0x105b1 }, { 0x105b3, 0x105b9 }, { 0x105bb, 0x105bc }, + { 0x10780, 0x10780 }, + { 0x10783, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, { 0x10cc0, 0x10cf2 }, + { 0x10d70, 0x10d85 }, { 0x118c0, 0x118df }, { 0x16e60, 0x16e7f }, { 0x1d41a, 0x1d433 }, @@ -2758,10 +2865,11 @@ inline constexpr CharRange lowercase_letter[] = { { 0x1df00, 0x1df09 }, { 0x1df0b, 0x1df1e }, { 0x1df25, 0x1df2a }, + { 0x1e030, 0x1e06d }, { 0x1e922, 0x1e943 }, }; -inline constexpr CharRange unicode_letter[] = { +constexpr inline CharRange unicode_letter[] = { { 0x41, 0x5a }, { 0x61, 0x7a }, { 0xaa, 0xaa }, @@ -2774,7 +2882,8 @@ inline constexpr CharRange unicode_letter[] = { { 0x2e0, 0x2e4 }, { 0x2ec, 0x2ec }, { 0x2ee, 0x2ee }, - { 0x370, 0x374 }, + { 0x345, 0x345 }, + { 0x363, 0x374 }, { 0x376, 0x377 }, { 0x37a, 0x37d }, { 0x37f, 0x37f }, @@ -2788,49 +2897,58 @@ inline constexpr CharRange unicode_letter[] = { { 0x531, 0x556 }, { 0x559, 0x559 }, { 0x560, 0x588 }, + { 0x5b0, 0x5bd }, + { 0x5bf, 0x5bf }, + { 0x5c1, 0x5c2 }, + { 0x5c4, 0x5c5 }, + { 0x5c7, 0x5c7 }, { 0x5d0, 0x5ea }, { 0x5ef, 0x5f2 }, - { 0x620, 0x64a }, - { 0x66e, 0x66f }, - { 0x671, 0x6d3 }, - { 0x6d5, 0x6d5 }, - { 0x6e5, 0x6e6 }, - { 0x6ee, 0x6ef }, + { 0x610, 0x61a }, + { 0x620, 0x657 }, + { 0x659, 0x65f }, + { 0x66e, 0x6d3 }, + { 0x6d5, 0x6dc }, + { 0x6e1, 0x6e8 }, + { 0x6ed, 0x6ef }, { 0x6fa, 0x6fc }, { 0x6ff, 0x6ff }, - { 0x710, 0x710 }, - { 0x712, 0x72f }, - { 0x74d, 0x7a5 }, - { 0x7b1, 0x7b1 }, + { 0x710, 0x73f }, + { 0x74d, 0x7b1 }, { 0x7ca, 0x7ea }, { 0x7f4, 0x7f5 }, { 0x7fa, 0x7fa }, - { 0x800, 0x815 }, - { 0x81a, 0x81a }, - { 0x824, 0x824 }, - { 0x828, 0x828 }, + { 0x800, 0x817 }, + { 0x81a, 0x82c }, { 0x840, 0x858 }, { 0x860, 0x86a }, { 0x870, 0x887 }, { 0x889, 0x88e }, + { 0x897, 0x897 }, { 0x8a0, 0x8c9 }, - { 0x904, 0x939 }, - { 0x93d, 0x93d }, - { 0x950, 0x950 }, - { 0x958, 0x961 }, - { 0x971, 0x980 }, + { 0x8d4, 0x8df }, + { 0x8e3, 0x8e9 }, + { 0x8f0, 0x93b }, + { 0x93d, 0x94c }, + { 0x94e, 0x950 }, + { 0x955, 0x963 }, + { 0x971, 0x983 }, { 0x985, 0x98c }, { 0x98f, 0x990 }, { 0x993, 0x9a8 }, { 0x9aa, 0x9b0 }, { 0x9b2, 0x9b2 }, { 0x9b6, 0x9b9 }, - { 0x9bd, 0x9bd }, + { 0x9bd, 0x9c4 }, + { 0x9c7, 0x9c8 }, + { 0x9cb, 0x9cc }, { 0x9ce, 0x9ce }, + { 0x9d7, 0x9d7 }, { 0x9dc, 0x9dd }, - { 0x9df, 0x9e1 }, + { 0x9df, 0x9e3 }, { 0x9f0, 0x9f1 }, { 0x9fc, 0x9fc }, + { 0xa01, 0xa03 }, { 0xa05, 0xa0a }, { 0xa0f, 0xa10 }, { 0xa13, 0xa28 }, @@ -2838,30 +2956,41 @@ inline constexpr CharRange unicode_letter[] = { { 0xa32, 0xa33 }, { 0xa35, 0xa36 }, { 0xa38, 0xa39 }, + { 0xa3e, 0xa42 }, + { 0xa47, 0xa48 }, + { 0xa4b, 0xa4c }, + { 0xa51, 0xa51 }, { 0xa59, 0xa5c }, { 0xa5e, 0xa5e }, - { 0xa72, 0xa74 }, + { 0xa70, 0xa75 }, + { 0xa81, 0xa83 }, { 0xa85, 0xa8d }, { 0xa8f, 0xa91 }, { 0xa93, 0xaa8 }, { 0xaaa, 0xab0 }, { 0xab2, 0xab3 }, { 0xab5, 0xab9 }, - { 0xabd, 0xabd }, + { 0xabd, 0xac5 }, + { 0xac7, 0xac9 }, + { 0xacb, 0xacc }, { 0xad0, 0xad0 }, - { 0xae0, 0xae1 }, - { 0xaf9, 0xaf9 }, + { 0xae0, 0xae3 }, + { 0xaf9, 0xafc }, + { 0xb01, 0xb03 }, { 0xb05, 0xb0c }, { 0xb0f, 0xb10 }, { 0xb13, 0xb28 }, { 0xb2a, 0xb30 }, { 0xb32, 0xb33 }, { 0xb35, 0xb39 }, - { 0xb3d, 0xb3d }, + { 0xb3d, 0xb44 }, + { 0xb47, 0xb48 }, + { 0xb4b, 0xb4c }, + { 0xb56, 0xb57 }, { 0xb5c, 0xb5d }, - { 0xb5f, 0xb61 }, + { 0xb5f, 0xb63 }, { 0xb71, 0xb71 }, - { 0xb83, 0xb83 }, + { 0xb82, 0xb83 }, { 0xb85, 0xb8a }, { 0xb8e, 0xb90 }, { 0xb92, 0xb95 }, @@ -2871,65 +3000,80 @@ inline constexpr CharRange unicode_letter[] = { { 0xba3, 0xba4 }, { 0xba8, 0xbaa }, { 0xbae, 0xbb9 }, + { 0xbbe, 0xbc2 }, + { 0xbc6, 0xbc8 }, + { 0xbca, 0xbcc }, { 0xbd0, 0xbd0 }, - { 0xc05, 0xc0c }, + { 0xbd7, 0xbd7 }, + { 0xc00, 0xc0c }, { 0xc0e, 0xc10 }, { 0xc12, 0xc28 }, { 0xc2a, 0xc39 }, - { 0xc3d, 0xc3d }, + { 0xc3d, 0xc44 }, + { 0xc46, 0xc48 }, + { 0xc4a, 0xc4c }, + { 0xc55, 0xc56 }, { 0xc58, 0xc5a }, { 0xc5d, 0xc5d }, - { 0xc60, 0xc61 }, - { 0xc80, 0xc80 }, + { 0xc60, 0xc63 }, + { 0xc80, 0xc83 }, { 0xc85, 0xc8c }, { 0xc8e, 0xc90 }, { 0xc92, 0xca8 }, { 0xcaa, 0xcb3 }, { 0xcb5, 0xcb9 }, - { 0xcbd, 0xcbd }, + { 0xcbd, 0xcc4 }, + { 0xcc6, 0xcc8 }, + { 0xcca, 0xccc }, + { 0xcd5, 0xcd6 }, { 0xcdd, 0xcde }, - { 0xce0, 0xce1 }, - { 0xcf1, 0xcf2 }, - { 0xd04, 0xd0c }, + { 0xce0, 0xce3 }, + { 0xcf1, 0xcf3 }, + { 0xd00, 0xd0c }, { 0xd0e, 0xd10 }, { 0xd12, 0xd3a }, - { 0xd3d, 0xd3d }, + { 0xd3d, 0xd44 }, + { 0xd46, 0xd48 }, + { 0xd4a, 0xd4c }, { 0xd4e, 0xd4e }, - { 0xd54, 0xd56 }, - { 0xd5f, 0xd61 }, + { 0xd54, 0xd57 }, + { 0xd5f, 0xd63 }, { 0xd7a, 0xd7f }, + { 0xd81, 0xd83 }, { 0xd85, 0xd96 }, { 0xd9a, 0xdb1 }, { 0xdb3, 0xdbb }, { 0xdbd, 0xdbd }, { 0xdc0, 0xdc6 }, - { 0xe01, 0xe30 }, - { 0xe32, 0xe33 }, + { 0xdcf, 0xdd4 }, + { 0xdd6, 0xdd6 }, + { 0xdd8, 0xddf }, + { 0xdf2, 0xdf3 }, + { 0xe01, 0xe3a }, { 0xe40, 0xe46 }, + { 0xe4d, 0xe4d }, { 0xe81, 0xe82 }, { 0xe84, 0xe84 }, { 0xe86, 0xe8a }, { 0xe8c, 0xea3 }, { 0xea5, 0xea5 }, - { 0xea7, 0xeb0 }, - { 0xeb2, 0xeb3 }, - { 0xebd, 0xebd }, + { 0xea7, 0xeb9 }, + { 0xebb, 0xebd }, { 0xec0, 0xec4 }, { 0xec6, 0xec6 }, + { 0xecd, 0xecd }, { 0xedc, 0xedf }, { 0xf00, 0xf00 }, { 0xf40, 0xf47 }, { 0xf49, 0xf6c }, - { 0xf88, 0xf8c }, - { 0x1000, 0x102a }, - { 0x103f, 0x103f }, - { 0x1050, 0x1055 }, - { 0x105a, 0x105d }, - { 0x1061, 0x1061 }, - { 0x1065, 0x1066 }, - { 0x106e, 0x1070 }, - { 0x1075, 0x1081 }, - { 0x108e, 0x108e }, + { 0xf71, 0xf83 }, + { 0xf88, 0xf97 }, + { 0xf99, 0xfbc }, + { 0x1000, 0x1036 }, + { 0x1038, 0x1038 }, + { 0x103b, 0x103f }, + { 0x1050, 0x108f }, + { 0x109a, 0x109d }, { 0x10a0, 0x10c5 }, { 0x10c7, 0x10c7 }, { 0x10cd, 0x10cd }, @@ -2957,37 +3101,44 @@ inline constexpr CharRange unicode_letter[] = { { 0x166f, 0x167f }, { 0x1681, 0x169a }, { 0x16a0, 0x16ea }, - { 0x16f1, 0x16f8 }, - { 0x1700, 0x1711 }, - { 0x171f, 0x1731 }, - { 0x1740, 0x1751 }, + { 0x16ee, 0x16f8 }, + { 0x1700, 0x1713 }, + { 0x171f, 0x1733 }, + { 0x1740, 0x1753 }, { 0x1760, 0x176c }, { 0x176e, 0x1770 }, + { 0x1772, 0x1773 }, { 0x1780, 0x17b3 }, + { 0x17b6, 0x17c8 }, { 0x17d7, 0x17d7 }, { 0x17dc, 0x17dc }, { 0x1820, 0x1878 }, - { 0x1880, 0x1884 }, - { 0x1887, 0x18a8 }, - { 0x18aa, 0x18aa }, + { 0x1880, 0x18aa }, { 0x18b0, 0x18f5 }, { 0x1900, 0x191e }, + { 0x1920, 0x192b }, + { 0x1930, 0x1938 }, { 0x1950, 0x196d }, { 0x1970, 0x1974 }, { 0x1980, 0x19ab }, { 0x19b0, 0x19c9 }, - { 0x1a00, 0x1a16 }, - { 0x1a20, 0x1a54 }, + { 0x1a00, 0x1a1b }, + { 0x1a20, 0x1a5e }, + { 0x1a61, 0x1a74 }, { 0x1aa7, 0x1aa7 }, - { 0x1b05, 0x1b33 }, + { 0x1abf, 0x1ac0 }, + { 0x1acc, 0x1ace }, + { 0x1b00, 0x1b33 }, + { 0x1b35, 0x1b43 }, { 0x1b45, 0x1b4c }, - { 0x1b83, 0x1ba0 }, - { 0x1bae, 0x1baf }, + { 0x1b80, 0x1ba9 }, + { 0x1bac, 0x1baf }, { 0x1bba, 0x1be5 }, - { 0x1c00, 0x1c23 }, + { 0x1be7, 0x1bf1 }, + { 0x1c00, 0x1c36 }, { 0x1c4d, 0x1c4f }, { 0x1c5a, 0x1c7d }, - { 0x1c80, 0x1c88 }, + { 0x1c80, 0x1c8a }, { 0x1c90, 0x1cba }, { 0x1cbd, 0x1cbf }, { 0x1ce9, 0x1cec }, @@ -2995,6 +3146,7 @@ inline constexpr CharRange unicode_letter[] = { { 0x1cf5, 0x1cf6 }, { 0x1cfa, 0x1cfa }, { 0x1d00, 0x1dbf }, + { 0x1dd3, 0x1df4 }, { 0x1e00, 0x1f15 }, { 0x1f18, 0x1f1d }, { 0x1f20, 0x1f45 }, @@ -3030,7 +3182,8 @@ inline constexpr CharRange unicode_letter[] = { { 0x213c, 0x213f }, { 0x2145, 0x2149 }, { 0x214e, 0x214e }, - { 0x2183, 0x2184 }, + { 0x2160, 0x2188 }, + { 0x24b6, 0x24e9 }, { 0x2c00, 0x2ce4 }, { 0x2ceb, 0x2cee }, { 0x2cf2, 0x2cf3 }, @@ -3048,10 +3201,12 @@ inline constexpr CharRange unicode_letter[] = { { 0x2dc8, 0x2dce }, { 0x2dd0, 0x2dd6 }, { 0x2dd8, 0x2dde }, + { 0x2de0, 0x2dff }, { 0x2e2f, 0x2e2f }, - { 0x3005, 0x3006 }, + { 0x3005, 0x3007 }, + { 0x3021, 0x3029 }, { 0x3031, 0x3035 }, - { 0x303b, 0x303c }, + { 0x3038, 0x303c }, { 0x3041, 0x3096 }, { 0x309d, 0x309f }, { 0x30a1, 0x30fa }, @@ -3067,45 +3222,39 @@ inline constexpr CharRange unicode_letter[] = { { 0xa610, 0xa61f }, { 0xa62a, 0xa62b }, { 0xa640, 0xa66e }, - { 0xa67f, 0xa69d }, - { 0xa6a0, 0xa6e5 }, + { 0xa674, 0xa67b }, + { 0xa67f, 0xa6ef }, { 0xa717, 0xa71f }, { 0xa722, 0xa788 }, - { 0xa78b, 0xa7ca }, + { 0xa78b, 0xa7cd }, { 0xa7d0, 0xa7d1 }, { 0xa7d3, 0xa7d3 }, - { 0xa7d5, 0xa7d9 }, - { 0xa7f2, 0xa801 }, - { 0xa803, 0xa805 }, - { 0xa807, 0xa80a }, - { 0xa80c, 0xa822 }, + { 0xa7d5, 0xa7dc }, + { 0xa7f2, 0xa805 }, + { 0xa807, 0xa827 }, { 0xa840, 0xa873 }, - { 0xa882, 0xa8b3 }, + { 0xa880, 0xa8c3 }, + { 0xa8c5, 0xa8c5 }, { 0xa8f2, 0xa8f7 }, { 0xa8fb, 0xa8fb }, - { 0xa8fd, 0xa8fe }, - { 0xa90a, 0xa925 }, - { 0xa930, 0xa946 }, + { 0xa8fd, 0xa8ff }, + { 0xa90a, 0xa92a }, + { 0xa930, 0xa952 }, { 0xa960, 0xa97c }, - { 0xa984, 0xa9b2 }, + { 0xa980, 0xa9b2 }, + { 0xa9b4, 0xa9bf }, { 0xa9cf, 0xa9cf }, - { 0xa9e0, 0xa9e4 }, - { 0xa9e6, 0xa9ef }, + { 0xa9e0, 0xa9ef }, { 0xa9fa, 0xa9fe }, - { 0xaa00, 0xaa28 }, - { 0xaa40, 0xaa42 }, - { 0xaa44, 0xaa4b }, + { 0xaa00, 0xaa36 }, + { 0xaa40, 0xaa4d }, { 0xaa60, 0xaa76 }, - { 0xaa7a, 0xaa7a }, - { 0xaa7e, 0xaaaf }, - { 0xaab1, 0xaab1 }, - { 0xaab5, 0xaab6 }, - { 0xaab9, 0xaabd }, + { 0xaa7a, 0xaabe }, { 0xaac0, 0xaac0 }, { 0xaac2, 0xaac2 }, { 0xaadb, 0xaadd }, - { 0xaae0, 0xaaea }, - { 0xaaf2, 0xaaf4 }, + { 0xaae0, 0xaaef }, + { 0xaaf2, 0xaaf5 }, { 0xab01, 0xab06 }, { 0xab09, 0xab0e }, { 0xab11, 0xab16 }, @@ -3113,7 +3262,7 @@ inline constexpr CharRange unicode_letter[] = { { 0xab28, 0xab2e }, { 0xab30, 0xab5a }, { 0xab5c, 0xab69 }, - { 0xab70, 0xabe2 }, + { 0xab70, 0xabea }, { 0xac00, 0xd7a3 }, { 0xd7b0, 0xd7c6 }, { 0xd7cb, 0xd7fb }, @@ -3121,8 +3270,7 @@ inline constexpr CharRange unicode_letter[] = { { 0xfa70, 0xfad9 }, { 0xfb00, 0xfb06 }, { 0xfb13, 0xfb17 }, - { 0xfb1d, 0xfb1d }, - { 0xfb1f, 0xfb28 }, + { 0xfb1d, 0xfb28 }, { 0xfb2a, 0xfb36 }, { 0xfb38, 0xfb3c }, { 0xfb3e, 0xfb3e }, @@ -3149,15 +3297,16 @@ inline constexpr CharRange unicode_letter[] = { { 0x1003f, 0x1004d }, { 0x10050, 0x1005d }, { 0x10080, 0x100fa }, + { 0x10140, 0x10174 }, { 0x10280, 0x1029c }, { 0x102a0, 0x102d0 }, { 0x10300, 0x1031f }, - { 0x1032d, 0x10340 }, - { 0x10342, 0x10349 }, - { 0x10350, 0x10375 }, + { 0x1032d, 0x1034a }, + { 0x10350, 0x1037a }, { 0x10380, 0x1039d }, { 0x103a0, 0x103c3 }, { 0x103c8, 0x103cf }, + { 0x103d1, 0x103d5 }, { 0x10400, 0x1049d }, { 0x104b0, 0x104d3 }, { 0x104d8, 0x104fb }, @@ -3171,6 +3320,7 @@ inline constexpr CharRange unicode_letter[] = { { 0x105a3, 0x105b1 }, { 0x105b3, 0x105b9 }, { 0x105bb, 0x105bc }, + { 0x105c0, 0x105f3 }, { 0x10600, 0x10736 }, { 0x10740, 0x10755 }, { 0x10760, 0x10767 }, @@ -3191,8 +3341,9 @@ inline constexpr CharRange unicode_letter[] = { { 0x10920, 0x10939 }, { 0x10980, 0x109b7 }, { 0x109be, 0x109bf }, - { 0x10a00, 0x10a00 }, - { 0x10a10, 0x10a13 }, + { 0x10a00, 0x10a03 }, + { 0x10a05, 0x10a06 }, + { 0x10a0c, 0x10a13 }, { 0x10a15, 0x10a17 }, { 0x10a19, 0x10a35 }, { 0x10a60, 0x10a7c }, @@ -3206,104 +3357,143 @@ inline constexpr CharRange unicode_letter[] = { { 0x10c00, 0x10c48 }, { 0x10c80, 0x10cb2 }, { 0x10cc0, 0x10cf2 }, - { 0x10d00, 0x10d23 }, + { 0x10d00, 0x10d27 }, + { 0x10d4a, 0x10d65 }, + { 0x10d69, 0x10d69 }, + { 0x10d6f, 0x10d85 }, { 0x10e80, 0x10ea9 }, + { 0x10eab, 0x10eac }, { 0x10eb0, 0x10eb1 }, + { 0x10ec2, 0x10ec4 }, + { 0x10efc, 0x10efc }, { 0x10f00, 0x10f1c }, { 0x10f27, 0x10f27 }, { 0x10f30, 0x10f45 }, { 0x10f70, 0x10f81 }, { 0x10fb0, 0x10fc4 }, { 0x10fe0, 0x10ff6 }, - { 0x11003, 0x11037 }, - { 0x11071, 0x11072 }, - { 0x11075, 0x11075 }, - { 0x11083, 0x110af }, + { 0x11000, 0x11045 }, + { 0x11071, 0x11075 }, + { 0x11080, 0x110b8 }, + { 0x110c2, 0x110c2 }, { 0x110d0, 0x110e8 }, - { 0x11103, 0x11126 }, - { 0x11144, 0x11144 }, - { 0x11147, 0x11147 }, + { 0x11100, 0x11132 }, + { 0x11144, 0x11147 }, { 0x11150, 0x11172 }, { 0x11176, 0x11176 }, - { 0x11183, 0x111b2 }, + { 0x11180, 0x111bf }, { 0x111c1, 0x111c4 }, + { 0x111ce, 0x111cf }, { 0x111da, 0x111da }, { 0x111dc, 0x111dc }, { 0x11200, 0x11211 }, - { 0x11213, 0x1122b }, - { 0x1123f, 0x11240 }, + { 0x11213, 0x11234 }, + { 0x11237, 0x11237 }, + { 0x1123e, 0x11241 }, { 0x11280, 0x11286 }, { 0x11288, 0x11288 }, { 0x1128a, 0x1128d }, { 0x1128f, 0x1129d }, { 0x1129f, 0x112a8 }, - { 0x112b0, 0x112de }, + { 0x112b0, 0x112e8 }, + { 0x11300, 0x11303 }, { 0x11305, 0x1130c }, { 0x1130f, 0x11310 }, { 0x11313, 0x11328 }, { 0x1132a, 0x11330 }, { 0x11332, 0x11333 }, { 0x11335, 0x11339 }, - { 0x1133d, 0x1133d }, + { 0x1133d, 0x11344 }, + { 0x11347, 0x11348 }, + { 0x1134b, 0x1134c }, { 0x11350, 0x11350 }, - { 0x1135d, 0x11361 }, - { 0x11400, 0x11434 }, + { 0x11357, 0x11357 }, + { 0x1135d, 0x11363 }, + { 0x11380, 0x11389 }, + { 0x1138b, 0x1138b }, + { 0x1138e, 0x1138e }, + { 0x11390, 0x113b5 }, + { 0x113b7, 0x113c0 }, + { 0x113c2, 0x113c2 }, + { 0x113c5, 0x113c5 }, + { 0x113c7, 0x113ca }, + { 0x113cc, 0x113cd }, + { 0x113d1, 0x113d1 }, + { 0x113d3, 0x113d3 }, + { 0x11400, 0x11441 }, + { 0x11443, 0x11445 }, { 0x11447, 0x1144a }, { 0x1145f, 0x11461 }, - { 0x11480, 0x114af }, + { 0x11480, 0x114c1 }, { 0x114c4, 0x114c5 }, { 0x114c7, 0x114c7 }, - { 0x11580, 0x115ae }, - { 0x115d8, 0x115db }, - { 0x11600, 0x1162f }, + { 0x11580, 0x115b5 }, + { 0x115b8, 0x115be }, + { 0x115d8, 0x115dd }, + { 0x11600, 0x1163e }, + { 0x11640, 0x11640 }, { 0x11644, 0x11644 }, - { 0x11680, 0x116aa }, + { 0x11680, 0x116b5 }, { 0x116b8, 0x116b8 }, { 0x11700, 0x1171a }, + { 0x1171d, 0x1172a }, { 0x11740, 0x11746 }, - { 0x11800, 0x1182b }, + { 0x11800, 0x11838 }, { 0x118a0, 0x118df }, { 0x118ff, 0x11906 }, { 0x11909, 0x11909 }, { 0x1190c, 0x11913 }, { 0x11915, 0x11916 }, - { 0x11918, 0x1192f }, - { 0x1193f, 0x1193f }, - { 0x11941, 0x11941 }, + { 0x11918, 0x11935 }, + { 0x11937, 0x11938 }, + { 0x1193b, 0x1193c }, + { 0x1193f, 0x11942 }, { 0x119a0, 0x119a7 }, - { 0x119aa, 0x119d0 }, + { 0x119aa, 0x119d7 }, + { 0x119da, 0x119df }, { 0x119e1, 0x119e1 }, - { 0x119e3, 0x119e3 }, - { 0x11a00, 0x11a00 }, - { 0x11a0b, 0x11a32 }, - { 0x11a3a, 0x11a3a }, - { 0x11a50, 0x11a50 }, - { 0x11a5c, 0x11a89 }, + { 0x119e3, 0x119e4 }, + { 0x11a00, 0x11a32 }, + { 0x11a35, 0x11a3e }, + { 0x11a50, 0x11a97 }, { 0x11a9d, 0x11a9d }, { 0x11ab0, 0x11af8 }, + { 0x11bc0, 0x11be0 }, { 0x11c00, 0x11c08 }, - { 0x11c0a, 0x11c2e }, + { 0x11c0a, 0x11c36 }, + { 0x11c38, 0x11c3e }, { 0x11c40, 0x11c40 }, { 0x11c72, 0x11c8f }, + { 0x11c92, 0x11ca7 }, + { 0x11ca9, 0x11cb6 }, { 0x11d00, 0x11d06 }, { 0x11d08, 0x11d09 }, - { 0x11d0b, 0x11d30 }, - { 0x11d46, 0x11d46 }, + { 0x11d0b, 0x11d36 }, + { 0x11d3a, 0x11d3a }, + { 0x11d3c, 0x11d3d }, + { 0x11d3f, 0x11d41 }, + { 0x11d43, 0x11d43 }, + { 0x11d46, 0x11d47 }, { 0x11d60, 0x11d65 }, { 0x11d67, 0x11d68 }, - { 0x11d6a, 0x11d89 }, + { 0x11d6a, 0x11d8e }, + { 0x11d90, 0x11d91 }, + { 0x11d93, 0x11d96 }, { 0x11d98, 0x11d98 }, - { 0x11ee0, 0x11ef2 }, - { 0x11f02, 0x11f02 }, - { 0x11f04, 0x11f10 }, - { 0x11f12, 0x11f33 }, + { 0x11ee0, 0x11ef6 }, + { 0x11f00, 0x11f10 }, + { 0x11f12, 0x11f3a }, + { 0x11f3e, 0x11f40 }, { 0x11fb0, 0x11fb0 }, { 0x12000, 0x12399 }, + { 0x12400, 0x1246e }, { 0x12480, 0x12543 }, { 0x12f90, 0x12ff0 }, { 0x13000, 0x1342f }, { 0x13441, 0x13446 }, + { 0x13460, 0x143fa }, { 0x14400, 0x14646 }, + { 0x16100, 0x1612e }, { 0x16800, 0x16a38 }, { 0x16a40, 0x16a5e }, { 0x16a70, 0x16abe }, @@ -3312,15 +3502,17 @@ inline constexpr CharRange unicode_letter[] = { { 0x16b40, 0x16b43 }, { 0x16b63, 0x16b77 }, { 0x16b7d, 0x16b8f }, + { 0x16d40, 0x16d6c }, { 0x16e40, 0x16e7f }, { 0x16f00, 0x16f4a }, - { 0x16f50, 0x16f50 }, - { 0x16f93, 0x16f9f }, + { 0x16f4f, 0x16f87 }, + { 0x16f8f, 0x16f9f }, { 0x16fe0, 0x16fe1 }, { 0x16fe3, 0x16fe3 }, + { 0x16ff0, 0x16ff1 }, { 0x17000, 0x187f7 }, { 0x18800, 0x18cd5 }, - { 0x18d00, 0x18d08 }, + { 0x18cff, 0x18d08 }, { 0x1aff0, 0x1aff3 }, { 0x1aff5, 0x1affb }, { 0x1affd, 0x1affe }, @@ -3334,6 +3526,7 @@ inline constexpr CharRange unicode_letter[] = { { 0x1bc70, 0x1bc7c }, { 0x1bc80, 0x1bc88 }, { 0x1bc90, 0x1bc99 }, + { 0x1bc9e, 0x1bc9e }, { 0x1d400, 0x1d454 }, { 0x1d456, 0x1d49c }, { 0x1d49e, 0x1d49f }, @@ -3366,19 +3559,28 @@ inline constexpr CharRange unicode_letter[] = { { 0x1d7c4, 0x1d7cb }, { 0x1df00, 0x1df1e }, { 0x1df25, 0x1df2a }, + { 0x1e000, 0x1e006 }, + { 0x1e008, 0x1e018 }, + { 0x1e01b, 0x1e021 }, + { 0x1e023, 0x1e024 }, + { 0x1e026, 0x1e02a }, { 0x1e030, 0x1e06d }, + { 0x1e08f, 0x1e08f }, { 0x1e100, 0x1e12c }, { 0x1e137, 0x1e13d }, { 0x1e14e, 0x1e14e }, { 0x1e290, 0x1e2ad }, { 0x1e2c0, 0x1e2eb }, { 0x1e4d0, 0x1e4eb }, + { 0x1e5d0, 0x1e5ed }, + { 0x1e5f0, 0x1e5f0 }, { 0x1e7e0, 0x1e7e6 }, { 0x1e7e8, 0x1e7eb }, { 0x1e7ed, 0x1e7ee }, { 0x1e7f0, 0x1e7fe }, { 0x1e800, 0x1e8c4 }, { 0x1e900, 0x1e943 }, + { 0x1e947, 0x1e947 }, { 0x1e94b, 0x1e94b }, { 0x1ee00, 0x1ee03 }, { 0x1ee05, 0x1ee1f }, @@ -3413,6 +3615,9 @@ inline constexpr CharRange unicode_letter[] = { { 0x1eea1, 0x1eea3 }, { 0x1eea5, 0x1eea9 }, { 0x1eeab, 0x1eebb }, + { 0x1f130, 0x1f149 }, + { 0x1f150, 0x1f169 }, + { 0x1f170, 0x1f189 }, { 0x20000, 0x2a6df }, { 0x2a700, 0x2b739 }, { 0x2b740, 0x2b81d }, diff --git a/core/string/char_utils.h b/core/string/char_utils.h index 4acb81253f..62ab4e9584 100644 --- a/core/string/char_utils.h +++ b/core/string/char_utils.h @@ -38,97 +38,97 @@ #define BSEARCH_CHAR_RANGE(m_array) \ int low = 0; \ int high = sizeof(m_array) / sizeof(m_array[0]) - 1; \ - int middle; \ + int middle = (low + high) / 2; \ \ while (low <= high) { \ - middle = (low + high) / 2; \ - \ - if (c < m_array[middle].start) { \ + if (p_char < m_array[middle].start) { \ high = middle - 1; \ - } else if (c > m_array[middle].end) { \ + } else if (p_char > m_array[middle].end) { \ low = middle + 1; \ } else { \ return true; \ } \ + \ + middle = (low + high) / 2; \ } \ \ return false -static _FORCE_INLINE_ bool is_unicode_identifier_start(char32_t c) { +constexpr bool is_unicode_identifier_start(char32_t p_char) { BSEARCH_CHAR_RANGE(xid_start); } -static _FORCE_INLINE_ bool is_unicode_identifier_continue(char32_t c) { +constexpr bool is_unicode_identifier_continue(char32_t p_char) { BSEARCH_CHAR_RANGE(xid_continue); } -static _FORCE_INLINE_ bool is_unicode_upper_case(char32_t c) { +constexpr bool is_unicode_upper_case(char32_t p_char) { BSEARCH_CHAR_RANGE(uppercase_letter); } -static _FORCE_INLINE_ bool is_unicode_lower_case(char32_t c) { +constexpr bool is_unicode_lower_case(char32_t p_char) { BSEARCH_CHAR_RANGE(lowercase_letter); } -static _FORCE_INLINE_ bool is_unicode_letter(char32_t c) { +constexpr bool is_unicode_letter(char32_t p_char) { BSEARCH_CHAR_RANGE(unicode_letter); } #undef BSEARCH_CHAR_RANGE -static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) { - return (c >= 'A' && c <= 'Z'); +constexpr bool is_ascii_upper_case(char32_t p_char) { + return (p_char >= 'A' && p_char <= 'Z'); } -static _FORCE_INLINE_ bool is_ascii_lower_case(char32_t c) { - return (c >= 'a' && c <= 'z'); +constexpr bool is_ascii_lower_case(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z'); } -static _FORCE_INLINE_ bool is_digit(char32_t c) { - return (c >= '0' && c <= '9'); +constexpr bool is_digit(char32_t p_char) { + return (p_char >= '0' && p_char <= '9'); } -static _FORCE_INLINE_ bool is_hex_digit(char32_t c) { - return (is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); +constexpr bool is_hex_digit(char32_t p_char) { + return (is_digit(p_char) || (p_char >= 'a' && p_char <= 'f') || (p_char >= 'A' && p_char <= 'F')); } -static _FORCE_INLINE_ bool is_binary_digit(char32_t c) { - return (c == '0' || c == '1'); +constexpr bool is_binary_digit(char32_t p_char) { + return (p_char == '0' || p_char == '1'); } -static _FORCE_INLINE_ bool is_ascii_alphabet_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +constexpr bool is_ascii_alphabet_char(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z'); } -static _FORCE_INLINE_ bool is_ascii_alphanumeric_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); +constexpr bool is_ascii_alphanumeric_char(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z') || (p_char >= '0' && p_char <= '9'); } -static _FORCE_INLINE_ bool is_ascii_identifier_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; +constexpr bool is_ascii_identifier_char(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z') || (p_char >= '0' && p_char <= '9') || p_char == '_'; } -static _FORCE_INLINE_ bool is_symbol(char32_t c) { - return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' '); +constexpr bool is_symbol(char32_t p_char) { + return p_char != '_' && ((p_char >= '!' && p_char <= '/') || (p_char >= ':' && p_char <= '@') || (p_char >= '[' && p_char <= '`') || (p_char >= '{' && p_char <= '~') || p_char == '\t' || p_char == ' '); } -static _FORCE_INLINE_ bool is_control(char32_t p_char) { +constexpr bool is_control(char32_t p_char) { return (p_char <= 0x001f) || (p_char >= 0x007f && p_char <= 0x009f); } -static _FORCE_INLINE_ bool is_whitespace(char32_t p_char) { +constexpr bool is_whitespace(char32_t p_char) { return (p_char == ' ') || (p_char == 0x00a0) || (p_char == 0x1680) || (p_char >= 0x2000 && p_char <= 0x200a) || (p_char == 0x202f) || (p_char == 0x205f) || (p_char == 0x3000) || (p_char == 0x2028) || (p_char == 0x2029) || (p_char >= 0x0009 && p_char <= 0x000d) || (p_char == 0x0085); } -static _FORCE_INLINE_ bool is_linebreak(char32_t p_char) { +constexpr bool is_linebreak(char32_t p_char) { return (p_char >= 0x000a && p_char <= 0x000d) || (p_char == 0x0085) || (p_char == 0x2028) || (p_char == 0x2029); } -static _FORCE_INLINE_ bool is_punct(char32_t p_char) { +constexpr bool is_punct(char32_t p_char) { return (p_char >= ' ' && p_char <= '/') || (p_char >= ':' && p_char <= '@') || (p_char >= '[' && p_char <= '^') || (p_char == '`') || (p_char >= '{' && p_char <= '~') || (p_char >= 0x2000 && p_char <= 0x206f) || (p_char >= 0x3000 && p_char <= 0x303f); } -static _FORCE_INLINE_ bool is_underscore(char32_t p_char) { +constexpr bool is_underscore(char32_t p_char) { return (p_char == '_'); } diff --git a/core/string/fuzzy_search.cpp b/core/string/fuzzy_search.cpp new file mode 100644 index 0000000000..2fd0d3995e --- /dev/null +++ b/core/string/fuzzy_search.cpp @@ -0,0 +1,349 @@ +/**************************************************************************/ +/* fuzzy_search.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "fuzzy_search.h" + +constexpr float cull_factor = 0.1f; +constexpr float cull_cutoff = 30.0f; +const String boundary_chars = "/\\-_."; + +static bool _is_valid_interval(const Vector2i &p_interval) { + // Empty intervals are represented as (-1, -1). + return p_interval.x >= 0 && p_interval.y >= p_interval.x; +} + +static Vector2i _extend_interval(const Vector2i &p_a, const Vector2i &p_b) { + if (!_is_valid_interval(p_a)) { + return p_b; + } + if (!_is_valid_interval(p_b)) { + return p_a; + } + return Vector2i(MIN(p_a.x, p_b.x), MAX(p_a.y, p_b.y)); +} + +static bool _is_word_boundary(const String &p_str, int p_index) { + if (p_index == -1 || p_index == p_str.size()) { + return true; + } + return boundary_chars.find_char(p_str[p_index]) != -1; +} + +bool FuzzySearchToken::try_exact_match(FuzzyTokenMatch &p_match, const String &p_target, int p_offset) const { + p_match.token_idx = idx; + p_match.token_length = string.length(); + int match_idx = p_target.find(string, p_offset); + if (match_idx == -1) { + return false; + } + p_match.add_substring(match_idx, string.length()); + return true; +} + +bool FuzzySearchToken::try_fuzzy_match(FuzzyTokenMatch &p_match, const String &p_target, int p_offset, int p_miss_budget) const { + p_match.token_idx = idx; + p_match.token_length = string.length(); + int run_start = -1; + int run_len = 0; + + // Search for the subsequence p_token in p_target starting from p_offset, recording each substring for + // later scoring and display. + for (int i = 0; i < string.length(); i++) { + int new_offset = p_target.find_char(string[i], p_offset); + if (new_offset < 0) { + p_miss_budget--; + if (p_miss_budget < 0) { + return false; + } + } else { + if (run_start == -1 || p_offset != new_offset) { + if (run_start != -1) { + p_match.add_substring(run_start, run_len); + } + run_start = new_offset; + run_len = 1; + } else { + run_len += 1; + } + p_offset = new_offset + 1; + } + } + + if (run_start != -1) { + p_match.add_substring(run_start, run_len); + } + + return true; +} + +void FuzzyTokenMatch::add_substring(int p_substring_start, int p_substring_length) { + substrings.append(Vector2i(p_substring_start, p_substring_length)); + matched_length += p_substring_length; + Vector2i substring_interval = { p_substring_start, p_substring_start + p_substring_length - 1 }; + interval = _extend_interval(interval, substring_interval); +} + +bool FuzzyTokenMatch::intersects(const Vector2i &p_other_interval) const { + if (!_is_valid_interval(interval) || !_is_valid_interval(p_other_interval)) { + return false; + } + return interval.y >= p_other_interval.x && interval.x <= p_other_interval.y; +} + +bool FuzzySearchResult::can_add_token_match(const FuzzyTokenMatch &p_match) const { + if (p_match.get_miss_count() > miss_budget) { + return false; + } + + if (p_match.intersects(match_interval)) { + if (token_matches.size() == 1) { + return false; + } + for (const FuzzyTokenMatch &existing_match : token_matches) { + if (existing_match.intersects(p_match.interval)) { + return false; + } + } + } + + return true; +} + +bool FuzzyTokenMatch::is_case_insensitive(const String &p_original, const String &p_adjusted) const { + for (const Vector2i &substr : substrings) { + const int end = substr.x + substr.y; + for (int i = substr.x; i < end; i++) { + if (p_original[i] != p_adjusted[i]) { + return true; + } + } + } + return false; +} + +void FuzzySearchResult::score_token_match(FuzzyTokenMatch &p_match, bool p_case_insensitive) const { + // This can always be tweaked more. The intuition is that exact matches should almost always + // be prioritized over broken up matches, and other criteria more or less act as tie breakers. + + p_match.score = -20 * p_match.get_miss_count() - (p_case_insensitive ? 3 : 0); + + for (const Vector2i &substring : p_match.substrings) { + // Score longer substrings higher than short substrings. + int substring_score = substring.y * substring.y; + // Score matches deeper in path higher than shallower matches + if (substring.x > dir_index) { + substring_score *= 2; + } + // Score matches on a word boundary higher than matches within a word + if (_is_word_boundary(target, substring.x - 1) || _is_word_boundary(target, substring.x + substring.y)) { + substring_score += 4; + } + // Score exact query matches higher than non-compact subsequence matches + if (substring.y == p_match.token_length) { + substring_score += 100; + } + p_match.score += substring_score; + } +} + +void FuzzySearchResult::maybe_apply_score_bonus() { + // This adds a small bonus to results which match tokens in the same order they appear in the query. + int *token_range_starts = (int *)alloca(sizeof(int) * token_matches.size()); + + for (const FuzzyTokenMatch &match : token_matches) { + token_range_starts[match.token_idx] = match.interval.x; + } + + int last = token_range_starts[0]; + for (int i = 1; i < token_matches.size(); i++) { + if (last > token_range_starts[i]) { + return; + } + last = token_range_starts[i]; + } + + score += 1; +} + +void FuzzySearchResult::add_token_match(const FuzzyTokenMatch &p_match) { + score += p_match.score; + match_interval = _extend_interval(match_interval, p_match.interval); + miss_budget -= p_match.get_miss_count(); + token_matches.append(p_match); +} + +void remove_low_scores(Vector<FuzzySearchResult> &p_results, float p_cull_score) { + // Removes all results with score < p_cull_score in-place. + int i = 0; + int j = p_results.size() - 1; + FuzzySearchResult *results = p_results.ptrw(); + + while (true) { + // Advances i to an element to remove and j to an element to keep. + while (j >= i && results[j].score < p_cull_score) { + j--; + } + while (i < j && results[i].score >= p_cull_score) { + i++; + } + if (i >= j) { + break; + } + results[i++] = results[j--]; + } + + p_results.resize(j + 1); +} + +void FuzzySearch::sort_and_filter(Vector<FuzzySearchResult> &p_results) const { + if (p_results.is_empty()) { + return; + } + + float avg_score = 0; + float max_score = 0; + + for (const FuzzySearchResult &result : p_results) { + avg_score += result.score; + max_score = MAX(max_score, result.score); + } + + // TODO: Tune scoring and culling here to display fewer subsequence soup matches when good matches + // are available. + avg_score /= p_results.size(); + float cull_score = MIN(cull_cutoff, Math::lerp(avg_score, max_score, cull_factor)); + remove_low_scores(p_results, cull_score); + + struct FuzzySearchResultComparator { + bool operator()(const FuzzySearchResult &p_lhs, const FuzzySearchResult &p_rhs) const { + // Sort on (score, length, alphanumeric) to ensure consistent ordering. + if (p_lhs.score == p_rhs.score) { + if (p_lhs.target.length() == p_rhs.target.length()) { + return p_lhs.target < p_rhs.target; + } + return p_lhs.target.length() < p_rhs.target.length(); + } + return p_lhs.score > p_rhs.score; + } + }; + + SortArray<FuzzySearchResult, FuzzySearchResultComparator> sorter; + + if (p_results.size() > max_results) { + sorter.partial_sort(0, p_results.size(), max_results, p_results.ptrw()); + p_results.resize(max_results); + } else { + sorter.sort(p_results.ptrw(), p_results.size()); + } +} + +void FuzzySearch::set_query(const String &p_query) { + tokens.clear(); + for (const String &string : p_query.split(" ", false)) { + tokens.append({ static_cast<int>(tokens.size()), string }); + } + + case_sensitive = !p_query.is_lowercase(); + + struct TokenComparator { + bool operator()(const FuzzySearchToken &A, const FuzzySearchToken &B) const { + if (A.string.length() == B.string.length()) { + return A.idx < B.idx; + } + return A.string.length() > B.string.length(); + } + }; + + // Prioritize matching longer tokens before shorter ones since match overlaps are not accepted. + tokens.sort_custom<TokenComparator>(); +} + +bool FuzzySearch::search(const String &p_target, FuzzySearchResult &p_result) const { + p_result.target = p_target; + p_result.dir_index = p_target.rfind_char('/'); + p_result.miss_budget = max_misses; + + String adjusted_target = case_sensitive ? p_target : p_target.to_lower(); + + // For each token, eagerly generate subsequences starting from index 0 and keep the best scoring one + // which does not conflict with prior token matches. This is not ensured to find the highest scoring + // combination of matches, or necessarily the highest scoring single subsequence, as it only considers + // eager subsequences for a given index, and likewise eagerly finds matches for each token in sequence. + for (const FuzzySearchToken &token : tokens) { + FuzzyTokenMatch best_match; + int offset = start_offset; + + while (true) { + FuzzyTokenMatch match; + if (allow_subsequences) { + if (!token.try_fuzzy_match(match, adjusted_target, offset, p_result.miss_budget)) { + break; + } + } else { + if (!token.try_exact_match(match, adjusted_target, offset)) { + break; + } + } + if (p_result.can_add_token_match(match)) { + p_result.score_token_match(match, match.is_case_insensitive(p_target, adjusted_target)); + if (best_match.token_idx == -1 || best_match.score < match.score) { + best_match = match; + } + } + if (_is_valid_interval(match.interval)) { + offset = match.interval.x + 1; + } else { + break; + } + } + + if (best_match.token_idx == -1) { + return false; + } + + p_result.add_token_match(best_match); + } + + p_result.maybe_apply_score_bonus(); + return true; +} + +void FuzzySearch::search_all(const PackedStringArray &p_targets, Vector<FuzzySearchResult> &p_results) const { + p_results.clear(); + + for (const String &target : p_targets) { + FuzzySearchResult result; + if (search(target, result)) { + p_results.append(result); + } + } + + sort_and_filter(p_results); +} diff --git a/core/string/fuzzy_search.h b/core/string/fuzzy_search.h new file mode 100644 index 0000000000..5d8ed813c7 --- /dev/null +++ b/core/string/fuzzy_search.h @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* fuzzy_search.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef FUZZY_SEARCH_H +#define FUZZY_SEARCH_H + +#include "core/variant/variant.h" + +class FuzzyTokenMatch; + +struct FuzzySearchToken { + int idx = -1; + String string; + + bool try_exact_match(FuzzyTokenMatch &p_match, const String &p_target, int p_offset) const; + bool try_fuzzy_match(FuzzyTokenMatch &p_match, const String &p_target, int p_offset, int p_miss_budget) const; +}; + +class FuzzyTokenMatch { + friend struct FuzzySearchToken; + friend class FuzzySearchResult; + friend class FuzzySearch; + + int matched_length = 0; + int token_length = 0; + int token_idx = -1; + Vector2i interval = Vector2i(-1, -1); // x and y are both inclusive indices. + + void add_substring(int p_substring_start, int p_substring_length); + bool intersects(const Vector2i &p_other_interval) const; + bool is_case_insensitive(const String &p_original, const String &p_adjusted) const; + int get_miss_count() const { return token_length - matched_length; } + +public: + int score = 0; + Vector<Vector2i> substrings; // x is start index, y is length. +}; + +class FuzzySearchResult { + friend class FuzzySearch; + + int miss_budget = 0; + Vector2i match_interval = Vector2i(-1, -1); + + bool can_add_token_match(const FuzzyTokenMatch &p_match) const; + void score_token_match(FuzzyTokenMatch &p_match, bool p_case_insensitive) const; + void add_token_match(const FuzzyTokenMatch &p_match); + void maybe_apply_score_bonus(); + +public: + String target; + int score = 0; + int dir_index = -1; + Vector<FuzzyTokenMatch> token_matches; +}; + +class FuzzySearch { + Vector<FuzzySearchToken> tokens; + + void sort_and_filter(Vector<FuzzySearchResult> &p_results) const; + +public: + int start_offset = 0; + bool case_sensitive = false; + int max_results = 100; + int max_misses = 2; + bool allow_subsequences = true; + + void set_query(const String &p_query); + bool search(const String &p_target, FuzzySearchResult &p_result) const; + void search_all(const PackedStringArray &p_targets, Vector<FuzzySearchResult> &p_results) const; +}; + +#endif // FUZZY_SEARCH_H diff --git a/core/string/node_path.cpp b/core/string/node_path.cpp index fdc72bc8dc..40c81edf4c 100644 --- a/core/string/node_path.cpp +++ b/core/string/node_path.cpp @@ -407,7 +407,7 @@ NodePath::NodePath(const String &p_path) { bool absolute = (path[0] == '/'); bool last_is_slash = true; int slices = 0; - int subpath_pos = path.find(":"); + int subpath_pos = path.find_char(':'); if (subpath_pos != -1) { int from = subpath_pos + 1; @@ -420,7 +420,7 @@ NodePath::NodePath(const String &p_path) { continue; // Allow end-of-path : } - ERR_FAIL_MSG("Invalid NodePath '" + p_path + "'."); + ERR_FAIL_MSG(vformat("Invalid NodePath '%s'.", p_path)); } subpath.push_back(str); diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 020949371f..d944135a70 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -80,8 +80,10 @@ void Translation::set_locale(const String &p_locale) { if (Thread::is_main_thread()) { _notify_translation_changed_if_applies(); } else { - // Avoid calling non-thread-safe functions here. - callable_mp(this, &Translation::_notify_translation_changed_if_applies).call_deferred(); + // This has to happen on the main thread (bypassing the ResourceLoader per-thread call queue) + // because it interacts with the generally non-thread-safe window management, leading to + // different issues across platforms otherwise. + MessageQueue::get_main_singleton()->push_callable(callable_mp(this, &Translation::_notify_translation_changed_if_applies)); } } diff --git a/core/string/translation_domain.cpp b/core/string/translation_domain.cpp index 53b9ce8379..1ff8dcd752 100644 --- a/core/string/translation_domain.cpp +++ b/core/string/translation_domain.cpp @@ -123,7 +123,7 @@ String TranslationDomain::_double_vowels(const String &p_message) const { } } return res; -}; +} String TranslationDomain::_replace_with_accented_string(const String &p_message) const { String res; @@ -247,7 +247,10 @@ PackedStringArray TranslationDomain::get_loaded_locales() const { PackedStringArray locales; for (const Ref<Translation> &E : translations) { ERR_CONTINUE(E.is_null()); - locales.push_back(E->get_locale()); + const String &locale = E->get_locale(); + if (!locales.has(locale)) { + locales.push_back(locale); + } } return locales; } diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index 8e275505b0..7eb8a2afeb 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -227,11 +227,11 @@ void TranslationPO::set_plural_rule(const String &p_plural_rule) { // Set plural_forms and plural_rule. // p_plural_rule passed in has the form "Plural-Forms: nplurals=2; plural=(n >= 2);". - int first_semi_col = p_plural_rule.find(";"); - plural_forms = p_plural_rule.substr(p_plural_rule.find("=") + 1, first_semi_col - (p_plural_rule.find("=") + 1)).to_int(); + int first_semi_col = p_plural_rule.find_char(';'); + plural_forms = p_plural_rule.substr(p_plural_rule.find_char('=') + 1, first_semi_col - (p_plural_rule.find_char('=') + 1)).to_int(); - int expression_start = p_plural_rule.find("=", first_semi_col) + 1; - int second_semi_col = p_plural_rule.rfind(";"); + int expression_start = p_plural_rule.find_char('=', first_semi_col) + 1; + int second_semi_col = p_plural_rule.rfind_char(';'); plural_rule = p_plural_rule.substr(expression_start, second_semi_col - expression_start).strip_edges(); // Setup the cache to make evaluating plural rule faster later on. @@ -246,7 +246,7 @@ void TranslationPO::add_message(const StringName &p_src_text, const StringName & HashMap<StringName, Vector<StringName>> &map_id_str = translation_map[p_context]; if (map_id_str.has(p_src_text)) { - WARN_PRINT("Double translations for \"" + String(p_src_text) + "\" under the same context \"" + String(p_context) + "\" for locale \"" + get_locale() + "\".\nThere should only be one unique translation for a given string under the same context."); + WARN_PRINT(vformat("Double translations for \"%s\" under the same context \"%s\" for locale \"%s\".\nThere should only be one unique translation for a given string under the same context.", String(p_src_text), String(p_context), get_locale())); map_id_str[p_src_text].set(0, p_xlated_text); } else { map_id_str[p_src_text].push_back(p_xlated_text); @@ -254,12 +254,12 @@ void TranslationPO::add_message(const StringName &p_src_text, const StringName & } void TranslationPO::add_plural_message(const StringName &p_src_text, const Vector<String> &p_plural_xlated_texts, const StringName &p_context) { - ERR_FAIL_COND_MSG(p_plural_xlated_texts.size() != plural_forms, "Trying to add plural texts that don't match the required number of plural forms for locale \"" + get_locale() + "\""); + ERR_FAIL_COND_MSG(p_plural_xlated_texts.size() != plural_forms, vformat("Trying to add plural texts that don't match the required number of plural forms for locale \"%s\".", get_locale())); HashMap<StringName, Vector<StringName>> &map_id_str = translation_map[p_context]; if (map_id_str.has(p_src_text)) { - WARN_PRINT("Double translations for \"" + p_src_text + "\" under the same context \"" + p_context + "\" for locale " + get_locale() + ".\nThere should only be one unique translation for a given string under the same context."); + WARN_PRINT(vformat("Double translations for \"%s\" under the same context \"%s\" for locale %s.\nThere should only be one unique translation for a given string under the same context.", p_src_text, p_context, get_locale())); map_id_str[p_src_text].clear(); } @@ -280,7 +280,7 @@ StringName TranslationPO::get_message(const StringName &p_src_text, const String if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) { return StringName(); } - ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug."); + ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), vformat("Source text \"%s\" is registered but doesn't have a translation. Please report this bug.", String(p_src_text))); return translation_map[p_context][p_src_text][0]; } @@ -296,7 +296,7 @@ StringName TranslationPO::get_plural_message(const StringName &p_src_text, const if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) { return StringName(); } - ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug."); + ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), vformat("Source text \"%s\" is registered but doesn't have a translation. Please report this bug.", String(p_src_text))); int plural_index = _get_plural_index(p_n); ERR_FAIL_COND_V_MSG(plural_index < 0 || translation_map[p_context][p_src_text].size() < plural_index + 1, StringName(), "Plural index returned or number of plural translations is not valid. Please report this bug."); diff --git a/core/string/translation_server.compat.inc b/core/string/translation_server.compat.inc new file mode 100644 index 0000000000..11f508c654 --- /dev/null +++ b/core/string/translation_server.compat.inc @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* translation_server.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +String TranslationServer::_standardize_locale_bind_compat_98972(const String &p_locale) const { + return standardize_locale(p_locale, false); +} + +void TranslationServer::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("standardize_locale", "locale"), &TranslationServer::_standardize_locale_bind_compat_98972); +} + +#endif // DISABLE_DEPRECATED diff --git a/core/string/translation_server.cpp b/core/string/translation_server.cpp index 89b37d0b8a..3d49d482dd 100644 --- a/core/string/translation_server.cpp +++ b/core/string/translation_server.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "translation_server.h" +#include "translation_server.compat.inc" #include "core/config/project_settings.h" #include "core/io/resource_loader.h" @@ -118,36 +119,45 @@ void TranslationServer::init_locale_info() { } } -String TranslationServer::standardize_locale(const String &p_locale) const { - return _standardize_locale(p_locale, false); +TranslationServer::Locale::operator String() const { + String out = language; + if (!script.is_empty()) { + out = out + "_" + script; + } + if (!country.is_empty()) { + out = out + "_" + country; + } + if (!variant.is_empty()) { + out = out + "_" + variant; + } + return out; } -String TranslationServer::_standardize_locale(const String &p_locale, bool p_add_defaults) const { +TranslationServer::Locale::Locale(const TranslationServer &p_server, const String &p_locale, bool p_add_defaults) { // Replaces '-' with '_' for macOS style locales. String univ_locale = p_locale.replace("-", "_"); // Extract locale elements. - String lang_name, script_name, country_name, variant_name; Vector<String> locale_elements = univ_locale.get_slice("@", 0).split("_"); - lang_name = locale_elements[0]; + language = locale_elements[0]; if (locale_elements.size() >= 2) { if (locale_elements[1].length() == 4 && is_ascii_upper_case(locale_elements[1][0]) && is_ascii_lower_case(locale_elements[1][1]) && is_ascii_lower_case(locale_elements[1][2]) && is_ascii_lower_case(locale_elements[1][3])) { - script_name = locale_elements[1]; + script = locale_elements[1]; } if (locale_elements[1].length() == 2 && is_ascii_upper_case(locale_elements[1][0]) && is_ascii_upper_case(locale_elements[1][1])) { - country_name = locale_elements[1]; + country = locale_elements[1]; } } if (locale_elements.size() >= 3) { if (locale_elements[2].length() == 2 && is_ascii_upper_case(locale_elements[2][0]) && is_ascii_upper_case(locale_elements[2][1])) { - country_name = locale_elements[2]; - } else if (variant_map.has(locale_elements[2].to_lower()) && variant_map[locale_elements[2].to_lower()] == lang_name) { - variant_name = locale_elements[2].to_lower(); + country = locale_elements[2]; + } else if (p_server.variant_map.has(locale_elements[2].to_lower()) && p_server.variant_map[locale_elements[2].to_lower()] == language) { + variant = locale_elements[2].to_lower(); } } if (locale_elements.size() >= 4) { - if (variant_map.has(locale_elements[3].to_lower()) && variant_map[locale_elements[3].to_lower()] == lang_name) { - variant_name = locale_elements[3].to_lower(); + if (p_server.variant_map.has(locale_elements[3].to_lower()) && p_server.variant_map[locale_elements[3].to_lower()] == language) { + variant = locale_elements[3].to_lower(); } } @@ -155,71 +165,62 @@ String TranslationServer::_standardize_locale(const String &p_locale, bool p_add Vector<String> script_extra = univ_locale.get_slice("@", 1).split(";"); for (int i = 0; i < script_extra.size(); i++) { if (script_extra[i].to_lower() == "cyrillic") { - script_name = "Cyrl"; + script = "Cyrl"; break; } else if (script_extra[i].to_lower() == "latin") { - script_name = "Latn"; + script = "Latn"; break; } else if (script_extra[i].to_lower() == "devanagari") { - script_name = "Deva"; + script = "Deva"; break; - } else if (variant_map.has(script_extra[i].to_lower()) && variant_map[script_extra[i].to_lower()] == lang_name) { - variant_name = script_extra[i].to_lower(); + } else if (p_server.variant_map.has(script_extra[i].to_lower()) && p_server.variant_map[script_extra[i].to_lower()] == language) { + variant = script_extra[i].to_lower(); } } // Handles known non-ISO language names used e.g. on Windows. - if (locale_rename_map.has(lang_name)) { - lang_name = locale_rename_map[lang_name]; + if (p_server.locale_rename_map.has(language)) { + language = p_server.locale_rename_map[language]; } // Handle country renames. - if (country_rename_map.has(country_name)) { - country_name = country_rename_map[country_name]; + if (p_server.country_rename_map.has(country)) { + country = p_server.country_rename_map[country]; } // Remove unsupported script codes. - if (!script_map.has(script_name)) { - script_name = ""; + if (!p_server.script_map.has(script)) { + script = ""; } // Add script code base on language and country codes for some ambiguous cases. if (p_add_defaults) { - if (script_name.is_empty()) { - for (int i = 0; i < locale_script_info.size(); i++) { - const LocaleScriptInfo &info = locale_script_info[i]; - if (info.name == lang_name) { - if (country_name.is_empty() || info.supported_countries.has(country_name)) { - script_name = info.script; + if (script.is_empty()) { + for (int i = 0; i < p_server.locale_script_info.size(); i++) { + const LocaleScriptInfo &info = p_server.locale_script_info[i]; + if (info.name == language) { + if (country.is_empty() || info.supported_countries.has(country)) { + script = info.script; break; } } } } - if (!script_name.is_empty() && country_name.is_empty()) { + if (!script.is_empty() && country.is_empty()) { // Add conntry code based on script for some ambiguous cases. - for (int i = 0; i < locale_script_info.size(); i++) { - const LocaleScriptInfo &info = locale_script_info[i]; - if (info.name == lang_name && info.script == script_name) { - country_name = info.default_country; + for (int i = 0; i < p_server.locale_script_info.size(); i++) { + const LocaleScriptInfo &info = p_server.locale_script_info[i]; + if (info.name == language && info.script == script) { + country = info.default_country; break; } } } } +} - // Combine results. - String out = lang_name; - if (!script_name.is_empty()) { - out = out + "_" + script_name; - } - if (!country_name.is_empty()) { - out = out + "_" + country_name; - } - if (!variant_name.is_empty()) { - out = out + "_" + variant_name; - } - return out; +String TranslationServer::standardize_locale(const String &p_locale, bool p_add_defaults) const { + return Locale(*this, p_locale, p_add_defaults).operator String(); } int TranslationServer::compare_locales(const String &p_locale_a, const String &p_locale_b) const { @@ -228,32 +229,56 @@ int TranslationServer::compare_locales(const String &p_locale_a, const String &p return 10; } - String locale_a = _standardize_locale(p_locale_a, true); - String locale_b = _standardize_locale(p_locale_b, true); + const String cache_key = p_locale_a + "|" + p_locale_b; + const int *cached_result = locale_compare_cache.getptr(cache_key); + if (cached_result) { + return *cached_result; + } + + Locale locale_a = Locale(*this, p_locale_a, true); + Locale locale_b = Locale(*this, p_locale_b, true); if (locale_a == locale_b) { // Exact match. + locale_compare_cache.insert(cache_key, 10); return 10; } - Vector<String> locale_a_elements = locale_a.split("_"); - Vector<String> locale_b_elements = locale_b.split("_"); - if (locale_a_elements[0] == locale_b_elements[0]) { - // Matching language, both locales have extra parts. - // Return number of matching elements. - int matching_elements = 1; - for (int i = 1; i < locale_a_elements.size(); i++) { - for (int j = 1; j < locale_b_elements.size(); j++) { - if (locale_a_elements[i] == locale_b_elements[j]) { - matching_elements++; - } - } - } - return matching_elements; - } else { + if (locale_a.language != locale_b.language) { // No match. + locale_compare_cache.insert(cache_key, 0); return 0; } + + // Matching language, both locales have extra parts. Compare the + // remaining elements. If both elements are non-empty, check the + // match to increase or decrease the score. If either element or + // both are empty, leave the score as is. + int score = 5; + if (!locale_a.script.is_empty() && !locale_b.script.is_empty()) { + if (locale_a.script == locale_b.script) { + score++; + } else { + score--; + } + } + if (!locale_a.country.is_empty() && !locale_b.country.is_empty()) { + if (locale_a.country == locale_b.country) { + score++; + } else { + score--; + } + } + if (!locale_a.variant.is_empty() && !locale_b.variant.is_empty()) { + if (locale_a.variant == locale_b.variant) { + score++; + } else { + score--; + } + } + + locale_compare_cache.insert(cache_key, score); + return score; } String TranslationServer::get_locale_name(const String &p_locale) const { @@ -387,8 +412,6 @@ StringName TranslationServer::translate_plural(const StringName &p_message, cons return main_domain->translate_plural(p_message, p_message_plural, p_n, p_context); } -TranslationServer *TranslationServer::singleton = nullptr; - bool TranslationServer::_load_translations(const String &p_from) { if (ProjectSettings::get_singleton()->has_setting(p_from)) { const Vector<String> &translation_names = GLOBAL_GET(p_from); @@ -569,7 +592,7 @@ void TranslationServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tool_locale"), &TranslationServer::get_tool_locale); ClassDB::bind_method(D_METHOD("compare_locales", "locale_a", "locale_b"), &TranslationServer::compare_locales); - ClassDB::bind_method(D_METHOD("standardize_locale", "locale"), &TranslationServer::standardize_locale); + ClassDB::bind_method(D_METHOD("standardize_locale", "locale", "add_defaults"), &TranslationServer::standardize_locale, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_all_languages"), &TranslationServer::get_all_languages); ClassDB::bind_method(D_METHOD("get_language_name", "language"), &TranslationServer::get_language_name); diff --git a/core/string/translation_server.h b/core/string/translation_server.h index a09230c019..b6e4bba6e5 100644 --- a/core/string/translation_server.h +++ b/core/string/translation_server.h @@ -46,14 +46,20 @@ class TranslationServer : public Object { Ref<TranslationDomain> doc_domain; HashMap<StringName, Ref<TranslationDomain>> custom_domains; + mutable HashMap<String, int> locale_compare_cache; + bool enabled = true; - static TranslationServer *singleton; + static inline TranslationServer *singleton = nullptr; bool _load_translations(const String &p_from); - String _standardize_locale(const String &p_locale, bool p_add_defaults) const; static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + String _standardize_locale_bind_compat_98972(const String &p_locale) const; + static void _bind_compatibility_methods(); +#endif + struct LocaleScriptInfo { String name; String script; @@ -62,6 +68,24 @@ class TranslationServer : public Object { }; static Vector<LocaleScriptInfo> locale_script_info; + struct Locale { + String language; + String script; + String country; + String variant; + + bool operator==(const Locale &p_locale) const { + return (p_locale.language == language) && + (p_locale.script == script) && + (p_locale.country == country) && + (p_locale.variant == variant); + } + + operator String() const; + + Locale(const TranslationServer &p_server, const String &p_locale, bool p_add_defaults); + }; + static HashMap<String, String> language_map; static HashMap<String, String> script_map; static HashMap<String, String> locale_rename_map; @@ -109,7 +133,7 @@ public: void set_pseudolocalization_enabled(bool p_enabled); void reload_pseudolocalization(); - String standardize_locale(const String &p_locale) const; + String standardize_locale(const String &p_locale, bool p_add_defaults = false) const; int compare_locales(const String &p_locale_a, const String &p_locale_b) const; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index e6f7492a18..9e99fc3b2f 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -33,6 +33,7 @@ #include "core/crypto/crypto_core.h" #include "core/math/color.h" #include "core/math/math_funcs.h" +#include "core/object/object.h" #include "core/os/memory.h" #include "core/string/print_string.h" #include "core/string/string_name.h" @@ -245,27 +246,27 @@ Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r base = base.substr(pos + 3, base.length() - pos - 3); } } - pos = base.find("#"); + pos = base.find_char('#'); // Fragment if (pos != -1) { r_fragment = base.substr(pos + 1); base = base.substr(0, pos); } - pos = base.find("/"); + pos = base.find_char('/'); // Path if (pos != -1) { r_path = base.substr(pos, base.length() - pos); base = base.substr(0, pos); } // Host - pos = base.find("@"); + pos = base.find_char('@'); if (pos != -1) { // Strip credentials base = base.substr(pos + 1, base.length() - pos - 1); } if (base.begins_with("[")) { // Literal IPv6 - pos = base.rfind("]"); + pos = base.rfind_char(']'); if (pos == -1) { return ERR_INVALID_PARAMETER; } @@ -276,7 +277,7 @@ Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r if (base.get_slice_count(":") > 2) { return ERR_INVALID_PARAMETER; } - pos = base.rfind(":"); + pos = base.rfind_char(':'); if (pos == -1) { r_host = base; base = ""; @@ -1818,7 +1819,7 @@ String String::num(double p_num, int p_decimals) { #endif buf[324] = 0; - //destroy trailing zeroes + // Destroy trailing zeroes, except one after period. { bool period = false; int z = 0; @@ -1835,7 +1836,7 @@ String String::num(double p_num, int p_decimals) { if (buf[z] == '0') { buf[z] = 0; } else if (buf[z] == '.') { - buf[z] = 0; + buf[z + 1] = '0'; break; } else { break; @@ -1850,6 +1851,8 @@ String String::num(double p_num, int p_decimals) { } String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { + ERR_FAIL_COND_V_MSG(base < 2 || base > 36, "", "Cannot convert to base " + itos(base) + ", since the value is " + (base < 2 ? "less than 2." : "greater than 36.")); + bool sign = p_num < 0; int64_t n = p_num; @@ -1888,6 +1891,8 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { } String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) { + ERR_FAIL_COND_V_MSG(base < 2 || base > 36, "", "Cannot convert to base " + itos(base) + ", since the value is " + (base < 2 ? "less than 2." : "greater than 36.")); + uint64_t n = p_num; int chars = 0; @@ -1924,14 +1929,28 @@ String String::num_real(double p_num, bool p_trailing) { return num_int64((int64_t)p_num); } } -#ifdef REAL_T_IS_DOUBLE int decimals = 14; -#else + // We want to align the digits to the above sane default, so we only need + // to subtract log10 for numbers with a positive power of ten magnitude. + const double abs_num = Math::abs(p_num); + if (abs_num > 10) { + decimals -= (int)floor(log10(abs_num)); + } + return num(p_num, decimals); +} + +String String::num_real(float p_num, bool p_trailing) { + if (p_num == (float)(int64_t)p_num) { + if (p_trailing) { + return num_int64((int64_t)p_num) + ".0"; + } else { + return num_int64((int64_t)p_num); + } + } int decimals = 6; -#endif // We want to align the digits to the above sane default, so we only need // to subtract log10 for numbers with a positive power of ten magnitude. - double abs_num = Math::abs(p_num); + const float abs_num = Math::abs(p_num); if (abs_num > 10) { decimals -= (int)floor(log10(abs_num)); } @@ -2622,7 +2641,7 @@ int64_t String::to_int() const { return 0; } - int to = (find(".") >= 0) ? find(".") : length(); + int to = (find_char('.') >= 0) ? find_char('.') : length(); int64_t integer = 0; int64_t sign = 1; @@ -3368,7 +3387,7 @@ int String::find(const char *p_str, int p_from) const { return -1; } -int String::find_char(const char32_t &p_char, int p_from) const { +int String::find_char(char32_t p_char, int p_from) const { return _cowdata.find(p_char, p_from); } @@ -3605,6 +3624,10 @@ int String::rfind(const char *p_str, int p_from) const { return -1; } +int String::rfind_char(char32_t p_char, int p_from) const { + return _cowdata.rfind(p_char, p_from); +} + int String::rfindn(const String &p_str, int p_from) const { // establish a limit int limit = length() - p_str.length(); @@ -3818,6 +3841,15 @@ bool String::is_quoted() const { return is_enclosed_in("\"") || is_enclosed_in("'"); } +bool String::is_lowercase() const { + for (const char32_t *str = &operator[](0); *str; str++) { + if (is_unicode_upper_case(*str)) { + return false; + } + } + return true; +} + int String::_count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const { if (p_string.is_empty()) { return 0; @@ -4060,8 +4092,18 @@ String String::format(const Variant &values, const String &placeholder) const { for (const Variant &key : keys) { new_string = new_string.replace(placeholder.replace("_", key), d[key]); } + } else if (values.get_type() == Variant::OBJECT) { + Object *obj = values.get_validated_object(); + ERR_FAIL_NULL_V(obj, new_string); + + List<PropertyInfo> props; + obj->get_property_list(&props); + + for (const PropertyInfo &E : props) { + new_string = new_string.replace(placeholder.replace("_", E.name), obj->get(E.name)); + } } else { - ERR_PRINT(String("Invalid type: use Array or Dictionary.").ascii().get_data()); + ERR_PRINT(String("Invalid type: use Array, Dictionary or Object.").ascii().get_data()); } return new_string; @@ -4538,7 +4580,7 @@ String String::simplify_path() const { if (p == -1) { p = s.find(":\\"); } - if (p != -1 && p < s.find("/")) { + if (p != -1 && p < s.find_char('/')) { drive = s.substr(0, p + 2); s = s.substr(p + 2); } @@ -4601,7 +4643,7 @@ String String::humanize_size(uint64_t p_size) { } if (magnitude == 0) { - return String::num(p_size) + " " + RTR("B"); + return String::num_uint64(p_size) + " " + RTR("B"); } else { String suffix; switch (magnitude) { @@ -4983,7 +5025,7 @@ String String::xml_unescape() const { String String::pad_decimals(int p_digits) const { String s = *this; - int c = s.find("."); + int c = s.find_char('.'); if (c == -1) { if (p_digits <= 0) { @@ -5007,7 +5049,7 @@ String String::pad_decimals(int p_digits) const { String String::pad_zeros(int p_digits) const { String s = *this; - int end = s.find("."); + int end = s.find_char('.'); if (end == -1) { end = s.length(); @@ -5274,7 +5316,7 @@ String String::validate_filename() const { } bool String::is_valid_ip_address() const { - if (find(":") >= 0) { + if (find_char(':') >= 0) { Vector<String> ip = split(":"); for (int i = 0; i < ip.size(); i++) { const String &n = ip[i]; @@ -5344,13 +5386,13 @@ String String::get_base_dir() const { // Windows UNC network share path. if (end == 0) { if (is_network_share_path()) { - basepos = find("/", 2); + basepos = find_char('/', 2); if (basepos == -1) { - basepos = find("\\", 2); + basepos = find_char('\\', 2); } - int servpos = find("/", basepos + 1); + int servpos = find_char('/', basepos + 1); if (servpos == -1) { - servpos = find("\\", basepos + 1); + servpos = find_char('\\', basepos + 1); } if (servpos != -1) { end = servpos + 1; @@ -5374,7 +5416,7 @@ String String::get_base_dir() const { rs = *this; } - int sep = MAX(rs.rfind("/"), rs.rfind("\\")); + int sep = MAX(rs.rfind_char('/'), rs.rfind_char('\\')); if (sep == -1) { return base; } @@ -5383,7 +5425,7 @@ String String::get_base_dir() const { } String String::get_file() const { - int sep = MAX(rfind("/"), rfind("\\")); + int sep = MAX(rfind_char('/'), rfind_char('\\')); if (sep == -1) { return *this; } @@ -5392,8 +5434,8 @@ String String::get_file() const { } String String::get_extension() const { - int pos = rfind("."); - if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) { + int pos = rfind_char('.'); + if (pos < 0 || pos < MAX(rfind_char('/'), rfind_char('\\'))) { return ""; } @@ -5491,8 +5533,8 @@ String String::validate_node_name() const { } String String::get_basename() const { - int pos = rfind("."); - if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) { + int pos = rfind_char('.'); + if (pos < 0 || pos < MAX(rfind_char('/'), rfind_char('\\'))) { return *this; } diff --git a/core/string/ustring.h b/core/string/ustring.h index aa62c9cb18..d6e563223a 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -118,7 +118,7 @@ public: Char16String &operator+=(char16_t p_char); int length() const { return size() ? size() - 1 : 0; } const char16_t *get_data() const; - operator const char16_t *() const { return get_data(); }; + operator const char16_t *() const { return get_data(); } protected: void copy_from(const char16_t *p_cstr); @@ -160,7 +160,7 @@ public: CharString &operator+=(char p_char); int length() const { return size() ? size() - 1 : 0; } const char *get_data() const; - operator const char *() const { return get_data(); }; + operator const char *() const { return get_data(); } protected: void copy_from(const char *p_cstr); @@ -287,11 +287,12 @@ public: String substr(int p_from, int p_chars = -1) const; int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed - int find_char(const char32_t &p_char, int p_from = 0) const; ///< return <0 if failed + int find_char(char32_t p_char, int p_from = 0) const; ///< return <0 if failed int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive int findn(const char *p_str, int p_from = 0) const; ///< return <0 if failed int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed int rfind(const char *p_str, int p_from = -1) const; ///< return <0 if failed + int rfind_char(char32_t p_char, int p_from = -1) const; ///< return <0 if failed int rfindn(const String &p_str, int p_from = -1) const; ///< return <0 if failed, case insensitive int rfindn(const char *p_str, int p_from = -1) const; ///< return <0 if failed int findmk(const Vector<String> &p_keys, int p_from = 0, int *r_key = nullptr) const; ///< return <0 if failed @@ -305,6 +306,7 @@ public: bool is_subsequence_of(const String &p_string) const; bool is_subsequence_ofn(const String &p_string) const; bool is_quoted() const; + bool is_lowercase() const; Vector<String> bigrams() const; float similarity(const String &p_string) const; String format(const Variant &values, const String &placeholder = "{_}") const; @@ -332,6 +334,7 @@ public: static String num(double p_num, int p_decimals = -1); static String num_scientific(double p_num); static String num_real(double p_num, bool p_trailing = true); + static String num_real(float p_num, bool p_trailing = true); static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false); static String num_uint64(uint64_t p_num, int base = 10, bool capitalize_hex = false); static String chr(char32_t p_char); diff --git a/core/templates/a_hash_map.cpp b/core/templates/a_hash_map.cpp new file mode 100644 index 0000000000..04a14c261a --- /dev/null +++ b/core/templates/a_hash_map.cpp @@ -0,0 +1,39 @@ +/**************************************************************************/ +/* a_hash_map.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "a_hash_map.h" +#include "core/variant/variant.h" + +// Explicit instantiation. +template class AHashMap<int, int>; +template class AHashMap<String, int>; +template class AHashMap<StringName, StringName>; +template class AHashMap<StringName, Variant>; +template class AHashMap<StringName, int>; diff --git a/core/templates/a_hash_map.h b/core/templates/a_hash_map.h new file mode 100644 index 0000000000..6e3a978d50 --- /dev/null +++ b/core/templates/a_hash_map.h @@ -0,0 +1,733 @@ +/**************************************************************************/ +/* a_hash_map.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef A_HASH_MAP_H +#define A_HASH_MAP_H + +#include "core/templates/hash_map.h" + +struct HashMapData { + union { + struct + { + uint32_t hash; + uint32_t hash_to_key; + }; + uint64_t data; + }; +}; + +static_assert(sizeof(HashMapData) == 8); + +/** + * An array-based implementation of a hash map. It is very efficient in terms of performance and + * memory usage. Works like a dynamic array, adding elements to the end of the array, and + * allows you to access array elements by their index by using `get_by_index` method. + * Example: + * ``` + * AHashMap<int, Object *> map; + * + * int get_object_id_by_number(int p_number) { + * int id = map.get_index(p_number); + * return id; + * } + * + * Object *get_object_by_id(int p_id) { + * map.get_by_index(p_id).value; + * } + * ``` + * Still, don`t erase the elements because ID can break. + * + * When an element erase, its place is taken by the element from the end. + * + * <------------- + * | | + * 6 8 X 9 32 -1 5 -10 7 X X X + * 6 8 7 9 32 -1 5 -10 X X X X + * + * + * Use RBMap if you need to iterate over sorted elements. + * + * Use HashMap if: + * - You need to keep an iterator or const pointer to Key and you intend to add/remove elements in the meantime. + * - You need to preserve the insertion order when using erase. + * + * It is recommended to use `HashMap` if `KeyValue` size is very large. + */ +template <typename TKey, typename TValue, + typename Hasher = HashMapHasherDefault, + typename Comparator = HashMapComparatorDefault<TKey>> +class AHashMap { +public: + // Must be a power of two. + static constexpr uint32_t INITIAL_CAPACITY = 16; + static constexpr uint32_t EMPTY_HASH = 0; + static_assert(EMPTY_HASH == 0, "EMPTY_HASH must always be 0 for the memcpy() optimization."); + +private: + typedef KeyValue<TKey, TValue> MapKeyValue; + MapKeyValue *elements = nullptr; + HashMapData *map_data = nullptr; + + // Due to optimization, this is `capacity - 1`. Use + 1 to get normal capacity. + uint32_t capacity = 0; + uint32_t num_elements = 0; + + uint32_t _hash(const TKey &p_key) const { + uint32_t hash = Hasher::hash(p_key); + + if (unlikely(hash == EMPTY_HASH)) { + hash = EMPTY_HASH + 1; + } + + return hash; + } + + static _FORCE_INLINE_ uint32_t _get_resize_count(uint32_t p_capacity) { + return p_capacity ^ (p_capacity + 1) >> 2; // = get_capacity() * 0.75 - 1; Works only if p_capacity = 2^n - 1. + } + + static _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_local_capacity) { + const uint32_t original_pos = p_hash & p_local_capacity; + return (p_pos - original_pos + p_local_capacity + 1) & p_local_capacity; + } + + bool _lookup_pos(const TKey &p_key, uint32_t &r_pos, uint32_t &r_hash_pos) const { + if (unlikely(elements == nullptr)) { + return false; // Failed lookups, no elements. + } + return _lookup_pos_with_hash(p_key, r_pos, r_hash_pos, _hash(p_key)); + } + + bool _lookup_pos_with_hash(const TKey &p_key, uint32_t &r_pos, uint32_t &r_hash_pos, uint32_t p_hash) const { + if (unlikely(elements == nullptr)) { + return false; // Failed lookups, no elements. + } + + uint32_t pos = p_hash & capacity; + HashMapData data = map_data[pos]; + if (data.hash == p_hash && Comparator::compare(elements[data.hash_to_key].key, p_key)) { + r_pos = data.hash_to_key; + r_hash_pos = pos; + return true; + } + + if (data.data == EMPTY_HASH) { + return false; + } + + // A collision occurred. + pos = (pos + 1) & capacity; + uint32_t distance = 1; + while (true) { + data = map_data[pos]; + if (data.hash == p_hash && Comparator::compare(elements[data.hash_to_key].key, p_key)) { + r_pos = data.hash_to_key; + r_hash_pos = pos; + return true; + } + + if (data.data == EMPTY_HASH) { + return false; + } + + if (distance > _get_probe_length(pos, data.hash, capacity)) { + return false; + } + + pos = (pos + 1) & capacity; + distance++; + } + } + + uint32_t _insert_with_hash(uint32_t p_hash, uint32_t p_index) { + uint32_t pos = p_hash & capacity; + + if (map_data[pos].data == EMPTY_HASH) { + uint64_t data = ((uint64_t)p_index << 32) | p_hash; + map_data[pos].data = data; + return pos; + } + + uint32_t distance = 1; + pos = (pos + 1) & capacity; + HashMapData c_data; + c_data.hash = p_hash; + c_data.hash_to_key = p_index; + + while (true) { + if (map_data[pos].data == EMPTY_HASH) { +#ifdef DEV_ENABLED + if (unlikely(distance > 12)) { + WARN_PRINT("Excessive collision count (" + + itos(distance) + "), is the right hash function being used?"); + } +#endif + map_data[pos] = c_data; + return pos; + } + + // Not an empty slot, let's check the probing length of the existing one. + uint32_t existing_probe_len = _get_probe_length(pos, map_data[pos].hash, capacity); + if (existing_probe_len < distance) { + SWAP(c_data, map_data[pos]); + distance = existing_probe_len; + } + + pos = (pos + 1) & capacity; + distance++; + } + } + + void _resize_and_rehash(uint32_t p_new_capacity) { + uint32_t real_old_capacity = capacity + 1; + // Capacity can't be 0 and must be 2^n - 1. + capacity = MAX(4u, p_new_capacity); + uint32_t real_capacity = next_power_of_2(capacity); + capacity = real_capacity - 1; + + HashMapData *old_map_data = map_data; + + map_data = reinterpret_cast<HashMapData *>(Memory::alloc_static(sizeof(HashMapData) * real_capacity)); + elements = reinterpret_cast<MapKeyValue *>(Memory::realloc_static(elements, sizeof(MapKeyValue) * (_get_resize_count(capacity) + 1))); + + memset(map_data, EMPTY_HASH, real_capacity * sizeof(HashMapData)); + + if (num_elements != 0) { + for (uint32_t i = 0; i < real_old_capacity; i++) { + HashMapData data = old_map_data[i]; + if (data.data != EMPTY_HASH) { + _insert_with_hash(data.hash, data.hash_to_key); + } + } + } + + Memory::free_static(old_map_data); + } + + int32_t _insert_element(const TKey &p_key, const TValue &p_value, uint32_t p_hash) { + if (unlikely(elements == nullptr)) { + // Allocate on demand to save memory. + + uint32_t real_capacity = capacity + 1; + map_data = reinterpret_cast<HashMapData *>(Memory::alloc_static(sizeof(HashMapData) * real_capacity)); + elements = reinterpret_cast<MapKeyValue *>(Memory::alloc_static(sizeof(MapKeyValue) * (_get_resize_count(capacity) + 1))); + + memset(map_data, EMPTY_HASH, real_capacity * sizeof(HashMapData)); + } + + if (unlikely(num_elements > _get_resize_count(capacity))) { + _resize_and_rehash(capacity * 2); + } + + memnew_placement(&elements[num_elements], MapKeyValue(p_key, p_value)); + + _insert_with_hash(p_hash, num_elements); + num_elements++; + return num_elements - 1; + } + + void _init_from(const AHashMap &p_other) { + capacity = p_other.capacity; + uint32_t real_capacity = capacity + 1; + num_elements = p_other.num_elements; + + if (p_other.num_elements == 0) { + return; + } + + map_data = reinterpret_cast<HashMapData *>(Memory::alloc_static(sizeof(HashMapData) * real_capacity)); + elements = reinterpret_cast<MapKeyValue *>(Memory::alloc_static(sizeof(MapKeyValue) * (_get_resize_count(capacity) + 1))); + + if constexpr (std::is_trivially_copyable_v<TKey> && std::is_trivially_copyable_v<TValue>) { + void *destination = elements; + const void *source = p_other.elements; + memcpy(destination, source, sizeof(MapKeyValue) * num_elements); + } else { + for (uint32_t i = 0; i < num_elements; i++) { + memnew_placement(&elements[i], MapKeyValue(p_other.elements[i])); + } + } + + memcpy(map_data, p_other.map_data, sizeof(HashMapData) * real_capacity); + } + +public: + /* Standard Godot Container API */ + + _FORCE_INLINE_ uint32_t get_capacity() const { return capacity + 1; } + _FORCE_INLINE_ uint32_t size() const { return num_elements; } + + _FORCE_INLINE_ bool is_empty() const { + return num_elements == 0; + } + + void clear() { + if (elements == nullptr || num_elements == 0) { + return; + } + + memset(map_data, EMPTY_HASH, (capacity + 1) * sizeof(HashMapData)); + if constexpr (!(std::is_trivially_destructible_v<TKey> && std::is_trivially_destructible_v<TValue>)) { + for (uint32_t i = 0; i < num_elements; i++) { + elements[i].key.~TKey(); + elements[i].value.~TValue(); + } + } + + num_elements = 0; + } + + TValue &get(const TKey &p_key) { + uint32_t pos = 0; + uint32_t hash_pos = 0; + bool exists = _lookup_pos(p_key, pos, hash_pos); + CRASH_COND_MSG(!exists, "AHashMap key not found."); + return elements[pos].value; + } + + const TValue &get(const TKey &p_key) const { + uint32_t pos = 0; + uint32_t hash_pos = 0; + bool exists = _lookup_pos(p_key, pos, hash_pos); + CRASH_COND_MSG(!exists, "AHashMap key not found."); + return elements[pos].value; + } + + const TValue *getptr(const TKey &p_key) const { + uint32_t pos = 0; + uint32_t hash_pos = 0; + bool exists = _lookup_pos(p_key, pos, hash_pos); + + if (exists) { + return &elements[pos].value; + } + return nullptr; + } + + TValue *getptr(const TKey &p_key) { + uint32_t pos = 0; + uint32_t hash_pos = 0; + bool exists = _lookup_pos(p_key, pos, hash_pos); + + if (exists) { + return &elements[pos].value; + } + return nullptr; + } + + bool has(const TKey &p_key) const { + uint32_t _pos = 0; + uint32_t h_pos = 0; + return _lookup_pos(p_key, _pos, h_pos); + } + + bool erase(const TKey &p_key) { + uint32_t pos = 0; + uint32_t element_pos = 0; + bool exists = _lookup_pos(p_key, element_pos, pos); + + if (!exists) { + return false; + } + + uint32_t next_pos = (pos + 1) & capacity; + while (map_data[next_pos].hash != EMPTY_HASH && _get_probe_length(next_pos, map_data[next_pos].hash, capacity) != 0) { + SWAP(map_data[next_pos], map_data[pos]); + + pos = next_pos; + next_pos = (next_pos + 1) & capacity; + } + + map_data[pos].data = EMPTY_HASH; + elements[element_pos].key.~TKey(); + elements[element_pos].value.~TValue(); + num_elements--; + + if (element_pos < num_elements) { + void *destination = &elements[element_pos]; + const void *source = &elements[num_elements]; + memcpy(destination, source, sizeof(MapKeyValue)); + uint32_t h_pos = 0; + _lookup_pos(elements[num_elements].key, pos, h_pos); + map_data[h_pos].hash_to_key = element_pos; + } + + return true; + } + + // Replace the key of an entry in-place, without invalidating iterators or changing the entries position during iteration. + // p_old_key must exist in the map and p_new_key must not, unless it is equal to p_old_key. + bool replace_key(const TKey &p_old_key, const TKey &p_new_key) { + if (p_old_key == p_new_key) { + return true; + } + uint32_t pos = 0; + uint32_t element_pos = 0; + ERR_FAIL_COND_V(_lookup_pos(p_new_key, element_pos, pos), false); + ERR_FAIL_COND_V(!_lookup_pos(p_old_key, element_pos, pos), false); + MapKeyValue &element = elements[element_pos]; + const_cast<TKey &>(element.key) = p_new_key; + + uint32_t next_pos = (pos + 1) & capacity; + while (map_data[next_pos].hash != EMPTY_HASH && _get_probe_length(next_pos, map_data[next_pos].hash, capacity) != 0) { + SWAP(map_data[next_pos], map_data[pos]); + + pos = next_pos; + next_pos = (next_pos + 1) & capacity; + } + + map_data[pos].data = EMPTY_HASH; + + uint32_t hash = _hash(p_new_key); + _insert_with_hash(hash, element_pos); + + return true; + } + + // Reserves space for a number of elements, useful to avoid many resizes and rehashes. + // If adding a known (possibly large) number of elements at once, must be larger than old capacity. + void reserve(uint32_t p_new_capacity) { + ERR_FAIL_COND_MSG(p_new_capacity < get_capacity(), "It is impossible to reserve less capacity than is currently available."); + if (elements == nullptr) { + capacity = MAX(4u, p_new_capacity); + capacity = next_power_of_2(capacity) - 1; + return; // Unallocated yet. + } + _resize_and_rehash(p_new_capacity); + } + + /** Iterator API **/ + + struct ConstIterator { + _FORCE_INLINE_ const MapKeyValue &operator*() const { + return *pair; + } + _FORCE_INLINE_ const MapKeyValue *operator->() const { + return pair; + } + _FORCE_INLINE_ ConstIterator &operator++() { + pair++; + return *this; + } + + _FORCE_INLINE_ ConstIterator &operator--() { + pair--; + if (pair < begin) { + pair = end; + } + return *this; + } + + _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return pair == b.pair; } + _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return pair != b.pair; } + + _FORCE_INLINE_ explicit operator bool() const { + return pair != end; + } + + _FORCE_INLINE_ ConstIterator(MapKeyValue *p_key, MapKeyValue *p_begin, MapKeyValue *p_end) { + pair = p_key; + begin = p_begin; + end = p_end; + } + _FORCE_INLINE_ ConstIterator() {} + _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { + pair = p_it.pair; + begin = p_it.begin; + end = p_it.end; + } + _FORCE_INLINE_ void operator=(const ConstIterator &p_it) { + pair = p_it.pair; + begin = p_it.begin; + end = p_it.end; + } + + private: + MapKeyValue *pair = nullptr; + MapKeyValue *begin = nullptr; + MapKeyValue *end = nullptr; + }; + + struct Iterator { + _FORCE_INLINE_ MapKeyValue &operator*() const { + return *pair; + } + _FORCE_INLINE_ MapKeyValue *operator->() const { + return pair; + } + _FORCE_INLINE_ Iterator &operator++() { + pair++; + return *this; + } + _FORCE_INLINE_ Iterator &operator--() { + pair--; + if (pair < begin) { + pair = end; + } + return *this; + } + + _FORCE_INLINE_ bool operator==(const Iterator &b) const { return pair == b.pair; } + _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return pair != b.pair; } + + _FORCE_INLINE_ explicit operator bool() const { + return pair != end; + } + + _FORCE_INLINE_ Iterator(MapKeyValue *p_key, MapKeyValue *p_begin, MapKeyValue *p_end) { + pair = p_key; + begin = p_begin; + end = p_end; + } + _FORCE_INLINE_ Iterator() {} + _FORCE_INLINE_ Iterator(const Iterator &p_it) { + pair = p_it.pair; + begin = p_it.begin; + end = p_it.end; + } + _FORCE_INLINE_ void operator=(const Iterator &p_it) { + pair = p_it.pair; + begin = p_it.begin; + end = p_it.end; + } + + operator ConstIterator() const { + return ConstIterator(pair, begin, end); + } + + private: + MapKeyValue *pair = nullptr; + MapKeyValue *begin = nullptr; + MapKeyValue *end = nullptr; + }; + + _FORCE_INLINE_ Iterator begin() { + return Iterator(elements, elements, elements + num_elements); + } + _FORCE_INLINE_ Iterator end() { + return Iterator(elements + num_elements, elements, elements + num_elements); + } + _FORCE_INLINE_ Iterator last() { + if (unlikely(num_elements == 0)) { + return Iterator(nullptr, nullptr, nullptr); + } + return Iterator(elements + num_elements - 1, elements, elements + num_elements); + } + + Iterator find(const TKey &p_key) { + uint32_t pos = 0; + uint32_t h_pos = 0; + bool exists = _lookup_pos(p_key, pos, h_pos); + if (!exists) { + return end(); + } + return Iterator(elements + pos, elements, elements + num_elements); + } + + void remove(const Iterator &p_iter) { + if (p_iter) { + erase(p_iter->key); + } + } + + _FORCE_INLINE_ ConstIterator begin() const { + return ConstIterator(elements, elements, elements + num_elements); + } + _FORCE_INLINE_ ConstIterator end() const { + return ConstIterator(elements + num_elements, elements, elements + num_elements); + } + _FORCE_INLINE_ ConstIterator last() const { + if (unlikely(num_elements == 0)) { + return ConstIterator(nullptr, nullptr, nullptr); + } + return ConstIterator(elements + num_elements - 1, elements, elements + num_elements); + } + + ConstIterator find(const TKey &p_key) const { + uint32_t pos = 0; + uint32_t h_pos = 0; + bool exists = _lookup_pos(p_key, pos, h_pos); + if (!exists) { + return end(); + } + return ConstIterator(elements + pos, elements, elements + num_elements); + } + + /* Indexing */ + + const TValue &operator[](const TKey &p_key) const { + uint32_t pos = 0; + uint32_t h_pos = 0; + bool exists = _lookup_pos(p_key, pos, h_pos); + CRASH_COND(!exists); + return elements[pos].value; + } + + TValue &operator[](const TKey &p_key) { + uint32_t pos = 0; + uint32_t h_pos = 0; + uint32_t hash = _hash(p_key); + bool exists = _lookup_pos_with_hash(p_key, pos, h_pos, hash); + + if (exists) { + return elements[pos].value; + } else { + pos = _insert_element(p_key, TValue(), hash); + return elements[pos].value; + } + } + + /* Insert */ + + Iterator insert(const TKey &p_key, const TValue &p_value) { + uint32_t pos = 0; + uint32_t h_pos = 0; + uint32_t hash = _hash(p_key); + bool exists = _lookup_pos_with_hash(p_key, pos, h_pos, hash); + + if (!exists) { + pos = _insert_element(p_key, p_value, hash); + } else { + elements[pos].value = p_value; + } + return Iterator(elements + pos, elements, elements + num_elements); + } + + // Inserts an element without checking if it already exists. + Iterator insert_new(const TKey &p_key, const TValue &p_value) { + DEV_ASSERT(!has(p_key)); + uint32_t hash = _hash(p_key); + uint32_t pos = _insert_element(p_key, p_value, hash); + return Iterator(elements + pos, elements, elements + num_elements); + } + + /* Array methods. */ + + // Unsafe. Changing keys and going outside the bounds of an array can lead to undefined behavior. + KeyValue<TKey, TValue> *get_elements_ptr() { + return elements; + } + + // Returns the element index. If not found, returns -1. + int get_index(const TKey &p_key) { + uint32_t pos = 0; + uint32_t h_pos = 0; + bool exists = _lookup_pos(p_key, pos, h_pos); + if (!exists) { + return -1; + } + return pos; + } + + KeyValue<TKey, TValue> &get_by_index(uint32_t p_index) { + CRASH_BAD_UNSIGNED_INDEX(p_index, num_elements); + return elements[p_index]; + } + + bool erase_by_index(uint32_t p_index) { + if (p_index >= size()) { + return false; + } + return erase(elements[p_index].key); + } + + /* Constructors */ + + AHashMap(const AHashMap &p_other) { + _init_from(p_other); + } + + AHashMap(const HashMap<TKey, TValue> &p_other) { + reserve(p_other.size()); + for (const KeyValue<TKey, TValue> &E : p_other) { + uint32_t hash = _hash(E.key); + _insert_element(E.key, E.value, hash); + } + } + + void operator=(const AHashMap &p_other) { + if (this == &p_other) { + return; // Ignore self assignment. + } + + reset(); + + _init_from(p_other); + } + + void operator=(const HashMap<TKey, TValue> &p_other) { + reset(); + if (p_other.size() > get_capacity()) { + reserve(p_other.size()); + } + for (const KeyValue<TKey, TValue> &E : p_other) { + uint32_t hash = _hash(E.key); + _insert_element(E.key, E.value, hash); + } + } + + AHashMap(uint32_t p_initial_capacity) { + // Capacity can't be 0 and must be 2^n - 1. + capacity = MAX(4u, p_initial_capacity); + capacity = next_power_of_2(capacity) - 1; + } + AHashMap() : + capacity(INITIAL_CAPACITY - 1) { + } + + void reset() { + if (elements != nullptr) { + if constexpr (!(std::is_trivially_destructible_v<TKey> && std::is_trivially_destructible_v<TValue>)) { + for (uint32_t i = 0; i < num_elements; i++) { + elements[i].key.~TKey(); + elements[i].value.~TValue(); + } + } + Memory::free_static(elements); + Memory::free_static(map_data); + elements = nullptr; + } + capacity = INITIAL_CAPACITY - 1; + num_elements = 0; + } + + ~AHashMap() { + reset(); + } +}; + +extern template class AHashMap<int, int>; +extern template class AHashMap<String, int>; +extern template class AHashMap<StringName, StringName>; +extern template class AHashMap<StringName, Variant>; +extern template class AHashMap<StringName, int>; + +#endif // A_HASH_MAP_H diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h index fedcfaec3b..5f260ee870 100644 --- a/core/templates/cowdata.h +++ b/core/templates/cowdata.h @@ -241,7 +241,7 @@ public: _FORCE_INLINE_ CowData() {} _FORCE_INLINE_ ~CowData(); - _FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }; + _FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); } }; template <typename T> diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h index 21eef10297..e681835c5a 100644 --- a/core/templates/hashfuncs.h +++ b/core/templates/hashfuncs.h @@ -110,6 +110,16 @@ static _FORCE_INLINE_ uint32_t hash_one_uint64(const uint64_t p_int) { return uint32_t(v); } +static _FORCE_INLINE_ uint64_t hash64_murmur3_64(uint64_t key, uint64_t seed) { + key ^= seed; + key ^= key >> 33; + key *= 0xff51afd7ed558ccd; + key ^= key >> 33; + key *= 0xc4ceb9fe1a85ec53; + key ^= key >> 33; + return key; +} + #define HASH_MURMUR3_SEED 0x7F07C65 // Murmurhash3 32-bit version. // All MurmurHash versions are public domain software, and the author disclaims all copyright to their code. @@ -393,6 +403,13 @@ struct HashMapHasherDefault { } }; +struct HashHasher { + static _FORCE_INLINE_ uint32_t hash(const int32_t hash) { return hash; } + static _FORCE_INLINE_ uint32_t hash(const uint32_t hash) { return hash; } + static _FORCE_INLINE_ uint64_t hash(const int64_t hash) { return hash; } + static _FORCE_INLINE_ uint64_t hash(const uint64_t hash) { return hash; } +}; + // TODO: Fold this into HashMapHasherDefault once C++20 concepts are allowed template <typename T> struct HashableHasher { diff --git a/core/templates/list.h b/core/templates/list.h index 6663f06c30..02afeec74d 100644 --- a/core/templates/list.h +++ b/core/templates/list.h @@ -224,7 +224,7 @@ private: Element *last = nullptr; int size_cache = 0; - bool erase(const Element *p_I) { + bool erase(Element *p_I) { ERR_FAIL_NULL_V(p_I, false); ERR_FAIL_COND_V(p_I->data != this, false); @@ -244,7 +244,7 @@ private: p_I->next_ptr->prev_ptr = p_I->prev_ptr; } - memdelete_allocator<Element, A>(const_cast<Element *>(p_I)); + memdelete_allocator<Element, A>(p_I); size_cache--; return true; @@ -430,7 +430,7 @@ public: /** * erase an element in the list, by iterator pointing to it. Return true if it was found/erased. */ - bool erase(const Element *p_I) { + bool erase(Element *p_I) { if (_data && p_I) { bool ret = _data->erase(p_I); diff --git a/core/templates/lru.h b/core/templates/lru.h index 919c5605aa..7f48c3b2e8 100644 --- a/core/templates/lru.h +++ b/core/templates/lru.h @@ -35,9 +35,21 @@ #include "hash_map.h" #include "list.h" -template <typename TKey, typename TData, typename Hasher = HashMapHasherDefault, typename Comparator = HashMapComparatorDefault<TKey>> +#if defined(__GNUC__) && !defined(__clang__) +#define ADDRESS_DIAGNOSTIC_WARNING_DISABLE \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Waddress\""); + +#define ADDRESS_DIAGNOSTIC_POP \ + _Pragma("GCC diagnostic pop"); +#else +#define ADDRESS_DIAGNOSTIC_WARNING_DISABLE +#define ADDRESS_DIAGNOSTIC_POP +#endif + +template <typename TKey, typename TData, typename Hasher = HashMapHasherDefault, typename Comparator = HashMapComparatorDefault<TKey>, void (*BeforeEvict)(TKey &, TData &) = nullptr> class LRUCache { -private: +public: struct Pair { TKey key; TData data; @@ -51,16 +63,22 @@ private: typedef typename List<Pair>::Element *Element; +private: List<Pair> _list; HashMap<TKey, Element, Hasher, Comparator> _map; size_t capacity; public: - const TData *insert(const TKey &p_key, const TData &p_value) { + const Pair *insert(const TKey &p_key, const TData &p_value) { Element *e = _map.getptr(p_key); Element n = _list.push_front(Pair(p_key, p_value)); if (e) { + ADDRESS_DIAGNOSTIC_WARNING_DISABLE; + if constexpr (BeforeEvict != nullptr) { + BeforeEvict((*e)->get().key, (*e)->get().data); + } + ADDRESS_DIAGNOSTIC_POP; _list.erase(*e); _map.erase(p_key); } @@ -68,11 +86,16 @@ public: while (_map.size() > capacity) { Element d = _list.back(); + ADDRESS_DIAGNOSTIC_WARNING_DISABLE + if constexpr (BeforeEvict != nullptr) { + BeforeEvict(d->get().key, d->get().data); + } + ADDRESS_DIAGNOSTIC_POP _map.erase(d->get().key); _list.pop_back(); } - return &n->get().data; + return &n->get(); } void clear() { @@ -84,12 +107,23 @@ public: return _map.getptr(p_key); } + bool erase(const TKey &p_key) { + Element *e = _map.getptr(p_key); + if (!e) { + return false; + } + _list.move_to_front(*e); + _map.erase(p_key); + _list.pop_front(); + return true; + } + const TData &get(const TKey &p_key) { Element *e = _map.getptr(p_key); CRASH_COND(!e); _list.move_to_front(*e); return (*e)->get().data; - }; + } const TData *getptr(const TKey &p_key) { Element *e = _map.getptr(p_key); @@ -109,6 +143,11 @@ public: capacity = p_capacity; while (_map.size() > capacity) { Element d = _list.back(); + ADDRESS_DIAGNOSTIC_WARNING_DISABLE; + if constexpr (BeforeEvict != nullptr) { + BeforeEvict(d->get().key, d->get().data); + } + ADDRESS_DIAGNOSTIC_POP; _map.erase(d->get().key); _list.pop_back(); } @@ -124,4 +163,7 @@ public: } }; +#undef ADDRESS_DIAGNOSTIC_WARNING_DISABLE +#undef ADDRESS_DIAGNOSTIC_POP + #endif // LRU_H diff --git a/core/templates/rb_set.h b/core/templates/rb_set.h index ac7a8df36a..1b69f2f0c2 100644 --- a/core/templates/rb_set.h +++ b/core/templates/rb_set.h @@ -76,7 +76,7 @@ public: } const T &get() const { return value; - }; + } Element() {} }; diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 3e62d3dffa..f7a86b8fa3 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -385,7 +385,7 @@ int Array::find_custom(const Callable &p_callable, int p_from) const { Callable::CallError ce; p_callable.callp(argptrs, 1, res, ce); if (unlikely(ce.error != Callable::CallError::CALL_OK)) { - ERR_FAIL_V_MSG(ret, "Error calling method from 'find_custom': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + ERR_FAIL_V_MSG(ret, vformat("Error calling method from 'find_custom': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce))); } ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, ret, "Error on method from 'find_custom': Return type of callable must be boolean."); @@ -445,7 +445,7 @@ int Array::rfind_custom(const Callable &p_callable, int p_from) const { Callable::CallError ce; p_callable.callp(argptrs, 1, res, ce); if (unlikely(ce.error != Callable::CallError::CALL_OK)) { - ERR_FAIL_V_MSG(-1, "Error calling method from 'rfind_custom': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + ERR_FAIL_V_MSG(-1, vformat("Error calling method from 'rfind_custom': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce))); } ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, -1, "Error on method from 'rfind_custom': Return type of callable must be boolean."); @@ -574,7 +574,7 @@ Array Array::filter(const Callable &p_callable) const { Callable::CallError ce; p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(Array(), "Error calling method from 'filter': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + ERR_FAIL_V_MSG(Array(), vformat("Error calling method from 'filter': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce))); } if (result.operator bool()) { @@ -600,7 +600,7 @@ Array Array::map(const Callable &p_callable) const { Callable::CallError ce; p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(Array(), "Error calling method from 'map': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + ERR_FAIL_V_MSG(Array(), vformat("Error calling method from 'map': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce))); } new_arr[i] = result; @@ -626,7 +626,7 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const Callable::CallError ce; p_callable.callp(argptrs, 2, result, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(Variant(), "Error calling method from 'reduce': " + Variant::get_callable_error_text(p_callable, argptrs, 2, ce)); + ERR_FAIL_V_MSG(Variant(), vformat("Error calling method from 'reduce': %s.", Variant::get_callable_error_text(p_callable, argptrs, 2, ce))); } ret = result; } @@ -643,7 +643,7 @@ bool Array::any(const Callable &p_callable) const { Callable::CallError ce; p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + ERR_FAIL_V_MSG(false, vformat("Error calling method from 'any': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce))); } if (result.operator bool()) { @@ -665,7 +665,7 @@ bool Array::all(const Callable &p_callable) const { Callable::CallError ce; p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + ERR_FAIL_V_MSG(false, vformat("Error calling method from 'all': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce))); } if (!(result.operator bool())) { diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp index 5ce90cd8ff..ddeea27118 100644 --- a/core/variant/callable.cpp +++ b/core/variant/callable.cpp @@ -206,19 +206,17 @@ int Callable::get_bound_arguments_count() const { } } -void Callable::get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const { +void Callable::get_bound_arguments_ref(Vector<Variant> &r_arguments) const { if (!is_null() && is_custom()) { - custom->get_bound_arguments(r_arguments, r_argcount); + custom->get_bound_arguments(r_arguments); } else { r_arguments.clear(); - r_argcount = 0; } } Array Callable::get_bound_arguments() const { Vector<Variant> arr; - int ac; - get_bound_arguments_ref(arr, ac); + get_bound_arguments_ref(arr); Array ret; ret.resize(arr.size()); for (int i = 0; i < arr.size(); i++) { @@ -227,6 +225,14 @@ Array Callable::get_bound_arguments() const { return ret; } +int Callable::get_unbound_arguments_count() const { + if (!is_null() && is_custom()) { + return custom->get_unbound_arguments_count(); + } else { + return 0; + } +} + CallableCustom *Callable::get_custom() const { ERR_FAIL_COND_V_MSG(!is_custom(), nullptr, vformat("Can't get custom on non-CallableCustom \"%s\".", operator String())); @@ -464,9 +470,12 @@ int CallableCustom::get_bound_arguments_count() const { return 0; } -void CallableCustom::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const { - r_arguments = Vector<Variant>(); - r_argcount = 0; +void CallableCustom::get_bound_arguments(Vector<Variant> &r_arguments) const { + r_arguments.clear(); +} + +int CallableCustom::get_unbound_arguments_count() const { + return 0; } CallableCustom::CallableCustom() { diff --git a/core/variant/callable.h b/core/variant/callable.h index e3c940a0e5..e76b888ac2 100644 --- a/core/variant/callable.h +++ b/core/variant/callable.h @@ -111,8 +111,9 @@ public: CallableCustom *get_custom() const; int get_argument_count(bool *r_is_valid = nullptr) const; int get_bound_arguments_count() const; - void get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const; // Internal engine use, the exposed one is below. + void get_bound_arguments_ref(Vector<Variant> &r_arguments) const; // Internal engine use, the exposed one is below. Array get_bound_arguments() const; + int get_unbound_arguments_count() const; uint32_t hash() const; @@ -158,7 +159,8 @@ public: virtual const Callable *get_base_comparator() const; virtual int get_argument_count(bool &r_is_valid) const; virtual int get_bound_arguments_count() const; - virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const; + virtual void get_bound_arguments(Vector<Variant> &r_arguments) const; + virtual int get_unbound_arguments_count() const; CallableCustom(); virtual ~CallableCustom() {} diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp index d82aa3583d..43cac263c1 100644 --- a/core/variant/callable_bind.cpp +++ b/core/variant/callable_bind.cpp @@ -43,7 +43,7 @@ bool CallableCustomBind::_equal_func(const CallableCustom *p_a, const CallableCu const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a); const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b); - if (!(a->callable != b->callable)) { + if (a->callable != b->callable) { return false; } @@ -100,44 +100,42 @@ int CallableCustomBind::get_argument_count(bool &r_is_valid) const { } int CallableCustomBind::get_bound_arguments_count() const { - return callable.get_bound_arguments_count() + binds.size(); + return callable.get_bound_arguments_count() + MAX(0, binds.size() - callable.get_unbound_arguments_count()); } -void CallableCustomBind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const { - Vector<Variant> sub_args; - int sub_count; - callable.get_bound_arguments_ref(sub_args, sub_count); +void CallableCustomBind::get_bound_arguments(Vector<Variant> &r_arguments) const { + Vector<Variant> sub_bound_args; + callable.get_bound_arguments_ref(sub_bound_args); + int sub_bound_count = sub_bound_args.size(); - if (sub_count == 0) { + int sub_unbound_count = callable.get_unbound_arguments_count(); + + if (sub_bound_count == 0 && sub_unbound_count == 0) { r_arguments = binds; - r_argcount = binds.size(); return; } - int new_count = sub_count + binds.size(); - r_argcount = new_count; + int added_count = MAX(0, binds.size() - sub_unbound_count); + int new_count = sub_bound_count + added_count; - if (new_count <= 0) { - // Removed more arguments than it adds. - r_arguments = Vector<Variant>(); + if (added_count <= 0) { + // All added arguments are consumed by `sub_unbound_count`. + r_arguments = sub_bound_args; return; } r_arguments.resize(new_count); - - if (sub_count > 0) { - for (int i = 0; i < sub_count; i++) { - r_arguments.write[i] = sub_args[i]; - } - for (int i = 0; i < binds.size(); i++) { - r_arguments.write[i + sub_count] = binds[i]; - } - r_argcount = new_count; - } else { - for (int i = 0; i < binds.size() + sub_count; i++) { - r_arguments.write[i] = binds[i - sub_count]; - } + Variant *args = r_arguments.ptrw(); + for (int i = 0; i < added_count; i++) { + args[i] = binds[i]; } + for (int i = 0; i < sub_bound_count; i++) { + args[i + added_count] = sub_bound_args[i]; + } +} + +int CallableCustomBind::get_unbound_arguments_count() const { + return MAX(0, callable.get_unbound_arguments_count() - binds.size()); } void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { @@ -185,7 +183,7 @@ bool CallableCustomUnbind::_equal_func(const CallableCustom *p_a, const Callable const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a); const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b); - if (!(a->callable != b->callable)) { + if (a->callable != b->callable) { return false; } @@ -242,22 +240,15 @@ int CallableCustomUnbind::get_argument_count(bool &r_is_valid) const { } int CallableCustomUnbind::get_bound_arguments_count() const { - return callable.get_bound_arguments_count() - argcount; + return callable.get_bound_arguments_count(); } -void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const { - Vector<Variant> sub_args; - int sub_count; - callable.get_bound_arguments_ref(sub_args, sub_count); - - r_argcount = sub_args.size() - argcount; +void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments) const { + callable.get_bound_arguments_ref(r_arguments); +} - if (argcount >= sub_args.size()) { - r_arguments = Vector<Variant>(); - } else { - sub_args.resize(sub_args.size() - argcount); - r_arguments = sub_args; - } +int CallableCustomUnbind::get_unbound_arguments_count() const { + return callable.get_unbound_arguments_count() + argcount; } void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h index 43cebb45f0..1346277197 100644 --- a/core/variant/callable_bind.h +++ b/core/variant/callable_bind.h @@ -55,7 +55,8 @@ public: virtual const Callable *get_base_comparator() const override; virtual int get_argument_count(bool &r_is_valid) const override; virtual int get_bound_arguments_count() const override; - virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override; + virtual void get_bound_arguments(Vector<Variant> &r_arguments) const override; + virtual int get_unbound_arguments_count() const override; Callable get_callable() { return callable; } Vector<Variant> get_binds() { return binds; } @@ -84,7 +85,8 @@ public: virtual const Callable *get_base_comparator() const override; virtual int get_argument_count(bool &r_is_valid) const override; virtual int get_bound_arguments_count() const override; - virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override; + virtual void get_bound_arguments(Vector<Variant> &r_arguments) const override; + virtual int get_unbound_arguments_count() const override; Callable get_callable() { return callable; } int get_unbinds() { return argcount; } diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h index 0a23c69cb4..8971fadf73 100644 --- a/core/variant/container_type_validate.h +++ b/core/variant/container_type_validate.h @@ -94,7 +94,7 @@ struct ContainerTypeValidate { return true; } - ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(inout_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'."); + ERR_FAIL_V_MSG(false, vformat("Attempted to %s a variable of type '%s' into a %s of type '%s'.", String(p_operation), Variant::get_type_name(inout_variant.get_type()), where, Variant::get_type_name(type))); } if (type != Variant::OBJECT) { @@ -113,7 +113,7 @@ struct ContainerTypeValidate { return true; // This is fine, it's null. } Object *object = ObjectDB::get_instance(object_id); - ERR_FAIL_NULL_V_MSG(object, false, "Attempted to " + String(p_operation) + " an invalid (previously freed?) object instance into a '" + String(where) + "."); + ERR_FAIL_NULL_V_MSG(object, false, vformat("Attempted to %s an invalid (previously freed?) object instance into a '%s'.", String(p_operation), String(where))); #else Object *object = p_variant; if (object == nullptr) { @@ -126,7 +126,7 @@ struct ContainerTypeValidate { StringName obj_class = object->get_class_name(); if (obj_class != class_name) { - ERR_FAIL_COND_V_MSG(!ClassDB::is_parent_class(object->get_class_name(), class_name), false, "Attempted to " + String(p_operation) + " an object of type '" + object->get_class() + "' into a " + where + ", which does not inherit from '" + String(class_name) + "'."); + ERR_FAIL_COND_V_MSG(!ClassDB::is_parent_class(object->get_class_name(), class_name), false, vformat("Attempted to %s an object of type '%s' into a %s, which does not inherit from '%s'.", String(p_operation), object->get_class(), where, String(class_name))); } if (script.is_null()) { @@ -136,8 +136,8 @@ struct ContainerTypeValidate { Ref<Script> other_script = object->get_script(); // Check base script.. - ERR_FAIL_COND_V_MSG(other_script.is_null(), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'."); - ERR_FAIL_COND_V_MSG(!other_script->inherits_script(script), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'."); + ERR_FAIL_COND_V_MSG(other_script.is_null(), false, vformat("Attempted to %s an object into a %s, that does not inherit from '%s'.", String(p_operation), String(where), String(script->get_class_name()))); + ERR_FAIL_COND_V_MSG(!other_script->inherits_script(script), false, vformat("Attempted to %s an object into a %s, that does not inherit from '%s'.", String(p_operation), String(where), String(script->get_class_name()))); return true; } diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index e2865a06be..8aca56c1d5 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -951,7 +951,7 @@ bool Variant::is_zero() const { return *reinterpret_cast<const ::RID *>(_data._mem) == ::RID(); } case OBJECT: { - return _get_obj().obj == nullptr; + return get_validated_object() == nullptr; } case CALLABLE: { return reinterpret_cast<const Callable *>(_data._mem)->is_null(); @@ -1736,7 +1736,7 @@ String Variant::stringify(int recursion_count) const { case INT: return itos(_data._int); case FLOAT: - return rtos(_data._float); + return String::num_real(_data._float, true); case STRING: return *reinterpret_cast<const String *>(_data._mem); case VECTOR2: @@ -2719,8 +2719,7 @@ Variant::Variant(const Vector<Plane> &p_array) : } } -Variant::Variant(const Vector<Face3> &p_face_array) : - type(NIL) { +Variant::Variant(const Vector<Face3> &p_face_array) { PackedVector3Array vertices; int face_count = p_face_array.size(); vertices.resize(face_count * 3); @@ -2739,8 +2738,7 @@ Variant::Variant(const Vector<Face3> &p_face_array) : *this = vertices; } -Variant::Variant(const Vector<Variant> &p_array) : - type(NIL) { +Variant::Variant(const Vector<Variant> &p_array) { Array arr; arr.resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { @@ -2749,8 +2747,7 @@ Variant::Variant(const Vector<Variant> &p_array) : *this = arr; } -Variant::Variant(const Vector<StringName> &p_array) : - type(NIL) { +Variant::Variant(const Vector<StringName> &p_array) { PackedStringArray v; int len = p_array.size(); v.resize(len); @@ -2908,8 +2905,7 @@ Variant::Variant(const IPAddress &p_address) : memnew_placement(_data._mem, String(p_address)); } -Variant::Variant(const Variant &p_variant) : - type(NIL) { +Variant::Variant(const Variant &p_variant) { reference(p_variant); } @@ -3564,9 +3560,6 @@ bool Variant::is_ref_counted() const { return type == OBJECT && _get_obj().id.is_ref_counted(); } -void Variant::static_assign(const Variant &p_variant) { -} - bool Variant::is_type_shared(Variant::Type p_type) { switch (p_type) { case OBJECT: @@ -3668,18 +3661,20 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method, String Variant::get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) { Vector<Variant> binds; - int args_bound; - p_callable.get_bound_arguments_ref(binds, args_bound); - if (args_bound <= 0) { - return get_call_error_text(p_callable.get_object(), p_callable.get_method(), p_argptrs, MAX(0, p_argcount + args_bound), ce); + p_callable.get_bound_arguments_ref(binds); + + int args_unbound = p_callable.get_unbound_arguments_count(); + + if (p_argcount - args_unbound < 0) { + return "Callable unbinds " + itos(args_unbound) + " arguments, but called with " + itos(p_argcount); } else { Vector<const Variant *> argptrs; - argptrs.resize(p_argcount + binds.size()); - for (int i = 0; i < p_argcount; i++) { + argptrs.resize(p_argcount - args_unbound + binds.size()); + for (int i = 0; i < p_argcount - args_unbound; i++) { argptrs.write[i] = p_argptrs[i]; } for (int i = 0; i < binds.size(); i++) { - argptrs.write[i + p_argcount] = &binds[i]; + argptrs.write[i + p_argcount - args_unbound] = &binds[i]; } return get_call_error_text(p_callable.get_object(), p_callable.get_method(), (const Variant **)argptrs.ptr(), argptrs.size(), ce); } diff --git a/core/variant/variant.h b/core/variant/variant.h index c76b849abd..babd2cf084 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -792,7 +792,6 @@ public: String stringify(int recursion_count = 0) const; String to_json_string() const; - void static_assign(const Variant &p_variant); static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants); static int get_constants_count_for_type(Variant::Type p_type); static bool has_constant(Variant::Type p_type, const StringName &p_value); @@ -801,6 +800,8 @@ public: static void get_enums_for_type(Variant::Type p_type, List<StringName> *p_enums); static void get_enumerations_for_enum(Variant::Type p_type, const StringName &p_enum_name, List<StringName> *p_enumerations); static int get_enum_value(Variant::Type p_type, const StringName &p_enum_name, const StringName &p_enumeration, bool *r_valid = nullptr); + static bool has_enum(Variant::Type p_type, const StringName &p_enum_name); + static StringName get_enum_for_enumeration(Variant::Type p_type, const StringName &p_enumeration); typedef String (*ObjectDeConstruct)(const Variant &p_object, void *ud); typedef void (*ObjectConstruct)(const String &p_text, void *ud, Variant &r_value); @@ -814,8 +815,7 @@ public: static void unregister_types(); Variant(const Variant &p_variant); - _FORCE_INLINE_ Variant() : - type(NIL) {} + _FORCE_INLINE_ Variant() {} _FORCE_INLINE_ ~Variant() { clear(); } @@ -854,6 +854,19 @@ struct StringLikeVariantComparator { static bool compare(const Variant &p_lhs, const Variant &p_rhs); }; +struct StringLikeVariantOrder { + static _ALWAYS_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) { + if (p_lhs.is_string() && p_rhs.is_string()) { + return p_lhs.operator String() < p_rhs.operator String(); + } + return p_lhs < p_rhs; + } + + _ALWAYS_INLINE_ bool operator()(const Variant &p_lhs, const Variant &p_rhs) const { + return compare(p_lhs, p_rhs); + } +}; + Variant::ObjData &Variant::_get_obj() { return *reinterpret_cast<ObjData *>(&_data._mem[0]); } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 29e11462c9..d612cb9cea 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1091,6 +1091,11 @@ struct _VariantCall { static ConstantData *constant_data; static void add_constant(int p_type, const StringName &p_constant_name, int64_t p_constant_value) { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(constant_data[p_type].value.has(p_constant_name)); + ERR_FAIL_COND(enum_data[p_type].value.has(p_constant_name)); + ERR_FAIL_COND(enum_data[p_type].value_to_enum.has(p_constant_name)); +#endif constant_data[p_type].value[p_constant_name] = p_constant_value; #ifdef DEBUG_ENABLED constant_data[p_type].value_ordered.push_back(p_constant_name); @@ -1106,12 +1111,19 @@ struct _VariantCall { struct EnumData { HashMap<StringName, HashMap<StringName, int>> value; + HashMap<StringName, StringName> value_to_enum; }; static EnumData *enum_data; static void add_enum_constant(int p_type, const StringName &p_enum_type_name, const StringName &p_enumeration_name, int p_enum_value) { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(constant_data[p_type].value.has(p_enumeration_name)); + ERR_FAIL_COND(enum_data[p_type].value.has(p_enumeration_name)); + ERR_FAIL_COND(enum_data[p_type].value_to_enum.has(p_enumeration_name)); +#endif enum_data[p_type].value[p_enum_type_name][p_enumeration_name] = p_enum_value; + enum_data[p_type].value_to_enum[p_enumeration_name] = p_enum_type_name; } }; @@ -1561,6 +1573,23 @@ int Variant::get_enum_value(Variant::Type p_type, const StringName &p_enum_name, return V->value; } +bool Variant::has_enum(Variant::Type p_type, const StringName &p_enum_name) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + + _VariantCall::EnumData &enum_data = _VariantCall::enum_data[p_type]; + + return enum_data.value.has(p_enum_name); +} + +StringName Variant::get_enum_for_enumeration(Variant::Type p_type, const StringName &p_enumeration) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, StringName()); + + _VariantCall::EnumData &enum_data = _VariantCall::enum_data[p_type]; + + const StringName *enum_name = enum_data.value_to_enum.getptr(p_enumeration); + return (enum_name == nullptr) ? StringName() : *enum_name; +} + #ifdef DEBUG_METHODS_ENABLED #define bind_method(m_type, m_method, m_arg_names, m_default_args) \ METHOD_CLASS(m_type, m_method, &m_type::m_method); \ @@ -2116,6 +2145,7 @@ static void _register_variant_builtin_methods_misc() { bind_function(Callable, get_argument_count, _VariantCall::func_Callable_get_argument_count, sarray(), varray()); bind_method(Callable, get_bound_arguments_count, sarray(), varray()); bind_method(Callable, get_bound_arguments, sarray(), varray()); + bind_method(Callable, get_unbound_arguments_count, sarray(), varray()); bind_method(Callable, hash, sarray(), varray()); bind_method(Callable, bindv, sarray("arguments"), varray()); bind_method(Callable, unbind, sarray("argcount"), varray()); @@ -2659,10 +2689,6 @@ static void _register_variant_builtin_constants() { _VariantCall::add_variant_constant(Variant::COLOR, Color::get_named_color_name(i), Color::get_named_color(i)); } - _VariantCall::add_constant(Variant::VECTOR3, "AXIS_X", Vector3::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Y", Vector3::AXIS_Y); - _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Z", Vector3::AXIS_Z); - _VariantCall::add_enum_constant(Variant::VECTOR3, "Axis", "AXIS_X", Vector3::AXIS_X); _VariantCall::add_enum_constant(Variant::VECTOR3, "Axis", "AXIS_Y", Vector3::AXIS_Y); _VariantCall::add_enum_constant(Variant::VECTOR3, "Axis", "AXIS_Z", Vector3::AXIS_Z); @@ -2684,32 +2710,19 @@ static void _register_variant_builtin_constants() { _VariantCall::add_variant_constant(Variant::VECTOR3, "MODEL_FRONT", Vector3(0, 0, 1)); _VariantCall::add_variant_constant(Variant::VECTOR3, "MODEL_REAR", Vector3(0, 0, -1)); - _VariantCall::add_constant(Variant::VECTOR4, "AXIS_X", Vector4::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR4, "AXIS_Y", Vector4::AXIS_Y); - _VariantCall::add_constant(Variant::VECTOR4, "AXIS_Z", Vector4::AXIS_Z); - _VariantCall::add_constant(Variant::VECTOR4, "AXIS_W", Vector4::AXIS_W); - _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_X", Vector4::AXIS_X); _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_Y", Vector4::AXIS_Y); _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_Z", Vector4::AXIS_Z); _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_W", Vector4::AXIS_W); + _VariantCall::add_variant_constant(Variant::VECTOR4, "ZERO", Vector4(0, 0, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR4, "ONE", Vector4(1, 1, 1, 1)); _VariantCall::add_variant_constant(Variant::VECTOR4, "INF", Vector4(INFINITY, INFINITY, INFINITY, INFINITY)); - _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3i::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3i::AXIS_Y); - _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3i::AXIS_Z); - _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_X", Vector3i::AXIS_X); _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Y", Vector3i::AXIS_Y); _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Z", Vector3i::AXIS_Z); - _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_X", Vector4i::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_Y", Vector4i::AXIS_Y); - _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_Z", Vector4i::AXIS_Z); - _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_W", Vector4i::AXIS_W); - _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_X", Vector4i::AXIS_X); _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_Y", Vector4i::AXIS_Y); _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_Z", Vector4i::AXIS_Z); @@ -2731,15 +2744,9 @@ static void _register_variant_builtin_constants() { _VariantCall::add_variant_constant(Variant::VECTOR3I, "FORWARD", Vector3i(0, 0, -1)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "BACK", Vector3i(0, 0, 1)); - _VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y); - _VariantCall::add_enum_constant(Variant::VECTOR2, "Axis", "AXIS_X", Vector2::AXIS_X); _VariantCall::add_enum_constant(Variant::VECTOR2, "Axis", "AXIS_Y", Vector2::AXIS_Y); - _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_X", Vector2i::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_Y", Vector2i::AXIS_Y); - _VariantCall::add_enum_constant(Variant::VECTOR2I, "Axis", "AXIS_X", Vector2i::AXIS_X); _VariantCall::add_enum_constant(Variant::VECTOR2I, "Axis", "AXIS_Y", Vector2i::AXIS_Y); @@ -2788,13 +2795,6 @@ static void _register_variant_builtin_constants() { _VariantCall::add_variant_constant(Variant::QUATERNION, "IDENTITY", Quaternion(0, 0, 0, 1)); - _VariantCall::add_constant(Variant::PROJECTION, "PLANE_NEAR", Projection::PLANE_NEAR); - _VariantCall::add_constant(Variant::PROJECTION, "PLANE_FAR", Projection::PLANE_FAR); - _VariantCall::add_constant(Variant::PROJECTION, "PLANE_LEFT", Projection::PLANE_LEFT); - _VariantCall::add_constant(Variant::PROJECTION, "PLANE_TOP", Projection::PLANE_TOP); - _VariantCall::add_constant(Variant::PROJECTION, "PLANE_RIGHT", Projection::PLANE_RIGHT); - _VariantCall::add_constant(Variant::PROJECTION, "PLANE_BOTTOM", Projection::PLANE_BOTTOM); - _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_NEAR", Projection::PLANE_NEAR); _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_FAR", Projection::PLANE_FAR); _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_LEFT", Projection::PLANE_LEFT); diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp index 6c37d5e4b7..9706457549 100644 --- a/core/variant/variant_construct.cpp +++ b/core/variant/variant_construct.cpp @@ -43,7 +43,7 @@ static LocalVector<VariantConstructData> construct_data[Variant::VARIANT_MAX]; template <typename T> static void add_constructor(const Vector<String> &arg_names) { - ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), "Argument names size mismatch for " + Variant::get_type_name(T::get_base_type()) + "."); + ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), vformat("Argument names size mismatch for '%s'.", Variant::get_type_name(T::get_base_type()))); VariantConstructData cd; cd.construct = T::construct; diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index d2c1cde970..ce27fbdf67 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -980,6 +980,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInDictionaryHas<Color>>(Variant::OP_IN, Variant::COLOR, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<NodePath>>(Variant::OP_IN, Variant::NODE_PATH, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<::RID>>(Variant::OP_IN, Variant::RID, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHasObject>(Variant::OP_IN, Variant::OBJECT, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Callable>>(Variant::OP_IN, Variant::CALLABLE, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Signal>>(Variant::OP_IN, Variant::SIGNAL, Variant::DICTIONARY); @@ -1021,6 +1022,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInArrayFind<Color, Array>>(Variant::OP_IN, Variant::COLOR, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<StringName, Array>>(Variant::OP_IN, Variant::STRING_NAME, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<NodePath, Array>>(Variant::OP_IN, Variant::NODE_PATH, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<::RID, Array>>(Variant::OP_IN, Variant::RID, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFindObject>(Variant::OP_IN, Variant::OBJECT, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Callable, Array>>(Variant::OP_IN, Variant::CALLABLE, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Signal, Array>>(Variant::OP_IN, Variant::SIGNAL, Variant::ARRAY); diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index f5f96456d3..f05b9cd83a 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -2245,7 +2245,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } else { List<Variant> keys; dict.get_key_list(&keys); - keys.sort(); + keys.sort_custom<StringLikeVariantOrder>(); if (keys.is_empty()) { // Avoid unnecessary line break. diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index 1652f81d99..560067fc08 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -141,6 +141,10 @@ void register_named_setters_getters() { REGISTER_MEMBER(Color, h); REGISTER_MEMBER(Color, s); REGISTER_MEMBER(Color, v); + + REGISTER_MEMBER(Color, ok_hsl_h); + REGISTER_MEMBER(Color, ok_hsl_s); + REGISTER_MEMBER(Color, ok_hsl_l); } void unregister_named_setters_getters() { diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 384fe6c4a6..50932afbb6 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1671,7 +1671,7 @@ static void register_utility_function(const String &p_name, const Vector<String> bfi.argnames = argnames; bfi.argcount = T::get_argument_count(); if (!bfi.is_vararg) { - ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, "wrong number of arguments binding utility function: " + name); + ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, vformat("Wrong number of arguments binding utility function: '%s'.", name)); } bfi.get_arg_type = T::get_argument_type; bfi.return_type = T::get_return_type(); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 55d00b6cf9..06aec6a2f7 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -6,7 +6,7 @@ <description> A list of global scope enumerated constants and built-in functions. This is all that resides in the globals, constants regarding error codes, keycodes, property hints, etc. Singletons are also documented here, since they can be accessed from anywhere. - For the entries related to GDScript which can be accessed in any script see [@GDScript]. + For the entries that can only be accessed from scripts written in GDScript, see [@GDScript]. </description> <tutorials> <link title="Random number generation">$DOCS_URL/tutorials/math/random_number_generation.html</link> @@ -991,8 +991,8 @@ [codeblock] var a = rand_from_seed(4) - print(a[0]) # Prints 2879024997 - print(a[1]) # Prints 4 + print(a[0]) # Prints 2879024997 + print(a[1]) # Prints 4 [/codeblock] </description> </method> @@ -2941,7 +2941,10 @@ [/codeblock] [b]Note:[/b] A [Callable] cannot be properly serialized and stored in a file, so it is recommended to use [constant PROPERTY_USAGE_EDITOR] instead of [constant PROPERTY_USAGE_DEFAULT]. </constant> - <constant name="PROPERTY_HINT_MAX" value="40" enum="PropertyHint"> + <constant name="PROPERTY_HINT_ONESHOT" value="40" enum="PropertyHint"> + Hints that a property will be changed on its own after setting, such as [member AudioStreamPlayer.playing] or [member GPUParticles3D.emitting]. + </constant> + <constant name="PROPERTY_HINT_MAX" value="41" enum="PropertyHint"> Represents the size of the [enum PropertyHint] enum. </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags" is_bitfield="true"> @@ -2981,7 +2984,7 @@ Editing the property prompts the user for restarting the editor. </constant> <constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="4096" enum="PropertyUsageFlags" is_bitfield="true"> - The property is a script variable which should be serialized and saved in the scene file. + The property is a script variable. [constant PROPERTY_USAGE_SCRIPT_VARIABLE] can be used to distinguish between exported script variables from built-in variables (which don't have this usage flag). By default, [constant PROPERTY_USAGE_SCRIPT_VARIABLE] is [b]not[/b] applied to variables that are created by overriding [method Object._get_property_list] in a script. </constant> <constant name="PROPERTY_USAGE_STORE_IF_NULL" value="8192" enum="PropertyUsageFlags" is_bitfield="true"> The property value of type [Object] will be stored even if its value is [code]null[/code]. @@ -2992,7 +2995,7 @@ <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="32768" enum="PropertyUsageFlags" is_bitfield="true" deprecated="This flag is not used by the engine."> </constant> <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="65536" enum="PropertyUsageFlags" is_bitfield="true"> - The property is an enum, i.e. it only takes named integer constants from its associated enumeration. + The property is a variable of enum type, i.e. it only takes named integer constants from its associated enumeration. </constant> <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="131072" enum="PropertyUsageFlags" is_bitfield="true"> If property has [code]nil[/code] as default value, its type will be [Variant]. diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index 188d9652a8..57ac241eb2 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -326,13 +326,13 @@ <return type="bool" /> <param index="0" name="aabb" type="AABB" /> <description> - Returns [code]true[/code] if this bounding box and [param aabb] are approximately equal, by calling [method Vector2.is_equal_approx] on the [member position] and the [member size]. + Returns [code]true[/code] if this bounding box and [param aabb] are approximately equal, by calling [method Vector3.is_equal_approx] on the [member position] and the [member size]. </description> </method> <method name="is_finite" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if this bounding box's values are finite, by calling [method Vector2.is_finite] on the [member position] and the [member size]. + Returns [code]true[/code] if this bounding box's values are finite, by calling [method Vector3.is_finite] on the [member position] and the [member size]. </description> </method> <method name="merge" qualifiers="const"> @@ -345,14 +345,14 @@ </methods> <members> <member name="end" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> - The ending point. This is usually the corner on the top-right and forward of the bounding box, and is equivalent to [code]position + size[/code]. Setting this point affects the [member size]. + The ending point. This is usually the corner on the top-right and back of the bounding box, and is equivalent to [code]position + size[/code]. Setting this point affects the [member size]. </member> <member name="position" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> - The origin point. This is usually the corner on the bottom-left and back of the bounding box. + The origin point. This is usually the corner on the bottom-left and forward of the bounding box. </member> <member name="size" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> The bounding box's width, height, and depth starting from [member position]. Setting this value also affects the [member end] point. - [b]Note:[/b] It's recommended setting the width, height, and depth to non-negative values. This is because most methods in Godot assume that the [member position] is the bottom-left-back corner, and the [member end] is the top-right-forward corner. To get an equivalent bounding box with non-negative size, use [method abs]. + [b]Note:[/b] It's recommended setting the width, height, and depth to non-negative values. This is because most methods in Godot assume that the [member position] is the bottom-left-forward corner, and the [member end] is the top-right-back corner. To get an equivalent bounding box with non-negative size, use [method abs]. </member> </members> <operators> diff --git a/doc/classes/AStar2D.xml b/doc/classes/AStar2D.xml index a41da4c318..044e1206e9 100644 --- a/doc/classes/AStar2D.xml +++ b/doc/classes/AStar2D.xml @@ -278,7 +278,7 @@ <return type="void" /> <param index="0" name="num_nodes" type="int" /> <description> - Reserves space internally for [param num_nodes] points, useful if you're adding a known large number of points at once, such as points on a grid. New capacity must be greater or equals to old capacity. + Reserves space internally for [param num_nodes] points. Useful if you're adding a known large number of points at once, such as points on a grid. The new capacity must be greater or equal to the old capacity. </description> </method> <method name="set_point_disabled"> diff --git a/doc/classes/AnimatedSprite2D.xml b/doc/classes/AnimatedSprite2D.xml index 88e543591a..cc1e9117f9 100644 --- a/doc/classes/AnimatedSprite2D.xml +++ b/doc/classes/AnimatedSprite2D.xml @@ -55,7 +55,7 @@ <param index="1" name="progress" type="float" /> <description> Sets [member frame] the [member frame_progress] to the given values. Unlike setting [member frame], this method does not reset the [member frame_progress] to [code]0.0[/code] implicitly. - [b]Example:[/b] Change the animation while keeping the same [member frame] and [member frame_progress]. + [b]Example:[/b] Change the animation while keeping the same [member frame] and [member frame_progress]: [codeblocks] [gdscript] var current_frame = animated_sprite.get_frame() diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml index a466fc32ac..1b1f58e5f4 100644 --- a/doc/classes/AnimatedSprite3D.xml +++ b/doc/classes/AnimatedSprite3D.xml @@ -54,7 +54,7 @@ <param index="1" name="progress" type="float" /> <description> Sets [member frame] the [member frame_progress] to the given values. Unlike setting [member frame], this method does not reset the [member frame_progress] to [code]0.0[/code] implicitly. - [b]Example:[/b] Change the animation while keeping the same [member frame] and [member frame_progress]. + [b]Example:[/b] Change the animation while keeping the same [member frame] and [member frame_progress]: [codeblocks] [gdscript] var current_frame = animated_sprite.get_frame() diff --git a/doc/classes/AnimationMixer.xml b/doc/classes/AnimationMixer.xml index d762ffa5a6..36cb675776 100644 --- a/doc/classes/AnimationMixer.xml +++ b/doc/classes/AnimationMixer.xml @@ -112,13 +112,13 @@ The most basic example is applying position to [CharacterBody3D]: [codeblocks] [gdscript] - var current_rotation: Quaternion + var current_rotation func _process(delta): if Input.is_action_just_pressed("animate"): current_rotation = get_quaternion() state_machine.travel("Animate") - var velocity: Vector3 = current_rotation * animation_tree.get_root_motion_position() / delta + var velocity = current_rotation * animation_tree.get_root_motion_position() / delta set_velocity(velocity) move_and_slide() [/gdscript] @@ -130,7 +130,20 @@ if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation()) - var velocity: Vector3 = (animation_tree.get_root_motion_rotation_accumulator().inverse() * get_quaternion()) * animation_tree.get_root_motion_position() / delta + var velocity = (animation_tree.get_root_motion_rotation_accumulator().inverse() * get_quaternion()) * animation_tree.get_root_motion_position() / delta + set_velocity(velocity) + move_and_slide() + [/gdscript] + [/codeblocks] + If [member root_motion_local] is [code]true[/code], return the pre-multiplied translation value with the inverted rotation. + In this case, the code can be written as follows: + [codeblocks] + [gdscript] + func _process(delta): + if Input.is_action_just_pressed("animate"): + state_machine.travel("Animate") + set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation()) + var velocity = get_quaternion() * animation_tree.get_root_motion_position() / delta set_velocity(velocity) move_and_slide() [/gdscript] @@ -145,13 +158,13 @@ For example, if an animation with only one key [code]Vector3(0, 0, 0)[/code] is played in the previous frame and then an animation with only one key [code]Vector3(1, 0, 1)[/code] is played in the next frame, the difference can be calculated as follows: [codeblocks] [gdscript] - var prev_root_motion_position_accumulator: Vector3 + var prev_root_motion_position_accumulator func _process(delta): if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") - var current_root_motion_position_accumulator: Vector3 = animation_tree.get_root_motion_position_accumulator() - var difference: Vector3 = current_root_motion_position_accumulator - prev_root_motion_position_accumulator + var current_root_motion_position_accumulator = animation_tree.get_root_motion_position_accumulator() + var difference = current_root_motion_position_accumulator - prev_root_motion_position_accumulator prev_root_motion_position_accumulator = current_root_motion_position_accumulator transform.origin += difference [/gdscript] @@ -185,13 +198,13 @@ For example, if an animation with only one key [code]Quaternion(0, 0, 0, 1)[/code] is played in the previous frame and then an animation with only one key [code]Quaternion(0, 0.707, 0, 0.707)[/code] is played in the next frame, the difference can be calculated as follows: [codeblocks] [gdscript] - var prev_root_motion_rotation_accumulator: Quaternion + var prev_root_motion_rotation_accumulator func _process(delta): if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") - var current_root_motion_rotation_accumulator: Quaternion = animation_tree.get_root_motion_rotation_accumulator() - var difference: Quaternion = prev_root_motion_rotation_accumulator.inverse() * current_root_motion_rotation_accumulator + var current_root_motion_rotation_accumulator = animation_tree.get_root_motion_rotation_accumulator() + var difference = prev_root_motion_rotation_accumulator.inverse() * current_root_motion_rotation_accumulator prev_root_motion_rotation_accumulator = current_root_motion_rotation_accumulator transform.basis *= Basis(difference) [/gdscript] @@ -208,8 +221,8 @@ The most basic example is applying scale to [CharacterBody3D]: [codeblocks] [gdscript] - var current_scale: Vector3 = Vector3(1, 1, 1) - var scale_accum: Vector3 = Vector3(1, 1, 1) + var current_scale = Vector3(1, 1, 1) + var scale_accum = Vector3(1, 1, 1) func _process(delta): if Input.is_action_just_pressed("animate"): @@ -229,13 +242,13 @@ For example, if an animation with only one key [code]Vector3(1, 1, 1)[/code] is played in the previous frame and then an animation with only one key [code]Vector3(2, 2, 2)[/code] is played in the next frame, the difference can be calculated as follows: [codeblocks] [gdscript] - var prev_root_motion_scale_accumulator: Vector3 + var prev_root_motion_scale_accumulator func _process(delta): if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") - var current_root_motion_scale_accumulator: Vector3 = animation_tree.get_root_motion_scale_accumulator() - var difference: Vector3 = current_root_motion_scale_accumulator - prev_root_motion_scale_accumulator + var current_root_motion_scale_accumulator = animation_tree.get_root_motion_scale_accumulator() + var difference = current_root_motion_scale_accumulator - prev_root_motion_scale_accumulator prev_root_motion_scale_accumulator = current_root_motion_scale_accumulator transform.basis = transform.basis.scaled(difference) [/gdscript] @@ -304,6 +317,9 @@ This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation (the animation with the key [code]"RESET"[/code]) applied as if it had been seeked to time 0, with the editor keeping the values that the scene had before saving. This makes it more convenient to preview and edit animations in the editor, as changes to the scene will not be saved as long as they are set in the reset animation. </member> + <member name="root_motion_local" type="bool" setter="set_root_motion_local" getter="is_root_motion_local"> + If [code]true[/code], [method get_root_motion_position] value is extracted as a local translation value before blending. In other words, it is treated like the translation is done after the rotation. + </member> <member name="root_motion_track" type="NodePath" setter="set_root_motion_track" getter="get_root_motion_track" default="NodePath("")"> The path to the Animation track used for root motion. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. The [member root_motion_track] uses the same format as [method Animation.track_set_path], but note that a bone must be specified. If the track has type [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_ROTATION_3D], or [constant Animation.TYPE_SCALE_3D] the transformation will be canceled visually, and the animation will appear to stay in place. See also [method get_root_motion_position], [method get_root_motion_rotation], [method get_root_motion_scale], and [RootMotionView]. diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml index 4e093cb887..3b7cd9adad 100644 --- a/doc/classes/AnimationNode.xml +++ b/doc/classes/AnimationNode.xml @@ -63,7 +63,7 @@ When inheriting from [AnimationRootNode], implement this virtual method to return whether the [param parameter] is read-only. Parameters are custom local memory used for your animation nodes, given a resource can be reused in multiple trees. </description> </method> - <method name="_process" qualifiers="virtual const" deprecated="Currently this is mostly useless as there is a lack of many APIs to extend AnimationNode by GDScript. It is planned that a more flexible API using structures will be provided in the future."> + <method name="_process" qualifiers="virtual" deprecated="Currently this is mostly useless as there is a lack of many APIs to extend AnimationNode by GDScript. It is planned that a more flexible API using structures will be provided in the future."> <return type="float" /> <param index="0" name="time" type="float" /> <param index="1" name="seek" type="bool" /> diff --git a/doc/classes/AnimationNodeAnimation.xml b/doc/classes/AnimationNodeAnimation.xml index 70c3e5a26e..f4490bc167 100644 --- a/doc/classes/AnimationNodeAnimation.xml +++ b/doc/classes/AnimationNodeAnimation.xml @@ -12,6 +12,10 @@ <link title="Third Person Shooter (TPS) Demo">https://godotengine.org/asset-library/asset/2710</link> </tutorials> <members> + <member name="advance_on_start" type="bool" setter="set_advance_on_start" getter="is_advance_on_start" default="false"> + If [code]true[/code], on receiving a request to play an animation from the start, the first frame is not drawn, but only processed, and playback starts from the next frame. + See also the notes of [method AnimationPlayer.play]. + </member> <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="&"""> Animation to use as an output. It is one of the animations provided by [member AnimationTree.anim_player]. </member> diff --git a/doc/classes/AnimationNodeStateMachineTransition.xml b/doc/classes/AnimationNodeStateMachineTransition.xml index 7bd0bd7e7e..c729eeebba 100644 --- a/doc/classes/AnimationNodeStateMachineTransition.xml +++ b/doc/classes/AnimationNodeStateMachineTransition.xml @@ -26,7 +26,7 @@ Use an expression as a condition for state machine transitions. It is possible to create complex animation advance conditions for switching between states and gives much greater flexibility for creating complex state machines by directly interfacing with the script code. </member> <member name="advance_mode" type="int" setter="set_advance_mode" getter="get_advance_mode" enum="AnimationNodeStateMachineTransition.AdvanceMode" default="1"> - Determines whether the transition should disabled, enabled when using [method AnimationNodeStateMachinePlayback.travel], or traversed automatically if the [member advance_condition] and [member advance_expression] checks are true (if assigned). + Determines whether the transition should be disabled, enabled when using [method AnimationNodeStateMachinePlayback.travel], or traversed automatically if the [member advance_condition] and [member advance_expression] checks are [code]true[/code] (if assigned). </member> <member name="break_loop_at_end" type="bool" setter="set_break_loop_at_end" getter="is_loop_broken_at_end" default="false"> If [code]true[/code], breaks the loop at the end of the loop cycle for transition, even if the animation is looping. @@ -72,7 +72,7 @@ Only use this transition during [method AnimationNodeStateMachinePlayback.travel]. </constant> <constant name="ADVANCE_MODE_AUTO" value="2" enum="AdvanceMode"> - Automatically use this transition if the [member advance_condition] and [member advance_expression] checks are true (if assigned). + Automatically use this transition if the [member advance_condition] and [member advance_expression] checks are [code]true[/code] (if assigned). </constant> </constants> </class> diff --git a/doc/classes/AnimationNodeTimeSeek.xml b/doc/classes/AnimationNodeTimeSeek.xml index d00b3fca3a..865e94ec43 100644 --- a/doc/classes/AnimationNodeTimeSeek.xml +++ b/doc/classes/AnimationNodeTimeSeek.xml @@ -30,4 +30,9 @@ <tutorials> <link title="Using AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> + <members> + <member name="explicit_elapse" type="bool" setter="set_explicit_elapse" getter="is_explicit_elapse" default="true"> + If [code]true[/code], some processes are executed to handle keys between seeks, such as calculating root motion and finding the nearest discrete key. + </member> + </members> </class> diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index 4ad5db2b67..61a103f20d 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -132,7 +132,7 @@ <description> Emitted when a [Shape2D] of the received [param area] enters a shape of this area. Requires [member monitoring] to be set to [code]true[/code]. [param local_shape_index] and [param area_shape_index] contain indices of the interacting shapes from this area and the other area, respectively. [param area_rid] contains the [RID] of the other area. These values can be used with the [PhysicsServer2D]. - [b]Example of getting the[/b] [CollisionShape2D] [b]node from the shape index:[/b] + [b]Example:[/b] Get the [CollisionShape2D] node from the shape index: [codeblocks] [gdscript] var other_shape_owner = area.shape_find_owner(area_shape_index) @@ -174,7 +174,7 @@ <description> Emitted when a [Shape2D] of the received [param body] enters a shape of this area. [param body] can be a [PhysicsBody2D] or a [TileMap]. [TileMap]s are detected if their [TileSet] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code]. [param local_shape_index] and [param body_shape_index] contain indices of the interacting shapes from this area and the interacting body, respectively. [param body_rid] contains the [RID] of the body. These values can be used with the [PhysicsServer2D]. - [b]Example of getting the[/b] [CollisionShape2D] [b]node from the shape index:[/b] + [b]Example:[/b] Get the [CollisionShape2D] node from the shape index: [codeblocks] [gdscript] var body_shape_owner = body.shape_find_owner(body_shape_index) diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 8eedd3cdf2..aac98593ff 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -156,7 +156,7 @@ <description> Emitted when a [Shape3D] of the received [param area] enters a shape of this area. Requires [member monitoring] to be set to [code]true[/code]. [param local_shape_index] and [param area_shape_index] contain indices of the interacting shapes from this area and the other area, respectively. [param area_rid] contains the [RID] of the other area. These values can be used with the [PhysicsServer3D]. - [b]Example of getting the[/b] [CollisionShape3D] [b]node from the shape index:[/b] + [b]Example:[/b] Get the [CollisionShape3D] node from the shape index: [codeblocks] [gdscript] var other_shape_owner = area.shape_find_owner(area_shape_index) @@ -198,7 +198,7 @@ <description> Emitted when a [Shape3D] of the received [param body] enters a shape of this area. [param body] can be a [PhysicsBody3D] or a [GridMap]. [GridMap]s are detected if their [MeshLibrary] has collision shapes configured. Requires [member monitoring] to be set to [code]true[/code]. [param local_shape_index] and [param body_shape_index] contain indices of the interacting shapes from this area and the interacting body, respectively. [param body_rid] contains the [RID] of the body. These values can be used with the [PhysicsServer3D]. - [b]Example of getting the[/b] [CollisionShape3D] [b]node from the shape index:[/b] + [b]Example:[/b] Get the [CollisionShape3D] node from the shape index: [codeblocks] [gdscript] var body_shape_owner = body.shape_find_owner(body_shape_index) diff --git a/doc/classes/AtlasTexture.xml b/doc/classes/AtlasTexture.xml index 45877f4003..287f2cc19a 100644 --- a/doc/classes/AtlasTexture.xml +++ b/doc/classes/AtlasTexture.xml @@ -6,7 +6,7 @@ <description> [Texture2D] resource that draws only part of its [member atlas] texture, as defined by the [member region]. An additional [member margin] can also be set, which is useful for small adjustments. Multiple [AtlasTexture] resources can be cropped from the same [member atlas]. Packing many smaller textures into a singular large texture helps to optimize video memory costs and render calls. - [b]Note:[/b] [AtlasTexture] cannot be used in an [AnimatedTexture], and may not tile properly in nodes such as [TextureRect], when inside other [AtlasTexture] resources. + [b]Note:[/b] [AtlasTexture] cannot be used in an [AnimatedTexture], and will not tile properly in nodes such as [TextureRect] or [Sprite2D]. To tile an [AtlasTexture], modify its [member region] instead. </description> <tutorials> </tutorials> diff --git a/doc/classes/AudioEffectFilter.xml b/doc/classes/AudioEffectFilter.xml index e5c1f4ccf4..18540de736 100644 --- a/doc/classes/AudioEffectFilter.xml +++ b/doc/classes/AudioEffectFilter.xml @@ -14,6 +14,7 @@ Threshold frequency for the filter, in Hz. </member> <member name="db" type="int" setter="set_db" getter="get_db" enum="AudioEffectFilter.FilterDB" default="0"> + Steepness of the cutoff curve in dB per octave, also known as the order of the filter. Higher orders have a more aggressive cutoff. </member> <member name="gain" type="float" setter="set_gain" getter="get_gain" default="1.0"> Gain amount of the frequencies after the filter. @@ -24,12 +25,16 @@ </members> <constants> <constant name="FILTER_6DB" value="0" enum="FilterDB"> + Cutting off at 6dB per octave. </constant> <constant name="FILTER_12DB" value="1" enum="FilterDB"> + Cutting off at 12dB per octave. </constant> <constant name="FILTER_18DB" value="2" enum="FilterDB"> + Cutting off at 18dB per octave. </constant> <constant name="FILTER_24DB" value="3" enum="FilterDB"> + Cutting off at 24dB per octave. </constant> </constants> </class> diff --git a/doc/classes/AudioEffectSpectrumAnalyzer.xml b/doc/classes/AudioEffectSpectrumAnalyzer.xml index b90f87ef5b..5cbf3fb1cb 100644 --- a/doc/classes/AudioEffectSpectrumAnalyzer.xml +++ b/doc/classes/AudioEffectSpectrumAnalyzer.xml @@ -5,7 +5,7 @@ </brief_description> <description> This audio effect does not affect sound output, but can be used for real-time audio visualizations. - This resource configures an [AudioEffectSpectrumAnalyzerInstance], which performs the actual analysis at runtime. An instance can be acquired with [method AudioServer.get_bus_effect_instance]. + This resource configures an [AudioEffectSpectrumAnalyzerInstance], which performs the actual analysis at runtime. An instance can be obtained with [method AudioServer.get_bus_effect_instance]. See also [AudioStreamGenerator] for procedurally generating sounds. </description> <tutorials> diff --git a/doc/classes/AudioEffectSpectrumAnalyzerInstance.xml b/doc/classes/AudioEffectSpectrumAnalyzerInstance.xml index 184f80db2e..833ccafa6f 100644 --- a/doc/classes/AudioEffectSpectrumAnalyzerInstance.xml +++ b/doc/classes/AudioEffectSpectrumAnalyzerInstance.xml @@ -5,7 +5,7 @@ </brief_description> <description> The runtime part of an [AudioEffectSpectrumAnalyzer], which can be used to query the magnitude of a frequency range on its host bus. - An instance of this class can be acquired with [method AudioServer.get_bus_effect_instance]. + An instance of this class can be obtained with [method AudioServer.get_bus_effect_instance]. </description> <tutorials> <link title="Audio Spectrum Visualizer Demo">https://godotengine.org/asset-library/asset/2762</link> diff --git a/doc/classes/AudioEffectStereoEnhance.xml b/doc/classes/AudioEffectStereoEnhance.xml index f009bec5bb..459ae3ebc6 100644 --- a/doc/classes/AudioEffectStereoEnhance.xml +++ b/doc/classes/AudioEffectStereoEnhance.xml @@ -11,11 +11,13 @@ </tutorials> <members> <member name="pan_pullout" type="float" setter="set_pan_pullout" getter="get_pan_pullout" default="1.0"> - Values greater than 1.0 increase intensity of any panning on audio passing through this effect, whereas values less than 1.0 will decrease the panning intensity. A value of 0.0 will downmix audio to mono. + Amplifies the difference between stereo channels, increasing or decreasing existing panning. A value of 0.0 will downmix stereo to mono. Does not affect a mono signal. </member> <member name="surround" type="float" setter="set_surround" getter="get_surround" default="0.0"> + Widens sound stage through phase shifting in conjunction with [member time_pullout_ms]. Just pans sound to the left channel if [member time_pullout_ms] is 0. </member> <member name="time_pullout_ms" type="float" setter="set_time_pullout" getter="get_time_pullout" default="0.0"> + Widens sound stage through phase shifting in conjunction with [member surround]. Just delays the right channel if [member surround] is 0. </member> </members> </class> diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index 6830c632cf..5def0e7baf 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -110,6 +110,12 @@ Returns the volume of the bus at index [param bus_idx] in dB. </description> </method> + <method name="get_driver_name" qualifiers="const"> + <return type="String" /> + <description> + Returns the name of the current audio driver. The default usually depends on the operating system, but may be overridden via the [code]--audio-driver[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]. [code]--headless[/code] also automatically sets the audio driver to [code]Dummy[/code]. See also [member ProjectSettings.audio/driver/driver]. + </description> + </method> <method name="get_input_device_list"> <return type="PackedStringArray" /> <description> @@ -117,6 +123,12 @@ [b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings. </description> </method> + <method name="get_input_mix_rate" qualifiers="const"> + <return type="float" /> + <description> + Returns the sample rate at the input of the [AudioServer]. + </description> + </method> <method name="get_mix_rate" qualifiers="const"> <return type="float" /> <description> diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml index 44edff122e..d11e070d89 100644 --- a/doc/classes/AudioStream.xml +++ b/doc/classes/AudioStream.xml @@ -48,7 +48,7 @@ <method name="_instantiate_playback" qualifiers="virtual const"> <return type="AudioStreamPlayback" /> <description> - Override this method to customize the returned value of [method instantiate_playback]. Should returned a new [AudioStreamPlayback] created when the stream is played (such as by an [AudioStreamPlayer]).. + Override this method to customize the returned value of [method instantiate_playback]. Should return a new [AudioStreamPlayback] created when the stream is played (such as by an [AudioStreamPlayer]). </description> </method> <method name="_is_monophonic" qualifiers="virtual const"> diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml index 02f3407f79..f01406d0f1 100644 --- a/doc/classes/AudioStreamPlayback.xml +++ b/doc/classes/AudioStreamPlayback.xml @@ -79,12 +79,47 @@ Overridable method. Called whenever the audio stream is mixed if the playback is active and [method AudioServer.set_enable_tagging_used_audio_streams] has been set to [code]true[/code]. Editor plugins may use this method to "tag" the current position along the audio stream and display it in a preview. </description> </method> + <method name="get_loop_count" qualifiers="const"> + <return type="int" /> + <description> + Returns the number of times the stream has looped. + </description> + </method> + <method name="get_playback_position" qualifiers="const"> + <return type="float" /> + <description> + Returns the current position in the stream, in seconds. + </description> + </method> <method name="get_sample_playback" qualifiers="const" experimental=""> <return type="AudioSamplePlayback" /> <description> Returns the [AudioSamplePlayback] associated with this [AudioStreamPlayback] for playing back the audio sample of this stream. </description> </method> + <method name="is_playing" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the stream is playing. + </description> + </method> + <method name="mix_audio"> + <return type="PackedVector2Array" /> + <param index="0" name="rate_scale" type="float" /> + <param index="1" name="frames" type="int" /> + <description> + Mixes up to [param frames] of audio from the stream from the current position, at a rate of [param rate_scale], advancing the stream. + Returns a [PackedVector2Array] where each element holds the left and right channel volume levels of each frame. + [b]Note:[/b] Can return fewer frames than requested, make sure to use the size of the return value. + </description> + </method> + <method name="seek"> + <return type="void" /> + <param index="0" name="time" type="float" default="0.0" /> + <description> + Seeks the stream at the given [param time], in seconds. + </description> + </method> <method name="set_sample_playback" experimental=""> <return type="void" /> <param index="0" name="playback_sample" type="AudioSamplePlayback" /> @@ -92,5 +127,18 @@ Associates [AudioSamplePlayback] to this [AudioStreamPlayback] for playing back the audio sample of this stream. </description> </method> + <method name="start"> + <return type="void" /> + <param index="0" name="from_pos" type="float" default="0.0" /> + <description> + Starts the stream from the given [param from_pos], in seconds. + </description> + </method> + <method name="stop"> + <return type="void" /> + <description> + Stops the stream. + </description> + </method> </methods> </class> diff --git a/doc/classes/AudioStreamPlaybackPolyphonic.xml b/doc/classes/AudioStreamPlaybackPolyphonic.xml index f71762d6a5..894c9b2262 100644 --- a/doc/classes/AudioStreamPlaybackPolyphonic.xml +++ b/doc/classes/AudioStreamPlaybackPolyphonic.xml @@ -13,7 +13,7 @@ <return type="bool" /> <param index="0" name="stream" type="int" /> <description> - Return true whether the stream associated with an integer ID is still playing. Check [method play_stream] for information on when this ID becomes invalid. + Returns [code]true[/code] if the stream associated with the given integer ID is still playing. Check [method play_stream] for information on when this ID becomes invalid. </description> </method> <method name="play_stream"> diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml index 93680de21e..900318e4f4 100644 --- a/doc/classes/AudioStreamPlayer.xml +++ b/doc/classes/AudioStreamPlayer.xml @@ -22,6 +22,7 @@ <description> Returns the position in the [AudioStream] of the latest sound, in seconds. Returns [code]0.0[/code] if no sounds are playing. [b]Note:[/b] The position is not always accurate, as the [AudioServer] does not mix audio every processed frame. To get more accurate results, add [method AudioServer.get_time_since_last_mix] to the returned position. + [b]Note:[/b] This method always returns [code]0.0[/code] if the [member stream] is an [AudioStreamInteractive], since it can have multiple clips playing at once. </description> </method> <method name="get_stream_playback"> diff --git a/doc/classes/BackBufferCopy.xml b/doc/classes/BackBufferCopy.xml index 23d6bc3851..eb65765312 100644 --- a/doc/classes/BackBufferCopy.xml +++ b/doc/classes/BackBufferCopy.xml @@ -8,6 +8,7 @@ [b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), anchors and margins won't apply to child [Control]-derived nodes. This can be problematic when resizing the window. To avoid this, add [Control]-derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of adding them as children. </description> <tutorials> + <link title="Screen-reading shaders">$DOCS_URL/tutorials/shaders/screen-reading_shaders.html</link> </tutorials> <members> <member name="copy_mode" type="int" setter="set_copy_mode" getter="get_copy_mode" enum="BackBufferCopy.CopyMode" default="1"> diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index fc8af02869..b4a256c54f 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -350,7 +350,6 @@ </member> <member name="shading_mode" type="int" setter="set_shading_mode" getter="get_shading_mode" enum="BaseMaterial3D.ShadingMode" default="1"> Sets whether the shading takes place, per-pixel, per-vertex or unshaded. Per-vertex lighting is faster, making it the best choice for mobile applications, however it looks considerably worse than per-pixel. Unshaded rendering is the fastest, but disables all interactions with lights. - [b]Note:[/b] Setting the shading mode vertex shading currently has no effect, as vertex shading is not implemented yet. </member> <member name="shadow_to_opacity" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], enables the "shadow to opacity" render mode where lighting modifies the alpha so shadowed areas are opaque and non-shadowed areas are transparent. Useful for overlaying shadows onto a camera feed in AR. @@ -553,7 +552,7 @@ The object will be shaded per pixel. Useful for realistic shading effects. </constant> <constant name="SHADING_MODE_PER_VERTEX" value="2" enum="ShadingMode"> - The object will be shaded per vertex. Useful when you want cheaper shaders and do not care about visual quality. Not implemented yet (this mode will act like [constant SHADING_MODE_PER_PIXEL]). + The object will be shaded per vertex. Useful when you want cheaper shaders and do not care about visual quality. </constant> <constant name="SHADING_MODE_MAX" value="3" enum="ShadingMode"> Represents the size of the [enum ShadingMode] enum. diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index 322d2ab9d4..59c1195b00 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -25,6 +25,7 @@ <return type="Basis" /> <description> Constructs a [Basis] identical to the [constant IDENTITY]. + [b]Note:[/b] In C#, this constructs a [Basis] with all of its components set to [constant Vector3.ZERO]. </description> </constructor> <constructor name="Basis"> @@ -303,7 +304,7 @@ <param index="1" name="weight" type="float" /> <description> Performs a spherical-linear interpolation with the [param to] basis, given a [param weight]. Both this basis and [param to] should represent a rotation. - [b]Example:[/b] Smoothly rotate a [Node3D] to the target basis over time, with a [Tween]. + [b]Example:[/b] Smoothly rotate a [Node3D] to the target basis over time, with a [Tween]: [codeblock] var start_basis = Basis.IDENTITY var target_basis = Basis.IDENTITY.rotated(Vector3.UP, TAU / 2) diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml index 68fb918904..5b3f86c9f5 100644 --- a/doc/classes/Button.xml +++ b/doc/classes/Button.xml @@ -5,13 +5,13 @@ </brief_description> <description> [Button] is the standard themed button. It can contain text and an icon, and it will display them according to the current [Theme]. - [b]Example of creating a button and assigning an action when pressed by code:[/b] + [b]Example:[/b] Create a button and connect a method that will be called when the button is pressed: [codeblocks] [gdscript] func _ready(): var button = Button.new() button.text = "Click me" - button.pressed.connect(self._button_pressed) + button.pressed.connect(_button_pressed) add_child(button) func _button_pressed(): @@ -33,7 +33,7 @@ [/csharp] [/codeblocks] See also [BaseButton] which contains common properties and methods associated with this node. - [b]Note:[/b] Buttons do not interpret touch input and therefore don't support multitouch, since mouse emulation can only press one button at a given time. Use [TouchScreenButton] for buttons that trigger gameplay movement or actions. + [b]Note:[/b] Buttons do not detect touch input and therefore don't support multitouch, since mouse emulation can only press one button at a given time. Use [TouchScreenButton] for buttons that trigger gameplay movement or actions. </description> <tutorials> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/2712</link> @@ -127,6 +127,9 @@ <theme_item name="icon_max_width" data_type="constant" type="int" default="0"> The maximum allowed width of the [Button]'s icon. This limit is applied on top of the default size of the icon, or its expanded size if [member expand_icon] is [code]true[/code]. The height is adjusted according to the icon's ratio. If the button has additional icons (e.g. [CheckBox]), they will also be limited. </theme_item> + <theme_item name="line_spacing" data_type="constant" type="int" default="0"> + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. + </theme_item> <theme_item name="outline_size" data_type="constant" type="int" default="0"> The size of the text outline. [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended. diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index 99411c73aa..e8fa13fd0d 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -43,7 +43,7 @@ <return type="bool" /> <param index="0" name="particle_flag" type="int" enum="CPUParticles2D.ParticleFlags" /> <description> - Returns the enabled state of the given flag (see [enum ParticleFlags] for options). + Returns the enabled state of the given particle flag (see [enum ParticleFlags] for options). </description> </method> <method name="restart"> diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml index 0c8f3c66f5..cf3c3e06fd 100644 --- a/doc/classes/Callable.xml +++ b/doc/classes/Callable.xml @@ -155,13 +155,21 @@ <method name="get_bound_arguments" qualifiers="const"> <return type="Array" /> <description> - Return the bound arguments (as long as [method get_bound_arguments_count] is greater than zero), or empty (if [method get_bound_arguments_count] is less than or equal to zero). + Returns the array of arguments bound via successive [method bind] or [method unbind] calls. These arguments will be added [i]after[/i] the arguments passed to the call, from which [method get_unbound_arguments_count] arguments on the right have been previously excluded. + [codeblock] + func get_effective_arguments(callable, call_args): + assert(call_args.size() - callable.get_unbound_arguments_count() >= 0) + var result = call_args.slice(0, call_args.size() - callable.get_unbound_arguments_count()) + result.append_array(callable.get_bound_arguments()) + return result + [/codeblock] </description> </method> <method name="get_bound_arguments_count" qualifiers="const"> <return type="int" /> <description> - Returns the total amount of arguments bound (or unbound) via successive [method bind] or [method unbind] calls. If the amount of arguments unbound is greater than the ones bound, this function returns a value less than zero. + Returns the total amount of arguments bound via successive [method bind] or [method unbind] calls. This is the same as the size of the array returned by [method get_bound_arguments]. See [method get_bound_arguments] for details. + [b]Note:[/b] The [method get_bound_arguments_count] and [method get_unbound_arguments_count] methods can both return positive values. </description> </method> <method name="get_method" qualifiers="const"> @@ -182,6 +190,13 @@ Returns the ID of this [Callable]'s object (see [method Object.get_instance_id]). </description> </method> + <method name="get_unbound_arguments_count" qualifiers="const"> + <return type="int" /> + <description> + Returns the total amount of arguments unbound via successive [method bind] or [method unbind] calls. See [method get_bound_arguments] for details. + [b]Note:[/b] The [method get_bound_arguments_count] and [method get_unbound_arguments_count] methods can both return positive values. + </description> + </method> <method name="hash" qualifiers="const"> <return type="int" /> <description> diff --git a/doc/classes/CallbackTweener.xml b/doc/classes/CallbackTweener.xml index afb9e70601..3a617d2a43 100644 --- a/doc/classes/CallbackTweener.xml +++ b/doc/classes/CallbackTweener.xml @@ -16,7 +16,7 @@ <param index="0" name="delay" type="float" /> <description> Makes the callback call delayed by given time in seconds. - [b]Example:[/b] Call [method Node.queue_free] after 2 seconds. + [b]Example:[/b] Call [method Node.queue_free] after 2 seconds: [codeblock] var tween = get_tree().create_tween() tween.tween_callback(queue_free).set_delay(2) diff --git a/doc/classes/CameraAttributes.xml b/doc/classes/CameraAttributes.xml index 1b1365eed4..cb5a7778de 100644 --- a/doc/classes/CameraAttributes.xml +++ b/doc/classes/CameraAttributes.xml @@ -25,7 +25,9 @@ Multiplier for the exposure amount. A higher value results in a brighter image. </member> <member name="exposure_sensitivity" type="float" setter="set_exposure_sensitivity" getter="get_exposure_sensitivity" default="100.0"> - Sensitivity of camera sensors, measured in ISO. A higher sensitivity results in a brighter image. Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled. When [member auto_exposure_enabled] this can be used as a method of exposure compensation, doubling the value will increase the exposure value (measured in EV100) by 1 stop. + Sensitivity of camera sensors, measured in ISO. A higher sensitivity results in a brighter image. + If [member auto_exposure_enabled] is [code]true[/code], this can be used as a method of exposure compensation, doubling the value will increase the exposure value (measured in EV100) by 1 stop. + [b]Note:[/b] Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled. </member> </members> </class> diff --git a/doc/classes/CameraFeed.xml b/doc/classes/CameraFeed.xml index 2b6db13906..6748fdb95b 100644 --- a/doc/classes/CameraFeed.xml +++ b/doc/classes/CameraFeed.xml @@ -34,6 +34,21 @@ Returns the position of camera on the device. </description> </method> + <method name="get_texture_tex_id"> + <return type="int" /> + <param index="0" name="feed_image_type" type="int" enum="CameraServer.FeedImage" /> + <description> + Returns the texture backend ID (usable by some external libraries that need a handle to a texture to write data). + </description> + </method> + <method name="set_external"> + <return type="void" /> + <param index="0" name="width" type="int" /> + <param index="1" name="height" type="int" /> + <description> + Sets the feed as external feed provided by another library. + </description> + </method> <method name="set_format"> <return type="bool" /> <param index="0" name="index" type="int" /> @@ -110,6 +125,9 @@ <constant name="FEED_YCBCR_SEP" value="3" enum="FeedDataType"> Feed supplies separate Y and CbCr images that need to be combined and converted to RGB. </constant> + <constant name="FEED_EXTERNAL" value="4" enum="FeedDataType"> + Feed supplies external image. + </constant> <constant name="FEED_UNSPECIFIED" value="0" enum="FeedPosition"> Unspecified position. </constant> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index bc17c8b008..5710e08423 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -333,7 +333,7 @@ <param index="9" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> Draws [param text] using the specified [param font] at the [param pos] (bottom-left corner using the baseline of the font). The text will have its color multiplied by [param modulate]. If [param width] is greater than or equal to 0, the text will be clipped if it exceeds the specified width. - [b]Example using the default project font:[/b] + [b]Example:[/b] Draw "Hello world", using the project's default font: [codeblocks] [gdscript] # If using this method in a script that redraws constantly, move the @@ -533,9 +533,13 @@ </method> <method name="make_canvas_position_local" qualifiers="const"> <return type="Vector2" /> - <param index="0" name="screen_point" type="Vector2" /> + <param index="0" name="viewport_point" type="Vector2" /> <description> - Assigns [param screen_point] as this node's new local transform. + Transforms [param viewport_point] from the viewport's coordinates to this node's local coordinates. + For the opposite operation, use [method get_global_transform_with_canvas]. + [codeblock] + var viewport_point = get_global_transform_with_canvas() * local_point + [/codeblock] </description> </method> <method name="make_input_local" qualifiers="const"> @@ -590,6 +594,7 @@ <members> <member name="clip_children" type="int" setter="set_clip_children_mode" getter="get_clip_children_mode" enum="CanvasItem.ClipChildrenMode" default="0"> Allows the current node to clip child nodes, essentially acting as a mask. + [b]Note:[/b] Clipping nodes cannot be nested or placed within [CanvasGroup]s. If an ancestor of this node clips its children or is a [CanvasGroup], then this node's clip mode should be set to [constant CLIP_CHILDREN_DISABLED] to avoid unexpected behavior. </member> <member name="light_mask" type="int" setter="set_light_mask" getter="get_light_mask" default="1"> The rendering layers in which this [CanvasItem] responds to [Light2D] nodes. @@ -628,7 +633,7 @@ </member> <member name="y_sort_enabled" type="bool" setter="set_y_sort_enabled" getter="is_y_sort_enabled" default="false"> If [code]true[/code], this and child [CanvasItem] nodes with a higher Y position are rendered in front of nodes with a lower Y position. If [code]false[/code], this and child [CanvasItem] nodes are rendered normally in scene tree order. - With Y-sorting enabled on a parent node ('A') but disabled on a child node ('B'), the child node ('B') is sorted but its children ('C1', 'C2', etc) render together on the same Y position as the child node ('B'). This allows you to organize the render order of a scene without changing the scene tree. + With Y-sorting enabled on a parent node ('A') but disabled on a child node ('B'), the child node ('B') is sorted but its children ('C1', 'C2', etc.) render together on the same Y position as the child node ('B'). This allows you to organize the render order of a scene without changing the scene tree. Nodes sort relative to each other only if they are on the same [member z_index]. </member> <member name="z_as_relative" type="bool" setter="set_z_as_relative" getter="is_z_relative" default="true"> diff --git a/doc/classes/CanvasModulate.xml b/doc/classes/CanvasModulate.xml index 7db0361020..43505498b3 100644 --- a/doc/classes/CanvasModulate.xml +++ b/doc/classes/CanvasModulate.xml @@ -7,6 +7,7 @@ [CanvasModulate] applies a color tint to all nodes on a canvas. Only one can be used to tint a canvas, but [CanvasLayer]s can be used to render things independently. </description> <tutorials> + <link title="2D lights and shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link> </tutorials> <members> <member name="color" type="Color" setter="set_color" getter="get_color" default="Color(1, 1, 1, 1)" keywords="colour"> diff --git a/doc/classes/CharFXTransform.xml b/doc/classes/CharFXTransform.xml index 403033f85d..28f5d38ee4 100644 --- a/doc/classes/CharFXTransform.xml +++ b/doc/classes/CharFXTransform.xml @@ -8,7 +8,6 @@ </description> <tutorials> <link title="BBCode in RichTextLabel">$DOCS_URL/tutorials/ui/bbcode_in_richtextlabel.html</link> - <link title="RichTextEffect test project (third-party)">https://github.com/Eoin-ONeill-Yokai/Godot-Rich-Text-Effect-Test-Project</link> </tutorials> <members> <member name="color" type="Color" setter="set_color" getter="get_color" default="Color(0, 0, 0, 1)" keywords="colour"> diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml index ede4d63cfc..30438be18b 100644 --- a/doc/classes/CharacterBody2D.xml +++ b/doc/classes/CharacterBody2D.xml @@ -69,7 +69,7 @@ <param index="0" name="slide_idx" type="int" /> <description> Returns a [KinematicCollision2D], which contains information about a collision that occurred during the last call to [method move_and_slide]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_collision_count] - 1). - [b]Example usage:[/b] + [b]Example:[/b] Iterate through the collisions with a [code]for[/code] loop: [codeblocks] [gdscript] for i in get_slide_collision_count(): diff --git a/doc/classes/ClassDB.xml b/doc/classes/ClassDB.xml index d1b666097c..d01a308e32 100644 --- a/doc/classes/ClassDB.xml +++ b/doc/classes/ClassDB.xml @@ -16,7 +16,7 @@ Returns [code]true[/code] if objects can be instantiated from the specified [param class], otherwise returns [code]false[/code]. </description> </method> - <method name="class_call_static_method" qualifiers="vararg"> + <method name="class_call_static" qualifiers="vararg"> <return type="Variant" /> <param index="0" name="class" type="StringName" /> <param index="1" name="method" type="StringName" /> diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml index 136b8e5fc5..a65d587e8b 100644 --- a/doc/classes/CodeEdit.xml +++ b/doc/classes/CodeEdit.xml @@ -80,7 +80,7 @@ <return type="bool" /> <param index="0" name="line" type="int" /> <description> - Returns if the given line is foldable, that is, it has indented lines right below it or a comment / string block. + Returns [code]true[/code] if the given line is foldable. A line is foldable if it is the start of a valid code region (see [method get_code_region_start_tag]), if it is the start of a comment or string block, or if the next non-empty line is more indented (see [method TextEdit.get_indent_level]). </description> </method> <method name="cancel_code_completion"> @@ -153,7 +153,7 @@ <method name="do_indent"> <return type="void" /> <description> - Perform an indent as if the user activated the "ui_text_indent" action. + If there is no selection, indentation is inserted at the caret. Otherwise, the selected lines are indented like [method indent_lines]. Equivalent to the [member ProjectSettings.input/ui_text_indent] action. The indentation characters used depend on [member indent_use_spaces] and [member indent_size]. </description> </method> <method name="duplicate_lines"> @@ -276,7 +276,7 @@ <method name="get_folded_lines" qualifiers="const"> <return type="int[]" /> <description> - Returns all lines that are current folded. + Returns all lines that are currently folded. </description> </method> <method name="get_text_for_code_completion" qualifiers="const"> @@ -330,7 +330,7 @@ <method name="indent_lines"> <return type="void" /> <description> - Indents selected lines, or in the case of no selection the caret line by one. + Indents all lines that are selected or have a caret on them. Uses spaces or a tab depending on [member indent_use_spaces]. See [method unindent_lines]. </description> </method> <method name="is_in_comment" qualifiers="const"> @@ -353,42 +353,42 @@ <return type="bool" /> <param index="0" name="line" type="int" /> <description> - Returns whether the line at the specified index is bookmarked or not. + Returns [code]true[/code] if the given line is bookmarked. See [method set_line_as_bookmarked]. </description> </method> <method name="is_line_breakpointed" qualifiers="const"> <return type="bool" /> <param index="0" name="line" type="int" /> <description> - Returns whether the line at the specified index is breakpointed or not. + Returns [code]true[/code] if the given line is breakpointed. See [method set_line_as_breakpoint]. </description> </method> <method name="is_line_code_region_end" qualifiers="const"> <return type="bool" /> <param index="0" name="line" type="int" /> <description> - Returns whether the line at the specified index is a code region end. + Returns [code]true[/code] if the given line is a code region end. See [method set_code_region_tags]. </description> </method> <method name="is_line_code_region_start" qualifiers="const"> <return type="bool" /> <param index="0" name="line" type="int" /> <description> - Returns whether the line at the specified index is a code region start. + Returns [code]true[/code] if the given line is a code region start. See [method set_code_region_tags]. </description> </method> <method name="is_line_executing" qualifiers="const"> <return type="bool" /> <param index="0" name="line" type="int" /> <description> - Returns whether the line at the specified index is marked as executing or not. + Returns [code]true[/code] if the given line is marked as executing. See [method set_line_as_executing]. </description> </method> <method name="is_line_folded" qualifiers="const"> <return type="bool" /> <param index="0" name="line" type="int" /> <description> - Returns whether the line at the specified index is folded or not. + Returns [code]true[/code] if the given line is folded. See [method fold_line]. </description> </method> <method name="move_lines_down"> @@ -442,7 +442,7 @@ <return type="void" /> <param index="0" name="draw_below" type="bool" /> <description> - Sets if the code hint should draw below the text. + If [code]true[/code], the code hint will draw below the main caret. If [code]false[/code], the code hint will draw above the main caret. See [method set_code_hint]. </description> </method> <method name="set_code_region_tags"> @@ -458,7 +458,7 @@ <param index="0" name="line" type="int" /> <param index="1" name="bookmarked" type="bool" /> <description> - Sets the line as bookmarked. + Sets the given line as bookmarked. If [code]true[/code] and [member gutters_draw_bookmarks] is [code]true[/code], draws the [theme_item bookmark] icon in the gutter for this line. See [method get_bookmarked_lines] and [method is_line_bookmarked]. </description> </method> <method name="set_line_as_breakpoint"> @@ -466,7 +466,7 @@ <param index="0" name="line" type="int" /> <param index="1" name="breakpointed" type="bool" /> <description> - Sets the line as breakpointed. + Sets the given line as a breakpoint. If [code]true[/code] and [member gutters_draw_breakpoints_gutter] is [code]true[/code], draws the [theme_item breakpoint] icon in the gutter for this line. See [method get_breakpointed_lines] and [method is_line_breakpointed]. </description> </method> <method name="set_line_as_executing"> @@ -474,7 +474,7 @@ <param index="0" name="line" type="int" /> <param index="1" name="executing" type="bool" /> <description> - Sets the line as executing. + Sets the given line as executing. If [code]true[/code] and [member gutters_draw_executing_lines] is [code]true[/code], draws the [theme_item executing_line] icon in the gutter for this line. See [method get_executing_lines] and [method is_line_executing]. </description> </method> <method name="set_symbol_lookup_word_as_valid"> @@ -500,20 +500,20 @@ <method name="unfold_all_lines"> <return type="void" /> <description> - Unfolds all lines, folded or not. + Unfolds all lines that are folded. </description> </method> <method name="unfold_line"> <return type="void" /> <param index="0" name="line" type="int" /> <description> - Unfolds all lines that were previously folded. + Unfolds the given line if it is folded or if it is hidden under a folded line. </description> </method> <method name="unindent_lines"> <return type="void" /> <description> - Unindents selected lines, or in the case of no selection the caret line by one. Same as performing "ui_text_unindent" action. + Unindents all lines that are selected or have a caret on them. Uses spaces or a tab depending on [member indent_use_spaces]. Equivalent to the [member ProjectSettings.input/ui_text_dedent] action. See [method indent_lines]. </description> </method> <method name="update_code_completion_options"> @@ -527,16 +527,16 @@ </methods> <members> <member name="auto_brace_completion_enabled" type="bool" setter="set_auto_brace_completion_enabled" getter="is_auto_brace_completion_enabled" default="false"> - Sets whether brace pairs should be autocompleted. + If [code]true[/code], uses [member auto_brace_completion_pairs] to automatically insert the closing brace when the opening brace is inserted by typing or autocompletion. Also automatically removes the closing brace when using backspace on the opening brace. </member> <member name="auto_brace_completion_highlight_matching" type="bool" setter="set_highlight_matching_braces_enabled" getter="is_highlight_matching_braces_enabled" default="false"> - Highlight mismatching brace pairs. + If [code]true[/code], highlights brace pairs when the caret is on either one, using [member auto_brace_completion_pairs]. If matching, the pairs will be underlined. If a brace is unmatched, it is colored with [theme_item brace_mismatch_color]. </member> <member name="auto_brace_completion_pairs" type="Dictionary" setter="set_auto_brace_completion_pairs" getter="get_auto_brace_completion_pairs" default="{ "\"": "\"", "'": "'", "(": ")", "[": "]", "{": "}" }"> - Sets the brace pairs to be autocompleted. + Sets the brace pairs to be autocompleted. For each entry in the dictionary, the key is the opening brace and the value is the closing brace that matches it. A brace is a [String] made of symbols. See [member auto_brace_completion_enabled] and [member auto_brace_completion_highlight_matching]. </member> <member name="code_completion_enabled" type="bool" setter="set_code_completion_enabled" getter="is_code_completion_enabled" default="false"> - Sets whether code completion is allowed. + If [code]true[/code], the [member ProjectSettings.input/ui_text_completion_query] action requests code completion. To handle it, see [method _request_code_completion] or [signal code_completion_requested]. </member> <member name="code_completion_prefixes" type="String[]" setter="set_code_completion_prefixes" getter="get_code_completion_prefixes" default="[]"> Sets prefixes that will trigger code completion. @@ -548,28 +548,28 @@ Sets the string delimiters. All existing string delimiters will be removed. </member> <member name="gutters_draw_bookmarks" type="bool" setter="set_draw_bookmarks_gutter" getter="is_drawing_bookmarks_gutter" default="false"> - Sets if bookmarked should be drawn in the gutter. This gutter is shared with breakpoints and executing lines. + If [code]true[/code], bookmarks are drawn in the gutter. This gutter is shared with breakpoints and executing lines. See [method set_line_as_bookmarked]. </member> <member name="gutters_draw_breakpoints_gutter" type="bool" setter="set_draw_breakpoints_gutter" getter="is_drawing_breakpoints_gutter" default="false"> - Sets if breakpoints should be drawn in the gutter. This gutter is shared with bookmarks and executing lines. + If [code]true[/code], breakpoints are drawn in the gutter. This gutter is shared with bookmarks and executing lines. Clicking the gutter will toggle the breakpoint for the line, see [method set_line_as_breakpoint]. </member> <member name="gutters_draw_executing_lines" type="bool" setter="set_draw_executing_lines_gutter" getter="is_drawing_executing_lines_gutter" default="false"> - Sets if executing lines should be marked in the gutter. This gutter is shared with breakpoints and bookmarks lines. + If [code]true[/code], executing lines are marked in the gutter. This gutter is shared with breakpoints and bookmarks. See [method set_line_as_executing]. </member> <member name="gutters_draw_fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter" default="false"> - Sets if foldable lines icons should be drawn in the gutter. + If [code]true[/code], the fold gutter is drawn. In this gutter, the [theme_item can_fold_code_region] icon is drawn for each foldable line (see [method can_fold_line]) and the [theme_item folded_code_region] icon is drawn for each folded line (see [method is_line_folded]). These icons can be clicked to toggle the fold state, see [method toggle_foldable_line]. [member line_folding] must be [code]true[/code] to show icons. </member> <member name="gutters_draw_line_numbers" type="bool" setter="set_draw_line_numbers" getter="is_draw_line_numbers_enabled" default="false"> - Sets if line numbers should be drawn in the gutter. + If [code]true[/code], the line number gutter is drawn. Line numbers start at [code]1[/code] and are incremented for each line of text. Clicking and dragging in the line number gutter will select entire lines of text. </member> <member name="gutters_zero_pad_line_numbers" type="bool" setter="set_line_numbers_zero_padded" getter="is_line_numbers_zero_padded" default="false"> - Sets if line numbers drawn in the gutter are zero padded. + If [code]true[/code], line numbers drawn in the gutter are zero padded based on the total line count. Requires [member gutters_draw_line_numbers] to be set to [code]true[/code]. </member> <member name="indent_automatic" type="bool" setter="set_auto_indent_enabled" getter="is_auto_indent_enabled" default="false"> - Sets whether automatic indent are enabled, this will add an extra indent if a prefix or brace is found. + If [code]true[/code], an extra indent is automatically inserted when a new line is added and a prefix in [member indent_automatic_prefixes] is found. If a brace pair opening key is found, the matching closing brace will be moved to another new line (see [member auto_brace_completion_pairs]). </member> <member name="indent_automatic_prefixes" type="String[]" setter="set_auto_indent_prefixes" getter="get_auto_indent_prefixes" default="[":", "{", "[", "("]"> - Prefixes to trigger an automatic indent. + Prefixes to trigger an automatic indent. Used when [member indent_automatic] is set to [code]true[/code]. </member> <member name="indent_size" type="int" setter="set_indent_size" getter="get_indent_size" default="4"> Size of the tabulation indent (one [kbd]Tab[/kbd] press) in characters. If [member indent_use_spaces] is enabled the number of spaces to use. @@ -579,7 +579,7 @@ </member> <member name="layout_direction" type="int" setter="set_layout_direction" getter="get_layout_direction" overrides="Control" enum="Control.LayoutDirection" default="2" /> <member name="line_folding" type="bool" setter="set_line_folding_enabled" getter="is_line_folding_enabled" default="false"> - Sets whether line folding is allowed. + If [code]true[/code], lines can be folded. Otherwise, line folding methods like [method fold_line] will not work and [method can_fold_line] will always return [code]false[/code]. See [member gutters_draw_fold_gutter]. </member> <member name="line_length_guidelines" type="int[]" setter="set_line_length_guidelines" getter="get_line_length_guidelines" default="[]"> Draws vertical lines at the provided columns. The first entry is considered a main hard guideline and is draw more prominently. @@ -598,7 +598,7 @@ </signal> <signal name="code_completion_requested"> <description> - Emitted when the user requests code completion. + Emitted when the user requests code completion. This signal will not be sent if [method _request_code_completion] is overridden or [member code_completion_enabled] is [code]false[/code]. </description> </signal> <signal name="symbol_lookup"> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index 9fe42fff90..546d90fa3c 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -19,7 +19,7 @@ <return type="Color" /> <description> Constructs a default [Color] from opaque black. This is the same as [constant BLACK]. - [b]Note:[/b] in C#, constructs an empty color with all of its components set to [code]0.0[/code] (transparent black). + [b]Note:[/b] In C#, this constructs a [Color] with all of its components set to [code]0.0[/code] (transparent black). </description> </constructor> <constructor name="Color"> @@ -495,6 +495,15 @@ <member name="h" type="float" setter="" getter="" default="0.0"> The HSV hue of this color, on the range 0 to 1. </member> + <member name="ok_hsl_h" type="float" setter="" getter="" default="0.0"> + The OKHSL hue of this color, on the range 0 to 1. + </member> + <member name="ok_hsl_l" type="float" setter="" getter="" default="0.0"> + The OKHSL lightness of this color, on the range 0 to 1. + </member> + <member name="ok_hsl_s" type="float" setter="" getter="" default="0.0"> + The OKHSL saturation of this color, on the range 0 to 1. + </member> <member name="r" type="float" setter="" getter="" default="0.0"> The color's red component, typically on the range of 0 to 1. </member> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 9d36bc657b..342e20759e 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -65,7 +65,7 @@ [csharp] public override bool _CanDropData(Vector2 atPosition, Variant data) { - return data.VariantType == Variant.Type.Dictionary && dict.AsGodotDictionary().ContainsKey("color"); + return data.VariantType == Variant.Type.Dictionary && data.AsGodotDictionary().ContainsKey("color"); } public override void _DropData(Vector2 atPosition, Variant data) @@ -120,8 +120,8 @@ <return type="void" /> <param index="0" name="event" type="InputEvent" /> <description> - Virtual method to be implemented by the user. Use this method to process and accept inputs on UI elements. See [method accept_event]. - [b]Example usage for clicking a control:[/b] + Virtual method to be implemented by the user. Override this method to handle and accept inputs on UI elements. See also [method accept_event]. + [b]Example:[/b] Click on the control to print a message: [codeblocks] [gdscript] func _gui_input(event): @@ -142,13 +142,13 @@ } [/csharp] [/codeblocks] - The event won't trigger if: - * clicking outside the control (see [method _has_point]); - * control has [member mouse_filter] set to [constant MOUSE_FILTER_IGNORE]; - * control is obstructed by another [Control] on top of it, which doesn't have [member mouse_filter] set to [constant MOUSE_FILTER_IGNORE]; - * control's parent has [member mouse_filter] set to [constant MOUSE_FILTER_STOP] or has accepted the event; - * it happens outside the parent's rectangle and the parent has either [member clip_contents] enabled. - [b]Note:[/b] Event position is relative to the control origin. + If the [param event] inherits [InputEventMouse], this method will [b]not[/b] be called when: + - the control's [member mouse_filter] is set to [constant MOUSE_FILTER_IGNORE]; + - the control is obstructed by another control on top, that doesn't have [member mouse_filter] set to [constant MOUSE_FILTER_IGNORE]; + - the control's parent has [member mouse_filter] set to [constant MOUSE_FILTER_STOP] or has accepted the event; + - the control's parent has [member clip_contents] enabled and the [param event]'s position is outside the parent's rectangle; + - the [param event]'s position is outside the control (see [method _has_point]). + [b]Note:[/b] The [param event]'s position is relative to this control's origin. </description> </method> <method name="_has_point" qualifiers="virtual const"> @@ -168,8 +168,8 @@ The returned node must be of type [Control] or Control-derived. It can have child nodes of any type. It is freed when the tooltip disappears, so make sure you always provide a new instance (if you want to use a pre-existing node from your scene tree, you can duplicate it and pass the duplicated instance). When [code]null[/code] or a non-Control node is returned, the default tooltip will be used instead. The returned node will be added as child to a [PopupPanel], so you should only provide the contents of that panel. That [PopupPanel] can be themed using [method Theme.set_stylebox] for the type [code]"TooltipPanel"[/code] (see [member tooltip_text] for an example). [b]Note:[/b] The tooltip is shrunk to minimal size. If you want to ensure it's fully visible, you might want to set its [member custom_minimum_size] to some non-zero value. - [b]Note:[/b] The node (and any relevant children) should be [member CanvasItem.visible] when returned, otherwise, the viewport that instantiates it will not be able to calculate its minimum size reliably. - [b]Example of usage with a custom-constructed node:[/b] + [b]Note:[/b] The node (and any relevant children) should have their [member CanvasItem.visible] set to [code]true[/code] when returned, otherwise, the viewport that instantiates it will not be able to calculate its minimum size reliably. + [b]Example:[/b] Use a constructed node as a tooltip: [codeblocks] [gdscript] func _make_custom_tooltip(for_text): @@ -186,7 +186,7 @@ } [/csharp] [/codeblocks] - [b]Example of usage with a custom scene instance:[/b] + [b]Example:[/b] Usa a scene instance as a tooltip: [codeblocks] [gdscript] func _make_custom_tooltip(for_text): @@ -228,7 +228,7 @@ <description> Creates a local override for a theme [Color] with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_color_override]. See also [method get_theme_color]. - [b]Example of overriding a label's color and resetting it later:[/b] + [b]Example:[/b] Override a [Label]'s color and reset it later: [codeblocks] [gdscript] # Given the child Label node "MyLabel", override its font color with a custom value. @@ -292,10 +292,10 @@ <description> Creates a local override for a theme [StyleBox] with the specified [param name]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_stylebox_override]. See also [method get_theme_stylebox]. - [b]Example of modifying a property in a StyleBox by duplicating it:[/b] + [b]Example:[/b] Modify a property in a [StyleBox] by duplicating it: [codeblocks] [gdscript] - # The snippet below assumes the child node MyButton has a StyleBoxFlat assigned. + # The snippet below assumes the child node "MyButton" has a StyleBoxFlat assigned. # Resources are shared across instances, so we need to duplicate it # to avoid modifying the appearance of all other buttons. var new_stylebox_normal = $MyButton.get_theme_stylebox("normal").duplicate() @@ -306,7 +306,7 @@ $MyButton.remove_theme_stylebox_override("normal") [/gdscript] [csharp] - // The snippet below assumes the child node MyButton has a StyleBoxFlat assigned. + // The snippet below assumes the child node "MyButton" has a StyleBoxFlat assigned. // Resources are shared across instances, so we need to duplicate it // to avoid modifying the appearance of all other buttons. StyleBoxFlat newStyleboxNormal = GetNode<Button>("MyButton").GetThemeStylebox("normal").Duplicate() as StyleBoxFlat; @@ -446,7 +446,7 @@ <description> Returns the position of this [Control] in global screen coordinates (i.e. taking window position into account). Mostly useful for editor plugins. Equals to [member global_position] if the window is embedded (see [member Viewport.gui_embed_subwindows]). - [b]Example usage for showing a popup:[/b] + [b]Example:[/b] Show a popup at the mouse position: [codeblock] popup_menu.position = get_screen_position() + get_local_mouse_position() popup_menu.reset_size() @@ -559,7 +559,7 @@ <method name="grab_click_focus"> <return type="void" /> <description> - Creates an [InputEventMouseButton] that attempts to click the control. If the event is received, the control acquires focus. + Creates an [InputEventMouseButton] that attempts to click the control. If the event is received, the control gains focus. [codeblocks] [gdscript] func _process(delta): @@ -809,9 +809,11 @@ <param index="1" name="can_drop_func" type="Callable" /> <param index="2" name="drop_func" type="Callable" /> <description> - Forwards the handling of this control's [method _get_drag_data], [method _can_drop_data] and [method _drop_data] virtual functions to delegate callables. - For each argument, if not empty, the delegate callable is used, otherwise the local (virtual) function is used. - The function format for each callable should be exactly the same as the virtual functions described above. + Sets the given callables to be used instead of the control's own drag-and-drop virtual methods. If a callable is empty, its respective virtual method is used as normal. + The arguments for each callable should be exactly the same as their respective virtual methods, which would be: + - [param drag_func] corresponds to [method _get_drag_data] and requires a [Vector2]; + - [param can_drop_func] corresponds to [method _can_drop_data] and requires both a [Vector2] and a [Variant]; + - [param drop_func] corresponds to [method _drop_data] and requires both a [Vector2] and a [Variant]. </description> </method> <method name="set_drag_preview"> @@ -993,8 +995,9 @@ Controls whether the control will be able to receive mouse button input events through [method _gui_input] and how these events should be handled. Also controls whether the control can receive the [signal mouse_entered], and [signal mouse_exited] signals. See the constants to learn what each does. </member> <member name="mouse_force_pass_scroll_events" type="bool" setter="set_force_pass_scroll_events" getter="is_force_pass_scroll_events" default="true"> - When enabled, scroll wheel events processed by [method _gui_input] will be passed to the parent control even if [member mouse_filter] is set to [constant MOUSE_FILTER_STOP]. As it defaults to true, this allows nested scrollable containers to work out of the box. + When enabled, scroll wheel events processed by [method _gui_input] will be passed to the parent control even if [member mouse_filter] is set to [constant MOUSE_FILTER_STOP]. You should disable it on the root of your UI if you do not want scroll events to go to the [method Node._unhandled_input] processing. + [b]Note:[/b] Because this property defaults to [code]true[/code], this allows nested scrollable containers to work out of the box. </member> <member name="offset_bottom" type="float" setter="set_offset" getter="get_offset" default="0.0"> Distance between the node's bottom edge and its parent control, based on [member anchor_bottom]. @@ -1059,7 +1062,7 @@ </member> <member name="tooltip_auto_translate_mode" type="int" setter="set_tooltip_auto_translate_mode" getter="get_tooltip_auto_translate_mode" enum="Node.AutoTranslateMode" default="0"> Defines if tooltip text should automatically change to its translated version depending on the current locale. Uses the same auto translate mode as this control when set to [constant Node.AUTO_TRANSLATE_MODE_INHERIT]. - [b]Note:[/b] When the tooltip is customized using [method _make_custom_tooltip], this auto translate mode is applied automatically to the returned control. + [b]Note:[/b] Tooltips customized using [method _make_custom_tooltip] do not use this auto translate mode automatically. </member> <member name="tooltip_text" type="String" setter="set_tooltip_text" getter="get_tooltip_text" default=""""> The default tooltip text. The tooltip appears when the user's mouse cursor stays idle over this control for a few moments, provided that the [member mouse_filter] property is not [constant MOUSE_FILTER_IGNORE]. The time required for the tooltip to appear can be changed with the [member ProjectSettings.gui/timers/tooltip_delay_sec] option. See also [method get_tooltip]. @@ -1365,7 +1368,7 @@ <constant name="LAYOUT_DIRECTION_INHERITED" value="0" enum="LayoutDirection"> Automatic layout direction, determined from the parent control layout direction. </constant> - <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection"> + <constant name="LAYOUT_DIRECTION_APPLICATION_LOCALE" value="1" enum="LayoutDirection"> Automatic layout direction, determined from the current locale. </constant> <constant name="LAYOUT_DIRECTION_LTR" value="2" enum="LayoutDirection"> @@ -1374,6 +1377,14 @@ <constant name="LAYOUT_DIRECTION_RTL" value="3" enum="LayoutDirection"> Right-to-left layout direction. </constant> + <constant name="LAYOUT_DIRECTION_SYSTEM_LOCALE" value="4" enum="LayoutDirection"> + Automatic layout direction, determined from the system locale. + </constant> + <constant name="LAYOUT_DIRECTION_MAX" value="5" enum="LayoutDirection"> + Represents the size of the [enum LayoutDirection] enum. + </constant> + <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection" deprecated="Use [constant LAYOUT_DIRECTION_APPLICATION_LOCALE] instead."> + </constant> <constant name="TEXT_DIRECTION_INHERITED" value="3" enum="TextDirection"> Text writing direction is the same as layout direction. </constant> diff --git a/doc/classes/Cubemap.xml b/doc/classes/Cubemap.xml index b7da3c4ec6..8a850920f7 100644 --- a/doc/classes/Cubemap.xml +++ b/doc/classes/Cubemap.xml @@ -6,8 +6,27 @@ <description> A cubemap is made of 6 textures organized in layers. They are typically used for faking reflections in 3D rendering (see [ReflectionProbe]). It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods. This resource is typically used as a uniform in custom shaders. Few core Godot methods make use of [Cubemap] resources. - To create such a texture file yourself, reimport your image files using the Godot Editor import presets. - [b]Note:[/b] Godot doesn't support using cubemaps in a [PanoramaSkyMaterial]. You can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cubemap to an equirectangular sky map. + To create such a texture file yourself, reimport your image files using the Godot Editor import presets. The expected image order is X+, X-, Y+, Y-, Z+, Z- (in Godot's coordinate system, so Y+ is "up" and Z- is "forward"). You can use one of the following templates as a base: + - [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/cubemap_template_2x3.webp]2×3 cubemap template (default layout option)[/url] + - [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/cubemap_template_3x2.webp]3×2 cubemap template[/url] + - [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/cubemap_template_1x6.webp]1×6 cubemap template[/url] + - [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/cubemap_template_6x1.webp]6×1 cubemap template[/url] + [b]Note:[/b] Godot doesn't support using cubemaps in a [PanoramaSkyMaterial]. To use a cubemap as a skybox, convert the default [PanoramaSkyMaterial] to a [ShaderMaterial] using the [b]Convert to ShaderMaterial[/b] resource dropdown option, then replace its code with the following: + [codeblock lang=text] + shader_type sky; + + uniform samplerCube source_panorama : filter_linear, source_color, hint_default_black; + uniform float exposure : hint_range(0, 128) = 1.0; + + void sky() { + // If importing a cubemap from another engine, you may need to flip one of the `EYEDIR` components below + // by replacing it with `-EYEDIR`. + vec3 eyedir = vec3(EYEDIR.x, EYEDIR.y, EYEDIR.z); + COLOR = texture(source_panorama, eyedir).rgb * exposure; + } + [/codeblock] + After replacing the shader code and saving, specify the imported Cubemap resource in the Shader Parameters section of the ShaderMaterial in the inspector. + Alternatively, you can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cubemap to an equirectangular sky map and use [PanoramaSkyMaterial] as usual. </description> <tutorials> </tutorials> diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml index 9157649af2..f8386b73b2 100644 --- a/doc/classes/Curve3D.xml +++ b/doc/classes/Curve3D.xml @@ -204,6 +204,9 @@ <member name="bake_interval" type="float" setter="set_bake_interval" getter="get_bake_interval" default="0.2"> The distance in meters between two adjacent cached points. Changing it forces the cache to be recomputed the next time the [method get_baked_points] or [method get_baked_length] function is called. The smaller the distance, the more points in the cache and the more memory it will consume, so use with care. </member> + <member name="closed" type="bool" setter="set_closed" getter="is_closed" default="false"> + If [code]true[/code], and the curve has more than 2 control points, the last point and the first one will be connected in a loop. + </member> <member name="point_count" type="int" setter="set_point_count" getter="get_point_count" default="0"> The number of points describing the curve. </member> diff --git a/doc/classes/DirAccess.xml b/doc/classes/DirAccess.xml index 9c71addf0c..0f5844fd63 100644 --- a/doc/classes/DirAccess.xml +++ b/doc/classes/DirAccess.xml @@ -14,7 +14,7 @@ # Static DirAccess.make_dir_absolute("user://levels/world1") [/codeblock] - [b]Note:[/b] Many resources types are imported (e.g. textures or sound files), and their source asset will not be included in the exported game, as only the imported version is used. Use [ResourceLoader] to access imported resources. + [b]Note:[/b] Accessing project ("res://") directories once exported may behave unexpectedly as some files are converted to engine-specific formats and their original source files may not be present in the expected PCK package. Because of this, to access resources in an exported project, it is recommended to use [ResourceLoader] instead of [FileAccess]. Here is an example on how to iterate through the files of a directory: [codeblocks] [gdscript] @@ -60,6 +60,7 @@ } [/csharp] [/codeblocks] + Keep in mind that file names may change or be remapped after export. If you want to see the actual resource file list as it appears in the editor, use [method ResourceLoader.list_directory] instead. </description> <tutorials> <link title="File system">$DOCS_URL/tutorials/scripting/filesystem.html</link> @@ -115,6 +116,7 @@ <param index="0" name="path" type="String" /> <description> Returns whether the target directory exists. The argument can be relative to the current directory, or an absolute path. + [b]Note:[/b] The returned [bool] in the editor and after exporting when used on a path in the [code]res://[/code] directory may be different. Some files are converted to engine-specific formats when exported, potentially changing the directory structure. </description> </method> <method name="dir_exists_absolute" qualifiers="static"> @@ -122,6 +124,7 @@ <param index="0" name="path" type="String" /> <description> Static version of [method dir_exists]. Supports only absolute paths. + [b]Note:[/b] The returned [bool] in the editor and after exporting when used on a path in the [code]res://[/code] directory may be different. Some files are converted to engine-specific formats when exported, potentially changing the directory structure. </description> </method> <method name="file_exists"> @@ -130,6 +133,7 @@ <description> Returns whether the target file exists. The argument can be relative to the current directory, or an absolute path. For a static equivalent, use [method FileAccess.file_exists]. + [b]Note:[/b] Many resources types are imported (e.g. textures or sound files), and their source asset will not be included in the exported game, as only the imported version is used. See [method ResourceLoader.exists] for an alternative approach that takes resource remapping into account. </description> </method> <method name="get_current_dir" qualifiers="const"> @@ -150,6 +154,7 @@ <description> Returns a [PackedStringArray] containing filenames of the directory contents, excluding files. The array is sorted alphabetically. Affected by [member include_hidden] and [member include_navigational]. + [b]Note:[/b] The returned directories in the editor and after exporting in the [code]res://[/code] directory may differ as some files are converted to engine-specific formats when exported. </description> </method> <method name="get_directories_at" qualifiers="static"> @@ -158,6 +163,7 @@ <description> Returns a [PackedStringArray] containing filenames of the directory contents, excluding files, at the given [param path]. The array is sorted alphabetically. Use [method get_directories] if you want more control of what gets included. + [b]Note:[/b] The returned directories in the editor and after exporting in the [code]res://[/code] directory may differ as some files are converted to engine-specific formats when exported. </description> </method> <method name="get_drive_count" qualifiers="static"> @@ -193,6 +199,7 @@ <description> Returns a [PackedStringArray] containing filenames of the directory contents, excluding directories, at the given [param path]. The array is sorted alphabetically. Use [method get_files] if you want more control of what gets included. + [b]Note:[/b] When used on a [code]res://[/code] path in an exported project, only the files included in the PCK at the given folder level are returned. In practice, this means that since imported resources are stored in a top-level [code].godot/[/code] folder, only paths to [code].gd[/code] and [code].import[/code] files are returned (plus a few other files, such as [code]project.godot[/code] or [code]project.binary[/code] and the project icon). In an exported project, the list of returned files will also vary depending on [member ProjectSettings.editor/export/convert_text_resources_to_binary]. </description> </method> <method name="get_next"> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 37bf265d20..e2a352de9a 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -105,7 +105,7 @@ <param index="3" name="callback" type="Callable" /> <description> Shows a text input dialog which uses the operating system's native look-and-feel. [param callback] should accept a single [String] parameter which contains the text field's contents. - [b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG_INPUT] feature. Supported platforms include macOS and Windows. + [b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG_INPUT] feature. Supported platforms include macOS, Windows, and Android. </description> </method> <method name="dialog_show"> @@ -139,11 +139,12 @@ <description> Displays OS native dialog for selecting files or directories in the file system. Each filter string in the [param filters] array should be formatted like this: [code]*.txt,*.doc;Text Files[/code]. The description text of the filter is optional and can be omitted. See also [member FileDialog.filters]. - Callbacks have the following arguments: [code]status: bool, selected_paths: PackedStringArray, selected_filter_index: int[/code]. - [b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG_FILE] feature. Supported platforms include Linux (X11/Wayland), Windows, and macOS. + Callbacks have the following arguments: [code]status: bool, selected_paths: PackedStringArray, selected_filter_index: int[/code]. [b]On Android,[/b] callback argument [code]selected_filter_index[/code] is always zero. + [b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG_FILE] feature. Supported platforms include Linux (X11/Wayland), Windows, macOS, and Android. [b]Note:[/b] [param current_directory] might be ignored. - [b]Note:[/b] On Linux, [param show_hidden] is ignored. - [b]Note:[/b] On macOS, native file dialogs have no title. + [b]Note:[/b] On Android, the filter strings in the [param filters] array should be specified using MIME types, for example:[code]image/png, image/jpeg"[/code]. Additionally, the [param mode] [constant FILE_DIALOG_MODE_OPEN_ANY] is not supported on Android. + [b]Note:[/b] On Android and Linux, [param show_hidden] is ignored. + [b]Note:[/b] On Android and macOS, native file dialogs have no title. [b]Note:[/b] On macOS, sandboxed apps will save security-scoped bookmarks to retain access to the opened folders across multiple sessions. Use [method OS.get_granted_permissions] to get a list of saved bookmarks. </description> </method> @@ -166,7 +167,7 @@ - [code]"values"[/code] - [PackedStringArray] of values. If empty, boolean option (check box) is used. - [code]"default"[/code] - default selected option index ([int]) or default boolean value ([bool]). Callbacks have the following arguments: [code]status: bool, selected_paths: PackedStringArray, selected_filter_index: int, selected_option: Dictionary[/code]. - [b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG_FILE] feature. Supported platforms include Linux (X11/Wayland), Windows, and macOS. + [b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG_FILE_EXTRA] feature. Supported platforms include Linux (X11/Wayland), Windows, and macOS. [b]Note:[/b] [param current_directory] might be ignored. [b]Note:[/b] On Linux (X11), [param show_hidden] is ignored. [b]Note:[/b] On macOS, native file dialogs have no title. @@ -184,7 +185,7 @@ <return type="Color" /> <description> Returns OS theme accent color. Returns [code]Color(0, 0, 0, 0)[/code], if accent color is unknown. - [b]Note:[/b] This method is implemented on macOS and Windows. + [b]Note:[/b] This method is implemented on macOS, Windows, and Android. </description> </method> <method name="get_base_color" qualifiers="const"> @@ -236,7 +237,7 @@ <return type="int" /> <param index="0" name="rect" type="Rect2" /> <description> - Returns index of the screen which contains specified rectangle. + Returns the index of the screen that overlaps the most with the given rectangle. Returns [code]-1[/code] if the rectangle doesn't overlap with any screen or has no area. </description> </method> <method name="get_swap_cancel_ok"> @@ -1683,6 +1684,7 @@ <param index="1" name="window_id" type="int" default="0" /> <description> Sets window mode for the given window to [param mode]. See [enum WindowMode] for possible values and how each mode behaves. + [b]Note:[/b] On Android, setting it to [constant WINDOW_MODE_FULLSCREEN] or [constant WINDOW_MODE_EXCLUSIVE_FULLSCREEN] will enable immersive mode. [b]Note:[/b] Setting the window to full screen forcibly sets the borderless flag to [code]true[/code], so make sure to set it back to [code]false[/code] when not wanted. </description> </method> @@ -1888,7 +1890,10 @@ Display server supports spawning text input dialogs using the operating system's native look-and-feel. See [method dialog_input_text]. [b]Windows, macOS[/b] </constant> <constant name="FEATURE_NATIVE_DIALOG_FILE" value="25" enum="Feature"> - Display server supports spawning dialogs for selecting files or directories using the operating system's native look-and-feel. See [method file_dialog_show] and [method file_dialog_with_options_show]. [b]Windows, macOS, Linux (X11/Wayland)[/b] + Display server supports spawning dialogs for selecting files or directories using the operating system's native look-and-feel. See [method file_dialog_show]. [b]Windows, macOS, Linux (X11/Wayland), Android[/b] + </constant> + <constant name="FEATURE_NATIVE_DIALOG_FILE_EXTRA" value="26" enum="Feature"> + The display server supports all features of [constant FEATURE_NATIVE_DIALOG_FILE], with the added functionality of Options and native dialog file access to [code]res://[/code] and [code]user://[/code] paths. See [method file_dialog_show] and [method file_dialog_with_options_show]. [b]Windows, macOS, Linux (X11/Wayland)[/b] </constant> <constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode"> Makes the mouse cursor visible if it is hidden. @@ -2058,6 +2063,7 @@ <constant name="WINDOW_MODE_FULLSCREEN" value="3" enum="WindowMode"> Full screen mode with full multi-window support. Full screen window covers the entire display area of a screen and has no decorations. The display's video mode is not changed. + [b]On Android:[/b] This enables immersive mode. [b]On Windows:[/b] Multi-window full-screen mode has a 1px border of the [member ProjectSettings.rendering/environment/defaults/default_clear_color] color. [b]On macOS:[/b] A new desktop is used to display the running project. [b]Note:[/b] Regardless of the platform, enabling full screen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling full screen mode. @@ -2065,6 +2071,7 @@ <constant name="WINDOW_MODE_EXCLUSIVE_FULLSCREEN" value="4" enum="WindowMode"> A single window full screen mode. This mode has less overhead, but only one window can be open on a given screen at a time (opening a child window or application switching will trigger a full screen transition). Full screen window covers the entire display area of a screen and has no border or decorations. The display's video mode is not changed. + [b]On Android:[/b] This enables immersive mode. [b]On Windows:[/b] Depending on video driver, full screen transition might cause screens to go black for a moment. [b]On macOS:[/b] A new desktop is used to display the running project. Exclusive full screen mode prevents Dock and Menu from showing up when the mouse pointer is hovering the edge of the screen. [b]On Linux (X11):[/b] Exclusive full screen mode bypasses compositor. @@ -2099,7 +2106,11 @@ <constant name="WINDOW_FLAG_MOUSE_PASSTHROUGH" value="7" enum="WindowFlags"> All mouse events are passed to the underlying window of the same application. </constant> - <constant name="WINDOW_FLAG_MAX" value="8" enum="WindowFlags"> + <constant name="WINDOW_FLAG_SHARP_CORNERS" value="8" enum="WindowFlags"> + Window style is overridden, forcing sharp corners. + [b]Note:[/b] This flag is implemented only on Windows (11). + </constant> + <constant name="WINDOW_FLAG_MAX" value="9" enum="WindowFlags"> Max value of the [enum WindowFlags]. </constant> <constant name="WINDOW_EVENT_MOUSE_ENTER" value="0" enum="WindowEvent"> @@ -2145,12 +2156,14 @@ <constant name="DISPLAY_HANDLE" value="0" enum="HandleType"> Display handle: - Linux (X11): [code]X11::Display*[/code] for the display. + - Linux (Wayland): [code]wl_display[/code] for the display. - Android: [code]EGLDisplay[/code] for the display. </constant> <constant name="WINDOW_HANDLE" value="1" enum="HandleType"> Window handle: - Windows: [code]HWND[/code] for the window. - Linux (X11): [code]X11::Window*[/code] for the window. + - Linux (Wayland): [code]wl_surface[/code] for the window. - macOS: [code]NSWindow*[/code] for the window. - iOS: [code]UIViewController*[/code] for the view controller. - Android: [code]jObject[/code] for the activity. @@ -2165,9 +2178,20 @@ OpenGL context (only with the GL Compatibility renderer): - Windows: [code]HGLRC[/code] for the window (native GL), or [code]EGLContext[/code] for the window (ANGLE). - Linux (X11): [code]GLXContext*[/code] for the window. + - Linux (Wayland): [code]EGLContext[/code] for the window. - macOS: [code]NSOpenGLContext*[/code] for the window (native GL), or [code]EGLContext[/code] for the window (ANGLE). - Android: [code]EGLContext[/code] for the window. </constant> + <constant name="EGL_DISPLAY" value="4" enum="HandleType"> + - Windows: [code]EGLDisplay[/code] for the window (ANGLE). + - macOS: [code]EGLDisplay[/code] for the window (ANGLE). + - Linux (Wayland): [code]EGLDisplay[/code] for the window. + </constant> + <constant name="EGL_CONFIG" value="5" enum="HandleType"> + - Windows: [code]EGLConfig[/code] for the window (ANGLE). + - macOS: [code]EGLConfig[/code] for the window (ANGLE). + - Linux (Wayland): [code]EGLConfig[/code] for the window. + </constant> <constant name="TTS_UTTERANCE_STARTED" value="0" enum="TTSUtteranceEvent"> Utterance has begun to be spoken. </constant> diff --git a/doc/classes/EditorDebuggerPlugin.xml b/doc/classes/EditorDebuggerPlugin.xml index a519e43bc6..d513a4fce0 100644 --- a/doc/classes/EditorDebuggerPlugin.xml +++ b/doc/classes/EditorDebuggerPlugin.xml @@ -15,18 +15,20 @@ class ExampleEditorDebugger extends EditorDebuggerPlugin: - func _has_capture(prefix): - # Return true if you wish to handle message with this prefix. - return prefix == "my_plugin" + func _has_capture(capture): + # Return true if you wish to handle messages with the prefix "my_plugin:". + return capture == "my_plugin" func _capture(message, data, session_id): if message == "my_plugin:ping": get_session(session_id).send_message("my_plugin:echo", data) + return true + return false func _setup_session(session_id): # Add a new tab in the debugger session UI containing a label. var label = Label.new() - label.name = "Example plugin" + label.name = "Example plugin" # Will be used as the tab title. label.text = "Example plugin" var session = get_session(session_id) # Listens to the session started and stopped signals. @@ -43,6 +45,24 @@ remove_debugger_plugin(debugger) [/gdscript] [/codeblocks] + To connect on the running game side, use the [EngineDebugger] singleton: + [codeblocks] + [gdscript] + extends Node + + func _ready(): + EngineDebugger.register_message_capture("my_plugin", _capture) + EngineDebugger.send_message("my_plugin:ping", ["test"]) + + func _capture(message, data): + # Note that the "my_plugin:" prefix is not used here. + if message == "echo": + prints("Echo received:", data) + return true + return false + [/gdscript] + [/codeblocks] + [b]Note:[/b] While the game is running, [method @GlobalScope.print] and similar functions [i]called in the editor[/i] do not print anything, the Output Log prints only game messages. </description> <tutorials> </tutorials> @@ -68,7 +88,7 @@ <param index="1" name="data" type="Array" /> <param index="2" name="session_id" type="int" /> <description> - Override this method to process incoming messages. The [param session_id] is the ID of the [EditorDebuggerSession] that received the message (which you can retrieve via [method get_session]). + Override this method to process incoming messages. The [param session_id] is the ID of the [EditorDebuggerSession] that received the [param message]. Use [method get_session] to retrieve the session. This method should return [code]true[/code] if the message is recognized. </description> </method> <method name="_goto_script_line" qualifiers="virtual"> @@ -90,7 +110,7 @@ <return type="void" /> <param index="0" name="session_id" type="int" /> <description> - Override this method to be notified whenever a new [EditorDebuggerSession] is created (the session may be inactive during this stage). + Override this method to be notified whenever a new [EditorDebuggerSession] is created. Note that the session may be inactive during this stage. </description> </method> <method name="get_session"> diff --git a/doc/classes/EditorDebuggerSession.xml b/doc/classes/EditorDebuggerSession.xml index b4e754cc7e..f5fa3e34d5 100644 --- a/doc/classes/EditorDebuggerSession.xml +++ b/doc/classes/EditorDebuggerSession.xml @@ -14,7 +14,7 @@ <return type="void" /> <param index="0" name="control" type="Control" /> <description> - Adds the given [param control] to the debug session UI in the debugger bottom panel. + Adds the given [param control] to the debug session UI in the debugger bottom panel. The [param control]'s node name will be used as the tab title. </description> </method> <method name="is_active"> diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml index aa8e4b3d56..23e3f4139c 100644 --- a/doc/classes/EditorExportPlugin.xml +++ b/doc/classes/EditorExportPlugin.xml @@ -27,6 +27,7 @@ <description> Return [code]true[/code] if this plugin will customize scenes based on the platform and features used. When enabled, [method _get_customization_configuration_hash] and [method _customize_scene] will be called and must be implemented. + [b]Note:[/b] [method _customize_scene] will only be called for scenes that have been modified since the last export. </description> </method> <method name="_customize_resource" qualifiers="virtual"> @@ -34,9 +35,16 @@ <param index="0" name="resource" type="Resource" /> <param index="1" name="path" type="String" /> <description> - Customize a resource. If changes are made to it, return the same or a new resource. Otherwise, return [code]null[/code]. - The [i]path[/i] argument is only used when customizing an actual file, otherwise this means that this resource is part of another one and it will be empty. + Customize a resource. If changes are made to it, return the same or a new resource. Otherwise, return [code]null[/code]. When a new resource is returned, [param resource] will be replaced by a copy of the new resource. + The [param path] argument is only used when customizing an actual file, otherwise this means that this resource is part of another one and it will be empty. Implementing this method is required if [method _begin_customize_resources] returns [code]true[/code]. + [b]Note:[/b] When customizing any of the following types and returning another resource, the other resource should not be skipped using [method skip] in [method _export_file]: + - [AtlasTexture] + - [CompressedCubemap] + - [CompressedCubemapArray] + - [CompressedTexture2D] + - [CompressedTexture2DArray] + - [CompressedTexture3D] </description> </method> <method name="_customize_scene" qualifiers="virtual"> diff --git a/doc/classes/EditorFeatureProfile.xml b/doc/classes/EditorFeatureProfile.xml index 3aa1e63aac..c125c923ef 100644 --- a/doc/classes/EditorFeatureProfile.xml +++ b/doc/classes/EditorFeatureProfile.xml @@ -121,7 +121,10 @@ <constant name="FEATURE_HISTORY_DOCK" value="7" enum="Feature"> The History dock. If this feature is disabled, the History dock won't be visible. </constant> - <constant name="FEATURE_MAX" value="8" enum="Feature"> + <constant name="FEATURE_GAME" value="8" enum="Feature"> + The Game tab, which allows embedding the game window and selecting nodes by clicking inside of it. If this feature is disabled, the Game tab won't display. + </constant> + <constant name="FEATURE_MAX" value="9" enum="Feature"> Represents the size of the [enum Feature] enum. </constant> </constants> diff --git a/doc/classes/EditorFileSystemImportFormatSupportQuery.xml b/doc/classes/EditorFileSystemImportFormatSupportQuery.xml index b1a810fe6e..fc2feca911 100644 --- a/doc/classes/EditorFileSystemImportFormatSupportQuery.xml +++ b/doc/classes/EditorFileSystemImportFormatSupportQuery.xml @@ -24,7 +24,7 @@ <method name="_query" qualifiers="virtual const"> <return type="bool" /> <description> - Query support. Return false if import must not continue. + Query support. Return [code]false[/code] if import must not continue. </description> </method> </methods> diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml index 28614b6631..186f249281 100644 --- a/doc/classes/EditorImportPlugin.xml +++ b/doc/classes/EditorImportPlugin.xml @@ -124,7 +124,8 @@ <return type="bool" /> <description> Tells whether this importer can be run in parallel on threads, or, on the contrary, it's only safe for the editor to call it from the main thread, for one file at a time. - If this method is not overridden, it will return [code]true[/code] by default (i.e., safe for parallel importing). + If this method is not overridden, it will return [code]false[/code] by default. + If this importer's implementation is thread-safe and can be run in parallel, override this with [code]true[/code] to optimize for concurrency. </description> </method> <method name="_get_import_options" qualifiers="virtual const"> @@ -153,7 +154,7 @@ <param index="1" name="option_name" type="StringName" /> <param index="2" name="options" type="Dictionary" /> <description> - This method can be overridden to hide specific import options if conditions are met. This is mainly useful for hiding options that depend on others if one of them is disabled. For example: + This method can be overridden to hide specific import options if conditions are met. This is mainly useful for hiding options that depend on others if one of them is disabled. [codeblocks] [gdscript] func _get_option_visibility(option, options): diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 43059db8b2..624e828520 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -117,6 +117,12 @@ [b]Note:[/b] When creating custom editor UI, prefer accessing theme items directly from your GUI nodes using the [code]get_theme_*[/code] methods. </description> </method> + <method name="get_editor_toaster" qualifiers="const"> + <return type="EditorToaster" /> + <description> + Returns the editor's [EditorToaster]. + </description> + </method> <method name="get_editor_undo_redo" qualifiers="const"> <return type="EditorUndoRedoManager" /> <description> @@ -301,6 +307,15 @@ See also [method Window.set_unparent_when_invisible]. </description> </method> + <method name="popup_method_selector"> + <return type="void" /> + <param index="0" name="object" type="Object" /> + <param index="1" name="callback" type="Callable" /> + <param index="2" name="current_value" type="String" default="""" /> + <description> + Pops up an editor dialog for selecting a method from [param object]. The [param callback] must take a single argument of type [String] which will contain the name of the selected method or be empty if the dialog is canceled. If [param current_value] is provided, the method will be selected automatically in the method list, if it exists. + </description> + </method> <method name="popup_node_selector"> <return type="void" /> <param index="0" name="callback" type="Callable" /> diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml index 8fd7c167d9..6a91e3559d 100644 --- a/doc/classes/EditorNode3DGizmoPlugin.xml +++ b/doc/classes/EditorNode3DGizmoPlugin.xml @@ -54,7 +54,7 @@ <return type="EditorNode3DGizmo" /> <param index="0" name="for_node_3d" type="Node3D" /> <description> - Override this method to return a custom [EditorNode3DGizmo] for the spatial nodes of your choice, return [code]null[/code] for the rest of nodes. See also [method _has_gizmo]. + Override this method to return a custom [EditorNode3DGizmo] for the 3D nodes of your choice, return [code]null[/code] for the rest of nodes. See also [method _has_gizmo]. </description> </method> <method name="_get_gizmo_name" qualifiers="virtual const"> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 8189f253fb..2cc9e08dd3 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -416,7 +416,7 @@ <param index="1" name="title" type="String" /> <param index="2" name="shortcut" type="Shortcut" default="null" /> <description> - Adds a control to the bottom panel (together with Output, Debug, Animation, etc). Returns a reference to the button added. It's up to you to hide/show the button when needed. When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_bottom_panel] and free it with [method Node.queue_free]. + Adds a control to the bottom panel (together with Output, Debug, Animation, etc.). Returns a reference to the button added. It's up to you to hide/show the button when needed. When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_bottom_panel] and free it with [method Node.queue_free]. Optionally, you can specify a shortcut parameter. When pressed, this shortcut will toggle the bottom panel's visibility. See the default editor bottom panel shortcuts in the Editor Settings for inspiration. Per convention, they all use [kbd]Alt[/kbd] modifier. </description> </method> diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 2b1083393f..4ff541f72d 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -132,6 +132,13 @@ Emitted when a property was deleted. Used internally. </description> </signal> + <signal name="property_favorited"> + <param index="0" name="property" type="StringName" /> + <param index="1" name="favorited" type="bool" /> + <description> + Emit it if you want to mark a property as favorited, making it appear at the top of the inspector. + </description> + </signal> <signal name="property_keyed"> <param index="0" name="property" type="StringName" /> <description> diff --git a/doc/classes/EditorResourcePreview.xml b/doc/classes/EditorResourcePreview.xml index ed3fdae352..a0c1a43fb2 100644 --- a/doc/classes/EditorResourcePreview.xml +++ b/doc/classes/EditorResourcePreview.xml @@ -32,7 +32,7 @@ <param index="3" name="userdata" type="Variant" /> <description> Queue the [param resource] being edited for preview. Once the preview is ready, the [param receiver]'s [param receiver_func] will be called. The [param receiver_func] must take the following four arguments: [String] path, [Texture2D] preview, [Texture2D] thumbnail_preview, [Variant] userdata. [param userdata] can be anything, and will be returned when [param receiver_func] is called. - [b]Note:[/b] If it was not possible to create the preview the [param receiver_func] will still be called, but the preview will be null. + [b]Note:[/b] If it was not possible to create the preview the [param receiver_func] will still be called, but the preview will be [code]null[/code]. </description> </method> <method name="queue_resource_preview"> @@ -43,7 +43,7 @@ <param index="3" name="userdata" type="Variant" /> <description> Queue a resource file located at [param path] for preview. Once the preview is ready, the [param receiver]'s [param receiver_func] will be called. The [param receiver_func] must take the following four arguments: [String] path, [Texture2D] preview, [Texture2D] thumbnail_preview, [Variant] userdata. [param userdata] can be anything, and will be returned when [param receiver_func] is called. - [b]Note:[/b] If it was not possible to create the preview the [param receiver_func] will still be called, but the preview will be null. + [b]Note:[/b] If it was not possible to create the preview the [param receiver_func] will still be called, but the preview will be [code]null[/code]. </description> </method> <method name="remove_preview_generator"> diff --git a/doc/classes/EditorResourcePreviewGenerator.xml b/doc/classes/EditorResourcePreviewGenerator.xml index 9c9b6d11b2..89bfe836d7 100644 --- a/doc/classes/EditorResourcePreviewGenerator.xml +++ b/doc/classes/EditorResourcePreviewGenerator.xml @@ -4,7 +4,7 @@ Custom generator of previews. </brief_description> <description> - Custom code to generate previews. Please check [code]file_dialog/thumbnail_size[/code] in [EditorSettings] to find out the right size to do previews at. + Custom code to generate previews. Check [member EditorSettings.filesystem/file_dialog/thumbnail_size] to find a proper size to generate previews at. </description> <tutorials> </tutorials> diff --git a/doc/classes/EditorScenePostImport.xml b/doc/classes/EditorScenePostImport.xml index 7325d31fc5..f8938c459c 100644 --- a/doc/classes/EditorScenePostImport.xml +++ b/doc/classes/EditorScenePostImport.xml @@ -5,7 +5,7 @@ </brief_description> <description> Imported scenes can be automatically modified right after import by setting their [b]Custom Script[/b] Import property to a [code]tool[/code] script that inherits from this class. - The [method _post_import] callback receives the imported scene's root node and returns the modified version of the scene. Usage example: + The [method _post_import] callback receives the imported scene's root node and returns the modified version of the scene: [codeblocks] [gdscript] @tool # Needed so it runs in editor. diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml index 5c1c898c9d..0004ec65c6 100644 --- a/doc/classes/EditorScenePostImportPlugin.xml +++ b/doc/classes/EditorScenePostImportPlugin.xml @@ -28,7 +28,7 @@ <param index="0" name="category" type="int" /> <param index="1" name="option" type="String" /> <description> - Return true whether updating the 3D view of the import dialog needs to be updated if an option has changed. + Should return [code]true[/code] if the 3D view of the import dialog needs to update when changing the given option. </description> </method> <method name="_get_internal_option_visibility" qualifiers="virtual const"> @@ -37,7 +37,7 @@ <param index="1" name="for_animation" type="bool" /> <param index="2" name="option" type="String" /> <description> - Return true or false whether a given option should be visible. Return null to ignore. + Should return [code]true[/code] to show the given option, [code]false[/code] to hide the given option, or [code]null[/code] to ignore. </description> </method> <method name="_get_option_visibility" qualifiers="virtual const"> @@ -46,7 +46,7 @@ <param index="1" name="for_animation" type="bool" /> <param index="2" name="option" type="String" /> <description> - Return true or false whether a given option should be visible. Return null to ignore. + Should return [code]true[/code] to show the given option, [code]false[/code] to hide the given option, or [code]null[/code] to ignore. </description> </method> <method name="_internal_process" qualifiers="virtual"> diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml index bd18852dbc..e342966fe8 100644 --- a/doc/classes/EditorScript.xml +++ b/doc/classes/EditorScript.xml @@ -6,7 +6,7 @@ <description> Scripts extending this class and implementing its [method _run] method can be executed from the Script Editor's [b]File > Run[/b] menu option (or by pressing [kbd]Ctrl + Shift + X[/kbd]) while the editor is running. This is useful for adding custom in-editor functionality to Godot. For more complex additions, consider using [EditorPlugin]s instead. [b]Note:[/b] Extending scripts need to have [code]tool[/code] mode enabled. - [b]Example script:[/b] + [b]Example:[/b] Running the following script prints "Hello from the Godot Editor!": [codeblocks] [gdscript] @tool diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index a5097521dc..ea987da6f5 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -152,7 +152,7 @@ <param index="1" name="value" type="Variant" /> <param index="2" name="update_current" type="bool" /> <description> - Sets the initial value of the setting specified by [param name] to [param value]. This is used to provide a value for the Revert button in the Editor Settings. If [param update_current] is true, the current value of the setting will be set to [param value] as well. + Sets the initial value of the setting specified by [param name] to [param value]. This is used to provide a value for the Revert button in the Editor Settings. If [param update_current] is [code]true[/code], the setting is reset to [param value] as well. </description> </method> <method name="set_project_metadata"> @@ -230,7 +230,7 @@ If [code]true[/code], when a node is deleted with animation tracks referencing it, a confirmation dialog appears before the tracks are deleted. The dialog will appear even when using the "Delete (No Confirm)" shortcut. </member> <member name="docks/scene_tree/ask_before_revoking_unique_name" type="bool" setter="" getter=""> - If [code]true[/code], displays a confirmation dialog before left-clicking the "percent" icon next to a node name in the Scene tree dock. When clicked, this icon revokes the node's scene-unique name, which can impact the behavior of scripts that rely on this scene-unique name due to identifiers not being found anymore. + If [code]true[/code], displays a confirmation dialog after left-clicking the "percent" icon next to a node name in the Scene tree dock. When clicked, this icon revokes the node's scene-unique name, which can impact the behavior of scripts that rely on this scene-unique name due to identifiers not being found anymore. </member> <member name="docks/scene_tree/auto_expand_to_selected" type="bool" setter="" getter=""> If [code]true[/code], the scene tree dock will automatically unfold nodes when a node that has folded parents is selected. @@ -359,7 +359,7 @@ <member name="editors/3d/navigation/navigation_scheme" type="int" setter="" getter=""> The navigation scheme preset to use in the 3D editor. Changing this setting will affect the mouse button and modifier controls used to navigate the 3D editor viewport. All schemes can use [kbd]Mouse wheel[/kbd] to zoom. - - [b]Godot:[/b] [kbd]Middle mouse button[/kbd] to orbit. [kbd]Shift + Middle mouse button[/kbd] to pan. [kbd]Ctrl + Shift + Middle mouse button[/kbd] to zoom. + - [b]Godot:[/b] [kbd]Middle mouse button[/kbd] to orbit. [kbd]Shift + Middle mouse button[/kbd] to pan. [kbd]Ctrl + Middle mouse button[/kbd] to zoom. - [b]Maya:[/b] [kbd]Alt + Left mouse button[/kbd] to orbit. [kbd]Middle mouse button[/kbd] to pan, [kbd]Shift + Middle mouse button[/kbd] to pan 10 times faster. [kbd]Alt + Right mouse button[/kbd] to zoom. - [b]Modo:[/b] [kbd]Alt + Left mouse button[/kbd] to orbit. [kbd]Alt + Shift + Left mouse button[/kbd] to pan. [kbd]Ctrl + Alt + Left mouse button[/kbd] to zoom. See also [member editors/3d/navigation/orbit_mouse_button], [member editors/3d/navigation/pan_mouse_button], [member editors/3d/navigation/zoom_mouse_button], and [member editors/3d/freelook/freelook_navigation_scheme]. @@ -717,9 +717,21 @@ <member name="filesystem/quick_open_dialog/default_display_mode" type="int" setter="" getter=""> If set to [code]Adaptive[/code], the dialog opens in list view or grid view depending on the requested type. If set to [code]Last Used[/code], the display mode will always open the way you last used it. </member> + <member name="filesystem/quick_open_dialog/enable_fuzzy_matching" type="bool" setter="" getter=""> + If [code]true[/code], fuzzy matching of search tokens is allowed. + </member> <member name="filesystem/quick_open_dialog/include_addons" type="bool" setter="" getter=""> If [code]true[/code], results will include files located in the [code]addons[/code] folder. </member> + <member name="filesystem/quick_open_dialog/max_fuzzy_misses" type="int" setter="" getter=""> + The number of allowed missed query characters in a match, if fuzzy matching is enabled. For example, with the default value of 2, [code]foobar[/code] would match [code]foobur[/code] and [code]foob[/code] but not [code]foo[/code]. + </member> + <member name="filesystem/quick_open_dialog/max_results" type="int" setter="" getter=""> + Maximum number of matches to show in dialog. + </member> + <member name="filesystem/quick_open_dialog/show_search_highlight" type="bool" setter="" getter=""> + If [code]true[/code], results will be highlighted with their search matches. + </member> <member name="filesystem/tools/oidn/oidn_denoise_path" type="String" setter="" getter=""> The path to the directory containing the Open Image Denoise (OIDN) executable, used optionally for denoising lightmaps. It can be downloaded from [url=https://www.openimagedenoise.org/downloads.html]openimagedenoise.org[/url]. To enable this feature for your specific project, use [member ProjectSettings.rendering/lightmapping/denoising/denoiser]. @@ -1049,7 +1061,7 @@ Determines whether online features are enabled in the editor, such as the Asset Library or update checks. Disabling these online features helps alleviate privacy concerns by preventing the editor from making HTTP requests to the Godot website or third-party platforms hosting assets from the Asset Library. </member> <member name="network/debug/remote_host" type="String" setter="" getter=""> - The address to listen to when starting the remote debugger. This can be set to [code]0.0.0.0[/code] to allow external clients to connect to the remote debugger (instead of restricting the remote debugger to connections from [code]localhost[/code]). + The address to listen to when starting the remote debugger. This can be set to this device's local IP address to allow external clients to connect to the remote debugger (instead of restricting the remote debugger to connections from [code]localhost[/code]). </member> <member name="network/debug/remote_port" type="int" setter="" getter=""> The port to listen to when starting the remote debugger. Godot will try to use port numbers above the configured number if the configured number is already taken by another application. @@ -1079,9 +1091,11 @@ </member> <member name="run/bottom_panel/action_on_play" type="int" setter="" getter=""> The action to execute on the bottom panel when running the project. + [b]Note:[/b] This option won't do anything if the bottom panel switching is locked using the pin button in the corner of the bottom panel. </member> <member name="run/bottom_panel/action_on_stop" type="int" setter="" getter=""> The action to execute on the bottom panel when stopping the project. + [b]Note:[/b] This option won't do anything if the bottom panel switching is locked using the pin button in the corner of the bottom panel. </member> <member name="run/output/always_clear_output_on_play" type="bool" setter="" getter=""> If [code]true[/code], the editor will clear the Output panel when running the project. @@ -1261,7 +1275,7 @@ If [code]true[/code], adds [url=$DOCS_URL/tutorials/scripting/gdscript/static_typing.html]GDScript static typing[/url] hints such as [code]-> void[/code] and [code]: int[/code] when using code autocompletion or when creating onready variables by drag and dropping nodes into the script editor while pressing the [kbd]Ctrl[/kbd] key. If [code]true[/code], newly created scripts will also automatically have type hints added to their method parameters and return types. </member> <member name="text_editor/completion/auto_brace_complete" type="bool" setter="" getter=""> - If [code]true[/code], automatically completes braces when making use of code completion. + If [code]true[/code], automatically inserts the matching closing brace when the opening brace is inserted by typing or autocompletion. Also automatically removes the closing brace when pressing [kbd]Backspace[/kbd] on the opening brace. This includes brackets ([code]()[/code], [code][][/code], [code]{}[/code]), string quotation marks ([code]''[/code], [code]""[/code]), and comments ([code]/**/[/code]) if the language supports it. </member> <member name="text_editor/completion/code_complete_delay" type="float" setter="" getter=""> The delay in seconds after which autocompletion suggestions should be displayed when the user stops typing. @@ -1314,6 +1328,9 @@ <member name="text_editor/script_list/group_help_pages" type="bool" setter="" getter=""> If [code]true[/code], class reference pages are grouped together at the bottom of the Script Editor's script list. </member> + <member name="text_editor/script_list/highlight_scene_scripts" type="bool" setter="" getter=""> + If [code]true[/code], the scripts that are used by the current scene are highlighted in the Script Editor's script list. + </member> <member name="text_editor/script_list/list_script_names_as" type="int" setter="" getter=""> Specifies how script paths should be displayed in Script Editor's script list. If using the "Name" option and some scripts share the same file name, more parts of their paths are revealed to avoid conflicts. </member> @@ -1395,7 +1412,7 @@ The script editor's documentation comment color. In GDScript, this is used for comments starting with [code]##[/code]. In C#, this is used for comments starting with [code]///[/code] or [code]/**[/code]. </member> <member name="text_editor/theme/highlighting/engine_type_color" type="Color" setter="" getter=""> - The script editor's engine type color ([Vector2], [Vector3], [Color], ...). + The script editor's engine type color ([Object], [Mesh], [Node], ...). </member> <member name="text_editor/theme/highlighting/executing_line_color" type="Color" setter="" getter=""> The script editor's color for the debugger's executing line icon (displayed in the gutter). diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml index 83c65b736e..6cd375a46d 100644 --- a/doc/classes/EditorSpinSlider.xml +++ b/doc/classes/EditorSpinSlider.xml @@ -40,6 +40,11 @@ Emitted when the spinner/slider is ungrabbed. </description> </signal> + <signal name="updown_pressed"> + <description> + Emitted when the updown button is pressed. + </description> + </signal> <signal name="value_focus_entered"> <description> Emitted when the value form gains focus. diff --git a/doc/classes/EditorToaster.xml b/doc/classes/EditorToaster.xml new file mode 100644 index 0000000000..c30b94c989 --- /dev/null +++ b/doc/classes/EditorToaster.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="EditorToaster" inherits="HBoxContainer" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Manages toast notifications within the editor. + </brief_description> + <description> + This object manages the functionality and display of toast notifications within the editor, ensuring timely and informative alerts are presented to users. + [b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorInterface.get_editor_toaster]. + </description> + <tutorials> + </tutorials> + <methods> + <method name="push_toast"> + <return type="void" /> + <param index="0" name="message" type="String" /> + <param index="1" name="severity" type="int" enum="EditorToaster.Severity" default="0" /> + <param index="2" name="tooltip" type="String" default="""" /> + <description> + Pushes a toast notification to the editor for display. + </description> + </method> + </methods> + <constants> + <constant name="SEVERITY_INFO" value="0" enum="Severity"> + Toast will display with an INFO severity. + </constant> + <constant name="SEVERITY_WARNING" value="1" enum="Severity"> + Toast will display with a WARNING severity and have a corresponding color. + </constant> + <constant name="SEVERITY_ERROR" value="2" enum="Severity"> + Toast will display with an ERROR severity and have a corresponding color. + </constant> + </constants> +</class> diff --git a/doc/classes/EditorTranslationParserPlugin.xml b/doc/classes/EditorTranslationParserPlugin.xml index a47a41594e..b9dc654de3 100644 --- a/doc/classes/EditorTranslationParserPlugin.xml +++ b/doc/classes/EditorTranslationParserPlugin.xml @@ -69,8 +69,7 @@ msgidsContextPlural.Add(new Godot.Collections.Array{"Only with context", "a friendly context", ""}); [/csharp] [/codeblocks] - [b]Note:[/b] If you override parsing logic for standard script types (GDScript, C#, etc.), it would be better to load the [code]path[/code] argument using [method ResourceLoader.load]. This is because built-in scripts are loaded as [Resource] type, not [FileAccess] type. - For example: + [b]Note:[/b] If you override parsing logic for standard script types (GDScript, C#, etc.), it would be better to load the [code]path[/code] argument using [method ResourceLoader.load]. This is because built-in scripts are loaded as [Resource] type, not [FileAccess] type. For example: [codeblocks] [gdscript] func _parse_file(path, msgids, msgids_context_plural): @@ -100,6 +99,14 @@ <tutorials> </tutorials> <methods> + <method name="_get_comments" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="msgids_comment" type="String[]" /> + <param index="1" name="msgids_context_plural_comment" type="String[]" /> + <description> + If overridden, called after [method _parse_file] to get comments for the parsed entries. This method should fill the arrays with the same number of elements and in the same order as [method _parse_file]. + </description> + </method> <method name="_get_recognized_extensions" qualifiers="virtual const"> <return type="PackedStringArray" /> <description> diff --git a/doc/classes/EditorUndoRedoManager.xml b/doc/classes/EditorUndoRedoManager.xml index 0f8c69a1bb..6a66a35ce8 100644 --- a/doc/classes/EditorUndoRedoManager.xml +++ b/doc/classes/EditorUndoRedoManager.xml @@ -87,7 +87,7 @@ <return type="void" /> <param index="0" name="execute" type="bool" default="true" /> <description> - Commit the action. If [param execute] is true (default), all "do" methods/properties are called/set when this function is called. + Commits the action. If [param execute] is [code]true[/code] (default), all "do" methods/properties are called/set when this function is called. </description> </method> <method name="create_action"> diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index bba5157053..3ae3753930 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -13,21 +13,7 @@ <return type="String" /> <description> Returns the name of the CPU architecture the Godot binary was built for. Possible return values include [code]"x86_64"[/code], [code]"x86_32"[/code], [code]"arm64"[/code], [code]"arm32"[/code], [code]"rv64"[/code], [code]"riscv"[/code], [code]"ppc64"[/code], [code]"ppc"[/code], [code]"wasm64"[/code], and [code]"wasm32"[/code]. - To detect whether the current build is 64-bit, you can use the fact that all 64-bit architecture names contain [code]64[/code] in their name: - [codeblocks] - [gdscript] - if "64" in Engine.get_architecture_name(): - print("Running a 64-bit build of Godot.") - else: - print("Running a 32-bit build of Godot.") - [/gdscript] - [csharp] - if (Engine.GetArchitectureName().Contains("64")) - GD.Print("Running a 64-bit build of Godot."); - else - GD.Print("Running a 32-bit build of Godot."); - [/csharp] - [/codeblocks] + To detect whether the current build is 64-bit, or the type of architecture, don't use the architecture name. Instead, use [method OS.has_feature] to check for the [code]"64"[/code] feature tag, or tags such as [code]"x86"[/code] or [code]"arm"[/code]. See the [url=$DOCS_URL/tutorials/export/feature_tags.html]Feature Tags[/url] documentation for more details. [b]Note:[/b] This method does [i]not[/i] return the name of the system's CPU architecture (like [method OS.get_processor_name]). For example, when running an [code]x86_32[/code] Godot binary on an [code]x86_64[/code] system, the returned value will still be [code]"x86_32"[/code]. </description> </method> diff --git a/doc/classes/EngineDebugger.xml b/doc/classes/EngineDebugger.xml index bcc1ac5299..3540f098ba 100644 --- a/doc/classes/EngineDebugger.xml +++ b/doc/classes/EngineDebugger.xml @@ -113,7 +113,8 @@ <param index="1" name="callable" type="Callable" /> <description> Registers a message capture with given [param name]. If [param name] is "my_message" then messages starting with "my_message:" will be called with the given callable. - Callable must accept a message string and a data array as argument. If the message and data are valid then callable must return [code]true[/code] otherwise [code]false[/code]. + The callable must accept a message string and a data array as argument. The callable should return [code]true[/code] if the message is recognized. + [b]Note:[/b] The callable will receive the message with the prefix stripped, unlike [method EditorDebuggerPlugin._capture]. See the [EditorDebuggerPlugin] description for an example. </description> </method> <method name="register_profiler"> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 1779408a4d..47fc48305b 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -182,7 +182,8 @@ [b]Note:[/b] [member glow_map] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices. </member> <member name="glow_map_strength" type="float" setter="set_glow_map_strength" getter="get_glow_map_strength" default="0.8"> - How strong of an impact the [member glow_map] should have on the overall glow effect. A strength of [code]0.0[/code] means the glow map has no effect on the overall glow effect. A strength of [code]1.0[/code] means the glow has a full effect on the overall glow effect (and can turn off glow entirely in specific areas of the screen if the glow map has black areas). + How strong of an influence the [member glow_map] should have on the overall glow effect. A strength of [code]0.0[/code] means the glow map has no influence, while a strength of [code]1.0[/code] means the glow map has full influence. + [b]Note:[/b] If the glow map has black areas, a value of [code]1.0[/code] can also turn off the glow effect entirely in specific areas of the screen. [b]Note:[/b] [member glow_map_strength] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices. </member> <member name="glow_mix" type="float" setter="set_glow_mix" getter="get_glow_mix" default="0.05"> diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml index 5888e30339..846897a463 100644 --- a/doc/classes/FileAccess.xml +++ b/doc/classes/FileAccess.xml @@ -4,7 +4,7 @@ Provides methods for file reading and writing operations. </brief_description> <description> - This class can be used to permanently store data in the user device's file system and to read from it. This is useful for store game save data or player configuration files. + This class can be used to permanently store data in the user device's file system and to read from it. This is useful for storing game save data or player configuration files. Here's a sample on how to write and read from a file: [codeblocks] [gdscript] @@ -34,7 +34,7 @@ [/codeblocks] In the example above, the file will be saved in the user data folder as specified in the [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] documentation. [FileAccess] will close when it's freed, which happens when it goes out of scope or when it gets assigned with [code]null[/code]. [method close] can be used to close it before then explicitly. In C# the reference must be disposed manually, which can be done with the [code]using[/code] statement or by calling the [code]Dispose[/code] method directly. - [b]Note:[/b] To access project resources once exported, it is recommended to use [ResourceLoader] instead of [FileAccess], as some files are converted to engine-specific formats and their original source files might not be present in the exported PCK package. + [b]Note:[/b] To access project resources once exported, it is recommended to use [ResourceLoader] instead of [FileAccess], as some files are converted to engine-specific formats and their original source files might not be present in the exported PCK package. If using [FileAccess], make sure the file is included in the export by changing its import mode to [b]Keep File (exported as is)[/b] in the Import dock, or, for files where this option is not available, change the non-resource export filter in the Export dialog to include the file's extension (e.g. [code]*.txt[/code]). [b]Note:[/b] Files are automatically closed only if the process exits "normally" (such as by clicking the window manager's close button or pressing [b]Alt + F4[/b]). If you stop the project execution by pressing [b]F8[/b] while the project is running, the file won't be closed as the game process will be killed. You can work around this by calling [method flush] at regular intervals. </description> <tutorials> @@ -173,6 +173,12 @@ Returns the next 32 bits from the file as a floating-point number. </description> </method> + <method name="get_half" qualifiers="const"> + <return type="float" /> + <description> + Returns the next 16 bits from the file as a half-precision floating-point number. + </description> + </method> <method name="get_hidden_attribute" qualifiers="static"> <return type="bool" /> <param index="0" name="file" type="String" /> @@ -308,6 +314,7 @@ <param index="0" name="path" type="String" /> <param index="1" name="mode_flags" type="int" enum="FileAccess.ModeFlags" /> <param index="2" name="key" type="PackedByteArray" /> + <param index="3" name="iv" type="PackedByteArray" default="PackedByteArray()" /> <description> Creates a new [FileAccess] object and opens an encrypted file in write or read mode. You need to pass a binary key to encrypt/decrypt it. [b]Note:[/b] The provided key must be 32 bytes long. @@ -470,6 +477,13 @@ Stores a floating-point number as 32 bits in the file. </description> </method> + <method name="store_half"> + <return type="void" /> + <param index="0" name="value" type="float" /> + <description> + Stores a half-precision floating-point number as 16 bits in the file. + </description> + </method> <method name="store_line"> <return type="void" /> <param index="0" name="line" type="String" /> diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index 18b8eb1d39..64369bec30 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -146,6 +146,7 @@ </member> <member name="filters" type="PackedStringArray" setter="set_filters" getter="get_filters" default="PackedStringArray()"> The available file type filters. Each filter string in the array should be formatted like this: [code]*.txt,*.doc;Text Files[/code]. The description text of the filter is optional and can be omitted. + [b]Note:[/b] For android native dialog, MIME types are used like this: [code]image/*, application/pdf[/code]. </member> <member name="mode_overrides_title" type="bool" setter="set_mode_overrides_title" getter="is_mode_overriding_title" default="true"> If [code]true[/code], changing the [member file_mode] property will set the window title accordingly (e.g. setting [member file_mode] to [constant FILE_MODE_OPEN_FILE] will change the window title to "Open a File"). @@ -159,12 +160,13 @@ </member> <member name="show_hidden_files" type="bool" setter="set_show_hidden_files" getter="is_showing_hidden_files" default="false"> If [code]true[/code], the dialog will show hidden files. - [b]Note:[/b] This property is ignored by native file dialogs on Linux. + [b]Note:[/b] This property is ignored by native file dialogs on Android and Linux. </member> <member name="size" type="Vector2i" setter="set_size" getter="get_size" overrides="Window" default="Vector2i(640, 360)" /> <member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default=""Save a File"" /> <member name="use_native_dialog" type="bool" setter="set_use_native_dialog" getter="get_use_native_dialog" default="false"> If [code]true[/code], and if supported by the current [DisplayServer], OS native dialog will be used instead of custom one. + [b]Note:[/b] On Android, it is only supported when using [constant ACCESS_FILESYSTEM]. For access mode [constant ACCESS_RESOURCES] and [constant ACCESS_USERDATA], the system will fall back to custom FileDialog. [b]Note:[/b] On Linux and macOS, sandboxed apps always use native dialogs to access the host file system. [b]Note:[/b] On macOS, sandboxed apps will save security-scoped bookmarks to retain access to the opened folders across multiple sessions. Use [method OS.get_granted_permissions] to get a list of saved bookmarks. [b]Note:[/b] Native dialogs are isolated from the base process, file dialog properties can't be modified once the dialog is shown. diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 3c48f5ba31..96232f4277 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -136,7 +136,7 @@ <signal name="finished"> <description> Emitted when all active particles have finished processing. To immediately restart the emission cycle, call [method restart]. - Never emitted when [member one_shot] is disabled, as particles will be emitted and processed continuously. + This signal is never emitted when [member one_shot] is disabled, as particles will be emitted and processed continuously. [b]Note:[/b] For [member one_shot] emitters, due to the particles being computed on the GPU, there may be a short period after receiving the signal during which setting [member emitting] to [code]true[/code] will not restart the emission cycle. This delay is avoided by instead calling [method restart]. </description> </signal> diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index 61a3b467f1..f5df857391 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -160,8 +160,8 @@ <signals> <signal name="finished"> <description> - Emitted when all active particles have finished processing. To immediately emit new particles, call [method restart]. - Never emitted when [member one_shot] is disabled, as particles will be emitted and processed continuously. + Emitted when all active particles have finished processing. To immediately restart the emission cycle, call [method restart]. + This signal is never emitted when [member one_shot] is disabled, as particles will be emitted and processed continuously. [b]Note:[/b] For [member one_shot] emitters, due to the particles being computed on the GPU, there may be a short period after receiving the signal during which setting [member emitting] to [code]true[/code] will not restart the emission cycle. This delay is avoided by instead calling [method restart]. </description> </signal> diff --git a/doc/classes/GPUParticlesCollision3D.xml b/doc/classes/GPUParticlesCollision3D.xml index 089747b7ee..2d398edd5e 100644 --- a/doc/classes/GPUParticlesCollision3D.xml +++ b/doc/classes/GPUParticlesCollision3D.xml @@ -16,8 +16,8 @@ <members> <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="4294967295"> The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the collision shape. By default, all particles that have [member ParticleProcessMaterial.collision_mode] set to [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] will be affected by a collision shape. - After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by attractors. For example, this can be used if you're using an attractor as part of a spell effect but don't want the attractor to affect unrelated weather particles at the same position. - Particle attraction can also be disabled on a per-process material basis by setting [member ParticleProcessMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. + After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by colliders. For example, this can be used if you're using a collider as part of a spell effect but don't want the collider to affect unrelated weather particles at the same position. + Particle collision can also be disabled on a per-process material basis by setting [member ParticleProcessMaterial.collision_mode] on the [GPUParticles3D] node. </member> </members> </class> diff --git a/doc/classes/Geometry2D.xml b/doc/classes/Geometry2D.xml index 2dd76ad989..71e6cf93ae 100644 --- a/doc/classes/Geometry2D.xml +++ b/doc/classes/Geometry2D.xml @@ -9,6 +9,20 @@ <tutorials> </tutorials> <methods> + <method name="bresenham_line"> + <return type="Vector2i[]" /> + <param index="0" name="from" type="Vector2i" /> + <param index="1" name="to" type="Vector2i" /> + <description> + Returns the [url=https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm]Bresenham line[/url] between the [param from] and [param to] points. A Bresenham line is a series of pixels that draws a line and is always 1-pixel thick on every row and column of the drawing (never more, never less). + Example code to draw a line between two [Marker2D] nodes using a series of [method CanvasItem.draw_rect] calls: + [codeblock] + func _draw(): + for pixel in Geometry2D.bresenham_line($MarkerA.position, $MarkerB.position): + draw_rect(Rect2(pixel, Vector2.ONE), Color.WHITE) + [/codeblock] + </description> + </method> <method name="clip_polygons"> <return type="PackedVector2Array[]" /> <param index="0" name="polygon_a" type="PackedVector2Array" /> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index f4075af186..0c45154c8a 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -39,8 +39,12 @@ <member name="extra_cull_margin" type="float" setter="set_extra_cull_margin" getter="get_extra_cull_margin" default="0.0"> The extra distance added to the GeometryInstance3D's bounding box ([AABB]) to increase its cull box. </member> - <member name="gi_lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance3D.LightmapScale" default="0"> + <member name="gi_lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance3D.LightmapScale" default="0" deprecated="Use [member gi_lightmap_texel_scale] instead."> + The texel density to use for lightmapping in [LightmapGI]. + </member> + <member name="gi_lightmap_texel_scale" type="float" setter="set_lightmap_texel_scale" getter="get_lightmap_texel_scale" default="1.0"> The texel density to use for lightmapping in [LightmapGI]. Greater scale values provide higher resolution in the lightmap, which can result in sharper shadows for lights that have both direct and indirect light baked. However, greater scale values will also increase the space taken by the mesh in the lightmap texture, which increases the memory, storage, and bake time requirements. When using a single mesh at different scales, consider adjusting this value to keep the lightmap texel density consistent across meshes. + For example, doubling [member gi_lightmap_texel_scale] doubles the lightmap texture resolution for this object [i]on each axis[/i], so it will [i]quadruple[/i] the texel count. </member> <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" enum="GeometryInstance3D.GIMode" default="1" keywords="global_illumination_mode, light_bake_mode"> The global illumination mode to use for the whole geometry. To avoid inconsistent results, use a mode that matches the purpose of the mesh during gameplay (static/dynamic). @@ -111,19 +115,19 @@ <constant name="GI_MODE_DYNAMIC" value="2" enum="GIMode"> Dynamic global illumination mode. Use for dynamic objects that contribute to global illumination. This GI mode is only effective when using [VoxelGI], but it has a higher performance impact than [constant GI_MODE_STATIC]. When using other GI methods, this will act the same as [constant GI_MODE_DISABLED]. When using [LightmapGI], the object will receive indirect lighting using lightmap probes instead of using the baked lightmap texture. </constant> - <constant name="LIGHTMAP_SCALE_1X" value="0" enum="LightmapScale"> + <constant name="LIGHTMAP_SCALE_1X" value="0" enum="LightmapScale" deprecated="Use [member gi_lightmap_texel_scale] instead."> The standard texel density for lightmapping with [LightmapGI]. </constant> - <constant name="LIGHTMAP_SCALE_2X" value="1" enum="LightmapScale"> + <constant name="LIGHTMAP_SCALE_2X" value="1" enum="LightmapScale" deprecated="Use [member gi_lightmap_texel_scale] instead."> Multiplies texel density by 2× for lightmapping with [LightmapGI]. To ensure consistency in texel density, use this when scaling a mesh by a factor between 1.5 and 3.0. </constant> - <constant name="LIGHTMAP_SCALE_4X" value="2" enum="LightmapScale"> + <constant name="LIGHTMAP_SCALE_4X" value="2" enum="LightmapScale" deprecated="Use [member gi_lightmap_texel_scale] instead."> Multiplies texel density by 4× for lightmapping with [LightmapGI]. To ensure consistency in texel density, use this when scaling a mesh by a factor between 3.0 and 6.0. </constant> - <constant name="LIGHTMAP_SCALE_8X" value="3" enum="LightmapScale"> + <constant name="LIGHTMAP_SCALE_8X" value="3" enum="LightmapScale" deprecated="Use [member gi_lightmap_texel_scale] instead."> Multiplies texel density by 8× for lightmapping with [LightmapGI]. To ensure consistency in texel density, use this when scaling a mesh by a factor greater than 6.0. </constant> - <constant name="LIGHTMAP_SCALE_MAX" value="4" enum="LightmapScale"> + <constant name="LIGHTMAP_SCALE_MAX" value="4" enum="LightmapScale" deprecated="Use [member gi_lightmap_texel_scale] instead."> Represents the size of the [enum LightmapScale] enum. </constant> <constant name="VISIBILITY_RANGE_FADE_DISABLED" value="0" enum="VisibilityRangeFadeMode"> diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index cc3acad6d6..fc8bc15b5c 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -154,7 +154,7 @@ <return type="bool" /> <param index="0" name="slot_index" type="int" /> <description> - Returns true if the background [StyleBox] of the slot with the given [param slot_index] is drawn. + Returns [code]true[/code] if the background [StyleBox] of the slot with the given [param slot_index] is drawn. </description> </method> <method name="is_slot_enabled_left" qualifiers="const"> diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index af98636056..366038e43f 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -277,7 +277,11 @@ HTTP status code [code]102 Processing[/code] (WebDAV). Indicates that the server has received and is processing the request, but no response is available yet. </constant> <constant name="RESPONSE_OK" value="200" enum="ResponseCode"> - HTTP status code [code]200 OK[/code]. The request has succeeded. Default response for successful requests. Meaning varies depending on the request. GET: The resource has been fetched and is transmitted in the message body. HEAD: The entity headers are in the message body. POST: The resource describing the result of the action is transmitted in the message body. TRACE: The message body contains the request message as received by the server. + HTTP status code [code]200 OK[/code]. The request has succeeded. Default response for successful requests. Meaning varies depending on the request: + - [constant METHOD_GET]: The resource has been fetched and is transmitted in the message body. + - [constant METHOD_HEAD]: The entity headers are in the message body. + - [constant METHOD_POST]: The resource describing the result of the action is transmitted in the message body. + - [constant METHOD_TRACE]: The message body contains the request message as received by the server. </constant> <constant name="RESPONSE_CREATED" value="201" enum="ResponseCode"> HTTP status code [code]201 Created[/code]. The request has succeeded and a new resource has been created as a result of it. This is typically the response sent after a PUT request. diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 6efa675a71..36f5e82652 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -8,7 +8,7 @@ Can be used to make HTTP requests, i.e. download or upload files or web content via HTTP. [b]Warning:[/b] See the notes and warnings on [HTTPClient] for limitations, especially regarding TLS security. [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. - [b]Example of contacting a REST API and printing one of its returned fields:[/b] + [b]Example:[/b] Contact a REST API and print one of its returned fields: [codeblocks] [gdscript] func _ready(): @@ -80,7 +80,7 @@ } [/csharp] [/codeblocks] - [b]Example of loading and displaying an image using HTTPRequest:[/b] + [b]Example:[/b] Load an image using [HTTPRequest] and display it: [codeblocks] [gdscript] func _ready(): @@ -150,7 +150,7 @@ } [/csharp] [/codeblocks] - [b]Gzipped response bodies[/b]: HTTPRequest will automatically handle decompression of response bodies. A [code]Accept-Encoding[/code] header will be automatically added to each of your requests, unless one is already specified. Any response with a [code]Content-Encoding: gzip[/code] header will automatically be decompressed and delivered to you as uncompressed bytes. + [b]Note:[/b] [HTTPRequest] nodes will automatically handle decompression of response bodies. A [code]Accept-Encoding[/code] header will be automatically added to each of your requests, unless one is already specified. Any response with a [code]Content-Encoding: gzip[/code] header will automatically be decompressed and delivered to you as uncompressed bytes. </description> <tutorials> <link title="Making HTTP requests">$DOCS_URL/tutorials/networking/http_request_class.html</link> @@ -275,6 +275,7 @@ Request successful. </constant> <constant name="RESULT_CHUNKED_BODY_SIZE_MISMATCH" value="1" enum="Result"> + Request failed due to a mismatch between the expected and actual chunked body size during transfer. Possible causes include network errors, server misconfiguration, or issues with chunked encoding. </constant> <constant name="RESULT_CANT_CONNECT" value="2" enum="Result"> Request failed while connecting. @@ -295,6 +296,7 @@ Request exceeded its maximum size limit, see [member body_size_limit]. </constant> <constant name="RESULT_BODY_DECOMPRESS_FAILED" value="8" enum="Result"> + Request failed due to an error while decompressing the response body. Possible causes include unsupported or incorrect compression format, corrupted data, or incomplete transfer. </constant> <constant name="RESULT_REQUEST_FAILED" value="9" enum="Result"> Request failed (currently unused). diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 0fd84fb452..4421318be7 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -48,6 +48,7 @@ <param index="2" name="dst" type="Vector2i" /> <description> Copies [param src_rect] from [param src] image to this image at coordinates [param dst], clipped accordingly to both image bounds. This image and [param src] image [b]must[/b] have the same format. [param src_rect] with non-positive size is treated as empty. + [b]Note:[/b] The alpha channel data in [param src] will overwrite the corresponding data in this image at the target position. To blend alpha channels, use [method blend_rect] instead. </description> </method> <method name="blit_rect_mask"> @@ -510,7 +511,7 @@ <param index="1" name="lossy" type="bool" default="false" /> <param index="2" name="quality" type="float" default="0.75" /> <description> - Saves the image as a WebP (Web Picture) file to the file at [param path]. By default it will save lossless. If [param lossy] is true, the image will be saved lossy, using the [param quality] setting between 0.0 and 1.0 (inclusive). Lossless WebP offers more efficient compression than PNG. + Saves the image as a WebP (Web Picture) file to the file at [param path]. By default it will save lossless. If [param lossy] is [code]true[/code], the image will be saved lossy, using the [param quality] setting between [code]0.0[/code] and [code]1.0[/code] (inclusive). Lossless WebP offers more efficient compression than PNG. [b]Note:[/b] The WebP format is limited to a size of 16383×16383 pixels, while PNG can save larger images. </description> </method> @@ -519,7 +520,7 @@ <param index="0" name="lossy" type="bool" default="false" /> <param index="1" name="quality" type="float" default="0.75" /> <description> - Saves the image as a WebP (Web Picture) file to a byte array. By default it will save lossless. If [param lossy] is true, the image will be saved lossy, using the [param quality] setting between 0.0 and 1.0 (inclusive). Lossless WebP offers more efficient compression than PNG. + Saves the image as a WebP (Web Picture) file to a byte array. By default it will save lossless. If [param lossy] is [code]true[/code], the image will be saved lossy, using the [param quality] setting between [code]0.0[/code] and [code]1.0[/code] (inclusive). Lossless WebP offers more efficient compression than PNG. [b]Note:[/b] The WebP format is limited to a size of 16383×16383 pixels, while PNG can save larger images. </description> </method> diff --git a/doc/classes/ImporterMesh.xml b/doc/classes/ImporterMesh.xml index 28ee5710d9..745d7a3d5d 100644 --- a/doc/classes/ImporterMesh.xml +++ b/doc/classes/ImporterMesh.xml @@ -49,7 +49,8 @@ <param index="2" name="bone_transform_array" type="Array" /> <description> Generates all lods for this ImporterMesh. - [param normal_merge_angle] and [param normal_split_angle] are in degrees and used in the same way as the importer settings in [code]lods[/code]. As a good default, use 25 and 60 respectively. + [param normal_merge_angle] is in degrees and used in the same way as the importer settings in [code]lods[/code]. + [param normal_split_angle] is not used and only remains for compatibility with older versions of the API. The number of generated lods can be accessed using [method get_surface_lod_count], and each LOD is available in [method get_surface_lod_size] and [method get_surface_lod_indices]. [param bone_transform_array] is an [Array] which can be either empty or contain [Transform3D]s which, for each of the mesh's bone IDs, will apply mesh skinning when generating the LOD mesh variations. This is usually used to account for discrepancies in scale between the mesh itself and its skinning data. </description> diff --git a/doc/classes/InputEventMouseMotion.xml b/doc/classes/InputEventMouseMotion.xml index bcfe5b70fd..4c1461d03a 100644 --- a/doc/classes/InputEventMouseMotion.xml +++ b/doc/classes/InputEventMouseMotion.xml @@ -5,7 +5,7 @@ </brief_description> <description> Stores information about a mouse or a pen motion. This includes relative position, absolute position, and velocity. See [method Node._input]. - [b]Note:[/b] By default, this event is only emitted once per frame rendered at most. If you need more precise input reporting, set [member Input.use_accumulated_input] to [code]false[/code] to make events emitted as often as possible. If you use InputEventMouseMotion to draw lines, consider implementing [url=https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to avoid visible gaps in lines if the user is moving the mouse quickly. + [b]Note:[/b] By default, this event is only emitted once per frame rendered at most. If you need more precise input reporting, set [member Input.use_accumulated_input] to [code]false[/code] to make events emitted as often as possible. If you use InputEventMouseMotion to draw lines, consider using [method Geometry2D.bresenham_line] as well to avoid visible gaps in lines if the user is moving the mouse quickly. [b]Note:[/b] This event may be emitted even when the mouse hasn't moved, either by the operating system or by Godot itself. If you really need to know if the mouse has moved (e.g. to suppress displaying a tooltip), you should check that [code]relative.is_zero_approx()[/code] is [code]false[/code]. </description> <tutorials> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index fdaeb54bdf..7754a61e8c 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -29,7 +29,7 @@ <description> Adds an item to the item list with specified text. Returns the index of an added item. Specify an [param icon], or use [code]null[/code] as the [param icon] for a list item with no icon. - If selectable is [code]true[/code], the list item will be selectable. + If [param selectable] is [code]true[/code], the list item will be selectable. </description> </method> <method name="clear"> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index f91006f69a..ae5a62753f 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -122,7 +122,7 @@ [Color] of the text's shadow effect. </theme_item> <theme_item name="line_spacing" data_type="constant" type="int" default="3"> - Vertical space between lines in multiline [Label]. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. </theme_item> <theme_item name="outline_size" data_type="constant" type="int" default="0"> Text outline size. diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml index ff26c5490d..7584a1d526 100644 --- a/doc/classes/Label3D.xml +++ b/doc/classes/Label3D.xml @@ -79,7 +79,7 @@ Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. </member> <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0"> - Vertical space between lines in multiline [Label3D]. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. </member> <member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)" keywords="color, colour"> Text [Color] of the [Label3D]. diff --git a/doc/classes/LabelSettings.xml b/doc/classes/LabelSettings.xml index 8cdb30c303..ff7b8e7b0e 100644 --- a/doc/classes/LabelSettings.xml +++ b/doc/classes/LabelSettings.xml @@ -19,7 +19,7 @@ Size of the text. </member> <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="3.0"> - Vertical space between lines when the text is multiline. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. </member> <member name="outline_color" type="Color" setter="set_outline_color" getter="get_outline_color" default="Color(1, 1, 1, 1)"> The color of the outline. diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index bda5fb69de..966d0fdcb4 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -115,6 +115,9 @@ <member name="shadow_blur" type="float" setter="set_param" getter="get_param" default="1.0"> Blurs the edges of the shadow. Can be used to hide pixel artifacts in low-resolution shadow maps. A high value can impact performance, make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible. </member> + <member name="shadow_caster_mask" type="int" setter="set_shadow_caster_mask" getter="get_shadow_caster_mask" default="4294967295"> + The light will only cast shadows using objects in the selected layers. + </member> <member name="shadow_enabled" type="bool" setter="set_shadow" getter="has_shadow" default="false"> If [code]true[/code], the light will cast real-time shadows. This has a significant performance cost. Only enable shadow rendering when it makes a noticeable difference in the scene's appearance, and consider using [member distance_fade_enabled] to hide the light when far away from the [Camera3D]. </member> diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml index e7d44411ef..0a492364ec 100644 --- a/doc/classes/LightmapGI.xml +++ b/doc/classes/LightmapGI.xml @@ -66,10 +66,11 @@ </member> <member name="quality" type="int" setter="set_bake_quality" getter="get_bake_quality" enum="LightmapGI.BakeQuality" default="1"> The quality preset to use when baking lightmaps. This affects bake times, but output file sizes remain mostly identical across quality levels. - To further speed up bake times, decrease [member bounces], disable [member use_denoiser] and increase the lightmap texel size on 3D scenes in the Import doc. + To further speed up bake times, decrease [member bounces], disable [member use_denoiser] and increase the lightmap texel size on 3D scenes in the Import dock. </member> <member name="texel_scale" type="float" setter="set_texel_scale" getter="get_texel_scale" default="1.0"> Scales the lightmap texel density of all meshes for the current bake. This is a multiplier that builds upon the existing lightmap texel size defined in each imported 3D scene, along with the per-mesh density multiplier (which is designed to be used when the same mesh is used at different scales). Lower values will result in faster bake times. + For example, doubling [member texel_scale] doubles the lightmap texture resolution for all objects [i]on each axis[/i], so it will [i]quadruple[/i] the texel count. </member> <member name="use_denoiser" type="bool" setter="set_use_denoiser" getter="is_using_denoiser" default="true"> If [code]true[/code], uses a GPU-based denoising algorithm on the generated lightmap. This eliminates most noise within the generated lightmap at the cost of longer bake times. File sizes are generally not impacted significantly by the use of a denoiser, although lossless compression may do a better job at compressing a denoised image. diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 3e0c328dcb..91c9072f73 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -33,6 +33,7 @@ - [kbd]Cmd + E[/kbd]: Same as [kbd]End[/kbd], move the caret to the end of the line - [kbd]Cmd + Left Arrow[/kbd]: Same as [kbd]Home[/kbd], move the caret to the beginning of the line - [kbd]Cmd + Right Arrow[/kbd]: Same as [kbd]End[/kbd], move the caret to the end of the line + [b]Note:[/b] Caret movement shortcuts listed above are not affected by [member shortcut_keys_enabled]. </description> <tutorials> </tutorials> @@ -334,7 +335,7 @@ If [code]false[/code], it's impossible to select the text using mouse nor keyboard. </member> <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true"> - If [code]false[/code], using shortcuts will be disabled. + If [code]true[/code], shortcut keys for context menu items are enabled, even if the context menu is disabled. </member> <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. diff --git a/doc/classes/LookAtModifier3D.xml b/doc/classes/LookAtModifier3D.xml new file mode 100644 index 0000000000..b6d106c4c5 --- /dev/null +++ b/doc/classes/LookAtModifier3D.xml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="LookAtModifier3D" inherits="SkeletonModifier3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + The [LookAtModifier3D] rotates a bone to look at a target. + </brief_description> + <description> + This [SkeletonModifier3D] rotates a bone to look at a target. This is helpful for moving a character's head to look at the player, rotating a turret to look at a target, or any other case where you want to make a bone rotate towards something quickly and easily. + When applying multiple [LookAtModifier3D]s, the [LookAtModifier3D] assigned to the parent bone must be put above the [LookAtModifier3D] assigned to the child bone in the list in order for the child bone results to be correct. + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_interpolation_remaining" qualifiers="const"> + <return type="float" /> + <description> + Returns the remaining seconds of the time-based interpolation. + </description> + </method> + <method name="is_interpolating" qualifiers="const"> + <return type="bool" /> + <description> + Returns whether the time-based interpolation is running or not. If [code]true[/code], it is equivalent to [method get_interpolation_remaining] being [code]0[/code]. + This is useful to determine whether a [LookAtModifier3D] can be removed safely. + </description> + </method> + <method name="is_target_within_limitation" qualifiers="const"> + <return type="bool" /> + <description> + Returns whether the target is within the angle limitations. It is useful for unsetting the [member target_node] when the target is outside of the angle limitations. + [b]Note:[/b] The value is updated after [method SkeletonModifier3D._process_modification]. To retrieve this value correctly, we recommend using the signal [signal SkeletonModifier3D.modification_processed]. + </description> + </method> + </methods> + <members> + <member name="bone" type="int" setter="set_bone" getter="get_bone" default="0"> + The bone index of the [Skeleton3D] that the modification will operate on. + </member> + <member name="duration" type="float" setter="set_duration" getter="get_duration" default="0.0"> + The duration of the time-based interpolation. Interpolation is triggered at the following cases: + - When the target node is changed + - When an axis is flipped due to angle limitation + [b]Note:[/b] The flipping occurs when the target is outside the angle limitation and the internally computed secondary rotation axis of the forward vector is flipped. Visually, it occurs when the target is outside the angle limitation and crosses the plane of the [member forward_axis] and [member primary_rotation_axis]. + </member> + <member name="ease_type" type="int" setter="set_ease_type" getter="get_ease_type" enum="Tween.EaseType" default="0"> + The ease type of the time-based interpolation. See also [enum Tween.EaseType]. + </member> + <member name="forward_axis" type="int" setter="set_forward_axis" getter="get_forward_axis" enum="LookAtModifier3D.BoneAxis" default="4"> + The forward axis of the bone. This [SkeletonModifier3D] modifies the bone so that this axis points toward the [member target_node]. + </member> + <member name="origin_bone" type="int" setter="set_origin_bone" getter="get_origin_bone"> + If [member origin_from] is [constant ORIGIN_FROM_SPECIFIC_BONE], the bone global pose position specified for this is used as origin. + </member> + <member name="origin_external_node" type="NodePath" setter="set_origin_external_node" getter="get_origin_external_node"> + If [member origin_from] is [constant ORIGIN_FROM_EXTERNAL_NODE], the global position of the [Node3D] specified for this is used as origin. + </member> + <member name="origin_from" type="int" setter="set_origin_from" getter="get_origin_from" enum="LookAtModifier3D.OriginFrom" default="0"> + This value determines from what origin is retrieved for use in the calculation of the forward vector. + </member> + <member name="origin_offset" type="Vector3" setter="set_origin_offset" getter="get_origin_offset" default="Vector3(0, 0, 0)"> + The offset of the bone pose origin. Matching the origins by offset is useful for cases where multiple bones must always face the same direction, such as the eyes. + [b]Note:[/b] This value indicates the local position of the object set in [member origin_from]. + </member> + <member name="origin_safe_margin" type="float" setter="set_origin_safe_margin" getter="get_origin_safe_margin" default="0.1"> + If the target passes through too close to the origin than this value, time-based interpolation is used even if the target is within the angular limitations, to prevent the angular velocity from becoming too high. + </member> + <member name="primary_damp_threshold" type="float" setter="set_primary_damp_threshold" getter="get_primary_damp_threshold"> + The threshold to start damping for [member primary_limit_angle]. It provides non-linear (b-spline) interpolation, let it feel more resistance the more it rotate to the edge limit. This is useful for simulating the limits of human motion. + If [code]1.0[/code], no damping is performed. If [code]0.0[/code], damping is always performed. + </member> + <member name="primary_limit_angle" type="float" setter="set_primary_limit_angle" getter="get_primary_limit_angle"> + The limit angle of the primary rotation when [member symmetry_limitation] is [code]true[/code]. + </member> + <member name="primary_negative_damp_threshold" type="float" setter="set_primary_negative_damp_threshold" getter="get_primary_negative_damp_threshold"> + The threshold to start damping for [member primary_negative_limit_angle]. + </member> + <member name="primary_negative_limit_angle" type="float" setter="set_primary_negative_limit_angle" getter="get_primary_negative_limit_angle"> + The limit angle of negative side of the primary rotation when [member symmetry_limitation] is [code]false[/code]. + </member> + <member name="primary_positive_damp_threshold" type="float" setter="set_primary_positive_damp_threshold" getter="get_primary_positive_damp_threshold"> + The threshold to start damping for [member primary_positive_limit_angle]. + </member> + <member name="primary_positive_limit_angle" type="float" setter="set_primary_positive_limit_angle" getter="get_primary_positive_limit_angle"> + The limit angle of positive side of the primary rotation when [member symmetry_limitation] is [code]false[/code]. + </member> + <member name="primary_rotation_axis" type="int" setter="set_primary_rotation_axis" getter="get_primary_rotation_axis" enum="Vector3.Axis" default="1"> + The axis of the first rotation. This [SkeletonModifier3D] works by compositing the rotation by Euler angles to prevent to rotate the [member forward_axis]. + </member> + <member name="secondary_damp_threshold" type="float" setter="set_secondary_damp_threshold" getter="get_secondary_damp_threshold"> + The threshold to start damping for [member secondary_limit_angle]. + </member> + <member name="secondary_limit_angle" type="float" setter="set_secondary_limit_angle" getter="get_secondary_limit_angle"> + The limit angle of the secondary rotation when [member symmetry_limitation] is [code]true[/code]. + </member> + <member name="secondary_negative_damp_threshold" type="float" setter="set_secondary_negative_damp_threshold" getter="get_secondary_negative_damp_threshold"> + The threshold to start damping for [member secondary_negative_limit_angle]. + </member> + <member name="secondary_negative_limit_angle" type="float" setter="set_secondary_negative_limit_angle" getter="get_secondary_negative_limit_angle"> + The limit angle of negative side of the secondary rotation when [member symmetry_limitation] is [code]false[/code]. + </member> + <member name="secondary_positive_damp_threshold" type="float" setter="set_secondary_positive_damp_threshold" getter="get_secondary_positive_damp_threshold"> + The threshold to start damping for [member secondary_positive_limit_angle]. + </member> + <member name="secondary_positive_limit_angle" type="float" setter="set_secondary_positive_limit_angle" getter="get_secondary_positive_limit_angle"> + The limit angle of positive side of the secondary rotation when [member symmetry_limitation] is [code]false[/code]. + </member> + <member name="symmetry_limitation" type="bool" setter="set_symmetry_limitation" getter="is_limitation_symmetry"> + If [code]true[/code], the limitations are spread from the bone symmetrically. + If [code]false[/code], the limitation can be specified separately for each side of the bone rest. + </member> + <member name="target_node" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath("")"> + The [NodePath] to the node that is the target for the look at modification. This node is what the modification will rotate the bone to. + </member> + <member name="transition_type" type="int" setter="set_transition_type" getter="get_transition_type" enum="Tween.TransitionType" default="0"> + The transition type of the time-based interpolation. See also [enum Tween.TransitionType]. + </member> + <member name="use_angle_limitation" type="bool" setter="set_use_angle_limitation" getter="is_using_angle_limitation" default="false"> + If [code]true[/code], limits the degree of rotation. This helps prevent the character's neck from rotating 360 degrees. + [b]Note:[/b] As with [AnimationTree] blending, interpolation is provided that favors [method Skeleton3D.get_bone_rest]. This means that interpolation does not select the shortest path in some cases. + [b]Note:[/b] Some [member transition_type] may exceed the limitations (e.g. `Back`, `Elastic`, and `Spring`). If interpolation occurs while overshooting the limitations, the result might possibly not respect the bone rest. + </member> + <member name="use_secondary_rotation" type="bool" setter="set_use_secondary_rotation" getter="is_using_secondary_rotation" default="true"> + If [code]true[/code], provides rotation by two axes. + </member> + </members> + <constants> + <constant name="BONE_AXIS_PLUS_X" value="0" enum="BoneAxis"> + Enumerated value for the +X axis. + </constant> + <constant name="BONE_AXIS_MINUS_X" value="1" enum="BoneAxis"> + Enumerated value for the -X axis. + </constant> + <constant name="BONE_AXIS_PLUS_Y" value="2" enum="BoneAxis"> + Enumerated value for the +Y axis. + </constant> + <constant name="BONE_AXIS_MINUS_Y" value="3" enum="BoneAxis"> + Enumerated value for the -Y axis. + </constant> + <constant name="BONE_AXIS_PLUS_Z" value="4" enum="BoneAxis"> + Enumerated value for the +Z axis. + </constant> + <constant name="BONE_AXIS_MINUS_Z" value="5" enum="BoneAxis"> + Enumerated value for the -Z axis. + </constant> + <constant name="ORIGIN_FROM_SELF" value="0" enum="OriginFrom"> + The bone rest position of the bone specified in [member bone] is used as origin. + </constant> + <constant name="ORIGIN_FROM_SPECIFIC_BONE" value="1" enum="OriginFrom"> + The bone global pose position of the bone specified in [member origin_bone] is used as origin. + [b]Note:[/b] It is recommended that you select only the parent bone unless you are familiar with the bone processing process. The specified bone pose at the time the [LookAtModifier3D] is processed is used as a reference. In other words, if you specify a child bone and the [LookAtModifier3D] causes the child bone to move, the rendered result and direction will not match. + </constant> + <constant name="ORIGIN_FROM_EXTERNAL_NODE" value="2" enum="OriginFrom"> + The global position of the [Node3D] specified in [member origin_external_node] is used as origin. + [b]Note:[/b] Same as [constant ORIGIN_FROM_SPECIFIC_BONE], when specifying a [BoneAttachment3D] with a child bone assigned, the rendered result and direction will not match. + </constant> + </constants> +</class> diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml index 17cc0d78d3..2d88876d24 100644 --- a/doc/classes/MainLoop.xml +++ b/doc/classes/MainLoop.xml @@ -5,7 +5,7 @@ </brief_description> <description> [MainLoop] is the abstract base class for a Godot project's game loop. It is inherited by [SceneTree], which is the default game loop implementation used in Godot projects, though it is also possible to write and use one's own [MainLoop] subclass instead of the scene tree. - Upon the application start, a [MainLoop] implementation must be provided to the OS; otherwise, the application will exit. This happens automatically (and a [SceneTree] is created) unless a [MainLoop] [Script] is provided from the command line (with e.g. [code]godot -s my_loop.gd[/code]) or the "Main Loop Type" project setting is overwritten. + Upon the application start, a [MainLoop] implementation must be provided to the OS; otherwise, the application will exit. This happens automatically (and a [SceneTree] is created) unless a [MainLoop] [Script] is provided from the command line (with e.g. [code]godot -s my_loop.gd[/code]) or the [member ProjectSettings.application/run/main_loop_type] project setting is overwritten. Here is an example script implementing a simple [MainLoop]: [codeblocks] [gdscript] diff --git a/doc/classes/Material.xml b/doc/classes/Material.xml index 760773d5d9..94d12018ca 100644 --- a/doc/classes/Material.xml +++ b/doc/classes/Material.xml @@ -45,7 +45,7 @@ <method name="inspect_native_shader_code"> <return type="void" /> <description> - Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code. + Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code. See also [method Shader.inspect_native_shader_code]. </description> </method> </methods> diff --git a/doc/classes/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml index d8e2c43566..a0a773b90a 100644 --- a/doc/classes/MeshInstance3D.xml +++ b/doc/classes/MeshInstance3D.xml @@ -120,7 +120,7 @@ <param index="1" name="material" type="Material" /> <description> Sets the override [param material] for the specified [param surface] of the [Mesh] resource. This material is associated with this [MeshInstance3D] rather than with [member mesh]. - [b]Note:[/b] This assigns the [Material] associated to the [MeshInstance3D]'s Surface Material Override properties, not the material within the [Mesh] resource. To set the material within the [Mesh] resource, use [method Mesh.surface_get_material] instead. + [b]Note:[/b] This assigns the [Material] associated to the [MeshInstance3D]'s Surface Material Override properties, not the material within the [Mesh] resource. To set the material within the [Mesh] resource, use [method Mesh.surface_set_material] instead. </description> </method> </methods> diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml index d5016867a7..75cb13d25d 100644 --- a/doc/classes/MultiplayerAPI.xml +++ b/doc/classes/MultiplayerAPI.xml @@ -88,7 +88,7 @@ <param index="3" name="arguments" type="Array" default="[]" /> <description> Sends an RPC to the target [param peer]. The given [param method] will be called on the remote [param object] with the provided [param arguments]. The RPC may also be called locally depending on the implementation and RPC configuration. See [method Node.rpc] and [method Node.rpc_config]. - [b]Note:[/b] Prefer using [method Node.rpc], [method Node.rpc_id], or [code]my_method.rpc(peer, arg1, arg2, ...)[/code] (in GDScript), since they are faster. This method is mostly useful in conjunction with [MultiplayerAPIExtension] when augmenting or replacing the multiplayer capabilities. + [b]Note:[/b] Prefer using [method Node.rpc], [method Node.rpc_id], or [code]my_method.rpc(peer, arg1, arg2, ...)[/code] (in GDScript), since they are faster. This method is mostly useful in conjunction with [MultiplayerAPIExtension] when extending or replacing the multiplayer capabilities. </description> </method> <method name="set_default_interface" qualifiers="static"> diff --git a/doc/classes/MultiplayerAPIExtension.xml b/doc/classes/MultiplayerAPIExtension.xml index cc6d3b7fcf..acb6a2c176 100644 --- a/doc/classes/MultiplayerAPIExtension.xml +++ b/doc/classes/MultiplayerAPIExtension.xml @@ -4,14 +4,14 @@ Base class used for extending the [MultiplayerAPI]. </brief_description> <description> - This class can be used to augment or replace the default [MultiplayerAPI] implementation via script or extensions. - The following example augment the default implementation ([SceneMultiplayer]) by logging every RPC being made, and every object being configured for replication. + This class can be used to extend or replace the default [MultiplayerAPI] implementation via script or extensions. + The following example extend the default implementation ([SceneMultiplayer]) by logging every RPC being made, and every object being configured for replication. [codeblocks] [gdscript] extends MultiplayerAPIExtension class_name LogMultiplayer - # We want to augment the default SceneMultiplayer. + # We want to extend the default SceneMultiplayer. var base_multiplayer = SceneMultiplayer.new() func _init(): @@ -49,7 +49,7 @@ print("Removing node %s from the spawn list. Spawner: %s" % [object, config]) return base_multiplayer.object_configuration_remove(object, config) - # These can be optional, but in our case we want to augment SceneMultiplayer, so forward everything. + # These can be optional, but in our case we want to extend SceneMultiplayer, so forward everything. func _set_multiplayer_peer(p_peer: MultiplayerPeer): base_multiplayer.multiplayer_peer = p_peer @@ -69,7 +69,7 @@ # autoload.gd func _enter_tree(): # Sets our custom multiplayer as the main one in SceneTree. - get_tree().set_multiplayer(LogMultiplayer.new()) + get_tree().set_multiplayer(LogMultiplayer.new()) [/gdscript] [/codeblocks] Native extensions can alternatively use the [method MultiplayerAPI.set_default_interface] method during initialization to configure themselves as the default implementation. diff --git a/doc/classes/MultiplayerPeer.xml b/doc/classes/MultiplayerPeer.xml index edb2c39e24..cec9464102 100644 --- a/doc/classes/MultiplayerPeer.xml +++ b/doc/classes/MultiplayerPeer.xml @@ -65,7 +65,7 @@ <method name="is_server_relay_supported" qualifiers="const"> <return type="bool" /> <description> - Returns true if the server can act as a relay in the current configuration (i.e. if the higher level [MultiplayerAPI] should notify connected clients of other peers, and implement a relay protocol to allow communication between them). + Returns [code]true[/code] if the server can act as a relay in the current configuration. That is, if the higher level [MultiplayerAPI] should notify connected clients of other peers, and implement a relay protocol to allow communication between them. </description> </method> <method name="poll"> diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 7e78006240..5c19a6b355 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -133,7 +133,7 @@ <return type="bool" /> <param index="0" name="agent" type="RID" /> <description> - Returns true if the map got changed the previous frame. + Returns [code]true[/code] if the map got changed the previous frame. </description> </method> <method name="agent_set_avoidance_callback"> @@ -215,7 +215,7 @@ <param index="0" name="agent" type="RID" /> <param index="1" name="paused" type="bool" /> <description> - If [param paused] is true the specified [param agent] will not be processed, e.g. calculate avoidance velocities or receive avoidance callbacks. + If [param paused] is [code]true[/code] the specified [param agent] will not be processed, e.g. calculate avoidance velocities or receive avoidance callbacks. </description> </method> <method name="agent_set_position"> @@ -573,7 +573,7 @@ <return type="bool" /> <param index="0" name="map" type="RID" /> <description> - Returns true if the map is active. + Returns [code]true[/code] if the map is active. </description> </method> <method name="map_set_active"> @@ -707,7 +707,7 @@ <param index="0" name="obstacle" type="RID" /> <param index="1" name="paused" type="bool" /> <description> - If [param paused] is true the specified [param obstacle] will not be processed, e.g. affect avoidance velocities. + If [param paused] is [code]true[/code] the specified [param obstacle] will not be processed, e.g. affect avoidance velocities. </description> </method> <method name="obstacle_set_position"> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 7e206046d6..66a286758b 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -147,7 +147,7 @@ <return type="bool" /> <param index="0" name="agent" type="RID" /> <description> - Returns true if the map got changed the previous frame. + Returns [code]true[/code] if the map got changed the previous frame. </description> </method> <method name="agent_set_avoidance_callback"> @@ -237,7 +237,7 @@ <param index="0" name="agent" type="RID" /> <param index="1" name="paused" type="bool" /> <description> - If [param paused] is true the specified [param agent] will not be processed, e.g. calculate avoidance velocities or receive avoidance callbacks. + If [param paused] is [code]true[/code] the specified [param agent] will not be processed, e.g. calculate avoidance velocities or receive avoidance callbacks. </description> </method> <method name="agent_set_position"> @@ -645,14 +645,14 @@ <return type="bool" /> <param index="0" name="map" type="RID" /> <description> - Returns true if the navigation [param map] allows navigation regions to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin. + Returns [code]true[/code] if the navigation [param map] allows navigation regions to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin. </description> </method> <method name="map_is_active" qualifiers="const"> <return type="bool" /> <param index="0" name="map" type="RID" /> <description> - Returns true if the map is active. + Returns [code]true[/code] if the map is active. </description> </method> <method name="map_set_active"> @@ -832,7 +832,7 @@ <param index="0" name="obstacle" type="RID" /> <param index="1" name="paused" type="bool" /> <description> - If [param paused] is true the specified [param obstacle] will not be processed, e.g. affect avoidance velocities. + If [param paused] is [code]true[/code] the specified [param obstacle] will not be processed, e.g. affect avoidance velocities. </description> </method> <method name="obstacle_set_position"> @@ -1023,7 +1023,7 @@ <return type="bool" /> <param index="0" name="region" type="RID" /> <description> - Returns true if the navigation [param region] is set to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin. + Returns [code]true[/code] if the navigation [param region] is set to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin. </description> </method> <method name="region_owns_point" qualifiers="const"> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 42753f7071..3cb76e2926 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -73,6 +73,7 @@ <description> Called during the physics processing step of the main loop. Physics processing means that the frame rate is synced to the physics, i.e. the [param delta] variable should be constant. [param delta] is in seconds. It is only called if physics processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_physics_process]. + Processing happens in order of [member process_physics_priority], lower priority values are called first. Nodes with the same priority are processed in tree order, or top to bottom as seen in the editor (also known as pre-order traversal). Corresponds to the [constant NOTIFICATION_PHYSICS_PROCESS] notification in [method Object._notification]. [b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not an orphan). </description> @@ -83,6 +84,7 @@ <description> Called during the processing step of the main loop. Processing happens at every frame and as fast as possible, so the [param delta] time since the previous frame is not constant. [param delta] is in seconds. It is only called if processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process]. + Processing happens in order of [member process_priority], lower priority values are called first. Nodes with the same priority are processed in tree order, or top to bottom as seen in the editor (also known as pre-order traversal). Corresponds to the [constant NOTIFICATION_PROCESS] notification in [method Object._notification]. [b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not an orphan). </description> @@ -1004,8 +1006,8 @@ [b]Note:[/b] When changing the name, the following characters will be replaced with an underscore: ([code].[/code] [code]:[/code] [code]@[/code] [code]/[/code] [code]"[/code] [code]%[/code]). In particular, the [code]@[/code] character is reserved for auto-generated names. See also [method String.validate_node_name]. </member> <member name="owner" type="Node" setter="set_owner" getter="get_owner"> - The owner of this node. The owner must be an ancestor of this node. When packing the owner node in a [PackedScene], all the nodes it owns are also saved with it. - [b]Note:[/b] In the editor, nodes not owned by the scene root are usually not displayed in the Scene dock, and will [b]not[/b] be saved. To prevent this, remember to set the owner after calling [method add_child]. See also (see [member unique_name_in_owner]) + The owner of this node. The owner must be an ancestor of this node. When packing the owner node in a [PackedScene], all the nodes it owns are also saved with it. See also [member unique_name_in_owner]. + [b]Note:[/b] In the editor, nodes not owned by the scene root are usually not displayed in the Scene dock, and will [b]not[/b] be saved. To prevent this, remember to set the owner after calling [method add_child]. </member> <member name="physics_interpolation_mode" type="int" setter="set_physics_interpolation_mode" getter="get_physics_interpolation_mode" enum="Node.PhysicsInterpolationMode" default="0"> Allows enabling or disabling physics interpolation per node, offering a finer grain of control than turning physics interpolation on and off globally. See [member ProjectSettings.physics/common/physics_interpolation] and [member SceneTree.physics_interpolation] for the global setting. @@ -1015,10 +1017,10 @@ The node's processing behavior (see [enum ProcessMode]). To check if the node can process in its current mode, use [method can_process]. </member> <member name="process_physics_priority" type="int" setter="set_physics_process_priority" getter="get_physics_process_priority" default="0"> - Similar to [member process_priority] but for [constant NOTIFICATION_PHYSICS_PROCESS], [method _physics_process] or the internal version. + Similar to [member process_priority] but for [constant NOTIFICATION_PHYSICS_PROCESS], [method _physics_process], or [constant NOTIFICATION_INTERNAL_PHYSICS_PROCESS]. </member> <member name="process_priority" type="int" setter="set_process_priority" getter="get_process_priority" default="0"> - The node's execution order of the process callbacks ([method _process], [method _physics_process], and internal processing). Nodes whose priority value is [i]lower[/i] call their process callbacks first, regardless of tree order. + The node's execution order of the process callbacks ([method _process], [constant NOTIFICATION_PROCESS], and [constant NOTIFICATION_INTERNAL_PROCESS]). Nodes whose priority value is [i]lower[/i] call their process callbacks first, regardless of tree order. </member> <member name="process_thread_group" type="int" setter="set_process_thread_group" getter="get_process_thread_group" enum="Node.ProcessThreadGroup" default="0"> Set the process thread group for this node (basically, whether it receives [constant NOTIFICATION_PROCESS], [constant NOTIFICATION_PHYSICS_PROCESS], [method _process] or [method _physics_process] (and the internal versions) on the main thread or in a sub-thread. diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml index d0ec81ab45..628c7106f2 100644 --- a/doc/classes/NodePath.xml +++ b/doc/classes/NodePath.xml @@ -57,7 +57,7 @@ <description> Constructs a [NodePath] from a [String]. The created path is absolute if prefixed with a slash (see [method is_absolute]). The "subnames" optionally included after the path to the target node can point to properties, and can also be nested. - Examples of strings that could be node paths: + The following strings can be valid node paths: [codeblock] # Points to the Sprite2D node. "Level/RigidBody2D/Sprite2D" diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 777950c075..5ab7c27f4f 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -23,7 +23,7 @@ <return type="void" /> <description> Shuts down the system MIDI driver. Godot will no longer receive [InputEventMIDI]. See also [method open_midi_inputs] and [method get_connected_midi_inputs]. - [b]Note:[/b] This method is implemented on Linux, macOS and Windows. + [b]Note:[/b] This method is implemented on Linux, macOS, and Windows. </description> </method> <method name="crash"> @@ -53,7 +53,7 @@ Creates a new process that runs independently of Godot. It will not terminate when Godot terminates. The path specified in [param path] must exist and be an executable file or macOS [code].app[/code] bundle. The path is resolved based on the current platform. The [param arguments] are used in the given order and separated by a space. On Windows, if [param open_console] is [code]true[/code] and the process is a console app, a new terminal window will be opened. If the process is successfully created, this method returns its process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). Otherwise, this method returns [code]-1[/code]. - For example, running another instance of the project: + [b]Example:[/b] Run another instance of the project: [codeblocks] [gdscript] var pid = OS.create_process(OS.get_executable_path(), []) @@ -184,7 +184,7 @@ Command-line arguments can be written in any form, including both [code]--key value[/code] and [code]--key=value[/code] forms so they can be properly parsed, as long as custom command-line arguments do not conflict with engine arguments. You can also incorporate environment variables using the [method get_environment] method. You can set [member ProjectSettings.editor/run/main_run_args] to define command-line arguments to be passed by the editor when running the project. - Here's a minimal example on how to parse command-line arguments into a [Dictionary] using the [code]--key=value[/code] form for arguments: + [b]Example:[/b] Parse command-line arguments into a [Dictionary] using the [code]--key=value[/code] form for arguments: [codeblocks] [gdscript] var arguments = {} @@ -244,7 +244,7 @@ <return type="PackedStringArray" /> <description> Returns an array of connected MIDI device names, if they exist. Returns an empty array if the system MIDI driver has not previously been initialized with [method open_midi_inputs]. See also [method close_midi_inputs]. - [b]Note:[/b] This method is implemented on Linux, macOS and Windows. + [b]Note:[/b] This method is implemented on Linux, macOS, and Windows. </description> </method> <method name="get_data_dir" qualifiers="const"> @@ -356,7 +356,7 @@ <return type="String" /> <description> Returns the model name of the current device. - [b]Note:[/b] This method is implemented on Android and iOS. Returns [code]"GenericDevice"[/code] on unsupported platforms. + [b]Note:[/b] This method is implemented on Android, iOS, macOS, and Windows. Returns [code]"GenericDevice"[/code] on unsupported platforms. </description> </method> <method name="get_name" qualifiers="const"> @@ -466,6 +466,24 @@ Returns the amount of static memory being used by the program in bytes. Only works in debug builds. </description> </method> + <method name="get_stderr_type" qualifiers="const"> + <return type="int" enum="OS.StdHandleType" /> + <description> + Returns type of the standard error device. + </description> + </method> + <method name="get_stdin_type" qualifiers="const"> + <return type="int" enum="OS.StdHandleType" /> + <description> + Returns type of the standard input device. + </description> + </method> + <method name="get_stdout_type" qualifiers="const"> + <return type="int" enum="OS.StdHandleType" /> + <description> + Returns type of the standard output device. + </description> + </method> <method name="get_system_ca_certificates"> <return type="String" /> <description> @@ -680,15 +698,31 @@ <return type="void" /> <description> Initializes the singleton for the system MIDI driver, allowing Godot to receive [InputEventMIDI]. See also [method get_connected_midi_inputs] and [method close_midi_inputs]. - [b]Note:[/b] This method is implemented on Linux, macOS and Windows. + [b]Note:[/b] This method is implemented on Linux, macOS, and Windows. + </description> + </method> + <method name="read_buffer_from_stdin"> + <return type="PackedByteArray" /> + <param index="0" name="buffer_size" type="int" /> + <description> + Reads a user input as raw data from the standard input. This operation can be [i]blocking[/i], which causes the window to freeze if [method read_string_from_stdin] is called on the main thread. + - If standard input is console, this method will block until the program receives a line break in standard input (usually by the user pressing [kbd]Enter[/kbd]). + - If standard input is pipe, this method will block until a specific amount of data is read or pipe is closed. + - If standard input is a file, this method will read a specific amount of data (or less if end-of-file is reached) and return immediately. + [b]Note:[/b] This method is implemented on Linux, macOS, and Windows. + [b]Note:[/b] On exported Windows builds, run the console wrapper executable to access the terminal. If standard input is console, calling this method without console wrapped will freeze permanently. If standard input is pipe or file, it can be used without console wrapper. If you need a single executable with full console support, use a custom build compiled with the [code]windows_subsystem=console[/code] flag. </description> </method> <method name="read_string_from_stdin"> <return type="String" /> + <param index="0" name="buffer_size" type="int" /> <description> - Reads a user input string from the standard input (usually the terminal). This operation is [i]blocking[/i], which causes the window to freeze if [method read_string_from_stdin] is called on the main thread. The thread calling [method read_string_from_stdin] will block until the program receives a line break in standard input (usually by the user pressing [kbd]Enter[/kbd]). - [b]Note:[/b] This method is implemented on Linux, macOS and Windows. - [b]Note:[/b] On exported Windows builds, run the console wrapper executable to access the terminal. Otherwise, the standard input will not work correctly. If you need a single executable with console support, use a custom build compiled with the [code]windows_subsystem=console[/code] flag. + Reads a user input as a UTF-8 encoded string from the standard input. This operation can be [i]blocking[/i], which causes the window to freeze if [method read_string_from_stdin] is called on the main thread. + - If standard input is console, this method will block until the program receives a line break in standard input (usually by the user pressing [kbd]Enter[/kbd]). + - If standard input is pipe, this method will block until a specific amount of data is read or pipe is closed. + - If standard input is a file, this method will read a specific amount of data (or less if end-of-file is reached) and return immediately. + [b]Note:[/b] This method is implemented on Linux, macOS, and Windows. + [b]Note:[/b] On exported Windows builds, run the console wrapper executable to access the terminal. If standard input is console, calling this method without console wrapped will freeze permanently. If standard input is pipe or file, it can be used without console wrapper. If you need a single executable with full console support, use a custom build compiled with the [code]windows_subsystem=console[/code] flag. </description> </method> <method name="request_permission"> @@ -831,5 +865,20 @@ <constant name="SYSTEM_DIR_RINGTONES" value="7" enum="SystemDir"> Refers to the Ringtones directory path. </constant> + <constant name="STD_HANDLE_INVALID" value="0" enum="StdHandleType"> + Standard I/O device is invalid. No data can be received from or sent to these standard I/O devices. + </constant> + <constant name="STD_HANDLE_CONSOLE" value="1" enum="StdHandleType"> + Standard I/O device is a console. This typically occurs when Godot is run from a terminal with no redirection. This is also used for all standard I/O devices when running Godot from the editor, at least on desktop platforms. + </constant> + <constant name="STD_HANDLE_FILE" value="2" enum="StdHandleType"> + Standard I/O device is a regular file. This typically occurs with redirection from a terminal, e.g. [code]godot > stdout.txt[/code], [code]godot < stdin.txt[/code] or [code]godot > stdout_stderr.txt 2>&1[/code]. + </constant> + <constant name="STD_HANDLE_PIPE" value="3" enum="StdHandleType"> + Standard I/O device is a FIFO/pipe. This typically occurs with pipe usage from a terminal, e.g. [code]echo "Hello" | godot[/code]. + </constant> + <constant name="STD_HANDLE_UNKNOWN" value="4" enum="StdHandleType"> + Standard I/O device type is unknown. + </constant> </constants> </class> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 2767a11e80..d0c193ea31 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -343,7 +343,7 @@ return "Welcome to Godot 4!" func _init(): - print(self) # Prints Welcome to Godot 4!" + print(self) # Prints "Welcome to Godot 4!" var a = str(self) # a is "Welcome to Godot 4!" [/codeblock] </description> @@ -406,7 +406,7 @@ <param index="0" name="signal" type="String" /> <param index="1" name="arguments" type="Array" default="[]" /> <description> - Adds a user-defined [param signal]. Optional arguments for the signal can be added as an [Array] of dictionaries, each defining a [code]name[/code] [String] and a [code]type[/code] [int] (see [enum Variant.Type]). See also [method has_user_signal] and [method remove_user_signal]. + Adds a user-defined signal named [param signal]. Optional arguments for the signal can be added as an [Array] of dictionaries, each defining a [code]name[/code] [String] and a [code]type[/code] [int] (see [enum Variant.Type]). See also [method has_user_signal] and [method remove_user_signal]. [codeblocks] [gdscript] add_user_signal("hurt", [ @@ -454,7 +454,7 @@ <return type="Variant" /> <param index="0" name="method" type="StringName" /> <description> - Calls the [param method] on the object during idle time. Always returns null, [b]not[/b] the method's result. + Calls the [param method] on the object during idle time. Always returns [code]null[/code], [b]not[/b] the method's result. Idle time happens mainly at the end of process and physics frames. In it, deferred calls will be run until there are none left, which means you can defer calls from other deferred calls and they'll still be run in the current idle time cycle. This means you should not call a method deferred from itself (or from a method called by it), as this causes infinite recursion the same way as if you had called the method directly. This method supports a variable number of arguments, so parameters can be passed as a comma separated list. [codeblocks] @@ -854,7 +854,7 @@ <param index="0" name="signal" type="StringName" /> <description> Returns [code]true[/code] if the given [param signal] name exists in the object. - [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call. + [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot signals. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call. </description> </method> <method name="has_user_signal" qualifiers="const"> @@ -898,7 +898,7 @@ <param index="1" name="callable" type="Callable" /> <description> Returns [code]true[/code] if a connection exists between the given [param signal] name and [param callable]. - [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call. + [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot signals. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call. </description> </method> <method name="is_queued_for_deletion" qualifiers="const"> diff --git a/doc/classes/OccluderInstance3D.xml b/doc/classes/OccluderInstance3D.xml index 6f45d72249..b3e6366c12 100644 --- a/doc/classes/OccluderInstance3D.xml +++ b/doc/classes/OccluderInstance3D.xml @@ -6,7 +6,7 @@ <description> Occlusion culling can improve rendering performance in closed/semi-open areas by hiding geometry that is occluded by other objects. The occlusion culling system is mostly static. [OccluderInstance3D]s can be moved or hidden at run-time, but doing so will trigger a background recomputation that can take several frames. It is recommended to only move [OccluderInstance3D]s sporadically (e.g. for procedural generation purposes), rather than doing so every frame. - The occlusion culling system works by rendering the occluders on the CPU in parallel using [url=https://www.embree.org/]Embree[/url], drawing the result to a low-resolution buffer then using this to cull 3D nodes individually. In the 3D editor, you can preview the occlusion culling buffer by choosing [b]Perspective > Debug Advanced... > Occlusion Culling Buffer[/b] in the top-left corner of the 3D viewport. The occlusion culling buffer quality can be adjusted in the Project Settings. + The occlusion culling system works by rendering the occluders on the CPU in parallel using [url=https://www.embree.org/]Embree[/url], drawing the result to a low-resolution buffer then using this to cull 3D nodes individually. In the 3D editor, you can preview the occlusion culling buffer by choosing [b]Perspective > Display Advanced... > Occlusion Culling Buffer[/b] in the top-left corner of the 3D viewport. The occlusion culling buffer quality can be adjusted in the Project Settings. [b]Baking:[/b] Select an [OccluderInstance3D] node, then use the [b]Bake Occluders[/b] button at the top of the 3D editor. Only opaque materials will be taken into account; transparent materials (alpha-blended or alpha-tested) will be ignored by the occluder generation. [b]Note:[/b] Occlusion culling is only effective if [member ProjectSettings.rendering/occlusion_culling/use_occlusion_culling] is [code]true[/code]. Enabling occlusion culling has a cost on the CPU. Only enable occlusion culling if you actually plan to use it. Large open scenes with few or no objects blocking the view will generally not benefit much from occlusion culling. Large open scenes generally benefit more from mesh LOD and visibility ranges ([member GeometryInstance3D.visibility_range_begin] and [member GeometryInstance3D.visibility_range_end]) compared to occlusion culling. [b]Note:[/b] Due to memory constraints, occlusion culling is not supported by default in Web export templates. It can be enabled by compiling custom Web export templates with [code]module_raycast_enabled=yes[/code]. diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml index ec0300c068..f8f7dbee01 100644 --- a/doc/classes/PCKPacker.xml +++ b/doc/classes/PCKPacker.xml @@ -26,11 +26,18 @@ <methods> <method name="add_file"> <return type="int" enum="Error" /> - <param index="0" name="pck_path" type="String" /> + <param index="0" name="target_path" type="String" /> <param index="1" name="source_path" type="String" /> <param index="2" name="encrypt" type="bool" default="false" /> <description> - Adds the [param source_path] file to the current PCK package at the [param pck_path] internal path (should start with [code]res://[/code]). + Adds the [param source_path] file to the current PCK package at the [param target_path] internal path. The [code]res://[/code] prefix for [param target_path] is optional and stripped internally. + </description> + </method> + <method name="add_file_removal"> + <return type="int" enum="Error" /> + <param index="0" name="target_path" type="String" /> + <description> + Registers a file removal of the [param target_path] internal path to the PCK. This is mainly used for patches. If the file at this path has been loaded from a previous PCK, it will be removed. The [code]res://[/code] prefix for [param target_path] is optional and stripped internally. </description> </method> <method name="flush"> diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index cfaf012a55..b82d0de350 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -6,7 +6,7 @@ <description> An array specifically designed to hold 64-bit integer values. Packs data tightly, so it saves memory for large array sizes. [b]Note:[/b] This type stores signed 64-bit integers, which means it can take values in the interval [code][-2^63, 2^63 - 1][/code], i.e. [code][-9223372036854775808, 9223372036854775807][/code]. Exceeding those bounds will wrap around. If you only need to pack 32-bit integers tightly, see [PackedInt32Array] for a more memory-friendly alternative. - [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedInt32Array] versus [code]Array[int][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays. + [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedInt64Array] versus [code]Array[int][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays. [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again. </description> <tutorials> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index 415e468e21..baff5fed57 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -7,7 +7,7 @@ A simplified interface to a scene file. Provides access to operations and checks that can be performed on the scene resource itself. Can be used to save a node to a file. When saving, the node as well as all the nodes it owns get saved (see [member Node.owner] property). [b]Note:[/b] The node doesn't need to own itself. - [b]Example of loading a saved scene:[/b] + [b]Example:[/b] Load a saved scene: [codeblocks] [gdscript] # Use load() instead of preload() if the path isn't known at compile-time. @@ -22,7 +22,7 @@ AddChild(scene); [/csharp] [/codeblocks] - [b]Example of saving a node with different owners:[/b] The following example creates 3 objects: [Node2D] ([code]node[/code]), [RigidBody2D] ([code]body[/code]) and [CollisionObject2D] ([code]collision[/code]). [code]collision[/code] is a child of [code]body[/code] which is a child of [code]node[/code]. Only [code]body[/code] is owned by [code]node[/code] and [method pack] will therefore only save those two nodes, but not [code]collision[/code]. + [b]Example:[/b] Save a node with different owners. The following example creates 3 objects: [Node2D] ([code]node[/code]), [RigidBody2D] ([code]body[/code]) and [CollisionObject2D] ([code]collision[/code]). [code]collision[/code] is a child of [code]body[/code] which is a child of [code]node[/code]. Only [code]body[/code] is owned by [code]node[/code] and [method pack] will therefore only save those two nodes, but not [code]collision[/code]. [codeblocks] [gdscript] # Create the objects. diff --git a/doc/classes/PackedVector4Array.xml b/doc/classes/PackedVector4Array.xml index 6dbfc7413d..7bebee79c7 100644 --- a/doc/classes/PackedVector4Array.xml +++ b/doc/classes/PackedVector4Array.xml @@ -5,6 +5,7 @@ </brief_description> <description> An array specifically designed to hold [Vector4]. Packs data tightly, so it saves memory for large array sizes. + [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedVector4Array] versus [code]Array[Vector4][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays. [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again. </description> <tutorials> diff --git a/doc/classes/PacketPeerUDP.xml b/doc/classes/PacketPeerUDP.xml index 12d3178797..05b6e646c0 100644 --- a/doc/classes/PacketPeerUDP.xml +++ b/doc/classes/PacketPeerUDP.xml @@ -4,7 +4,32 @@ UDP packet peer. </brief_description> <description> - UDP packet peer. Can be used to send raw UDP packets as well as [Variant]s. + UDP packet peer. Can be used to send and receive raw UDP packets as well as [Variant]s. + [b]Example:[/b] Send a packet: + [codeblock] + var peer = PacketPeerUDP.new() + + # Optionally, you can select the local port used to send the packet. + peer.bind(4444) + + peer.set_dest_address("1.1.1.1", 4433) + peer.put_packet("hello".to_utf8_buffer()) + [/codeblock] + [b]Example:[/b] Listen for packets: + [codeblock] + var peer + + func _ready(): + peer = PacketPeerUDP.new() + peer.bind(4433) + + + func _process(_delta): + if peer.get_available_packet_count() > 0: + var array_bytes = peer.get_packet() + var packet_string = array_bytes.get_string_from_ascii() + print("Received message: ", packet_string) + [/codeblock] [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. </description> <tutorials> diff --git a/doc/classes/PhysicalBone3D.xml b/doc/classes/PhysicalBone3D.xml index ca1948e8e1..e2ad3db0a5 100644 --- a/doc/classes/PhysicalBone3D.xml +++ b/doc/classes/PhysicalBone3D.xml @@ -21,6 +21,9 @@ <return type="void" /> <param index="0" name="impulse" type="Vector3" /> <description> + Applies a directional impulse without affecting rotation. + An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_integrate_forces" functions otherwise). + This is equivalent to using [method apply_impulse] at the body's center of mass. </description> </method> <method name="apply_impulse"> @@ -28,27 +31,33 @@ <param index="0" name="impulse" type="Vector3" /> <param index="1" name="position" type="Vector3" default="Vector3(0, 0, 0)" /> <description> + Applies a positioned impulse to the PhysicsBone3D. + An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_integrate_forces" functions otherwise). + [param position] is the offset from the PhysicsBone3D origin in global coordinates. </description> </method> <method name="get_bone_id" qualifiers="const"> <return type="int" /> <description> + Returns the unique identifier of the PhysicsBone3D. </description> </method> <method name="get_simulate_physics"> <return type="bool" /> <description> + Returns [code]true[/code] if the PhysicsBone3D is allowed to simulate physics. </description> </method> <method name="is_simulating_physics"> <return type="bool" /> <description> + Returns [code]true[/code] if the PhysicsBone3D is currently simulating physics. </description> </method> </methods> <members> <member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp" default="0.0"> - Damps the body's rotation. By default, the body will use the [b]Default Angular Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. + Damps the body's rotation. By default, the body will use the [member ProjectSettings.physics/3d/default_angular_damp] project setting or any value override set by an [Area3D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/3d/default_angular_damp] for more details about damping. </member> <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="PhysicalBone3D.DampMode" default="0"> @@ -75,7 +84,7 @@ The body's friction, from [code]0[/code] (frictionless) to [code]1[/code] (max friction). </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale" default="1.0"> - This is multiplied by the global 3D gravity setting found in [b]Project > Project Settings > Physics > 3d[/b] to produce the body's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. + This is multiplied by [member ProjectSettings.physics/3d/default_gravity] to produce this body's gravity. For example, a value of [code]1.0[/code] will apply normal gravity, [code]2.0[/code] will apply double the gravity, and [code]0.5[/code] will apply half the gravity to this body. </member> <member name="joint_offset" type="Transform3D" setter="set_joint_offset" getter="get_joint_offset" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)"> Sets the joint's transform. @@ -87,7 +96,7 @@ Sets the joint type. See [enum JointType] for possible values. </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp" default="0.0"> - Damps the body's movement. By default, the body will use the [b]Default Linear Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. + Damps the body's movement. By default, the body will use [member ProjectSettings.physics/3d/default_linear_damp] or any value override set by an [Area3D] the body is in. Depending on [member linear_damp_mode], [member linear_damp] may be added to or replace the body's damping value. See [member ProjectSettings.physics/3d/default_linear_damp] for more details about damping. </member> <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="PhysicalBone3D.DampMode" default="0"> @@ -108,16 +117,22 @@ In this mode, the body's damping value replaces any value set in areas or the default value. </constant> <constant name="JOINT_TYPE_NONE" value="0" enum="JointType"> + No joint is applied to the PhysicsBone3D. </constant> <constant name="JOINT_TYPE_PIN" value="1" enum="JointType"> + A pin joint is applied to the PhysicsBone3D. </constant> <constant name="JOINT_TYPE_CONE" value="2" enum="JointType"> + A cone joint is applied to the PhysicsBone3D. </constant> <constant name="JOINT_TYPE_HINGE" value="3" enum="JointType"> + A hinge joint is applied to the PhysicsBone3D. </constant> <constant name="JOINT_TYPE_SLIDER" value="4" enum="JointType"> + A slider joint is applied to the PhysicsBone3D. </constant> <constant name="JOINT_TYPE_6DOF" value="5" enum="JointType"> + A 6 degrees of freedom joint is applied to the PhysicsBone3D. </constant> </constants> </class> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index d73cda7460..9fd47cf7f5 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -135,8 +135,6 @@ Adds a new multistate item with text [param label]. Contrarily to normal binary items, multistate items can have more than two states, as defined by [param max_states]. The default value is defined by [param default_state]. An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided, then the default value of 0 (corresponding to [constant @GlobalScope.KEY_NONE]) will be assigned to the item (which means it won't have any accelerator). See [method get_item_accelerator] for more info on accelerators. - [b]Note:[/b] Multistate items don't update their state automatically and must be done manually. See [method toggle_item_multistate], [method set_item_multistate] and [method get_item_multistate] for more info on how to control it. - Example usage: [codeblock] func _ready(): add_multistate_item("Item", 3, 0) @@ -152,6 +150,7 @@ print("Third state") ) [/codeblock] + [b]Note:[/b] Multistate items don't update their state automatically and must be done manually. See [method toggle_item_multistate], [method set_item_multistate] and [method get_item_multistate] for more info on how to control it. </description> </method> <method name="add_radio_check_item"> diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml index 58a8da12da..ba48d2dcf5 100644 --- a/doc/classes/PrimitiveMesh.xml +++ b/doc/classes/PrimitiveMesh.xml @@ -18,7 +18,8 @@ <method name="get_mesh_arrays" qualifiers="const"> <return type="Array" /> <description> - Returns mesh arrays used to constitute surface of [Mesh]. The result can be passed to [method ArrayMesh.add_surface_from_arrays] to create a new surface. For example: + Returns the mesh arrays used to make up the surface of this primitive mesh. + [b]Example:[/b] Pass the result to [method ArrayMesh.add_surface_from_arrays] to create a new surface: [codeblocks] [gdscript] var c = CylinderMesh.new() diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 1684edb9b8..91961fcf02 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -10,6 +10,7 @@ [b]Overriding:[/b] Any project setting can be overridden by creating a file named [code]override.cfg[/code] in the project's root directory. This can also be used in exported projects by placing this file in the same directory as the project binary. Overriding will still take the base project settings' [url=$DOCS_URL/tutorials/export/feature_tags.html]feature tags[/url] in account. Therefore, make sure to [i]also[/i] override the setting with the desired feature tags if you want them to override base project settings on all platforms and configurations. </description> <tutorials> + <link title="Project Settings">$DOCS_URL/tutorials/editor/project_settings.html</link> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/2747</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/2748</link> <link title="Operating System Testing Demo">https://godotengine.org/asset-library/asset/2789</link> @@ -102,7 +103,7 @@ <param index="0" name="name" type="StringName" /> <description> Similar to [method get_setting], but applies feature tag overrides if any exists and is valid. - [b]Example:[/b] If the setting override [code]"application/config/name.windows"[/code] exists, and the following code is executed on a [i]Windows[/i] operating system, the overridden setting is printed instead: + [b]Example:[/b] If the setting override [code]"application/config/name.windows"[/code] exists, and the following code is executed on a [i]Windows[/i] operating system, the overridden setting is printed instead: [codeblocks] [gdscript] print(ProjectSettings.get_setting_with_override("application/config/name")) @@ -376,6 +377,7 @@ <member name="audio/driver/driver" type="String" setter="" getter=""> Specifies the audio driver to use. This setting is platform-dependent as each platform supports different audio drivers. If left empty, the default audio driver will be used. The [code]Dummy[/code] audio driver disables all audio playback and recording, which is useful for non-game applications as it reduces CPU usage. It also prevents the engine from appearing as an application playing audio in the OS' audio mixer. + To query the value that is being used at run-time (which may be overridden by command-line arguments or headless mode), use [method AudioServer.get_driver_name]. [b]Note:[/b] The driver in use can be overridden at runtime via the [code]--audio-driver[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]. </member> <member name="audio/driver/enable_input" type="bool" setter="" getter="" default="false"> @@ -467,10 +469,10 @@ If the [code]--log-file <file>[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url] is used, log rotation is always disabled. </member> <member name="debug/gdscript/warnings/assert_always_false" type="int" setter="" getter="" default="1"> - When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when an [code]assert[/code] call always evaluates to false. + When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when an [code]assert[/code] call always evaluates to [code]false[/code]. </member> <member name="debug/gdscript/warnings/assert_always_true" type="int" setter="" getter="" default="1"> - When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when an [code]assert[/code] call always evaluates to true. + When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when an [code]assert[/code] call always evaluates to [code]true[/code]. </member> <member name="debug/gdscript/warnings/confusable_capture_reassignment" type="int" setter="" getter="" default="1"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local variable captured by a lambda is reassigned, since this does not modify the outer local variable. @@ -559,10 +561,10 @@ When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or member variable, signal, or enum that would have the same name as a built-in function or global class name, thus shadowing it. </member> <member name="debug/gdscript/warnings/shadowed_variable" type="int" setter="" getter="" default="1"> - When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or member variable that would shadow a member variable that the class defines. + When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local variable or local constant shadows a member declared in the current class. </member> <member name="debug/gdscript/warnings/shadowed_variable_base_class" type="int" setter="" getter="" default="1"> - When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or subclass member variable that would shadow a variable that is inherited from a parent class. + When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local variable or local constant shadows a member declared in a base class. </member> <member name="debug/gdscript/warnings/standalone_expression" type="int" setter="" getter="" default="1"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling an expression that may have no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement. @@ -816,6 +818,17 @@ <member name="display/window/energy_saving/keep_screen_on" type="bool" setter="" getter="" default="true"> If [code]true[/code], keeps the screen on (even in case of inactivity), so the screensaver does not take over. Works on desktop and mobile platforms. </member> + <member name="display/window/frame_pacing/android/enable_frame_pacing" type="bool" setter="" getter="" default="true"> + Enable Swappy for stable frame pacing on Android. Highly recommended. + [b]Note:[/b] This option will be forced off when using OpenXR. + </member> + <member name="display/window/frame_pacing/android/swappy_mode" type="int" setter="" getter="" default="2"> + Swappy mode to use. The options are: + - pipeline_forced_on: Try to honor [member Engine.max_fps]. Pipelining is always on. This is the same behavior as Desktop PC. + - auto_fps_pipeline_forced_on: Autocalculate max fps. Actual max_fps will be between 0 and [member Engine.max_fps]. While this sounds convenient, beware that Swappy will often downgrade max fps until it finds something that can be met and sustained. That means if your game runs between 40fps and 60fps on a 60hz screen, after some time Swappy will downgrade max fps so that the game renders at perfect 30fps. + - auto_fps_auto_pipeline: Same as auto_fps_pipeline_forced_on, but if Swappy detects that rendering is very fast (e.g. it takes < 8ms to render on a 60hz screen) Swappy will disable pipelining to minimize input latency. This is the default. + [b]Note:[/b] If [member Engine.max_fps] is 0, actual max_fps will considered as to be the screen's refresh rate (often 60hz, 90hz or 120hz depending on device model and OS settings). + </member> <member name="display/window/handheld/orientation" type="int" setter="" getter="" default="0"> The default screen orientation to use on mobile devices. See [enum DisplayServer.ScreenOrientation] for possible values. [b]Note:[/b] When set to a portrait orientation, this project setting does not flip the project resolution's width and height automatically. Instead, you have to set [member display/window/size/viewport_width] and [member display/window/size/viewport_height] accordingly. @@ -875,6 +888,10 @@ [b]Note:[/b] Certain window managers can be configured to ignore the non-resizable status of a window. Do not rely on this setting as a guarantee that the window will [i]never[/i] be resizable. [b]Note:[/b] This setting is ignored on iOS. </member> + <member name="display/window/size/sharp_corners" type="bool" setter="" getter="" default="false"> + If [code]true[/code], the main window uses sharp corners by default. + [b]Note:[/b] This property is implemented only on Windows (11). + </member> <member name="display/window/size/transparent" type="bool" setter="" getter="" default="false"> If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/viewport/transparent_background]. [b]Note:[/b] To use a transparent splash screen, set [member application/boot_splash/bg_color] to [code]Color(0, 0, 0, 0)[/code]. @@ -2350,6 +2367,10 @@ <member name="rendering/2d/batching/item_buffer_size" type="int" setter="" getter="" default="16384"> Maximum number of canvas item commands that can be batched into a single draw call. </member> + <member name="rendering/2d/batching/uniform_set_cache_size" type="int" setter="" getter="" default="256"> + Maximum number of uniform sets that will be cached by the 2D renderer when batching draw calls. + [b]Note:[/b] A project that uses a large number of unique sprite textures per frame may benefit from increasing this value. + </member> <member name="rendering/2d/sdf/oversize" type="int" setter="" getter="" default="1"> Controls how much of the original viewport size should be covered by the 2D signed distance field. This SDF can be sampled in [CanvasItem] shaders and is used for [GPUParticles2D] collision. Higher values allow portions of occluders located outside the viewport to still be taken into account in the generated signed distance field, at the cost of performance. If you notice particles falling through [LightOccluder2D]s as the occluders leave the viewport, increase this setting. The percentage specified is added on each axis and on both sides. For example, with the default setting of 120%, the signed distance field will cover 20% of the viewport's size outside the viewport on each side (top, right, bottom, left). @@ -2453,10 +2474,10 @@ Number of blur passes to use when computing screen-space ambient occlusion. A higher number will result in a smoother look, but will be slower to compute and will have less high-frequency detail. </member> <member name="rendering/environment/ssao/fadeout_from" type="float" setter="" getter="" default="50.0"> - Distance at which the screen-space ambient occlusion effect starts to fade out. Use this hide ambient occlusion at great distances. + Distance at which the screen-space ambient occlusion effect starts to fade out. Use this hide ambient occlusion from far away. </member> <member name="rendering/environment/ssao/fadeout_to" type="float" setter="" getter="" default="300.0"> - Distance at which the screen-space ambient occlusion is fully faded out. Use this hide ambient occlusion at great distances. + Distance at which the screen-space ambient occlusion is fully faded out. Use this hide ambient occlusion from far away. </member> <member name="rendering/environment/ssao/half_size" type="bool" setter="" getter="" default="true"> If [code]true[/code], screen-space ambient occlusion will be rendered at half size and then upscaled before being added to the scene. This is significantly faster but may miss small details. If [code]false[/code], screen-space ambient occlusion will be rendered at full size. @@ -2471,10 +2492,10 @@ Number of blur passes to use when computing screen-space indirect lighting. A higher number will result in a smoother look, but will be slower to compute and will have less high-frequency detail. </member> <member name="rendering/environment/ssil/fadeout_from" type="float" setter="" getter="" default="50.0"> - Distance at which the screen-space indirect lighting effect starts to fade out. Use this hide screen-space indirect lighting at great distances. + Distance at which the screen-space indirect lighting effect starts to fade out. Use this to hide screen-space indirect lighting from far away. </member> <member name="rendering/environment/ssil/fadeout_to" type="float" setter="" getter="" default="300.0"> - Distance at which the screen-space indirect lighting is fully faded out. Use this hide screen-space indirect lighting at great distances. + Distance at which the screen-space indirect lighting is fully faded out. Use this to hide screen-space indirect lighting from far away. </member> <member name="rendering/environment/ssil/half_size" type="bool" setter="" getter="" default="true"> If [code]true[/code], screen-space indirect lighting will be rendered at half size and then upscaled before being added to the scene. This is significantly faster but may miss small details and may result in some objects appearing to glow at their edges. @@ -2757,6 +2778,8 @@ [b]Forward Plus[/b]: High-end renderer designed for Desktop devices. Has a higher base overhead, but scales well with complex scenes. Not suitable for older devices or mobile. [b]Mobile[/b]: Modern renderer designed for mobile devices. Has a lower base overhead than Forward Plus, but does not scale as well to large scenes with many elements. [b]GL Compatibility[/b]: Low-end renderer designed for older devices. Based on the limitations of the OpenGL 3.3/ OpenGL ES 3.0 / WebGL 2 APIs. + This can be overridden using the [code]--rendering-method <method>[/code] command line argument. + [b]Note:[/b] The actual rendering method may be automatically changed by the engine as a result of a fallback, or a user-specified command line argument. To get the actual rendering method that is used at runtime, use [method RenderingServer.get_current_rendering_method] instead of reading this project setting's value. </member> <member name="rendering/renderer/rendering_method.mobile" type="String" setter="" getter="" default=""mobile""> Override for [member rendering/renderer/rendering_method] on mobile devices. @@ -2780,7 +2803,8 @@ Depending on the complexity of scenes, this value may be lowered or may need to be raised. </member> <member name="rendering/rendering_device/driver" type="String" setter="" getter=""> - Sets the driver to be used by the renderer when using a RenderingDevice-based renderer like the clustered renderer or the mobile renderer. This property can not be edited directly, instead, set the driver using the platform-specific overrides. + Sets the driver to be used by the renderer when using a RenderingDevice-based renderer like the clustered renderer or the mobile renderer. This property can't be edited directly. Instead, set the driver using the platform-specific overrides. This can be overridden using the [code]--rendering-driver <driver>[/code] command line argument. + [b]Note:[/b] The actual rendering driver may be automatically changed by the engine as a result of a fallback, or a user-specified command line argument. To get the actual rendering driver that is used at runtime, use [method RenderingServer.get_current_rendering_driver_name] instead of reading this project setting's value. </member> <member name="rendering/rendering_device/driver.android" type="String" setter="" getter=""> Android override for [member rendering/rendering_device/driver]. @@ -2869,11 +2893,11 @@ If [code]true[/code], forces vertex shading for all rendering. This can increase performance a lot, but also reduces quality immensely. Can be used to optimize performance on low-end mobile devices. </member> <member name="rendering/textures/canvas_textures/default_texture_filter" type="int" setter="" getter="" default="1"> - The default texture filtering mode to use on [CanvasItem]s. + The default texture filtering mode to use for [CanvasItem]s built-in texture. In shaders, this texture is accessed as [code]TEXTURE[/code]. [b]Note:[/b] For pixel art aesthetics, see also [member rendering/2d/snap/snap_2d_vertices_to_pixel] and [member rendering/2d/snap/snap_2d_transforms_to_pixel]. </member> <member name="rendering/textures/canvas_textures/default_texture_repeat" type="int" setter="" getter="" default="0"> - The default texture repeating mode to use on [CanvasItem]s. + The default texture repeating mode to use for [CanvasItem]s built-in texture. In shaders, this texture is accessed as [code]TEXTURE[/code]. </member> <member name="rendering/textures/decals/filter" type="int" setter="" getter="" default="3"> The filtering quality to use for [Decal] nodes. When using one of the anisotropic filtering modes, the anisotropic filtering level is controlled by [member rendering/textures/default_filters/anisotropic_filtering_level]. @@ -2993,7 +3017,7 @@ Specify whether OpenXR should be configured for an HMD or a hand held device. </member> <member name="xr/openxr/foveation_dynamic" type="bool" setter="" getter="" default="false"> - If true and foveation is supported, will automatically adjust foveation level based on framerate up to the level set on [member xr/openxr/foveation_level]. + If [code]true[/code] and foveation is supported, will automatically adjust foveation level based on framerate up to the level set on [member xr/openxr/foveation_level]. [b]Note:[/b] Only works on the Compatibility rendering method. </member> <member name="xr/openxr/foveation_level" type="int" setter="" getter="" default=""0""> diff --git a/doc/classes/Projection.xml b/doc/classes/Projection.xml index 1665660da3..091e0bf54f 100644 --- a/doc/classes/Projection.xml +++ b/doc/classes/Projection.xml @@ -14,7 +14,8 @@ <constructor name="Projection"> <return type="Projection" /> <description> - Constructs a default-initialized [Projection] set to [constant IDENTITY]. + Constructs a default-initialized [Projection] identical to [constant IDENTITY]. + [b]Note:[/b] In C#, this constructs a [Projection] identical to [constant ZERO]. </description> </constructor> <constructor name="Projection"> @@ -277,22 +278,22 @@ </member> </members> <constants> - <constant name="PLANE_NEAR" value="0"> + <constant name="PLANE_NEAR" value="0" enum="Planes"> The index value of the projection's near clipping plane. </constant> - <constant name="PLANE_FAR" value="1"> + <constant name="PLANE_FAR" value="1" enum="Planes"> The index value of the projection's far clipping plane. </constant> - <constant name="PLANE_LEFT" value="2"> + <constant name="PLANE_LEFT" value="2" enum="Planes"> The index value of the projection's left clipping plane. </constant> - <constant name="PLANE_TOP" value="3"> + <constant name="PLANE_TOP" value="3" enum="Planes"> The index value of the projection's top clipping plane. </constant> - <constant name="PLANE_RIGHT" value="4"> + <constant name="PLANE_RIGHT" value="4" enum="Planes"> The index value of the projection's right clipping plane. </constant> - <constant name="PLANE_BOTTOM" value="5"> + <constant name="PLANE_BOTTOM" value="5" enum="Planes"> The index value of the projection bottom clipping plane. </constant> <constant name="IDENTITY" value="Projection(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)"> diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml index 665c6335f2..c74a6453e0 100644 --- a/doc/classes/Quaternion.xml +++ b/doc/classes/Quaternion.xml @@ -22,6 +22,7 @@ <return type="Quaternion" /> <description> Constructs a [Quaternion] identical to the [constant IDENTITY]. + [b]Note:[/b] In C#, this constructs a [Quaternion] with all of its components set to [code]0.0[/code]. </description> </constructor> <constructor name="Quaternion"> diff --git a/doc/classes/RDPipelineDepthStencilState.xml b/doc/classes/RDPipelineDepthStencilState.xml index dc1e70eb55..425890bb8d 100644 --- a/doc/classes/RDPipelineDepthStencilState.xml +++ b/doc/classes/RDPipelineDepthStencilState.xml @@ -34,10 +34,10 @@ The method used for comparing the previous and current depth values. </member> <member name="depth_range_max" type="float" setter="set_depth_range_max" getter="get_depth_range_max" default="0.0"> - The maximum depth that returns true for [member enable_depth_range]. + The maximum depth that returns [code]true[/code] for [member enable_depth_range]. </member> <member name="depth_range_min" type="float" setter="set_depth_range_min" getter="get_depth_range_min" default="0.0"> - The minimum depth that returns true for [member enable_depth_range]. + The minimum depth that returns [code]true[/code] for [member enable_depth_range]. </member> <member name="enable_depth_range" type="bool" setter="set_enable_depth_range" getter="get_enable_depth_range" default="false"> If [code]true[/code], each depth value will be tested to see if it is between [member depth_range_min] and [member depth_range_max]. If it is outside of these values, it is discarded. @@ -46,7 +46,7 @@ If [code]true[/code], enables depth testing which allows objects to be automatically occluded by other objects based on their depth. This also allows objects to be partially occluded by other objects. If [code]false[/code], objects will appear in the order they were drawn (like in Godot's 2D renderer). </member> <member name="enable_depth_write" type="bool" setter="set_enable_depth_write" getter="get_enable_depth_write" default="false"> - If [code]true[/code], writes to the depth buffer whenever the depth test returns true. Only works when enable_depth_test is also true. + If [code]true[/code], writes to the depth buffer whenever the depth test returns [code]true[/code]. Only works when enable_depth_test is also [code]true[/code]. </member> <member name="enable_stencil" type="bool" setter="set_enable_stencil" getter="get_enable_stencil" default="false"> If [code]true[/code], enables stencil testing. There are separate stencil buffers for front-facing triangles and back-facing triangles. See properties that begin with "front_op" and properties with "back_op" for each. diff --git a/doc/classes/RDTextureFormat.xml b/doc/classes/RDTextureFormat.xml index f8de7feda0..ac875ab7c1 100644 --- a/doc/classes/RDTextureFormat.xml +++ b/doc/classes/RDTextureFormat.xml @@ -13,12 +13,14 @@ <return type="void" /> <param index="0" name="format" type="int" enum="RenderingDevice.DataFormat" /> <description> + Adds [param format] as a valid format for the corresponding [RDTextureView]'s [member RDTextureView.format_override] property. If any format is added as shareable, then the main [member format] must also be added. </description> </method> <method name="remove_shareable_format"> <return type="void" /> <param index="0" name="format" type="int" enum="RenderingDevice.DataFormat" /> <description> + Removes [param format] from the list of valid formats that the corresponding [RDTextureView]'s [member RDTextureView.format_override] property can be set to. </description> </method> </methods> diff --git a/doc/classes/RDTextureView.xml b/doc/classes/RDTextureView.xml index 30b6bfedf5..bd8102d553 100644 --- a/doc/classes/RDTextureView.xml +++ b/doc/classes/RDTextureView.xml @@ -10,7 +10,7 @@ </tutorials> <members> <member name="format_override" type="int" setter="set_format_override" getter="get_format_override" enum="RenderingDevice.DataFormat" default="218"> - Optional override for the data format to return sampled values in. The default value of [constant RenderingDevice.DATA_FORMAT_MAX] does not override the format. + Optional override for the data format to return sampled values in. The corresponding [RDTextureFormat] must have had this added as a shareable format. The default value of [constant RenderingDevice.DATA_FORMAT_MAX] does not override the format. </member> <member name="swizzle_a" type="int" setter="set_swizzle_a" getter="get_swizzle_a" enum="RenderingDevice.TextureSwizzle" default="6"> The channel to sample when sampling the alpha channel. diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml index 820ff04b70..a76676489f 100644 --- a/doc/classes/Range.xml +++ b/doc/classes/Range.xml @@ -54,7 +54,7 @@ Minimum value. Range is clamped if [member value] is less than [member min_value]. </member> <member name="page" type="float" setter="set_page" getter="get_page" default="0.0"> - Page size. Used mainly for [ScrollBar]. ScrollBar's length is its size multiplied by [member page] over the difference between [member min_value] and [member max_value]. + Page size. Used mainly for [ScrollBar]. A [ScrollBar]'s grabber length is the [ScrollBar]'s size multiplied by [member page] over the difference between [member min_value] and [member max_value]. </member> <member name="ratio" type="float" setter="set_as_ratio" getter="get_as_ratio"> The value mapped between 0 and 1. diff --git a/doc/classes/RenderData.xml b/doc/classes/RenderData.xml index 065505e6c6..c2a598c43f 100644 --- a/doc/classes/RenderData.xml +++ b/doc/classes/RenderData.xml @@ -19,7 +19,7 @@ <method name="get_environment" qualifiers="const"> <return type="RID" /> <description> - Returns the [RID] of the environments object in the [RenderingServer] being used to render this viewport. + Returns the [RID] of the environment object in the [RenderingServer] being used to render this viewport. </description> </method> <method name="get_render_scene_buffers" qualifiers="const"> diff --git a/doc/classes/RenderSceneBuffersRD.xml b/doc/classes/RenderSceneBuffersRD.xml index 212a65337e..6a5aba1dbc 100644 --- a/doc/classes/RenderSceneBuffersRD.xml +++ b/doc/classes/RenderSceneBuffersRD.xml @@ -52,7 +52,7 @@ <param index="2" name="view_name" type="StringName" /> <param index="3" name="view" type="RDTextureView" /> <description> - Create a new texture view for an existing texture and cache this under the given view_name. Will return the existing teture view if it already exists. Will error if the source texture doesn't exist. + Create a new texture view for an existing texture and cache this under the given [param view_name]. Will return the existing texture view if it already exists. Will error if the source texture doesn't exist. </description> </method> <method name="get_color_layer"> @@ -61,7 +61,7 @@ <param index="1" name="msaa" type="bool" default="false" /> <description> Returns the specified layer from the color texture we are rendering 3D content to. - If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. + If [param msaa] is [code]true[/code] and MSAA is enabled, this returns the MSAA variant of the buffer. </description> </method> <method name="get_color_texture"> @@ -69,7 +69,7 @@ <param index="0" name="msaa" type="bool" default="false" /> <description> Returns the color texture we are rendering 3D content to. If multiview is used this will be a texture array with all views. - If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. + If [param msaa] is [code]true[/code] and MSAA is enabled, this returns the MSAA variant of the buffer. </description> </method> <method name="get_depth_layer"> @@ -78,7 +78,7 @@ <param index="1" name="msaa" type="bool" default="false" /> <description> Returns the specified layer from the depth texture we are rendering 3D content to. - If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. + If [param msaa] is [code]true[/code] and MSAA is enabled, this returns the MSAA variant of the buffer. </description> </method> <method name="get_depth_texture"> @@ -86,7 +86,7 @@ <param index="0" name="msaa" type="bool" default="false" /> <description> Returns the depth texture we are rendering 3D content to. If multiview is used this will be a texture array with all views. - If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. + If [param msaa] is [code]true[/code] and MSAA is enabled, this returns the MSAA variant of the buffer. </description> </method> <method name="get_fsr_sharpness" qualifiers="const"> diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 2ff7e934e9..fe23f79119 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -324,6 +324,18 @@ Submits [param draw_list] for rendering on the GPU. This is the raster equivalent to [method compute_list_dispatch]. </description> </method> + <method name="draw_list_draw_indirect"> + <return type="void" /> + <param index="0" name="draw_list" type="int" /> + <param index="1" name="use_indices" type="bool" /> + <param index="2" name="buffer" type="RID" /> + <param index="3" name="offset" type="int" default="0" /> + <param index="4" name="draw_count" type="int" default="1" /> + <param index="5" name="stride" type="int" default="0" /> + <description> + Submits [param draw_list] for rendering on the GPU with the given parameters stored in the [param buffer] at [param offset]. Parameters being integers: vertex count, instance count, first vertex, first instance. And when using indices: index count, instance count, first index, vertex offset, first instance. Buffer must have been created with [constant STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT] flag. + </description> + </method> <method name="draw_list_enable_scissor"> <return type="void" /> <param index="0" name="draw_list" type="int" /> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 66a69b7902..6be53b336b 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -224,7 +224,7 @@ <param index="0" name="item" type="RID" /> <param index="1" name="ignore" type="bool" /> <description> - If [param ignore] is [code]true[/code], ignore clipping on items drawn with this canvas item until this is called again with [param ignore] set to false. + If [param ignore] is [code]true[/code], ignore clipping on items drawn with this canvas item until this is called again with [param ignore] set to [code]false[/code]. </description> </method> <method name="canvas_item_add_lcd_texture_rect_region"> @@ -1278,6 +1278,14 @@ Sets the intensity of the background color. </description> </method> + <method name="environment_set_camera_id"> + <return type="void" /> + <param index="0" name="env" type="RID" /> + <param index="1" name="id" type="int" /> + <description> + Sets the camera ID to be used as environment background. + </description> + </method> <method name="environment_set_canvas_max_layer"> <return type="void" /> <param index="0" name="env" type="RID" /> @@ -1540,6 +1548,20 @@ Tries to free an object in the RenderingServer. To avoid memory leaks, this should be called after using an object as memory management does not occur automatically when using RenderingServer directly. </description> </method> + <method name="get_current_rendering_driver_name" qualifiers="const"> + <return type="String" /> + <description> + Returns the name of the current rendering driver. This can be [code]vulkan[/code], [code]d3d12[/code], [code]metal[/code], [code]opengl3[/code], [code]opengl3_es[/code], or [code]opengl3_angle[/code]. See also [method get_current_rendering_method]. + The rendering driver is determined by [member ProjectSettings.rendering/rendering_device/driver], the [code]--rendering-driver[/code] command line argument that overrides this project setting, or an automatic fallback that is applied depending on the hardware. + </description> + </method> + <method name="get_current_rendering_method" qualifiers="const"> + <return type="String" /> + <description> + Returns the name of the current rendering method. This can be [code]forward_plus[/code], [code]mobile[/code], or [code]gl_compatibility[/code]. See also [method get_current_rendering_driver_name]. + The rendering method is determined by [member ProjectSettings.rendering/renderer/rendering_method], the [code]--rendering-method[/code] command line argument that overrides this project setting, or an automatic fallback that is applied depending on the hardware. + </description> + </method> <method name="get_default_clear_color"> <return type="Color" /> <description> @@ -1592,7 +1614,7 @@ <return type="RID" /> <description> Returns the RID of a 256×256 texture with a testing pattern on it (in [constant Image.FORMAT_RGB8] format). This texture will be created and returned on the first call to [method get_test_texture], then it will be cached for subsequent calls. See also [method get_white_texture]. - Example of getting the test texture and applying it to a [Sprite2D] node: + [b]Example:[/b] Get the test texture and apply it to a [Sprite2D] node: [codeblock] var texture_rid = RenderingServer.get_test_texture() var texture = ImageTexture.create_from_image(RenderingServer.texture_2d_get(texture_rid)) @@ -1633,7 +1655,7 @@ <return type="RID" /> <description> Returns the ID of a 4×4 white texture (in [constant Image.FORMAT_RGB8] format). This texture will be created and returned on the first call to [method get_white_texture], then it will be cached for subsequent calls. See also [method get_test_texture]. - Example of getting the white texture and applying it to a [Sprite2D] node: + [b]Example:[/b] Get the white texture and apply it to a [Sprite2D] node: [codeblock] var texture_rid = RenderingServer.get_white_texture() var texture = ImageTexture.create_from_image(RenderingServer.texture_2d_get(texture_rid)) @@ -2137,6 +2159,14 @@ If [code]true[/code], light will cast shadows. Equivalent to [member Light3D.shadow_enabled]. </description> </method> + <method name="light_set_shadow_caster_mask"> + <return type="void" /> + <param index="0" name="light" type="RID" /> + <param index="1" name="mask" type="int" /> + <description> + Sets the shadow caster mask for this 3D light. Shadows will only be cast using objects in the selected layers. Equivalent to [member Light3D.shadow_caster_mask]. + </description> + </method> <method name="lightmap_create"> <return type="RID" /> <description> @@ -2515,6 +2545,13 @@ [b]Note:[/b] If the buffer is in the engine's internal cache, it will have to be fetched from GPU memory and possibly decompressed. This means [method multimesh_get_buffer] is potentially a slow operation and should be avoided whenever possible. </description> </method> + <method name="multimesh_get_buffer_rd_rid" qualifiers="const"> + <return type="RID" /> + <param index="0" name="multimesh" type="RID" /> + <description> + Returns the [RenderingDevice] [RID] handle of the [MultiMesh], which can be used as any other buffer on the Rendering Device. + </description> + </method> <method name="multimesh_get_custom_aabb" qualifiers="const"> <return type="AABB" /> <param index="0" name="multimesh" type="RID" /> @@ -2941,7 +2978,7 @@ <param index="0" name="particles" type="RID" /> <param index="1" name="emitting" type="bool" /> <description> - If [code]true[/code], particles will emit over time. Setting to false does not reset the particles, but only stops their emission. Equivalent to [member GPUParticles3D.emitting]. + If [code]true[/code], particles will emit over time. Setting to [code]false[/code] does not reset the particles, but only stops their emission. Equivalent to [member GPUParticles3D.emitting]. </description> </method> <method name="particles_set_explosiveness_ratio"> @@ -3284,7 +3321,8 @@ <return type="void" /> <param index="0" name="generate" type="bool" /> <description> - This method is currently unimplemented and does nothing if called with [param generate] set to [code]true[/code]. + If [param generate] is [code]true[/code], generates debug wireframes for all meshes that are loaded when using the Compatibility renderer. By default, the engine does not generate debug wireframes at runtime, since they slow down loading of assets and take up VRAM. + [b]Note:[/b] You must call this method before loading any meshes when using the Compatibility renderer, otherwise wireframes will not be used. </description> </method> <method name="set_default_clear_color"> @@ -3498,7 +3536,7 @@ <param index="0" name="texture" type="RID" /> <description> Returns an [Image] instance from the given [param texture] [RID]. - Example of getting the test texture from [method get_test_texture] and applying it to a [Sprite2D] node: + [b]Example:[/b] Get the test texture from [method get_test_texture] and apply it to a [Sprite2D] node: [codeblock] var texture_rid = RenderingServer.get_test_texture() var texture = ImageTexture.create_from_image(RenderingServer.texture_2d_get(texture_rid)) @@ -5017,6 +5055,7 @@ </constant> <constant name="VIEWPORT_DEBUG_DRAW_WIREFRAME" value="4" enum="ViewportDebugDraw"> Debug draw draws objects in wireframe. + [b]Note:[/b] [method set_debug_generate_wireframes] must be called before loading any meshes for wireframes to be visible when using the Compatibility renderer. </constant> <constant name="VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER" value="5" enum="ViewportDebugDraw"> Normal buffer is drawn instead of regular scene so you can see the per-pixel normals that will be used by post-processing effects. diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml index 18d4047339..0f3a231cb7 100644 --- a/doc/classes/Resource.xml +++ b/doc/classes/Resource.xml @@ -37,7 +37,7 @@ <return type="void" /> <description> Override this method to customize the newly duplicated resource created from [method PackedScene.instantiate], if the original's [member resource_local_to_scene] is set to [code]true[/code]. - [b]Example:[/b] Set a random [code]damage[/code] value to every local resource from an instantiated scene. + [b]Example:[/b] Set a random [code]damage[/code] value to every local resource from an instantiated scene: [codeblock] extends Resource diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml index 4e4adc86c4..cdbf8b3f9a 100644 --- a/doc/classes/ResourceFormatLoader.xml +++ b/doc/classes/ResourceFormatLoader.xml @@ -57,6 +57,7 @@ <return type="int" /> <param index="0" name="path" type="String" /> <description> + Should return the unique ID for the resource associated with the given path. If this method is not overridden, a [code].uid[/code] file is generated along with the resource file, containing the unique ID. </description> </method> <method name="_handles_type" qualifiers="virtual const"> diff --git a/doc/classes/ResourceImporterOBJ.xml b/doc/classes/ResourceImporterOBJ.xml index a63dddb0e8..084638f62b 100644 --- a/doc/classes/ResourceImporterOBJ.xml +++ b/doc/classes/ResourceImporterOBJ.xml @@ -14,6 +14,19 @@ <member name="force_disable_mesh_compression" type="bool" setter="" getter="" default="false"> If [code]true[/code], mesh compression will not be used. Consider enabling if you notice blocky artifacts in your mesh normals or UVs, or if you have meshes that are larger than a few thousand meters in each direction. </member> + <member name="generate_lightmap_uv2" type="bool" setter="" getter="" default="false"> + If [code]true[/code], generates UV2 on import for [LightmapGI] baking. + </member> + <member name="generate_lightmap_uv2_texel_size" type="float" setter="" getter="" default="0.2"> + Controls the size of each texel on the baked lightmap. A smaller value results in more precise lightmaps, at the cost of larger lightmap sizes and longer bake times. + [b]Note:[/b] Only effective if [member generate_lightmap_uv2] is [code]true[/code]. + </member> + <member name="generate_lods" type="bool" setter="" getter="" default="true"> + If [code]true[/code], generates lower detail variants of the mesh which will be displayed in the distance to improve rendering performance. Not all meshes benefit from LOD, especially if they are never rendered from far away. Disabling this can reduce output file size and speed up importing. See [url=$DOCS_URL/tutorials/3d/mesh_lod.html#doc-mesh-lod]Mesh level of detail (LOD)[/url] for more information. + </member> + <member name="generate_shadow_mesh" type="bool" setter="" getter="" default="true"> + If [code]true[/code], enables the generation of shadow meshes on import. This optimizes shadow rendering without reducing quality by welding vertices together when possible. This in turn reduces the memory bandwidth required to render shadows. Shadow mesh generation currently doesn't support using a lower detail level than the source mesh (but shadow rendering will make use of LODs when relevant). + </member> <member name="generate_tangents" type="bool" setter="" getter="" default="true"> If [code]true[/code], generate vertex tangents using [url=http://www.mikktspace.com/]Mikktspace[/url] if the source mesh doesn't have tangent data. When possible, it's recommended to let the 3D modeling software generate tangents on export instead on relying on this option. Tangents are required for correct display of normal and height maps, along with any material/shader features that require tangents. If you don't need material features that require tangents, disabling this can reduce output file size and speed up importing if the source 3D file doesn't contain tangents. diff --git a/doc/classes/ResourceImporterTexture.xml b/doc/classes/ResourceImporterTexture.xml index 0761702aa1..a39e48c7bf 100644 --- a/doc/classes/ResourceImporterTexture.xml +++ b/doc/classes/ResourceImporterTexture.xml @@ -90,9 +90,13 @@ <member name="process/size_limit" type="int" setter="" getter="" default="0"> If set to a value greater than [code]0[/code], the size of the texture is limited on import to a value smaller than or equal to the value specified here. For non-square textures, the size limit affects the longer dimension, with the shorter dimension scaled to preserve aspect ratio. Resizing is performed using cubic interpolation. This can be used to reduce memory usage without affecting the source images, or avoid issues with textures not displaying on mobile/web platforms (as these usually can't display textures larger than 4096×4096). + [b]Note:[/b] Even if this is set to [code]0[/code], import size is limited to the following dimensions for technical reasons. Depending on [member compress/mode], textures will be downsampled on import if necessary: + - [b]Lossy:[/b] 16383 pixels width or height, whichever is larger; + - [b]Basis Universal:[/b] 16384 pixels width or height, whichever is larger; + - [b]All other modes:[/b] 32768 pixels width or height, whichever is larger. </member> <member name="roughness/mode" type="int" setter="" getter="" default="0"> - The color channel to consider as a roughness map in this texture. Only effective if Roughness > Src Normal is not empty. + The color channel to consider as a roughness map in this texture. Only effective if [member roughness/src_normal] is not empty. </member> <member name="roughness/src_normal" type="String" setter="" getter="" default=""""> The path to the texture to consider as a normal map for roughness filtering on import. Specifying this can help decrease specular aliasing slightly in 3D. diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml index 56c3208fc3..ae862dd52f 100644 --- a/doc/classes/ResourceLoader.xml +++ b/doc/classes/ResourceLoader.xml @@ -7,6 +7,7 @@ A singleton used to load resource files from the filesystem. It uses the many [ResourceFormatLoader] classes registered in the engine (either built-in or from a plugin) to load files into memory and convert them to a format that can be used by the engine. [b]Note:[/b] You have to import the files into the engine first to load them using [method load]. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data]. + [b]Note:[/b] Non-resource files such as plain text files cannot be read using [ResourceLoader]. Use [FileAccess] for those files instead, and be aware that non-resource files are not exported by default (see notes in the [FileAccess] class description for instructions on exporting them). </description> <tutorials> <link title="Operating System Testing Demo">https://godotengine.org/asset-library/asset/2789</link> @@ -74,6 +75,13 @@ Once a resource has been loaded by the engine, it is cached in memory for faster access, and future calls to the [method load] method will use the cached version. The cached resource can be overridden by using [method Resource.take_over_path] on a new resource for that same path. </description> </method> + <method name="list_directory"> + <return type="PackedStringArray" /> + <param index="0" name="directory_path" type="String" /> + <description> + Lists a directory (as example: "res://assets/enemies"), returning all resources contained within. The resource files are the original file names as visible in the editor before exporting. + </description> + </method> <method name="load"> <return type="Resource" /> <param index="0" name="path" type="String" /> @@ -104,7 +112,7 @@ <param index="1" name="progress" type="Array" default="[]" /> <description> Returns the status of a threaded loading operation started with [method load_threaded_request] for the resource at [param path]. See [enum ThreadLoadStatus] for possible return values. - An array variable can optionally be passed via [param progress], and will return a one-element array containing the percentage of completion of the threaded loading. + An array variable can optionally be passed via [param progress], and will return a one-element array containing the ratio of completion of the threaded loading (between [code]0.0[/code] and [code]1.0[/code]). [b]Note:[/b] The recommended way of using this method is to call it during different frames (e.g., in [method Node._process], instead of a loop). </description> </method> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 4a2cbbc3d8..8472e57840 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -225,8 +225,8 @@ <return type="void" /> <param index="0" name="effect" type="Variant" /> <description> - Installs a custom effect. This can also be done in the RichTextLabel inspector using the [member custom_effects] property. [param effect] should be a valid [RichTextEffect]. - Example RichTextEffect: + Installs a custom effect. This can also be done in the Inspector through the [member custom_effects] property. [param effect] should be a valid [RichTextEffect]. + [b]Example:[/b] With the following script extending from [RichTextEffect]: [codeblock] # effect.gd class_name MyCustomEffect @@ -236,7 +236,7 @@ # ... [/codeblock] - Registering the above effect in RichTextLabel from script: + The above effect can be installed in [RichTextLabel] from a script: [codeblock] # rich_text_label.gd extends RichTextLabel @@ -810,7 +810,7 @@ The default background color for odd rows. </theme_item> <theme_item name="line_separation" data_type="constant" type="int" default="0"> - The vertical space between lines. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. </theme_item> <theme_item name="outline_size" data_type="constant" type="int" default="0"> The size of the text outline. diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index 5661d1a276..1977b238e4 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -123,7 +123,7 @@ </methods> <members> <member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp" default="0.0"> - Damps the body's rotation. By default, the body will use the [b]Default Angular Damp[/b] in [b]Project > Project Settings > Physics > 2d[/b] or any value override set by an [Area2D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. + Damps the body's rotation. By default, the body will use the [member ProjectSettings.physics/2d/default_angular_damp] setting or any value override set by an [Area2D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/2d/default_angular_damp] for more details about damping. </member> <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidBody2D.DampMode" default="0"> @@ -172,7 +172,7 @@ For a body that is always frozen, use [StaticBody2D] or [AnimatableBody2D] instead. </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale" default="1.0"> - Multiplies the gravity applied to the body. The body's gravity is calculated from the [b]Default Gravity[/b] value in [b]Project > Project Settings > Physics > 2d[/b] and/or any additional gravity vector applied by [Area2D]s. + Multiplies the gravity applied to the body. The body's gravity is calculated from the [member ProjectSettings.physics/2d/default_gravity] project setting and/or any additional gravity vector applied by [Area2D]s. </member> <member name="inertia" type="float" setter="set_inertia" getter="get_inertia" default="0.0"> The body's moment of inertia. This is like mass, but for rotation: it determines how much torque it takes to rotate the body. The moment of inertia is usually computed automatically from the mass and the shapes, but this property allows you to set a custom value. @@ -201,7 +201,7 @@ [/codeblocks] </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp" default="0.0"> - Damps the body's movement. By default, the body will use the [b]Default Linear Damp[/b] in [b]Project > Project Settings > Physics > 2d[/b] or any value override set by an [Area2D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. + Damps the body's movement. By default, the body will use the [member ProjectSettings.physics/2d/default_linear_damp] setting or any value override set by an [Area2D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/2d/default_linear_damp] for more details about damping. </member> <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidBody2D.DampMode" default="0"> diff --git a/doc/classes/RigidBody3D.xml b/doc/classes/RigidBody3D.xml index dae904e2a3..de6d5cde3d 100644 --- a/doc/classes/RigidBody3D.xml +++ b/doc/classes/RigidBody3D.xml @@ -130,7 +130,7 @@ </methods> <members> <member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp" default="0.0"> - Damps the body's rotation. By default, the body will use the [b]Default Angular Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. + Damps the body's rotation. By default, the body will use the [member ProjectSettings.physics/3d/default_angular_damp] project setting or any value override set by an [Area3D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/3d/default_angular_damp] for more details about damping. </member> <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidBody3D.DampMode" default="0"> @@ -179,7 +179,7 @@ For a body that is always frozen, use [StaticBody3D] or [AnimatableBody3D] instead. </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale" default="1.0"> - This is multiplied by the global 3D gravity setting found in [b]Project > Project Settings > Physics > 3d[/b] to produce RigidBody3D's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. + This is multiplied by [member ProjectSettings.physics/3d/default_gravity] to produce this body's gravity. For example, a value of [code]1.0[/code] will apply normal gravity, [code]2.0[/code] will apply double the gravity, and [code]0.5[/code] will apply half the gravity to this body. </member> <member name="inertia" type="Vector3" setter="set_inertia" getter="get_inertia" default="Vector3(0, 0, 0)"> The body's moment of inertia. This is like mass, but for rotation: it determines how much torque it takes to rotate the body on each axis. The moment of inertia is usually computed automatically from the mass and the shapes, but this property allows you to set a custom value. @@ -208,7 +208,7 @@ [/codeblocks] </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp" default="0.0"> - Damps the body's movement. By default, the body will use the [b]Default Linear Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. + Damps the body's movement. By default, the body will use the [member ProjectSettings.physics/3d/default_linear_damp] project setting or any value override set by an [Area3D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/3d/default_linear_damp] for more details about damping. </member> <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidBody3D.DampMode" default="0"> diff --git a/doc/classes/Shader.xml b/doc/classes/Shader.xml index 68176dea14..3fbe1da687 100644 --- a/doc/classes/Shader.xml +++ b/doc/classes/Shader.xml @@ -31,8 +31,14 @@ <return type="Array" /> <param index="0" name="get_groups" type="bool" default="false" /> <description> - Get the list of shader uniforms that can be assigned to a [ShaderMaterial], for use with [method ShaderMaterial.set_shader_parameter] and [method ShaderMaterial.get_shader_parameter]. The parameters returned are contained in dictionaries in a similar format to the ones returned by [method Object.get_property_list]. - If argument [param get_groups] is true, parameter grouping hints will be provided. + Returns the list of shader uniforms that can be assigned to a [ShaderMaterial], for use with [method ShaderMaterial.set_shader_parameter] and [method ShaderMaterial.get_shader_parameter]. The parameters returned are contained in dictionaries in a similar format to the ones returned by [method Object.get_property_list]. + If argument [param get_groups] is [code]true[/code], parameter grouping hints are also included in the list. + </description> + </method> + <method name="inspect_native_shader_code"> + <return type="void" /> + <description> + Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code. See also [method Material.inspect_native_shader_code]. </description> </method> <method name="set_default_texture_parameter"> diff --git a/doc/classes/Shortcut.xml b/doc/classes/Shortcut.xml index b1e931aef8..c0ff3ebdb5 100644 --- a/doc/classes/Shortcut.xml +++ b/doc/classes/Shortcut.xml @@ -5,7 +5,7 @@ </brief_description> <description> Shortcuts are commonly used for interacting with a [Control] element from an [InputEvent] (also known as hotkeys). - One shortcut can contain multiple [InputEvent]'s, allowing the possibility of triggering one action with multiple different inputs. + One shortcut can contain multiple [InputEvent]s, allowing the possibility of triggering one action with multiple different inputs. </description> <tutorials> </tutorials> diff --git a/doc/classes/SkeletonIK3D.xml b/doc/classes/SkeletonIK3D.xml index 4858a6ce22..dbb099a22b 100644 --- a/doc/classes/SkeletonIK3D.xml +++ b/doc/classes/SkeletonIK3D.xml @@ -31,7 +31,7 @@ <method name="get_parent_skeleton" qualifiers="const"> <return type="Skeleton3D" /> <description> - Returns the parent [Skeleton3D] Node that was present when SkeletonIK entered the [SceneTree]. Returns null if the parent node was not a [Skeleton3D] Node when SkeletonIK3D entered the [SceneTree]. + Returns the parent [Skeleton3D] node that was present when SkeletonIK entered the scene tree. Returns [code]null[/code] if the parent node was not a [Skeleton3D] node when SkeletonIK3D entered the scene tree. </description> </method> <method name="is_running"> diff --git a/doc/classes/SkeletonModification2DTwoBoneIK.xml b/doc/classes/SkeletonModification2DTwoBoneIK.xml index 1c7bb32f4a..d2417ba7bf 100644 --- a/doc/classes/SkeletonModification2DTwoBoneIK.xml +++ b/doc/classes/SkeletonModification2DTwoBoneIK.xml @@ -65,7 +65,7 @@ </methods> <members> <member name="flip_bend_direction" type="bool" setter="set_flip_bend_direction" getter="get_flip_bend_direction" default="false"> - If [code]true[/code], the bones in the modification will blend outward as opposed to inwards when contracting. If [code]false[/code], the bones will bend inwards when contracting. + If [code]true[/code], the bones in the modification will bend outward as opposed to inwards when contracting. If [code]false[/code], the bones will bend inwards when contracting. </member> <member name="target_maximum_distance" type="float" setter="set_target_maximum_distance" getter="get_target_maximum_distance" default="0.0"> The maximum distance the target can be at. If the target is farther than this distance, the modification will solve as if it's at this maximum distance. When set to [code]0[/code], the modification will solve without distance constraints. diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml index a4ffa5c1e7..b1e78e8987 100644 --- a/doc/classes/Slider.xml +++ b/doc/classes/Slider.xml @@ -28,12 +28,12 @@ <signal name="drag_ended"> <param index="0" name="value_changed" type="bool" /> <description> - Emitted when dragging stops. If [param value_changed] is true, [member Range.value] is different from the value when you started the dragging. + Emitted when the grabber stops being dragged. If [param value_changed] is [code]true[/code], [member Range.value] is different from the value when the dragging was started. </description> </signal> <signal name="drag_started"> <description> - Emitted when dragging is started. This is emitted before the corresponding [signal Range.value_changed] signal. + Emitted when the grabber starts being dragged. This is emitted before the corresponding [signal Range.value_changed] signal. </description> </signal> </signals> diff --git a/doc/classes/SplitContainer.xml b/doc/classes/SplitContainer.xml index 650c396190..daafbbdd87 100644 --- a/doc/classes/SplitContainer.xml +++ b/doc/classes/SplitContainer.xml @@ -30,7 +30,7 @@ </methods> <members> <member name="collapsed" type="bool" setter="set_collapsed" getter="is_collapsed" default="false"> - If [code]true[/code], the area of the first [Control] will be collapsed and the dragger will be disabled. + If [code]true[/code], the dragger will be disabled and the children will be sized as if the [member split_offset] was [code]0[/code]. </member> <member name="drag_area_highlight_in_editor" type="bool" setter="set_drag_area_highlight_in_editor" getter="is_drag_area_highlight_in_editor_enabled" default="false"> Highlights the drag area [Rect2] so you can see where it is during development. The drag area is gold if [member dragging_enabled] is [code]true[/code], and red if [code]false[/code]. diff --git a/doc/classes/SpringArm3D.xml b/doc/classes/SpringArm3D.xml index 99389fb78d..330317f352 100644 --- a/doc/classes/SpringArm3D.xml +++ b/doc/classes/SpringArm3D.xml @@ -7,6 +7,7 @@ [SpringArm3D] casts a ray or a shape along its Z axis and moves all its direct children to the collision point, with an optional margin. This is useful for 3rd person cameras that move closer to the player when inside a tight space (you may need to exclude the player's collider from the [SpringArm3D]'s collision check). </description> <tutorials> + <link title="Third-person camera with spring arm">$DOCS_URL/tutorials/3d/spring_arm.html</link> </tutorials> <methods> <method name="add_excluded_object"> diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml index ad5c5472b8..acff5cf604 100644 --- a/doc/classes/StreamPeer.xml +++ b/doc/classes/StreamPeer.xml @@ -59,6 +59,12 @@ Gets a single-precision float from the stream. </description> </method> + <method name="get_half"> + <return type="float" /> + <description> + Gets a half-precision float from the stream. + </description> + </method> <method name="get_partial_data"> <return type="Array" /> <param index="0" name="bytes" type="int" /> @@ -162,6 +168,13 @@ Puts a single-precision float into the stream. </description> </method> + <method name="put_half"> + <return type="void" /> + <param index="0" name="value" type="float" /> + <description> + Puts a half-precision float into the stream. + </description> + </method> <method name="put_partial_data"> <return type="Array" /> <param index="0" name="data" type="PackedByteArray" /> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 40f08dafe6..d0512b8e1c 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -6,6 +6,7 @@ <description> This is the built-in string Variant type (and the one used by GDScript). Strings may contain any number of Unicode characters, and expose methods useful for manipulating and generating strings. Strings are reference-counted and use a copy-on-write approach (every modification to a string returns a new [String]), so passing them around is cheap in resources. Some string methods have corresponding variations. Variations suffixed with [code]n[/code] ([method countn], [method findn], [method replacen], etc.) are [b]case-insensitive[/b] (they make no distinction between uppercase and lowercase letters). Method variations prefixed with [code]r[/code] ([method rfind], [method rsplit], etc.) are reversed, and start from the end of the string, instead of the beginning. + To convert any Variant to or from a string, see [method @GlobalScope.str], [method @GlobalScope.str_to_var], and [method @GlobalScope.var_to_str]. [b]Note:[/b] In a boolean context, a string will evaluate to [code]false[/code] if it is empty ([code]""[/code]). Otherwise, a string will always evaluate to [code]true[/code]. </description> <tutorials> @@ -247,7 +248,7 @@ <param index="1" name="placeholder" type="String" default=""{_}"" /> <description> Formats the string by replacing all occurrences of [param placeholder] with the elements of [param values]. - [param values] can be a [Dictionary] or an [Array]. Any underscores in [param placeholder] will be replaced with the corresponding keys in advance. Array elements use their index as keys. + [param values] can be a [Dictionary], an [Array], or an [Object]. Any underscores in [param placeholder] will be replaced with the corresponding keys in advance. Array elements use their index as keys. [codeblock] # Prints "Waiting for Godot is a play by Samuel Beckett, and Godot Engine is named after it." var use_array_values = "Waiting for {0} is a play by {1}, and {0} Engine is named after it." @@ -262,13 +263,19 @@ print("User {} is {}.".format([42, "Godot"], "{}")) print("User {id} is {name}.".format([["id", 42], ["name", "Godot"]])) [/codeblock] + When passing an [Object], the property names from [method Object.get_property_list] are used as keys. + [codeblock] + # Prints "Visible true, position (0, 0)" + var node = Node2D.new() + print("Visible {visible}, position {position}".format(node)) + [/codeblock] See also the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format string[/url] tutorial. - [b]Note:[/b] The replacement of placeholders is not done all at once, instead each placeholder is replaced in the order they are passed, this means that if one of the replacement strings contains a key it will also be replaced. This can be very powerful, but can also cause unexpected results if you are not careful. If you do not need to perform replacement in the replacement strings, make sure your replacements do not contain placeholders to ensure reliable results. + [b]Note:[/b] Each replacement is done sequentially for each element of [param values], [b]not[/b] all at once. This means that if any element is inserted and it contains another placeholder, it may be changed by the next replacement. While this can be very useful, it often causes unexpected results. If not necessary, make sure [param values]'s elements do not contain placeholders. [codeblock] - print("{0} {1}".format(["{1}", "x"])) # Prints "x x". - print("{0} {1}".format(["x", "{0}"])) # Prints "x {0}". - print("{foo} {bar}".format({"foo": "{bar}", "bar": "baz"})) # Prints "baz baz". - print("{foo} {bar}".format({"bar": "baz", "foo": "{bar}"})) # Prints "{bar} baz". + print("{0} {1}".format(["{1}", "x"])) # Prints "x x". + print("{0} {1}".format(["x", "{0}"])) # Prints "x {0}". + print("{a} {b}".format({"a": "{b}", "b": "c"})) # Prints "c c". + print("{a} {b}".format({"b": "c", "a": "{b}"})) # Prints "{b} c". [/codeblock] [b]Note:[/b] In C#, it's recommended to [url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated]interpolate strings with "$"[/url], instead. </description> @@ -880,7 +887,7 @@ <return type="float" /> <param index="0" name="text" type="String" /> <description> - Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sorensen-Dice coefficient[/url]) of this string compared to another. A result of [code]1.0[/code] means totally similar, while [code]0.0[/code] means totally dissimilar. + Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sørensen-Dice coefficient[/url]) of this string compared to another. A result of [code]1.0[/code] means totally similar, while [code]0.0[/code] means totally dissimilar. [codeblock] print("ABC123".similarity("ABC123")) # Prints 1.0 print("ABC123".similarity("XYZ456")) # Prints 0.0 diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml index 3a2b492496..e561ef54fa 100644 --- a/doc/classes/StringName.xml +++ b/doc/classes/StringName.xml @@ -231,7 +231,7 @@ <param index="1" name="placeholder" type="String" default=""{_}"" /> <description> Formats the string by replacing all occurrences of [param placeholder] with the elements of [param values]. - [param values] can be a [Dictionary] or an [Array]. Any underscores in [param placeholder] will be replaced with the corresponding keys in advance. Array elements use their index as keys. + [param values] can be a [Dictionary], an [Array], or an [Object]. Any underscores in [param placeholder] will be replaced with the corresponding keys in advance. Array elements use their index as keys. [codeblock] # Prints "Waiting for Godot is a play by Samuel Beckett, and Godot Engine is named after it." var use_array_values = "Waiting for {0} is a play by {1}, and {0} Engine is named after it." @@ -246,7 +246,20 @@ print("User {} is {}.".format([42, "Godot"], "{}")) print("User {id} is {name}.".format([["id", 42], ["name", "Godot"]])) [/codeblock] + When passing an [Object], the property names from [method Object.get_property_list] are used as keys. + [codeblock] + # Prints "Visible true, position (0, 0)" + var node = Node2D.new() + print("Visible {visible}, position {position}".format(node)) + [/codeblock] See also the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format string[/url] tutorial. + [b]Note:[/b] Each replacement is done sequentially for each element of [param values], [b]not[/b] all at once. This means that if any element is inserted and it contains another placeholder, it may be changed by the next replacement. While this can be very useful, it often causes unexpected results. If not necessary, make sure [param values]'s elements do not contain placeholders. + [codeblock] + print("{0} {1}".format(["{1}", "x"])) # Prints "x x". + print("{0} {1}".format(["x", "{0}"])) # Prints "x {0}". + print("{a} {b}".format({"a": "{b}", "b": "c"})) # Prints "c c". + print("{a} {b}".format({"b": "c", "a": "{b}"})) # Prints "{b} c". + [/codeblock] [b]Note:[/b] In C#, it's recommended to [url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated]interpolate strings with "$"[/url], instead. </description> </method> @@ -299,7 +312,7 @@ <param index="0" name="delimiter" type="String" /> <param index="1" name="slice" type="int" /> <description> - Splits the string using a [param delimiter] and returns the substring at index [param slice]. Returns an empty string if the [param slice] does not exist. + Splits the string using a [param delimiter] and returns the substring at index [param slice]. Returns the original string if [param delimiter] does not occur in the string. Returns an empty string if the [param slice] does not exist. This is faster than [method split], if you only need one substring. [codeblock] print("i/am/example/hi".get_slice("/", 2)) # Prints "example" @@ -782,7 +795,7 @@ <return type="float" /> <param index="0" name="text" type="String" /> <description> - Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sorensen-Dice coefficient[/url]) of this string compared to another. A result of [code]1.0[/code] means totally similar, while [code]0.0[/code] means totally dissimilar. + Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sørensen-Dice coefficient[/url]) of this string compared to another. A result of [code]1.0[/code] means totally similar, while [code]0.0[/code] means totally dissimilar. [codeblock] print("ABC123".similarity("ABC123")) # Prints 1.0 print("ABC123".similarity("XYZ456")) # Prints 0.0 @@ -871,7 +884,7 @@ <method name="to_ascii_buffer" qualifiers="const"> <return type="PackedByteArray" /> <description> - Converts the string to an [url=https://en.wikipedia.org/wiki/ASCII]ASCII[/url]/Latin-1 encoded [PackedByteArray]. This method is slightly faster than [method to_utf8_buffer], but replaces all unsupported characters with spaces. + Converts the string to an [url=https://en.wikipedia.org/wiki/ASCII]ASCII[/url]/Latin-1 encoded [PackedByteArray]. This method is slightly faster than [method to_utf8_buffer], but replaces all unsupported characters with spaces. This is the inverse of [method PackedByteArray.get_string_from_ascii]. </description> </method> <method name="to_camel_case" qualifiers="const"> @@ -885,11 +898,11 @@ <description> Converts the string representing a decimal number into a [float]. This method stops on the first non-number character, except the first decimal point ([code].[/code]) and the exponent letter ([code]e[/code]). See also [method is_valid_float]. [codeblock] - var a = "12.35".to_float() # a is 12.35 - var b = "1.2.3".to_float() # b is 1.2 - var c = "12xy3".to_float() # c is 12.0 - var d = "1e3".to_float() # d is 1000.0 - var e = "Hello!".to_int() # e is 0.0 + var a = "12.35".to_float() # a is 12.35 + var b = "1.2.3".to_float() # b is 1.2 + var c = "12xy3".to_float() # c is 12.0 + var d = "1e3".to_float() # d is 1000.0 + var e = "Hello!".to_float() # e is 0.0 [/codeblock] </description> </method> @@ -945,25 +958,25 @@ <method name="to_utf8_buffer" qualifiers="const"> <return type="PackedByteArray" /> <description> - Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-8]UTF-8[/url] encoded [PackedByteArray]. This method is slightly slower than [method to_ascii_buffer], but supports all UTF-8 characters. For most cases, prefer using this method. + Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-8]UTF-8[/url] encoded [PackedByteArray]. This method is slightly slower than [method to_ascii_buffer], but supports all UTF-8 characters. For most cases, prefer using this method. This is the inverse of [method PackedByteArray.get_string_from_utf8]. </description> </method> <method name="to_utf16_buffer" qualifiers="const"> <return type="PackedByteArray" /> <description> - Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-16]UTF-16[/url] encoded [PackedByteArray]. + Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-16]UTF-16[/url] encoded [PackedByteArray]. This is the inverse of [method PackedByteArray.get_string_from_utf16]. </description> </method> <method name="to_utf32_buffer" qualifiers="const"> <return type="PackedByteArray" /> <description> - Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-32]UTF-32[/url] encoded [PackedByteArray]. + Converts the string to a [url=https://en.wikipedia.org/wiki/UTF-32]UTF-32[/url] encoded [PackedByteArray]. This is the inverse of [method PackedByteArray.get_string_from_utf32]. </description> </method> <method name="to_wchar_buffer" qualifiers="const"> <return type="PackedByteArray" /> <description> - Converts the string to a [url=https://en.wikipedia.org/wiki/Wide_character]wide character[/url] ([code]wchar_t[/code], UTF-16 on Windows, UTF-32 on other platforms) encoded [PackedByteArray]. + Converts the string to a [url=https://en.wikipedia.org/wiki/Wide_character]wide character[/url] ([code]wchar_t[/code], UTF-16 on Windows, UTF-32 on other platforms) encoded [PackedByteArray]. This is the inverse of [method PackedByteArray.get_string_from_wchar]. </description> </method> <method name="trim_prefix" qualifiers="const"> @@ -990,7 +1003,7 @@ <method name="uri_decode" qualifiers="const"> <return type="String" /> <description> - Decodes the string from its URL-encoded format. This method is meant to properly decode the parameters in a URL when receiving an HTTP request. + Decodes the string from its URL-encoded format. This method is meant to properly decode the parameters in a URL when receiving an HTTP request. See also [method uri_encode]. [codeblocks] [gdscript] var url = "$DOCS_URL/?highlight=Godot%20Engine%3%docs" @@ -1006,7 +1019,7 @@ <method name="uri_encode" qualifiers="const"> <return type="String" /> <description> - Encodes the string to URL-friendly format. This method is meant to properly encode the parameters in a URL when sending an HTTP request. + Encodes the string to URL-friendly format. This method is meant to properly encode the parameters in a URL when sending an HTTP request. See also [method uri_decode]. [codeblocks] [gdscript] var prefix = "$DOCS_URL/?highlight=" diff --git a/doc/classes/StyleBoxTexture.xml b/doc/classes/StyleBoxTexture.xml index 14bceb4d4c..07d4b13f36 100644 --- a/doc/classes/StyleBoxTexture.xml +++ b/doc/classes/StyleBoxTexture.xml @@ -80,9 +80,9 @@ Modulates the color of the texture when this style box is drawn. </member> <member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2(0, 0, 0, 0)"> - Species a sub-region of the texture to use. - This is equivalent to first wrapping the texture in an [AtlasTexture] with the same region. - If empty ([code]Rect2(0, 0, 0, 0)[/code]), the whole texture will be used. + The region to use from the [member texture]. + This is equivalent to first wrapping the [member texture] in an [AtlasTexture] with the same region. + If empty ([code]Rect2(0, 0, 0, 0)[/code]), the whole [member texture] is used. </member> <member name="texture" type="Texture2D" setter="set_texture" getter="get_texture"> The texture to use when drawing this style box. diff --git a/doc/classes/SubViewportContainer.xml b/doc/classes/SubViewportContainer.xml index b7d097cc91..310f235abf 100644 --- a/doc/classes/SubViewportContainer.xml +++ b/doc/classes/SubViewportContainer.xml @@ -20,6 +20,10 @@ </method> </methods> <members> + <member name="consume_drag_and_drop" type="bool" setter="set_consume_drag_and_drop" getter="is_consume_drag_and_drop_enabled" default="false"> + If [code]false[/code], the [SubViewportContainer] is not available as a drop target in drag-and-drop operations, and instead the [Control] nodes inside its [Viewport] children are potential drop targets. + If [code]true[/code], the [SubViewportContainer] itself will be considered as a drop target in drag-and-drop operations, preventing the [Control] nodes inside its [Viewport] children from becoming drop targets. + </member> <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="1" /> <member name="stretch" type="bool" setter="set_stretch" getter="is_stretch_enabled" default="false"> If [code]true[/code], the sub-viewport will be automatically resized to the control's size. diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index 9c1525d8f8..9265e6b345 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -140,7 +140,7 @@ <param index="0" name="flip" type="bool" default="false" /> <description> Generates normals from vertices so you do not have to do it manually. If [param flip] is [code]true[/code], the resulting normals will be inverted. [method generate_normals] should be called [i]after[/i] generating geometry and [i]before[/i] committing the mesh using [method commit] or [method commit_to_arrays]. For correct display of normal-mapped surfaces, you will also have to generate tangents using [method generate_tangents]. - [b]Note:[/b] [method generate_normals] only works if the primitive type to be set to [constant Mesh.PRIMITIVE_TRIANGLES]. + [b]Note:[/b] [method generate_normals] only works if the primitive type is set to [constant Mesh.PRIMITIVE_TRIANGLES]. [b]Note:[/b] [method generate_normals] takes smooth groups into account. To generate smooth normals, set the smooth group to a value greater than or equal to [code]0[/code] using [method set_smooth_group] or leave the smooth group at the default of [code]0[/code]. To generate flat normals, set the smooth group to [code]-1[/code] using [method set_smooth_group] prior to adding vertices. </description> </method> diff --git a/doc/classes/SyntaxHighlighter.xml b/doc/classes/SyntaxHighlighter.xml index 27cee26c50..22d20d24e5 100644 --- a/doc/classes/SyntaxHighlighter.xml +++ b/doc/classes/SyntaxHighlighter.xml @@ -41,11 +41,11 @@ <return type="Dictionary" /> <param index="0" name="line" type="int" /> <description> - Returns syntax highlighting data for a single line. If the line is not cached, calls [method _get_line_syntax_highlighting] to calculate the data. - The return [Dictionary] is column number to [Dictionary]. The column number notes the start of a region, the region will end if another region is found, or at the end of the line. The nested [Dictionary] contains the data for that region, currently only the key "color" is supported. - [b]Example return:[/b] + Returns the syntax highlighting data for the line at index [param line]. If the line is not cached, calls [method _get_line_syntax_highlighting] first to calculate the data. + Each entry is a column number containing a nested [Dictionary]. The column number denotes the start of a region, the region will end if another region is found, or at the end of the line. The nested [Dictionary] contains the data for that region. Currently only the key [code]"color"[/code] is supported. + [b]Example:[/b] Possible return value. This means columns [code]0[/code] to [code]4[/code] should be red, and columns [code]5[/code] to the end of the line should be green: [codeblock] - var color_map = { + { 0: { "color": Color(1, 0, 0) }, @@ -54,7 +54,6 @@ } } [/codeblock] - This will color columns 0-4 red, and columns 5-eol in green. </description> </method> <method name="get_text_edit" qualifiers="const"> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 42558bf992..b884fa5958 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -124,7 +124,6 @@ <return type="void" /> <description> Starts an edit for multiple carets. The edit must be ended with [method end_multicaret_edit]. Multicaret edits can be used to edit text at multiple carets and delay merging the carets until the end, so the caret indexes aren't affected immediately. [method begin_multicaret_edit] and [method end_multicaret_edit] can be nested, and the merge will happen at the last [method end_multicaret_edit]. - Example usage: [codeblock] begin_complex_operation() begin_multicaret_edit() @@ -266,7 +265,7 @@ <return type="int" /> <param index="0" name="line" type="int" /> <description> - Returns the first column containing a non-whitespace character. + Returns the first column containing a non-whitespace character on the given line. If there is only whitespace, returns the number of characters. </description> </method> <method name="get_first_visible_line" qualifiers="const"> @@ -312,7 +311,7 @@ <return type="int" /> <param index="0" name="line" type="int" /> <description> - Returns the number of spaces and [code]tab * tab_size[/code] before the first char. + Returns the indent level of the given line. This is the number of spaces and tabs at the beginning of the line, with the tabs taking the tab size into account (see [method get_tab_size]). </description> </method> <method name="get_last_full_visible_line" qualifiers="const"> @@ -344,7 +343,7 @@ <return type="Color" /> <param index="0" name="line" type="int" /> <description> - Returns the current background color of the line. [code]Color(0, 0, 0, 0)[/code] is returned if no color is set. + Returns the custom background color of the given line. If no color is set, returns [code]Color(0, 0, 0, 0)[/code]. </description> </method> <method name="get_line_column_at_pos" qualifiers="const"> @@ -429,7 +428,7 @@ <param index="0" name="line" type="int" /> <param index="1" name="column" type="int" /> <description> - Returns the wrap index of the given line column. + Returns the wrap index of the given column on the given line. This ranges from [code]0[/code] to [method get_line_wrap_count]. </description> </method> <method name="get_line_wrapped_text" qualifiers="const"> @@ -656,7 +655,7 @@ <method name="get_total_visible_line_count" qualifiers="const"> <return type="int" /> <description> - Returns the number of lines that may be drawn. + Returns the total number of lines in the text. This includes wrapped lines and excludes folded lines. If [member wrap_mode] is set to [constant LINE_WRAPPING_NONE] and no lines are folded (see [method CodeEdit.is_line_folded]) then this is equivalent to [method get_line_count]. See [method get_visible_line_count_in_range] for a limited range of lines. </description> </method> <method name="get_v_scroll_bar" qualifiers="const"> @@ -674,7 +673,7 @@ <method name="get_visible_line_count" qualifiers="const"> <return type="int" /> <description> - Returns the number of visible lines, including wrapped text. + Returns the number of lines that can visually fit, rounded down, based on this control's height. </description> </method> <method name="get_visible_line_count_in_range" qualifiers="const"> @@ -682,7 +681,7 @@ <param index="0" name="from_line" type="int" /> <param index="1" name="to_line" type="int" /> <description> - Returns the total number of visible + wrapped lines between the two lines. + Returns the total number of lines between [param from_line] and [param to_line] (inclusive) in the text. This includes wrapped lines and excludes folded lines. If the range covers all lines it is equivalent to [method get_total_visible_line_count]. </description> </method> <method name="get_word_at_pos" qualifiers="const"> @@ -764,7 +763,8 @@ <return type="bool" /> <param index="0" name="caret_index" type="int" default="0" /> <description> - Returns [code]true[/code] if the caret is visible on the screen. + Returns [code]true[/code] if the caret is visible, [code]false[/code] otherwise. A caret will be considered hidden if it is outside the scrollable area when scrolling is enabled. + [b]Note:[/b] [method is_caret_visible] does not account for a caret being off-screen if it is still within the scrollable area. It will return [code]true[/code] even if the caret is off-screen as long as it meets [TextEdit]'s own conditions for being visible. This includes uses of [member scroll_fit_content_width] and [member scroll_fit_content_height] that cause the [TextEdit] to expand beyond the viewport's bounds. </description> </method> <method name="is_dragging_cursor" qualifiers="const"> @@ -777,21 +777,21 @@ <return type="bool" /> <param index="0" name="gutter" type="int" /> <description> - Returns whether the gutter is clickable. + Returns [code]true[/code] if the gutter at the given index is clickable. See [method set_gutter_clickable]. </description> </method> <method name="is_gutter_drawn" qualifiers="const"> <return type="bool" /> <param index="0" name="gutter" type="int" /> <description> - Returns whether the gutter is currently drawn. + Returns [code]true[/code] if the gutter at the given index is currently drawn. See [method set_gutter_draw]. </description> </method> <method name="is_gutter_overwritable" qualifiers="const"> <return type="bool" /> <param index="0" name="gutter" type="int" /> <description> - Returns whether the gutter is overwritable. + Returns [code]true[/code] if the gutter at the given index is overwritable. See [method set_gutter_overwritable]. </description> </method> <method name="is_in_mulitcaret_edit" qualifiers="const"> @@ -805,7 +805,7 @@ <param index="0" name="line" type="int" /> <param index="1" name="gutter" type="int" /> <description> - Returns whether the gutter on the given line is clickable. + Returns [code]true[/code] if the gutter at the given index on the given line is clickable. See [method set_line_gutter_clickable]. </description> </method> <method name="is_line_wrapped" qualifiers="const"> @@ -818,7 +818,7 @@ <method name="is_menu_visible" qualifiers="const"> <return type="bool" /> <description> - Returns whether the menu is visible. Use this instead of [code]get_menu().visible[/code] to improve performance (so the creation of the menu is avoided). + Returns [code]true[/code] if the menu is visible. Use this instead of [code]get_menu().visible[/code] to improve performance (so the creation of the menu is avoided). See [method get_menu]. </description> </method> <method name="is_mouse_over_selection" qualifiers="const"> @@ -826,13 +826,13 @@ <param index="0" name="edges" type="bool" /> <param index="1" name="caret_index" type="int" default="-1" /> <description> - Returns whether the mouse is over selection. If [param edges] is [code]true[/code], the edges are considered part of the selection. + Returns [code]true[/code] if the mouse is over a selection. If [param edges] is [code]true[/code], the edges are considered part of the selection. </description> </method> <method name="is_overtype_mode_enabled" qualifiers="const"> <return type="bool" /> <description> - Returns whether the user is in overtype mode. + Returns [code]true[/code] if overtype mode is enabled. See [method set_overtype_mode_enabled]. </description> </method> <method name="menu_option"> @@ -847,7 +847,7 @@ <param index="0" name="from_line" type="int" /> <param index="1" name="to_line" type="int" /> <description> - Merge the gutters from [param from_line] into [param to_line]. Only overwritable gutters will be copied. + Merge the gutters from [param from_line] into [param to_line]. Only overwritable gutters will be copied. See [method set_gutter_overwritable]. </description> </method> <method name="merge_overlapping_carets"> @@ -898,7 +898,7 @@ <return type="void" /> <param index="0" name="gutter" type="int" /> <description> - Removes the gutter from this [TextEdit]. + Removes the gutter at the given index. </description> </method> <method name="remove_line_at"> @@ -1013,7 +1013,7 @@ <param index="0" name="gutter" type="int" /> <param index="1" name="clickable" type="bool" /> <description> - Sets the gutter as clickable. This will change the mouse cursor to a pointing hand when hovering over the gutter. + If [code]true[/code], the mouse cursor will change to a pointing hand ([constant Control.CURSOR_POINTING_HAND]) when hovering over the gutter at the given index. See [method is_gutter_clickable] and [method set_line_gutter_clickable]. </description> </method> <method name="set_gutter_custom_draw"> @@ -1021,7 +1021,7 @@ <param index="0" name="column" type="int" /> <param index="1" name="draw_callback" type="Callable" /> <description> - Set a custom draw method for the gutter. The callback method must take the following args: [code]line: int, gutter: int, Area: Rect2[/code]. This only works when the gutter type is [constant GUTTER_TYPE_CUSTOM] (see [method set_gutter_type]). + Set a custom draw callback for the gutter at the given index. [param draw_callback] must take the following arguments: A line index [int], a gutter index [int], and an area [Rect2]. This callback only works when the gutter type is [constant GUTTER_TYPE_CUSTOM] (see [method set_gutter_type]). </description> </method> <method name="set_gutter_draw"> @@ -1029,7 +1029,7 @@ <param index="0" name="gutter" type="int" /> <param index="1" name="draw" type="bool" /> <description> - Sets whether the gutter should be drawn. + If [code]true[/code], the gutter at the given index is drawn. The gutter type ([method set_gutter_type]) determines how it is drawn. See [method is_gutter_drawn]. </description> </method> <method name="set_gutter_name"> @@ -1037,7 +1037,7 @@ <param index="0" name="gutter" type="int" /> <param index="1" name="name" type="String" /> <description> - Sets the name of the gutter. + Sets the name of the gutter at the given index. </description> </method> <method name="set_gutter_overwritable"> @@ -1045,7 +1045,7 @@ <param index="0" name="gutter" type="int" /> <param index="1" name="overwritable" type="bool" /> <description> - Sets the gutter to overwritable. See [method merge_gutters]. + If [code]true[/code], the line data of the gutter at the given index can be overridden when using [method merge_gutters]. See [method is_gutter_overwritable]. </description> </method> <method name="set_gutter_type"> @@ -1053,7 +1053,7 @@ <param index="0" name="gutter" type="int" /> <param index="1" name="type" type="int" enum="TextEdit.GutterType" /> <description> - Sets the type of gutter. Gutters can contain icons, text, or custom visuals. See [enum TextEdit.GutterType] for options. + Sets the type of gutter at the given index. Gutters can contain icons, text, or custom visuals. See [enum TextEdit.GutterType] for options. </description> </method> <method name="set_gutter_width"> @@ -1061,7 +1061,7 @@ <param index="0" name="gutter" type="int" /> <param index="1" name="width" type="int" /> <description> - Set the width of the gutter. + Set the width of the gutter at the given index. </description> </method> <method name="set_line"> @@ -1102,7 +1102,7 @@ <param index="0" name="line" type="int" /> <param index="1" name="color" type="Color" /> <description> - Sets the current background color of the line. Set to [code]Color(0, 0, 0, 0)[/code] for no color. + Sets the custom background color of the given line. If transparent, this color is applied on top of the default background color (See [theme_item background_color]). If set to [code]Color(0, 0, 0, 0)[/code], no additional color is applied. </description> </method> <method name="set_line_gutter_clickable"> @@ -1111,7 +1111,7 @@ <param index="1" name="gutter" type="int" /> <param index="2" name="clickable" type="bool" /> <description> - If [param clickable] is [code]true[/code], makes the [param gutter] on [param line] clickable. See [signal gutter_clicked]. + If [param clickable] is [code]true[/code], makes the [param gutter] on the given [param line] clickable. This is like [method set_gutter_clickable], but for a single line. If [method is_gutter_clickable] is [code]true[/code], this will not have any effect. See [method is_line_gutter_clickable] and [signal gutter_clicked]. </description> </method> <method name="set_line_gutter_icon"> @@ -1154,7 +1154,7 @@ <return type="void" /> <param index="0" name="enabled" type="bool" /> <description> - If [code]true[/code], sets the user into overtype mode. When the user types in this mode, it will override existing text. + If [code]true[/code], enables overtype mode. In this mode, typing overrides existing text instead of inserting text. The [member ProjectSettings.input/ui_text_toggle_insert_mode] action toggles overtype mode. See [method is_overtype_mode_enabled]. </description> </method> <method name="set_search_flags"> @@ -1269,7 +1269,7 @@ If [code]false[/code], the context menu ignores mouse location. </member> <member name="caret_multiple" type="bool" setter="set_multiple_carets_enabled" getter="is_multiple_carets_enabled" default="true"> - Sets if multiple carets are allowed. + If [code]true[/code], multiple carets are allowed. Left-clicking with [kbd]Alt[/kbd] adds a new caret. See [method add_caret] and [method get_caret_count]. </member> <member name="caret_type" type="int" setter="set_caret_type" getter="get_caret_type" enum="TextEdit.CaretType" default="0"> Set the type of caret to draw. @@ -1624,7 +1624,7 @@ The caret's width in pixels. Greater values can be used to improve accessibility by ensuring the caret is easily visible, or to ensure consistency with a large font size. If set to [code]0[/code] or lower, the caret width is automatically set to 1 pixel and multiplied by the display scaling factor. </theme_item> <theme_item name="line_spacing" data_type="constant" type="int" default="4"> - Sets the spacing between the lines. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. </theme_item> <theme_item name="outline_size" data_type="constant" type="int" default="0"> The size of the text outline. diff --git a/doc/classes/TextMesh.xml b/doc/classes/TextMesh.xml index 898d19aed3..b6b1052af5 100644 --- a/doc/classes/TextMesh.xml +++ b/doc/classes/TextMesh.xml @@ -37,7 +37,7 @@ Language code used for text shaping algorithms, if left empty current locale is used instead. </member> <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0"> - Vertical space between lines in multiline [TextMesh]. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. </member> <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)"> The text drawing offset (in pixels). diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml index 46197f19b8..c9ac660b8c 100644 --- a/doc/classes/TextParagraph.xml +++ b/doc/classes/TextParagraph.xml @@ -280,6 +280,9 @@ <member name="justification_flags" type="int" setter="set_justification_flags" getter="get_justification_flags" enum="TextServer.JustificationFlag" is_bitfield="true" default="163"> Line fill alignment rules. See [enum TextServer.JustificationFlag] for more information. </member> + <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0"> + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. + </member> <member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible" default="-1"> Limits the lines of text shown. </member> diff --git a/doc/classes/TextureProgressBar.xml b/doc/classes/TextureProgressBar.xml index d3e334ef55..c68b521da9 100644 --- a/doc/classes/TextureProgressBar.xml +++ b/doc/classes/TextureProgressBar.xml @@ -42,6 +42,7 @@ </member> <member name="radial_initial_angle" type="float" setter="set_radial_initial_angle" getter="get_radial_initial_angle" default="0.0"> Starting angle for the fill of [member texture_progress] if [member fill_mode] is [constant FILL_CLOCKWISE], [constant FILL_COUNTER_CLOCKWISE], or [constant FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE]. When the node's [code]value[/code] is equal to its [code]min_value[/code], the texture doesn't show up at all. When the [code]value[/code] increases, the texture fills and tends towards [member radial_fill_degrees]. + [b]Note:[/b] [member radial_initial_angle] is wrapped between [code]0[/code] and [code]360[/code] degrees (inclusive). </member> <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" enum="Control.SizeFlags" is_bitfield="true" default="1" /> <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="1.0" /> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 0995a5a672..4683f063f1 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -380,7 +380,7 @@ <param index="4" name="ignore_empty_terrains" type="bool" default="true" /> <description> Update all the cells in the [param cells] coordinates array so that they use the given [param terrain] for the given [param terrain_set]. If an updated cell has the same terrain as one of its neighboring cells, this function tries to join the two. This function might update neighboring tiles if needed to create correct terrain transitions. - If [param ignore_empty_terrains] is true, empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. + If [param ignore_empty_terrains] is [code]true[/code], empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. If [param layer] is negative, the layers are accessed from the last one. [b]Note:[/b] To work correctly, this method requires the TileMap's TileSet to have terrains set up with all required terrain combinations. Otherwise, it may produce unexpected results. </description> @@ -394,7 +394,7 @@ <param index="4" name="ignore_empty_terrains" type="bool" default="true" /> <description> Update all the cells in the [param path] coordinates array so that they use the given [param terrain] for the given [param terrain_set]. The function will also connect two successive cell in the path with the same terrain. This function might update neighboring tiles if needed to create correct terrain transitions. - If [param ignore_empty_terrains] is true, empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. + If [param ignore_empty_terrains] is [code]true[/code], empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. If [param layer] is negative, the layers are accessed from the last one. [b]Note:[/b] To work correctly, this method requires the TileMap's TileSet to have terrains set up with all required terrain combinations. Otherwise, it may produce unexpected results. </description> diff --git a/doc/classes/TileMapLayer.xml b/doc/classes/TileMapLayer.xml index 135f85de69..43708ca142 100644 --- a/doc/classes/TileMapLayer.xml +++ b/doc/classes/TileMapLayer.xml @@ -22,6 +22,21 @@ [b]Note:[/b] If the properties of [param tile_data] object should change over time, use [method notify_runtime_tile_data_update] to notify the [TileMapLayer] it needs an update. </description> </method> + <method name="_update_cells" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="coords" type="Vector2i[]" /> + <param index="1" name="forced_cleanup" type="bool" /> + <description> + Called when this [TileMapLayer]'s cells need an internal update. This update may be caused from individual cells being modified or by a change in the [member tile_set] (causing all cells to be queued for an update). The first call to this function is always for initializing all the [TileMapLayer]'s cells. [param coords] contains the coordinates of all modified cells, roughly in the order they were modified. [param forced_cleanup] is [code]true[/code] when the [TileMapLayer]'s internals should be fully cleaned up. This is the case when: + - The layer is disabled; + - The layer is not visible; + - [member tile_set] is set to [code]null[/code]; + - The node is removed from the tree; + - The node is freed. + Note that any internal update happening while one of these conditions is verified is considered to be a "cleanup". See also [method update_internals]. + [b]Warning:[/b] Implementing this method may degrade the [TileMapLayer]'s performance. + </description> + </method> <method name="_use_tile_data_runtime_update" qualifiers="virtual"> <return type="bool" /> <param index="0" name="coords" type="Vector2i" /> @@ -120,7 +135,7 @@ <return type="Vector2i[]" /> <param index="0" name="coords" type="Vector2i" /> <description> - Returns the list of all neighboring cells to the one at [param coords]. + Returns the list of all neighboring cells to the one at [param coords]. Any neighboring cell is one that is touching edges, so for a square cell 4 cells would be returned, for a hexagon 6 cells are returned. </description> </method> <method name="get_used_cells" qualifiers="const"> @@ -228,7 +243,7 @@ <param index="3" name="ignore_empty_terrains" type="bool" default="true" /> <description> Update all the cells in the [param cells] coordinates array so that they use the given [param terrain] for the given [param terrain_set]. If an updated cell has the same terrain as one of its neighboring cells, this function tries to join the two. This function might update neighboring tiles if needed to create correct terrain transitions. - If [param ignore_empty_terrains] is true, empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. + If [param ignore_empty_terrains] is [code]true[/code], empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. [b]Note:[/b] To work correctly, this method requires the [TileMapLayer]'s TileSet to have terrains set up with all required terrain combinations. Otherwise, it may produce unexpected results. </description> </method> @@ -240,7 +255,7 @@ <param index="3" name="ignore_empty_terrains" type="bool" default="true" /> <description> Update all the cells in the [param path] coordinates array so that they use the given [param terrain] for the given [param terrain_set]. The function will also connect two successive cell in the path with the same terrain. This function might update neighboring tiles if needed to create correct terrain transitions. - If [param ignore_empty_terrains] is true, empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. + If [param ignore_empty_terrains] is [code]true[/code], empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints. [b]Note:[/b] To work correctly, this method requires the [TileMapLayer]'s TileSet to have terrains set up with all required terrain combinations. Otherwise, it may produce unexpected results. </description> </method> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 64cd4fb7b2..19b6e8d92c 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -4,7 +4,7 @@ Tile library for tilemaps. </brief_description> <description> - A TileSet is a library of tiles for a [TileMap]. A TileSet handles a list of [TileSetSource], each of them storing a set of tiles. + A TileSet is a library of tiles for a [TileMapLayer]. A TileSet handles a list of [TileSetSource], each of them storing a set of tiles. Tiles can either be from a [TileSetAtlasSource], which renders tiles out of a texture with support for physics, navigation, etc., or from a [TileSetScenesCollectionSource], which exposes scene-based tiles. Tiles are referenced by using three IDs: their source ID, their atlas coordinates ID, and their alternative tile ID. A TileSet can be configured so that its tiles expose more or fewer properties. To do so, the TileSet resources use property layers, which you can add or remove depending on your needs. @@ -218,6 +218,13 @@ Returns the collision mask of bodies on the given TileSet's physics layer. </description> </method> + <method name="get_physics_layer_collision_priority" qualifiers="const"> + <return type="float" /> + <param index="0" name="layer_index" type="int" /> + <description> + Returns the collision priority of bodies on the given TileSet's physics layer. + </description> + </method> <method name="get_physics_layer_physics_material" qualifiers="const"> <return type="PhysicsMaterial" /> <param index="0" name="layer_index" type="int" /> @@ -547,7 +554,7 @@ <param index="0" name="layer_index" type="int" /> <param index="1" name="layer" type="int" /> <description> - Sets the physics layer (as in the physics server) for bodies in the given TileSet physics layer. + Sets the collision layer (as in the physics server) for bodies in the given TileSet physics layer. </description> </method> <method name="set_physics_layer_collision_mask"> @@ -555,7 +562,15 @@ <param index="0" name="layer_index" type="int" /> <param index="1" name="mask" type="int" /> <description> - Sets the physics layer (as in the physics server) for bodies in the given TileSet physics layer. + Sets the collision mask for bodies in the given TileSet physics layer. + </description> + </method> + <method name="set_physics_layer_collision_priority"> + <return type="void" /> + <param index="0" name="layer_index" type="int" /> + <param index="1" name="priority" type="float" /> + <description> + Sets the collision priority for bodies in the given TileSet physics layer. </description> </method> <method name="set_physics_layer_physics_material"> diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml index f8f9393847..09f3dba8cf 100644 --- a/doc/classes/Timer.xml +++ b/doc/classes/Timer.xml @@ -43,6 +43,7 @@ <member name="autostart" type="bool" setter="set_autostart" getter="has_autostart" default="false"> If [code]true[/code], the timer will start immediately when it enters the scene tree. [b]Note:[/b] After the timer enters the tree, this property is automatically set to [code]false[/code]. + [b]Note:[/b] This property does nothing when the timer is running in the editor. </member> <member name="one_shot" type="bool" setter="set_one_shot" getter="is_one_shot" default="false"> If [code]true[/code], the timer will stop after reaching the end. Otherwise, as by default, the timer will automatically restart. diff --git a/doc/classes/TouchScreenButton.xml b/doc/classes/TouchScreenButton.xml index 5052518583..faeaaba5b6 100644 --- a/doc/classes/TouchScreenButton.xml +++ b/doc/classes/TouchScreenButton.xml @@ -5,7 +5,7 @@ </brief_description> <description> TouchScreenButton allows you to create on-screen buttons for touch devices. It's intended for gameplay use, such as a unit you have to touch to move. Unlike [Button], TouchScreenButton supports multitouch out of the box. Several TouchScreenButtons can be pressed at the same time with touch input. - This node inherits from [Node2D]. Unlike with [Control] nodes, you cannot set anchors on it. If you want to create menus or user interfaces, you may want to use [Button] nodes instead. To make button nodes react to touch events, you can enable the Emulate Mouse option in the Project Settings. + This node inherits from [Node2D]. Unlike with [Control] nodes, you cannot set anchors on it. If you want to create menus or user interfaces, you may want to use [Button] nodes instead. To make button nodes react to touch events, you can enable [member ProjectSettings.input_devices/pointing/emulate_mouse_from_touch] in the Project Settings. You can configure TouchScreenButton to be visible only on touch devices, helping you develop your game both for desktop and mobile devices. </description> <tutorials> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index 4158fbe710..665e5e9d67 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -20,6 +20,7 @@ <return type="Transform2D" /> <description> Constructs a [Transform2D] identical to [constant IDENTITY]. + [b]Note:[/b] In C#, this constructs a [Transform2D] with all of its components set to [constant Vector2.ZERO]. </description> </constructor> <constructor name="Transform2D"> @@ -251,14 +252,14 @@ </member> <member name="y" type="Vector2" setter="" getter="" default="Vector2(0, 1)"> The transform basis's Y axis, and the column [code]1[/code] of the matrix. Combined with [member x], this represents the transform's rotation, scale, and skew. - On the identity transform, this vector points up ([constant Vector2.UP]). + On the identity transform, this vector points down ([constant Vector2.DOWN]). </member> </members> <constants> <constant name="IDENTITY" value="Transform2D(1, 0, 0, 1, 0, 0)"> The identity [Transform2D]. A transform with no translation, no rotation, and its scale being [code]1[/code]. When multiplied by another [Variant] such as [Rect2] or another [Transform2D], no transformation occurs. This means that: - The [member x] points right ([constant Vector2.RIGHT]); - - The [member y] points up ([constant Vector2.UP]). + - The [member y] points down ([constant Vector2.DOWN]). [codeblock] var transform = Transform2D.IDENTITY print("| X | Y | Origin") diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index 30c141659a..98e9d56adb 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -21,6 +21,7 @@ <return type="Transform3D" /> <description> Constructs a [Transform3D] identical to the [constant IDENTITY]. + [b]Note:[/b] In C#, this constructs a [Transform3D] with its [member origin] and the components of its [member basis] set to [constant Vector3.ZERO]. </description> </constructor> <constructor name="Transform3D"> @@ -128,7 +129,7 @@ <param index="1" name="angle" type="float" /> <description> Returns a copy of this transform rotated around the given [param axis] by the given [param angle] (in radians). - The [param axis] must be a normalized vector. + The [param axis] must be a normalized vector in the transform's local coordinate system. For example, to rotate around the local X-axis, use [constant Vector3.RIGHT]. This method is an optimized version of multiplying the given transform [code]X[/code] with a corresponding rotation transform [code]R[/code] from the right, i.e., [code]X * R[/code]. This can be seen as transforming with respect to the local frame. </description> diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml index 69ca984f67..f30a1da014 100644 --- a/doc/classes/TranslationServer.xml +++ b/doc/classes/TranslationServer.xml @@ -160,8 +160,9 @@ <method name="standardize_locale" qualifiers="const"> <return type="String" /> <param index="0" name="locale" type="String" /> + <param index="1" name="add_defaults" type="bool" default="false" /> <description> - Returns a [param locale] string standardized to match known locales (e.g. [code]en-US[/code] would be matched to [code]en_US[/code]). + Returns a [param locale] string standardized to match known locales (e.g. [code]en-US[/code] would be matched to [code]en_US[/code]). If [param add_defaults] is [code]true[/code], the locale may have a default script or country added. </description> </method> <method name="translate" qualifiers="const"> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index b0cb25fafd..9510d237da 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -509,6 +509,12 @@ <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Text [Color] for a [constant TreeItem.CELL_MODE_CHECK] mode cell when it's non-editable (see [method TreeItem.set_editable]). </theme_item> + <theme_item name="font_hovered_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> + Text [Color] used when the item is hovered. + </theme_item> + <theme_item name="font_hovered_dimmed_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> + Text [Color] used when the item is hovered, while a button of the same item is hovered as the same time. + </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> The tint of text outline of the item. </theme_item> @@ -645,6 +651,9 @@ <theme_item name="updown" data_type="icon" type="Texture2D"> The updown arrow icon to display for the [constant TreeItem.CELL_MODE_RANGE] mode cell. </theme_item> + <theme_item name="button_hover" data_type="style" type="StyleBox"> + [StyleBox] used when a button in the tree is hovered. + </theme_item> <theme_item name="button_pressed" data_type="style" type="StyleBox"> [StyleBox] used when a button in the tree is pressed. </theme_item> @@ -666,6 +675,12 @@ <theme_item name="focus" data_type="style" type="StyleBox"> The focused style for the [Tree], drawn on top of everything. </theme_item> + <theme_item name="hovered" data_type="style" type="StyleBox"> + [StyleBox] for the item being hovered. + </theme_item> + <theme_item name="hovered_dimmed" data_type="style" type="StyleBox"> + [StyleBox] for the item being hovered, while a button of the same item is hovered as the same time. + </theme_item> <theme_item name="panel" data_type="style" type="StyleBox"> The background style for the [Tree]. </theme_item> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index 132ecc3f92..d04a6f7316 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -267,7 +267,7 @@ <method name="get_next" qualifiers="const"> <return type="TreeItem" /> <description> - Returns the next sibling TreeItem in the tree or a null object if there is none. + Returns the next sibling TreeItem in the tree or a [code]null[/code] object if there is none. </description> </method> <method name="get_next_in_tree"> @@ -289,13 +289,13 @@ <method name="get_parent" qualifiers="const"> <return type="TreeItem" /> <description> - Returns the parent TreeItem or a null object if there is none. + Returns the parent TreeItem or a [code]null[/code] object if there is none. </description> </method> <method name="get_prev"> <return type="TreeItem" /> <description> - Returns the previous sibling TreeItem in the tree or a null object if there is none. + Returns the previous sibling TreeItem in the tree or a [code]null[/code] object if there is none. </description> </method> <method name="get_prev_in_tree"> diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 86a8130acc..147d9fa4bd 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -218,8 +218,14 @@ <return type="Tween" /> <param index="0" name="ease" type="int" enum="Tween.EaseType" /> <description> - Sets the default ease type for [PropertyTweener]s and [MethodTweener]s animated by this [Tween]. - If not specified, the default value is [constant EASE_IN_OUT]. + Sets the default ease type for [PropertyTweener]s and [MethodTweener]s appended after this method. + Before this method is called, the default ease type is [constant EASE_IN_OUT]. + [codeblock] + var tween = create_tween() + tween.tween_property(self, "position", Vector2(300, 0), 0.5) # Uses EASE_IN_OUT. + tween.set_ease(Tween.EASE_IN) + tween.tween_property(self, "rotation_degrees", 45.0, 0.5) # Uses EASE_IN. + [/codeblock] </description> </method> <method name="set_loops"> @@ -271,14 +277,36 @@ <return type="Tween" /> <param index="0" name="trans" type="int" enum="Tween.TransitionType" /> <description> - Sets the default transition type for [PropertyTweener]s and [MethodTweener]s animated by this [Tween]. - If not specified, the default value is [constant TRANS_LINEAR]. + Sets the default transition type for [PropertyTweener]s and [MethodTweener]s appended after this method. + Before this method is called, the default transition type is [constant TRANS_LINEAR]. + [codeblock] + var tween = create_tween() + tween.tween_property(self, "position", Vector2(300, 0), 0.5) # Uses TRANS_LINEAR. + tween.set_trans(Tween.TRANS_SINE) + tween.tween_property(self, "rotation_degrees", 45.0, 0.5) # Uses TRANS_SINE. + [/codeblock] </description> </method> <method name="stop"> <return type="void" /> <description> Stops the tweening and resets the [Tween] to its initial state. This will not remove any appended [Tweener]s. + [b]Note:[/b] This does [i]not[/i] reset targets of [PropertyTweener]s to their values when the [Tween] first started. + [codeblock] + var tween = create_tween() + + # Will move from 0 to 500 over 1 second. + position.x = 0.0 + tween.tween_property(self, "position:x", 500, 1.0) + + # Will be at (about) 250 when the timer finishes. + await get_tree().create_timer(0.5).timeout + + # Will now move from (about) 250 to 500 over 1 second, + # thus at half the speed as before. + tween.stop() + tween.play() + [/codeblock] [b]Note:[/b] If a Tween is stopped and not bound to any node, it will exist indefinitely until manually started or invalidated. If you lose a reference to such Tween, you can retrieve it using [method SceneTree.get_processed_tweens]. </description> </method> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 78183ae36c..c03262bb33 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -424,10 +424,10 @@ </member> </members> <constants> - <constant name="AXIS_X" value="0"> + <constant name="AXIS_X" value="0" enum="Axis"> Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Y" value="1"> + <constant name="AXIS_Y" value="1" enum="Axis"> Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="ZERO" value="Vector2(0, 0)"> diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml index 4afc62e038..53c7c92ca3 100644 --- a/doc/classes/Vector2i.xml +++ b/doc/classes/Vector2i.xml @@ -170,10 +170,10 @@ </member> </members> <constants> - <constant name="AXIS_X" value="0"> + <constant name="AXIS_X" value="0" enum="Axis"> Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Y" value="1"> + <constant name="AXIS_Y" value="1" enum="Axis"> Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="ZERO" value="Vector2i(0, 0)"> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index c04fcd0b24..4ab3140eb6 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -421,13 +421,13 @@ </member> </members> <constants> - <constant name="AXIS_X" value="0"> + <constant name="AXIS_X" value="0" enum="Axis"> Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Y" value="1"> + <constant name="AXIS_Y" value="1" enum="Axis"> Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Z" value="2"> + <constant name="AXIS_Z" value="2" enum="Axis"> Enumerated value for the Z axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="ZERO" value="Vector3(0, 0, 0)"> diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index df4624dbb1..7fe469aec0 100644 --- a/doc/classes/Vector3i.xml +++ b/doc/classes/Vector3i.xml @@ -168,13 +168,13 @@ </member> </members> <constants> - <constant name="AXIS_X" value="0"> + <constant name="AXIS_X" value="0" enum="Axis"> Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Y" value="1"> + <constant name="AXIS_Y" value="1" enum="Axis"> Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Z" value="2"> + <constant name="AXIS_Z" value="2" enum="Axis"> Enumerated value for the Z axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="ZERO" value="Vector3i(0, 0, 0)"> diff --git a/doc/classes/Vector4.xml b/doc/classes/Vector4.xml index f70c59fbef..8fa17b57e6 100644 --- a/doc/classes/Vector4.xml +++ b/doc/classes/Vector4.xml @@ -287,16 +287,16 @@ </member> </members> <constants> - <constant name="AXIS_X" value="0"> + <constant name="AXIS_X" value="0" enum="Axis"> Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Y" value="1"> + <constant name="AXIS_Y" value="1" enum="Axis"> Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Z" value="2"> + <constant name="AXIS_Z" value="2" enum="Axis"> Enumerated value for the Z axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_W" value="3"> + <constant name="AXIS_W" value="3" enum="Axis"> Enumerated value for the W axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="ZERO" value="Vector4(0, 0, 0, 0)"> diff --git a/doc/classes/Vector4i.xml b/doc/classes/Vector4i.xml index b351f2ccb6..e1d65eb1b5 100644 --- a/doc/classes/Vector4i.xml +++ b/doc/classes/Vector4i.xml @@ -169,16 +169,16 @@ </member> </members> <constants> - <constant name="AXIS_X" value="0"> + <constant name="AXIS_X" value="0" enum="Axis"> Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Y" value="1"> + <constant name="AXIS_Y" value="1" enum="Axis"> Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_Z" value="2"> + <constant name="AXIS_Z" value="2" enum="Axis"> Enumerated value for the Z axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> - <constant name="AXIS_W" value="3"> + <constant name="AXIS_W" value="3" enum="Axis"> Enumerated value for the W axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="ZERO" value="Vector4i(0, 0, 0, 0)"> diff --git a/doc/classes/VideoStreamPlayback.xml b/doc/classes/VideoStreamPlayback.xml index 8b4a7f8d29..17e29ae337 100644 --- a/doc/classes/VideoStreamPlayback.xml +++ b/doc/classes/VideoStreamPlayback.xml @@ -54,7 +54,7 @@ <method name="_play" qualifiers="virtual"> <return type="void" /> <description> - Called in response to [member VideoStreamPlayer.autoplay] or [method VideoStreamPlayer.play]. Note that manual playback may also invoke [method _stop] multiple times before this method is called. [method _is_playing] should return true once playing. + Called in response to [member VideoStreamPlayer.autoplay] or [method VideoStreamPlayer.play]. Note that manual playback may also invoke [method _stop] multiple times before this method is called. [method _is_playing] should return [code]true[/code] once playing. </description> </method> <method name="_seek" qualifiers="virtual"> @@ -81,14 +81,14 @@ <method name="_stop" qualifiers="virtual"> <return type="void" /> <description> - Stops playback. May be called multiple times before [method _play], or in response to [method VideoStreamPlayer.stop]. [method _is_playing] should return false once stopped. + Stops playback. May be called multiple times before [method _play], or in response to [method VideoStreamPlayer.stop]. [method _is_playing] should return [code]false[/code] once stopped. </description> </method> <method name="_update" qualifiers="virtual"> <return type="void" /> <param index="0" name="delta" type="float" /> <description> - Ticks video playback for [param delta] seconds. Called every frame as long as [method _is_paused] and [method _is_playing] return true. + Ticks video playback for [param delta] seconds. Called every frame as long as both [method _is_paused] and [method _is_playing] return [code]true[/code]. </description> </method> <method name="mix_audio"> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 333e61d03f..678b7690d9 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -48,7 +48,7 @@ <method name="get_camera_2d" qualifiers="const"> <return type="Camera2D" /> <description> - Returns the currently active 2D camera. Returns null if there are no active cameras. + Returns the currently active 2D camera. Returns [code]null[/code] if there are no active cameras. </description> </method> <method name="get_camera_3d" qualifiers="const"> @@ -144,13 +144,13 @@ <method name="gui_get_focus_owner" qualifiers="const"> <return type="Control" /> <description> - Returns the [Control] having the focus within this viewport. If no [Control] has the focus, returns null. + Returns the currently focused [Control] within this viewport. If no [Control] is focused, returns [code]null[/code]. </description> </method> <method name="gui_get_hovered_control" qualifiers="const"> <return type="Control" /> <description> - Returns the [Control] that the mouse is currently hovering over in this viewport. If no [Control] has the cursor, returns null. + Returns the [Control] that the mouse is currently hovering over in this viewport. If no [Control] has the cursor, returns [code]null[/code]. Typically the leaf [Control] node or deepest level of the subtree which claims hover. This is very useful when used together with [method Node.is_ancestor_of] to find if the mouse is within a control tree. </description> </method> @@ -316,7 +316,7 @@ See also [member ProjectSettings.rendering/anti_aliasing/quality/msaa_2d] and [method RenderingServer.viewport_set_msaa_2d]. </member> <member name="msaa_3d" type="int" setter="set_msaa_3d" getter="get_msaa_3d" enum="Viewport.MSAA" default="0"> - The multisample antialiasing mode for 3D rendering. A higher number results in smoother edges at the cost of significantly worse performance. A value of [constant Viewport.MSAA_2X] or [constant Viewport.MSAA_4X] is best unless targeting very high-end systems. See also bilinear scaling 3d [member scaling_3d_mode] for supersampling, which provides higher quality but is much more expensive. This has no effect on shader-induced aliasing or texture aliasing. + The multisample antialiasing mode for 3D rendering. A higher number results in smoother edges at the cost of significantly worse performance. A value of [constant Viewport.MSAA_2X] or [constant Viewport.MSAA_4X] is best unless targeting very high-end systems. See also bilinear scaling 3D [member scaling_3d_mode] for supersampling, which provides higher quality but is much more expensive. This has no effect on shader-induced aliasing or texture aliasing. See also [member ProjectSettings.rendering/anti_aliasing/quality/msaa_3d] and [method RenderingServer.viewport_set_msaa_3d]. </member> <member name="own_world_3d" type="bool" setter="set_use_own_world_3d" getter="is_using_own_world_3d" default="false"> @@ -357,7 +357,7 @@ [b]Note:[/b] If this is set to [code]0[/code], no positional shadows will be visible at all. This can improve performance significantly on low-end systems by reducing both the CPU and GPU load (as fewer draw calls are needed to draw the scene without shadows). </member> <member name="scaling_3d_mode" type="int" setter="set_scaling_3d_mode" getter="get_scaling_3d_mode" enum="Viewport.Scaling3DMode" default="0"> - Sets scaling 3d mode. Bilinear scaling renders at different resolution to either undersample or supersample the viewport. FidelityFX Super Resolution 1.0, abbreviated to FSR, is an upscaling technology that produces high quality images at fast framerates by using a spatially aware upscaling algorithm. FSR is slightly more expensive than bilinear, but it produces significantly higher image quality. FSR should be used where possible. + Sets scaling 3D mode. Bilinear scaling renders at different resolution to either undersample or supersample the viewport. FidelityFX Super Resolution 1.0, abbreviated to FSR, is an upscaling technology that produces high quality images at fast framerates by using a spatially aware upscaling algorithm. FSR is slightly more expensive than bilinear, but it produces significantly higher image quality. FSR should be used where possible. To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/mode] project setting. </member> <member name="scaling_3d_scale" type="float" setter="set_scaling_3d_scale" getter="get_scaling_3d_scale" default="1.0"> @@ -555,6 +555,7 @@ </constant> <constant name="DEBUG_DRAW_WIREFRAME" value="4" enum="DebugDraw"> Objects are displayed as wireframe models. + [b]Note:[/b] [method RenderingServer.set_debug_generate_wireframes] must be called before loading any meshes for wireframes to be visible when using the Compatibility renderer. </constant> <constant name="DEBUG_DRAW_NORMAL_BUFFER" value="5" enum="DebugDraw"> Objects are displayed without lighting information and their textures replaced by normal mapping. diff --git a/doc/classes/VisualShaderNodeColorFunc.xml b/doc/classes/VisualShaderNodeColorFunc.xml index edb5238325..aa2dcca1d5 100644 --- a/doc/classes/VisualShaderNodeColorFunc.xml +++ b/doc/classes/VisualShaderNodeColorFunc.xml @@ -40,7 +40,32 @@ return vec3(r, g, b); [/codeblock] </constant> - <constant name="FUNC_MAX" value="4" enum="Function"> + <constant name="FUNC_LINEAR_TO_SRGB" value="4" enum="Function"> + Converts color from linear color space to sRGB color space using the following formula: + [codeblock] + vec3 c = clamp(c, vec3(0.0), vec3(1.0)); + const vec3 a = vec3(0.055f); + return mix((vec3(1.0f) + a) * pow(c.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * c.rgb, lessThan(c.rgb, vec3(0.0031308f))); + [/codeblock] + The Compatibility renderer uses a simpler formula: + [codeblock] + vec3 c = input; + return max(vec3(1.055) * pow(c, vec3(0.416666667)) - vec3(0.055), vec3(0.0)); + [/codeblock] + </constant> + <constant name="FUNC_SRGB_TO_LINEAR" value="5" enum="Function"> + Converts color from sRGB color space to linear color space using the following formula: + [codeblock] + vec3 c = input; + return mix(pow((c.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), c.rgb * (1.0 / 12.92), lessThan(c.rgb, vec3(0.04045))); + [/codeblock] + The Compatibility renderer uses a simpler formula: + [codeblock] + vec3 c = input; + return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); + [/codeblock] + </constant> + <constant name="FUNC_MAX" value="6" enum="Function"> Represents the size of the [enum Function] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeCompare.xml b/doc/classes/VisualShaderNodeCompare.xml index b566ca62f3..9f554dacb4 100644 --- a/doc/classes/VisualShaderNodeCompare.xml +++ b/doc/classes/VisualShaderNodeCompare.xml @@ -69,10 +69,10 @@ Represents the size of the [enum Function] enum. </constant> <constant name="COND_ALL" value="0" enum="Condition"> - The result will be true if all of component in vector satisfy the comparison condition. + The result will be [code]true[/code] if all components in the vector satisfy the comparison condition. </constant> <constant name="COND_ANY" value="1" enum="Condition"> - The result will be true if any of component in vector satisfy the comparison condition. + The result will be [code]true[/code] if any component in the vector satisfies the comparison condition. </constant> <constant name="COND_MAX" value="2" enum="Condition"> Represents the size of the [enum Condition] enum. diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index ca155881c8..424941b842 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -659,6 +659,11 @@ If [member ProjectSettings.display/window/subwindows/embed_subwindows] is [code]false[/code], the position is in absolute screen coordinates. This typically applies to editor plugins. If the setting is [code]true[/code], the window's position is in the coordinates of its parent [Viewport]. [b]Note:[/b] This property only works if [member initial_position] is set to [constant WINDOW_INITIAL_POSITION_ABSOLUTE]. </member> + <member name="sharp_corners" type="bool" setter="set_flag" getter="get_flag" default="false"> + If [code]true[/code], the [Window] will override the OS window style to display sharp corners. + [b]Note:[/b] This property is implemented only on Windows (11). + [b]Note:[/b] This property only works with native windows. + </member> <member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i(100, 100)"> The window's size in pixels. </member> @@ -720,8 +725,6 @@ <param index="0" name="files" type="PackedStringArray" /> <description> Emitted when files are dragged from the OS file manager and dropped in the game window. The argument is a list of file paths. - Note that this method only works with native windows, i.e. the main window and [Window]-derived nodes when [member Viewport.gui_embed_subwindows] is disabled in the main viewport. - Example usage: [codeblock] func _ready(): get_viewport().files_dropped.connect(on_files_dropped) @@ -729,6 +732,7 @@ func on_files_dropped(files): print(files) [/codeblock] + [b]Note:[/b] This signal only works with native windows, i.e. the main window and [Window]-derived nodes when [member Viewport.gui_embed_subwindows] is disabled in the main viewport. </description> </signal> <signal name="focus_entered"> @@ -842,7 +846,12 @@ All mouse events are passed to the underlying window of the same application. [b]Note:[/b] This flag has no effect in embedded windows. </constant> - <constant name="FLAG_MAX" value="8" enum="Flags"> + <constant name="FLAG_SHARP_CORNERS" value="8" enum="Flags"> + Window style is overridden, forcing sharp corners. + [b]Note:[/b] This flag has no effect in embedded windows. + [b]Note:[/b] This flag is implemented only on Windows (11). + </constant> + <constant name="FLAG_MAX" value="9" enum="Flags"> Max value of the [enum Flags]. </constant> <constant name="CONTENT_SCALE_MODE_DISABLED" value="0" enum="ContentScaleMode"> @@ -878,7 +887,7 @@ <constant name="LAYOUT_DIRECTION_INHERITED" value="0" enum="LayoutDirection"> Automatic layout direction, determined from the parent window layout direction. </constant> - <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection"> + <constant name="LAYOUT_DIRECTION_APPLICATION_LOCALE" value="1" enum="LayoutDirection"> Automatic layout direction, determined from the current locale. </constant> <constant name="LAYOUT_DIRECTION_LTR" value="2" enum="LayoutDirection"> @@ -887,6 +896,14 @@ <constant name="LAYOUT_DIRECTION_RTL" value="3" enum="LayoutDirection"> Right-to-left layout direction. </constant> + <constant name="LAYOUT_DIRECTION_SYSTEM_LOCALE" value="4" enum="LayoutDirection"> + Automatic layout direction, determined from the system locale. + </constant> + <constant name="LAYOUT_DIRECTION_MAX" value="5" enum="LayoutDirection"> + Represents the size of the [enum LayoutDirection] enum. + </constant> + <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection" deprecated="Use [constant LAYOUT_DIRECTION_APPLICATION_LOCALE] instead."> + </constant> <constant name="WINDOW_INITIAL_POSITION_ABSOLUTE" value="0" enum="WindowInitialPosition"> Initial window position is determined by [member position]. </constant> diff --git a/doc/classes/XRCamera3D.xml b/doc/classes/XRCamera3D.xml index a7904b3ada..e49e884f33 100644 --- a/doc/classes/XRCamera3D.xml +++ b/doc/classes/XRCamera3D.xml @@ -4,7 +4,7 @@ A camera node with a few overrules for AR/VR applied, such as location tracking. </brief_description> <description> - This is a helper spatial node for our camera; note that, if stereoscopic rendering is applicable (VR-HMD), most of the camera properties are ignored, as the HMD information overrides them. The only properties that can be trusted are the near and far planes. + This is a helper 3D node for our camera. Note that, if stereoscopic rendering is applicable (VR-HMD), most of the camera properties are ignored, as the HMD information overrides them. The only properties that can be trusted are the near and far planes. The position and orientation of this node is automatically updated by the XR Server to represent the location of the HMD if such tracking is available and can thus be used by game logic. Note that, in contrast to the XR Controller, the render thread has access to the most up-to-date tracking data of the HMD and the location of the XRCamera3D can lag a few milliseconds behind what is used for rendering as a result. </description> <tutorials> diff --git a/doc/classes/XRController3D.xml b/doc/classes/XRController3D.xml index 8a068661c9..508752e0ae 100644 --- a/doc/classes/XRController3D.xml +++ b/doc/classes/XRController3D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="XRController3D" inherits="XRNode3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - A spatial node representing a spatially-tracked controller. + A 3D node representing a spatially-tracked controller. </brief_description> <description> - This is a helper spatial node that is linked to the tracking of controllers. It also offers several handy passthroughs to the state of buttons and such on the controllers. + This is a helper 3D node that is linked to the tracking of controllers. It also offers several handy passthroughs to the state of buttons and such on the controllers. Controllers are linked by their ID. You can create controller nodes before the controllers are available. If your game always uses two controllers (one for each hand), you can predefine the controllers with ID 1 and 2; they will become active as soon as the controllers are identified. If you expect additional controllers to be used, you should react to the signals and add XRController3D nodes to your scene. The position of the controller node is automatically updated by the [XRServer]. This makes this node ideal to add child nodes to visualize the controller. As many XR runtimes now use a configurable action map all inputs are named. diff --git a/doc/classes/XRNode3D.xml b/doc/classes/XRNode3D.xml index 82f4fa4ab9..fce3708d9a 100644 --- a/doc/classes/XRNode3D.xml +++ b/doc/classes/XRNode3D.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="XRNode3D" inherits="Node3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - A spatial node that has its position automatically updated by the [XRServer]. + A 3D node that has its position automatically updated by the [XRServer]. </brief_description> <description> This node can be bound to a specific pose of a [XRPositionalTracker] and will automatically have its [member Node3D.transform] updated by the [XRServer]. Nodes of this type must be added as children of the [XROrigin3D] node. diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index e1a6aa4a98..38e3edef2f 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -1555,9 +1555,7 @@ def make_enum(t: str, is_bitfield: bool, state: State) -> str: else: return f":ref:`{e}<enum_{c}_{e}>`" - # Don't fail for `Vector3.Axis`, as this enum is a special case which is expected not to be resolved. - if f"{c}.{e}" != "Vector3.Axis": - print_error(f'{state.current_class}.xml: Unresolved enum "{t}".', state) + print_error(f'{state.current_class}.xml: Unresolved enum "{t}".', state) return t diff --git a/drivers/SCsub b/drivers/SCsub index e0bfa138f5..03ad70649b 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -14,7 +14,8 @@ SConscript("windows/SCsub") # Sounds drivers SConscript("alsa/SCsub") -SConscript("coreaudio/SCsub") +if env["platform"] == "ios" or env["platform"] == "macos": + SConscript("coreaudio/SCsub") SConscript("pulseaudio/SCsub") if env["platform"] == "windows": SConscript("wasapi/SCsub") diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 0c9635339b..6ee22b6eb5 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -80,7 +80,7 @@ Error AudioDriverALSA::init_output_device() { status = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); } else { String device = output_device_name; - int pos = device.find(";"); + int pos = device.find_char(';'); if (pos != -1) { device = device.substr(0, pos); } diff --git a/drivers/coreaudio/SCsub b/drivers/coreaudio/SCsub index 69d667c57b..83ac27f4b6 100644 --- a/drivers/coreaudio/SCsub +++ b/drivers/coreaudio/SCsub @@ -4,4 +4,4 @@ from misc.utility.scons_hints import * Import("env") # Driver source files -env.add_source_files(env.drivers_sources, "*.cpp") +env.add_source_files(env.drivers_sources, "*.mm") diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index 67ff3f3efc..54e02514ec 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -38,6 +38,8 @@ #import <AudioUnit/AudioUnit.h> #ifdef MACOS_ENABLED #import <CoreAudio/AudioHardware.h> +#else +#import <AVFoundation/AVFoundation.h> #endif class AudioDriverCoreAudio : public AudioDriver { @@ -51,9 +53,11 @@ class AudioDriverCoreAudio : public AudioDriver { String input_device_name = "Default"; int mix_rate = 0; + int capture_mix_rate = 0; unsigned int channels = 2; unsigned int capture_channels = 2; unsigned int buffer_frames = 0; + unsigned int capture_buffer_frames = 0; Vector<int32_t> samples_in; Vector<int16_t> input_buf; @@ -89,11 +93,12 @@ class AudioDriverCoreAudio : public AudioDriver { public: virtual const char *get_name() const override { return "CoreAudio"; - }; + } virtual Error init() override; virtual void start() override; virtual int get_mix_rate() const override; + virtual int get_input_mix_rate() const override; virtual SpeakerMode get_speaker_mode() const override; virtual void lock() override; diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.mm index fd0adb1fd1..4e6ff2edb3 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.mm @@ -1,5 +1,5 @@ /**************************************************************************/ -/* audio_driver_coreaudio.cpp */ +/* audio_driver_coreaudio.mm */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -121,7 +121,24 @@ Error AudioDriverCoreAudio::init() { break; } - mix_rate = _get_configured_mix_rate(); +#ifdef MACOS_ENABLED + AudioDeviceID device_id; + UInt32 dev_id_size = sizeof(AudioDeviceID); + + AudioObjectPropertyAddress property_dev_id = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property_dev_id, 0, nullptr, &dev_id_size, &device_id); + ERR_FAIL_COND_V(result != noErr, FAILED); + + double hw_mix_rate; + UInt32 hw_mix_rate_size = sizeof(hw_mix_rate); + + AudioObjectPropertyAddress property_sr = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain }; + result = AudioObjectGetPropertyData(device_id, &property_sr, 0, nullptr, &hw_mix_rate_size, &hw_mix_rate); + ERR_FAIL_COND_V(result != noErr, FAILED); +#else + double hw_mix_rate = [AVAudioSession sharedInstance].sampleRate; +#endif + mix_rate = hw_mix_rate; memset(&strdesc, 0, sizeof(strdesc)); strdesc.mFormatID = kAudioFormatLinearPCM; @@ -147,10 +164,10 @@ Error AudioDriverCoreAudio::init() { unsigned int buffer_size = buffer_frames * channels; samples_in.resize(buffer_size); - input_buf.resize(buffer_size); print_verbose("CoreAudio: detected " + itos(channels) + " channels"); - print_verbose("CoreAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); + print_verbose("CoreAudio: output sampling rate: " + itos(mix_rate) + " Hz"); + print_verbose("CoreAudio: output audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); AURenderCallbackStruct callback; memset(&callback, 0, sizeof(AURenderCallbackStruct)); @@ -250,7 +267,7 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon, } void AudioDriverCoreAudio::start() { - if (!active) { + if (!active && audio_unit != nullptr) { OSStatus result = AudioOutputUnitStart(audio_unit); if (result != noErr) { ERR_PRINT("AudioOutputUnitStart failed, code: " + itos(result)); @@ -275,6 +292,10 @@ int AudioDriverCoreAudio::get_mix_rate() const { return mix_rate; } +int AudioDriverCoreAudio::get_input_mix_rate() const { + return capture_mix_rate; +} + AudioDriver::SpeakerMode AudioDriverCoreAudio::get_speaker_mode() const { return get_speaker_mode_by_total_channels(channels); } @@ -378,14 +399,14 @@ Error AudioDriverCoreAudio::init_input_device() { UInt32 size; #ifdef MACOS_ENABLED - AudioDeviceID deviceId; + AudioDeviceID device_id; size = sizeof(AudioDeviceID); AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain }; - result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, nullptr, &size, &deviceId); + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, nullptr, &size, &device_id); ERR_FAIL_COND_V(result != noErr, FAILED); - result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &device_id, sizeof(AudioDeviceID)); ERR_FAIL_COND_V(result != noErr, FAILED); #endif @@ -410,13 +431,23 @@ Error AudioDriverCoreAudio::init_input_device() { break; } - mix_rate = _get_configured_mix_rate(); +#ifdef MACOS_ENABLED + double hw_mix_rate; + UInt32 hw_mix_rate_size = sizeof(hw_mix_rate); + + AudioObjectPropertyAddress property_sr = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain }; + result = AudioObjectGetPropertyData(device_id, &property_sr, 0, nullptr, &hw_mix_rate_size, &hw_mix_rate); + ERR_FAIL_COND_V(result != noErr, FAILED); +#else + double hw_mix_rate = [AVAudioSession sharedInstance].sampleRate; +#endif + capture_mix_rate = hw_mix_rate; memset(&strdesc, 0, sizeof(strdesc)); strdesc.mFormatID = kAudioFormatLinearPCM; strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; strdesc.mChannelsPerFrame = capture_channels; - strdesc.mSampleRate = mix_rate; + strdesc.mSampleRate = capture_mix_rate; strdesc.mFramesPerPacket = 1; strdesc.mBitsPerChannel = 16; strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; @@ -425,6 +456,13 @@ Error AudioDriverCoreAudio::init_input_device() { result = AudioUnitSetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); ERR_FAIL_COND_V(result != noErr, FAILED); + int latency = Engine::get_singleton()->get_audio_output_latency(); + // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) + capture_buffer_frames = closest_power_of_2(latency * capture_mix_rate / 1000); + + unsigned int buffer_size = capture_buffer_frames * capture_channels; + input_buf.resize(buffer_size); + AURenderCallbackStruct callback; memset(&callback, 0, sizeof(AURenderCallbackStruct)); callback.inputProc = &AudioDriverCoreAudio::input_callback; @@ -435,6 +473,9 @@ Error AudioDriverCoreAudio::init_input_device() { result = AudioUnitInitialize(input_unit); ERR_FAIL_COND_V(result != noErr, FAILED); + print_verbose("CoreAudio: input sampling rate: " + itos(capture_mix_rate) + " Hz"); + print_verbose("CoreAudio: input audio buffer frames: " + itos(capture_buffer_frames) + " calculated latency: " + itos(capture_buffer_frames * 1000 / capture_mix_rate) + "ms"); + return OK; } @@ -477,7 +518,7 @@ void AudioDriverCoreAudio::finish_input_device() { } Error AudioDriverCoreAudio::input_start() { - input_buffer_init(buffer_frames); + input_buffer_init(capture_buffer_frames); OSStatus result = AudioOutputUnitStart(input_unit); if (result != noErr) { @@ -561,7 +602,7 @@ PackedStringArray AudioDriverCoreAudio::_get_device_list(bool input) { } void AudioDriverCoreAudio::_set_device(const String &output_device, bool input) { - AudioDeviceID deviceId; + AudioDeviceID device_id; bool found = false; if (output_device != "Default") { AudioObjectPropertyAddress prop; @@ -608,7 +649,7 @@ void AudioDriverCoreAudio::_set_device(const String &output_device, bool input) if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) { String name = String::utf8(buffer) + " (" + itos(audioDevices[i]) + ")"; if (name == output_device) { - deviceId = audioDevices[i]; + device_id = audioDevices[i]; found = true; } } @@ -626,14 +667,14 @@ void AudioDriverCoreAudio::_set_device(const String &output_device, bool input) UInt32 elem = input ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice; AudioObjectPropertyAddress property = { elem, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain }; - OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, nullptr, &size, &deviceId); + OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, nullptr, &size, &device_id); ERR_FAIL_COND(result != noErr); found = true; } if (found) { - OSStatus result = AudioUnitSetProperty(input ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); + OSStatus result = AudioUnitSetProperty(input ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &device_id, sizeof(AudioDeviceID)); ERR_FAIL_COND(result != noErr); if (input) { diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp index 479afbba93..0b1b0651c8 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -2160,6 +2160,7 @@ RDD::FenceID RenderingDeviceDriverD3D12::fence_create() { Error RenderingDeviceDriverD3D12::fence_wait(FenceID p_fence) { FenceInfo *fence = (FenceInfo *)(p_fence.id); + fence->d3d_fence->SetEventOnCompletion(fence->fence_value, fence->event_handle); DWORD res = WaitForSingleObjectEx(fence->event_handle, INFINITE, FALSE); #ifdef PIX_ENABLED PIXNotifyWakeFromFenceSignal(fence->event_handle); @@ -2254,7 +2255,6 @@ Error RenderingDeviceDriverD3D12::command_queue_execute_and_present(CommandQueue FenceInfo *fence = (FenceInfo *)(p_cmd_fence.id); fence->fence_value++; command_queue->d3d_queue->Signal(fence->d3d_fence.Get(), fence->fence_value); - fence->d3d_fence->SetEventOnCompletion(fence->fence_value, fence->event_handle); } } @@ -2461,8 +2461,6 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue, break; } - print_verbose("Using swap chain flags: " + itos(creation_flags) + ", sync interval: " + itos(sync_interval) + ", present flags: " + itos(present_flags)); - if (swap_chain->d3d_swap_chain != nullptr && creation_flags != swap_chain->creation_flags) { // The swap chain must be recreated if the creation flags are different. _swap_chain_release(swap_chain); @@ -6179,6 +6177,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) { return false; case API_TRAIT_USE_GENERAL_IN_COPY_QUEUES: return true; + case API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS: + return !barrier_capabilities.enhanced_barriers_supported; default: return RenderingDeviceDriver::api_trait_get(p_trait); } @@ -6585,7 +6585,7 @@ static Error create_command_signature(ID3D12Device *device, D3D12_INDIRECT_ARGUM HRESULT res = device->CreateCommandSignature(&cs_desc, nullptr, IID_PPV_ARGS(r_cmd_sig->GetAddressOf())); ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "CreateCommandSignature failed with error " + vformat("0x%08ux", (uint64_t)res) + "."); return OK; -}; +} Error RenderingDeviceDriverD3D12::_initialize_frames(uint32_t p_frame_count) { Error err; diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp index 603dfadd4b..8ca0aa5943 100644 --- a/drivers/egl/egl_manager.cpp +++ b/drivers/egl/egl_manager.cpp @@ -414,6 +414,30 @@ EGLContext EGLManager::get_context(DisplayServer::WindowID p_window_id) { return display.egl_context; } +EGLDisplay EGLManager::get_display(DisplayServer::WindowID p_window_id) { + GLWindow &glwindow = windows[p_window_id]; + + if (!glwindow.initialized) { + return EGL_NO_CONTEXT; + } + + GLDisplay &display = displays[glwindow.gldisplay_id]; + + return display.egl_display; +} + +EGLConfig EGLManager::get_config(DisplayServer::WindowID p_window_id) { + GLWindow &glwindow = windows[p_window_id]; + + if (!glwindow.initialized) { + return nullptr; + } + + GLDisplay &display = displays[glwindow.gldisplay_id]; + + return display.egl_config; +} + Error EGLManager::initialize(void *p_native_display) { #if defined(GLAD_ENABLED) && !defined(EGL_STATIC) // Loading EGL with a new display gets us just the bare minimum API. We'll then diff --git a/drivers/egl/egl_manager.h b/drivers/egl/egl_manager.h index f1b3dc99b7..2e1ae6ec53 100644 --- a/drivers/egl/egl_manager.h +++ b/drivers/egl/egl_manager.h @@ -113,6 +113,8 @@ public: bool is_using_vsync() const; EGLContext get_context(DisplayServer::WindowID p_window_id); + EGLDisplay get_display(DisplayServer::WindowID p_window_id); + EGLConfig get_config(DisplayServer::WindowID p_window_id); Error initialize(void *p_native_display = nullptr); diff --git a/drivers/gles3/effects/feed_effects.cpp b/drivers/gles3/effects/feed_effects.cpp new file mode 100644 index 0000000000..8ca88da662 --- /dev/null +++ b/drivers/gles3/effects/feed_effects.cpp @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* feed_effects.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 GLES3_ENABLED + +#include "feed_effects.h" + +#ifdef ANDROID_ENABLED +#include <GLES3/gl3ext.h> +#endif + +#define GL_PROGRAM_POINT_SIZE 0x8642 + +using namespace GLES3; + +FeedEffects *FeedEffects::singleton = nullptr; + +FeedEffects *FeedEffects::get_singleton() { + return singleton; +} + +FeedEffects::FeedEffects() { + singleton = this; + + feed.shader.initialize(); + feed.shader_version = feed.shader.version_create(); + feed.shader.version_bind_shader(feed.shader_version, FeedShaderGLES3::MODE_DEFAULT); + + { // Screen Triangle. + glGenBuffers(1, &screen_triangle); + glBindBuffer(GL_ARRAY_BUFFER, screen_triangle); + + const float qv[6] = { + -1.0f, + -1.0f, + 3.0f, + -1.0f, + -1.0f, + 3.0f, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, qv, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + + glGenVertexArrays(1, &screen_triangle_array); + glBindVertexArray(screen_triangle_array); + glBindBuffer(GL_ARRAY_BUFFER, screen_triangle); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + } +} + +FeedEffects::~FeedEffects() { + singleton = nullptr; + glDeleteBuffers(1, &screen_triangle); + glDeleteVertexArrays(1, &screen_triangle_array); + feed.shader.version_free(feed.shader_version); +} + +Transform3D transform3D_from_mat4(const float *p_mat4) { + Transform3D res; + + res.basis.rows[0][0] = p_mat4[0]; + res.basis.rows[1][0] = p_mat4[1]; + res.basis.rows[2][0] = p_mat4[2]; + // p_mat4[3] = 0; + res.basis.rows[0][1] = p_mat4[4]; + res.basis.rows[1][1] = p_mat4[5]; + res.basis.rows[2][1] = p_mat4[6]; + // p_mat4[7] = 0; + res.basis.rows[0][2] = p_mat4[8]; + res.basis.rows[1][2] = p_mat4[9]; + res.basis.rows[2][2] = p_mat4[10]; + // p_mat4[11] = 0; + res.origin.x = p_mat4[12]; + res.origin.y = p_mat4[13]; + res.origin.z = p_mat4[14]; + // p_mat4[15] = 1; + + return res; +} + +void FeedEffects::draw() { + bool success = feed.shader.version_bind_shader(feed.shader_version, FeedShaderGLES3::MODE_DEFAULT, FeedShaderGLES3::USE_EXTERNAL_SAMPLER); + if (!success) { + OS::get_singleton()->print("Godot : FeedShaderGLES3 Could not bind version_bind_shader USE_EXTERNAL_SAMPLER"); + return; + } + + draw_screen_triangle(); +} + +void FeedEffects::draw_screen_triangle() { + glBindVertexArray(screen_triangle_array); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/effects/feed_effects.h b/drivers/gles3/effects/feed_effects.h new file mode 100644 index 0000000000..5856a3e04b --- /dev/null +++ b/drivers/gles3/effects/feed_effects.h @@ -0,0 +1,68 @@ +/**************************************************************************/ +/* feed_effects.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef FEED_EFFECTS_GLES3_H +#define FEED_EFFECTS_GLES3_H + +#ifdef GLES3_ENABLED + +#include "drivers/gles3/shaders/feed.glsl.gen.h" + +namespace GLES3 { + +class FeedEffects { +private: + struct Feed { + FeedShaderGLES3 shader; + RID shader_version; + } feed; + + static FeedEffects *singleton; + + GLuint screen_triangle = 0; + GLuint screen_triangle_array = 0; + +public: + static FeedEffects *get_singleton(); + + FeedEffects(); + ~FeedEffects(); + + void draw(); + +private: + void draw_screen_triangle(); +}; + +} // namespace GLES3 + +#endif // GLES3_ENABLED + +#endif // FEED_EFFECTS_GLES3_H diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 3c959f0143..5fd90744a4 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -687,6 +687,8 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou state.current_tex = RID(); + const uint64_t base_specialization = GLES3::Config::get_singleton()->float_texture_supported ? 0 : CanvasShaderGLES3::USE_RGBA_SHADOWS; + for (uint32_t i = 0; i <= state.current_batch_index; i++) { // Skipping when there is no instances. if (state.canvas_instance_batches[i].instance_count == 0) { @@ -705,10 +707,9 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } GLES3::CanvasMaterialData *material_data = state.canvas_instance_batches[i].material_data; - CanvasShaderGLES3::ShaderVariant variant = state.canvas_instance_batches[i].shader_variant; - uint64_t specialization = 0; - specialization |= uint64_t(state.canvas_instance_batches[i].lights_disabled); - specialization |= uint64_t(!GLES3::Config::get_singleton()->float_texture_supported) << 1; + CanvasShaderGLES3::ShaderVariant variant = CanvasShaderGLES3::MODE_DEFAULT; + uint64_t specialization = state.canvas_instance_batches[i].specialization; + specialization |= base_specialization; RID shader_version = data.canvas_shader_default_version; if (material_data) { @@ -719,11 +720,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } } - bool success = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization); + bool success = material_storage->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization); if (!success) { continue; } + // Bind per-batch uniforms. + material_storage->shaders.canvas_shader.version_set_uniform(CanvasShaderGLES3::BATCH_FLAGS, state.canvas_instance_batches[i].flags, shader_version, variant, specialization); + GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode; Color blend_color = state.canvas_instance_batches[i].blend_color; @@ -810,6 +814,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, const Point2 &p_repeat_offset) { RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter; + const uint64_t specialization_command_mask = ~(CanvasShaderGLES3::USE_NINEPATCH | CanvasShaderGLES3::USE_PRIMITIVE | CanvasShaderGLES3::USE_ATTRIBUTES | CanvasShaderGLES3::USE_INSTANCING); if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) { _new_batch(r_batch_broken); @@ -845,6 +850,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend uint32_t lights[4] = { 0, 0, 0, 0 }; uint16_t light_count = 0; + uint16_t shadow_mask = 0; { Light *light = p_lights; @@ -854,6 +860,10 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend uint32_t light_index = light->render_index_cache; lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + if (p_item->light_mask & light->item_shadow_mask) { + shadow_mask |= 1 << light_count; + } + light_count++; if (light_count == data.max_lights_per_item - 1) { @@ -863,14 +873,15 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend light = light->next_ptr; } - base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= light_count << INSTANCE_FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= shadow_mask << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT; } bool lights_disabled = light_count == 0 && !state.using_directional_lights; - if (lights_disabled != state.canvas_instance_batches[state.current_batch_index].lights_disabled) { + if (lights_disabled != bool(state.canvas_instance_batches[state.current_batch_index].specialization & CanvasShaderGLES3::DISABLE_LIGHTING)) { _new_batch(r_batch_broken); - state.canvas_instance_batches[state.current_batch_index].lights_disabled = lights_disabled; + state.canvas_instance_batches[state.current_batch_index].specialization ^= CanvasShaderGLES3::DISABLE_LIGHTING; } const Item::Command *c = p_item->commands; @@ -904,7 +915,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.instance_data_array[r_index].lights[2] = lights[2]; state.instance_data_array[r_index].lights[3] = lights[3]; - state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); // Reset on each command for safety, keep canvastexture binding config. + state.instance_data_array[r_index].flags = base_flags; Color blend_color = base_color; GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode; @@ -936,7 +947,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].tex = rect->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_RECT; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_QUAD; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].flags = 0; } _prepare_canvas_texture(rect->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -959,20 +971,18 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend if (rect->flags & CANVAS_RECT_FLIP_H) { src_rect.size.x *= -1; - state.instance_data_array[r_index].flags |= FLAGS_FLIP_H; } if (rect->flags & CANVAS_RECT_FLIP_V) { src_rect.size.y *= -1; - state.instance_data_array[r_index].flags |= FLAGS_FLIP_V; } if (rect->flags & CANVAS_RECT_TRANSPOSE) { - state.instance_data_array[r_index].flags |= FLAGS_TRANSPOSE_RECT; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_TRANSPOSE_RECT; } if (rect->flags & CANVAS_RECT_CLIP_UV) { - state.instance_data_array[r_index].flags |= FLAGS_CLIP_RECT_UV; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_CLIP_RECT_UV; } } else { @@ -991,13 +1001,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend } if (rect->flags & CANVAS_RECT_MSDF) { - state.instance_data_array[r_index].flags |= FLAGS_USE_MSDF; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_MSDF; state.instance_data_array[r_index].msdf[0] = rect->px_range; // Pixel range. state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size. state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved. state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved. } else if (rect->flags & CANVAS_RECT_LCD) { - state.instance_data_array[r_index].flags |= FLAGS_USE_LCD; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_LCD; } state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r; @@ -1026,7 +1036,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].tex = np->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_NINEPATCH; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_NINEPATCH; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_NINEPATCH; + state.canvas_instance_batches[state.current_batch_index].flags = 0; } _prepare_canvas_texture(np->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1064,11 +1076,11 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.instance_data_array[r_index].dst_rect[2] = dst_rect.size.width; state.instance_data_array[r_index].dst_rect[3] = dst_rect.size.height; - state.instance_data_array[r_index].flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT; - state.instance_data_array[r_index].flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT; + state.instance_data_array[r_index].flags |= int(np->axis_x) << INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT; + state.instance_data_array[r_index].flags |= int(np->axis_y) << INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT; if (np->draw_center) { - state.instance_data_array[r_index].flags |= FLAGS_NINEPACH_DRAW_CENTER; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_NINEPACH_DRAW_CENTER; } state.instance_data_array[r_index].ninepatch_margins[0] = np->margin[SIDE_LEFT]; @@ -1092,7 +1104,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].tex = polygon->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_POLYGON; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].flags = 0; _prepare_canvas_texture(polygon->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1119,7 +1133,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].primitive_points = primitive->point_count; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_PRIMITIVE; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_PRIMITIVE; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_PRIMITIVE; + state.canvas_instance_batches[state.current_batch_index].flags = 0; } _prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1160,11 +1176,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend case Item::Command::TYPE_MESH: case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { - // Mesh's can't be batched, so always create a new batch + // Meshes can't be batched, so always create a new batch. _new_batch(r_batch_broken); Color modulate(1, 1, 1, 1); - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].flags = 0; if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c); state.canvas_instance_batches[state.current_batch_index].tex = m->texture; @@ -1174,13 +1192,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend } else if (c->type == Item::Command::TYPE_MULTIMESH) { const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c); state.canvas_instance_batches[state.current_batch_index].tex = mm->texture; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING; if (GLES3::MeshStorage::get_singleton()->multimesh_uses_colors(mm->multimesh)) { - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; } if (GLES3::MeshStorage::get_singleton()->multimesh_uses_custom_data(mm->multimesh)) { - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; } } else if (c->type == Item::Command::TYPE_PARTICLES) { GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton(); @@ -1189,9 +1207,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c); RID particles = pt->particles; state.canvas_instance_batches[state.current_batch_index].tex = pt->texture; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED; - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS; - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) { // Pass collision information. @@ -1654,28 +1672,39 @@ void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, c return; } - for (int i = 0; i < 4; i++) { - glViewport((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); + Projection projection; + { + real_t fov = 90; + real_t nearp = p_near; + real_t farp = p_far; + real_t aspect = 1.0; - Projection projection; - { - real_t fov = 90; - real_t nearp = p_near; - real_t farp = p_far; - real_t aspect = 1.0; + real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5)); + real_t ymin = -ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; - real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5)); - real_t ymin = -ymax; - real_t xmin = ymin * aspect; - real_t xmax = ymax * aspect; + projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); + } - projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); - } + // Precomputed: + // Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); + // projection = projection * Projection(Transform3D().looking_at(cam_targets[i], Vector3(0, 0, -1)).affine_inverse()); + const Projection projections[4] = { + projection * Projection(Vector4(0, 0, -1, 0), Vector4(1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)), + + projection * Projection(Vector4(-1, 0, 0, 0), Vector4(0, 0, -1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)), + + projection * Projection(Vector4(0, 0, 1, 0), Vector4(-1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)), - Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); + projection * Projection(Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)) + + }; + + for (int i = 0; i < 4; i++) { + glViewport((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); - shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::PROJECTION, projection, shadow_render.shader_version, variant); + shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::PROJECTION, projections[i], shadow_render.shader_version, variant); static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::DIRECTION, directions[i].x, directions[i].y, shadow_render.shader_version, variant); @@ -2347,15 +2376,15 @@ void RasterizerCanvasGLES3::_prepare_canvas_texture(RID p_texture, RS::CanvasIte GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map); if (ct->specular_color.a < 0.999) { - state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED; } else { - state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_SPECULAR_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED; } if (normal_map) { - state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED; } else { - state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_NORMAL_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED; } state.instance_data_array[r_index].specular_shininess = uint32_t(CLAMP(ct->specular_color.a * 255.0, 0, 255)) << 24; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index a82e2713e0..e099fd0cc0 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -54,29 +54,27 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender { _FORCE_INLINE_ void _update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4); enum { + INSTANCE_FLAGS_LIGHT_COUNT_SHIFT = 0, // 4 bits for light count. - FLAGS_INSTANCING_MASK = 0x7F, - FLAGS_INSTANCING_HAS_COLORS = (1 << 7), - FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), + INSTANCE_FLAGS_CLIP_RECT_UV = (1 << 4), + INSTANCE_FLAGS_TRANSPOSE_RECT = (1 << 5), + INSTANCE_FLAGS_USE_MSDF = (1 << 6), + INSTANCE_FLAGS_USE_LCD = (1 << 7), - FLAGS_CLIP_RECT_UV = (1 << 9), - FLAGS_TRANSPOSE_RECT = (1 << 10), + INSTANCE_FLAGS_NINEPACH_DRAW_CENTER = (1 << 8), + INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT = 9, + INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT = 11, - FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), - - FLAGS_USE_SKELETON = (1 << 15), - FLAGS_NINEPATCH_H_MODE_SHIFT = 16, - FLAGS_NINEPATCH_V_MODE_SHIFT = 18, - FLAGS_LIGHT_COUNT_SHIFT = 20, - - FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26), - FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), + INSTANCE_FLAGS_SHADOW_MASKED_SHIFT = 13, // 16 bits. + }; - FLAGS_USE_MSDF = (1 << 28), - FLAGS_USE_LCD = (1 << 29), + enum { + BATCH_FLAGS_INSTANCING_MASK = 0x7F, + BATCH_FLAGS_INSTANCING_HAS_COLORS = (1 << 7), + BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), - FLAGS_FLIP_H = (1 << 30), - FLAGS_FLIP_V = (1 << 31), + BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 9), + BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 10), }; enum { @@ -273,14 +271,14 @@ public: RID material; GLES3::CanvasMaterialData *material_data = nullptr; - CanvasShaderGLES3::ShaderVariant shader_variant = CanvasShaderGLES3::MODE_QUAD; uint64_t vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_COLOR | RS::ARRAY_FORMAT_TEX_UV; + uint64_t specialization = 0; const Item::Command *command = nullptr; Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch. uint32_t primitive_points = 0; - bool lights_disabled = false; + uint32_t flags = 0; }; // DataBuffer contains our per-frame data. I.e. the resources that are updated each frame. diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 6e508c6ebf..0fda42979f 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -35,6 +35,7 @@ #include "core/config/project_settings.h" #include "core/io/dir_access.h" +#include "core/io/image.h" #include "core/os/os.h" #include "storage/texture_storage.h" @@ -217,6 +218,7 @@ void RasterizerGLES3::finalize() { memdelete(glow); memdelete(cubemap_filter); memdelete(copy_effects); + memdelete(feed_effects); memdelete(light_storage); memdelete(particles_storage); memdelete(mesh_storage); @@ -365,6 +367,7 @@ RasterizerGLES3::RasterizerGLES3() { cubemap_filter = memnew(GLES3::CubemapFilter); glow = memnew(GLES3::Glow); post_effects = memnew(GLES3::PostEffects); + feed_effects = memnew(GLES3::FeedEffects); gi = memnew(GLES3::GI); fog = memnew(GLES3::Fog); canvas = memnew(RasterizerCanvasGLES3()); diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index 6765d8b4d5..abda2a5e06 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -35,6 +35,7 @@ #include "effects/copy_effects.h" #include "effects/cubemap_filter.h" +#include "effects/feed_effects.h" #include "effects/glow.h" #include "effects/post_effects.h" #include "environment/fog.h" @@ -78,6 +79,7 @@ protected: GLES3::CubemapFilter *cubemap_filter = nullptr; GLES3::Glow *glow = nullptr; GLES3::PostEffects *post_effects = nullptr; + GLES3::FeedEffects *feed_effects = nullptr; RasterizerCanvasGLES3 *canvas = nullptr; RasterizerSceneGLES3 *scene = nullptr; static RasterizerGLES3 *singleton; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index a73f14c796..dfc7d02ac0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -31,6 +31,7 @@ #include "rasterizer_scene_gles3.h" #include "drivers/gles3/effects/copy_effects.h" +#include "drivers/gles3/effects/feed_effects.h" #include "rasterizer_gles3.h" #include "storage/config.h" #include "storage/mesh_storage.h" @@ -39,6 +40,8 @@ #include "core/config/project_settings.h" #include "core/templates/sort_array.h" +#include "servers/camera/camera_feed.h" +#include "servers/camera_server.h" #include "servers/rendering/rendering_server_default.h" #include "servers/rendering/rendering_server_globals.h" @@ -235,7 +238,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry GLES3::SceneMaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates && !p_material->shader_data->wireframe) { flags |= GeometryInstanceSurface::FLAG_USES_SHARED_SHADOW_MATERIAL; material_shadow = static_cast<GLES3::SceneMaterialData *>(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.default_material, RS::SHADER_SPATIAL)); @@ -2259,6 +2262,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ render_data.inv_cam_transform = render_data.cam_transform.affine_inverse(); render_data.cam_projection = p_camera_data->main_projection; render_data.cam_orthogonal = p_camera_data->is_orthogonal; + render_data.cam_frustum = p_camera_data->is_frustum; render_data.camera_visible_layers = p_camera_data->visible_layers; render_data.main_cam_transform = p_camera_data->main_transform; @@ -2382,7 +2386,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ bool draw_sky = false; bool draw_sky_fog_only = false; bool keep_color = false; + bool draw_feed = false; float sky_energy_multiplier = 1.0; + int camera_feed_id = -1; if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW)) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black @@ -2427,6 +2433,8 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ keep_color = true; } break; case RS::ENV_BG_CAMERA_FEED: { + camera_feed_id = environment_get_camera_feed_id(render_data.environment); + draw_feed = true; } break; default: { } @@ -2538,7 +2546,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ glClear(GL_DEPTH_BUFFER_BIT); } - if (!keep_color) { + if (!keep_color && !draw_feed) { clear_color.a = render_data.transparent_bg ? 0.0f : 1.0f; glClearBufferfv(GL_COLOR, 0, clear_color.components); } else if (fbo != rt->fbo) { @@ -2578,6 +2586,29 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ spec_constant_base_flags |= SceneShaderGLES3::APPLY_TONEMAPPING; } } + + if (draw_feed && camera_feed_id > -1) { + RENDER_TIMESTAMP("Render Camera feed"); + + scene_state.enable_gl_depth_draw(false); + scene_state.enable_gl_depth_test(false); + scene_state.enable_gl_blend(false); + scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_BACK); + + Ref<CameraFeed> feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id); + + if (feed.is_valid()) { + RID camera_YCBCR = feed->get_texture(CameraServer::FEED_YCBCR_IMAGE); + GLES3::TextureStorage::get_singleton()->texture_bind(camera_YCBCR, 0); + + GLES3::FeedEffects *feed_effects = GLES3::FeedEffects::get_singleton(); + feed_effects->draw(); + } + scene_state.enable_gl_depth_draw(true); + scene_state.enable_gl_depth_test(true); + scene_state.enable_gl_blend(true); + } + // Render Opaque Objects. RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe); @@ -2592,14 +2623,18 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ scene_state.enable_gl_blend(false); scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_BACK); + Transform3D transform = render_data.cam_transform; Projection projection = render_data.cam_projection; if (is_reflection_probe) { Projection correction; correction.columns[1][1] = -1.0; projection = correction * render_data.cam_projection; + } else if (render_data.cam_frustum) { + // Sky is drawn upside down, the frustum offset doesn't know the image is upside down so needs a flip. + projection[2].y = -projection[2].y; } - _draw_sky(render_data.environment, projection, render_data.cam_transform, sky_energy_multiplier, render_data.luminance_multiplier, p_camera_data->view_count > 1, flip_y, apply_color_adjustments_in_post); + _draw_sky(render_data.environment, projection, transform, sky_energy_multiplier, render_data.luminance_multiplier, p_camera_data->view_count > 1, flip_y, apply_color_adjustments_in_post); } if (rt && (scene_state.used_screen_texture || scene_state.used_depth_texture)) { @@ -3122,7 +3157,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } bool use_wireframe = false; - if (p_params->force_wireframe) { + if (p_params->force_wireframe || shader->wireframe) { GLuint wireframe_index_array_gl = mesh_storage->mesh_surface_get_index_buffer_wireframe(mesh_surface); if (wireframe_index_array_gl) { index_array_gl = wireframe_index_array_gl; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 06371b2b7f..4f088a0e7d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -103,6 +103,7 @@ struct RenderDataGLES3 { Transform3D inv_cam_transform; Projection cam_projection; bool cam_orthogonal = false; + bool cam_frustum = false; uint32_t camera_visible_layers = 0xFFFFFFFF; // For billboards to cast correct shadows. diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index b73debf04a..83f74865f6 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -168,6 +168,10 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant builder.append("#version 300 es\n"); } + if (GLES3::Config::get_singleton()->polyfill_half2float) { + builder.append("#define USE_HALF2FLOAT\n"); + } + for (int i = 0; i < specialization_count; i++) { if (p_specialization & (uint64_t(1) << uint64_t(i))) { builder.append("#define " + String(specializations[i].name) + "\n"); diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index df2c515035..0207ba12b7 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -17,6 +17,7 @@ if "GLES3_GLSL" in env["BUILDERS"]: # as we have a few, not yet, converted files we name the ones we want to include: env.GLES3_GLSL("canvas.glsl") + env.GLES3_GLSL("feed.glsl") env.GLES3_GLSL("scene.glsl") env.GLES3_GLSL("sky.glsl") env.GLES3_GLSL("canvas_occlusion.glsl") diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 5e7fb3b338..3857aa8841 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -1,17 +1,16 @@ /* clang-format off */ #[modes] -mode_quad = -mode_ninepatch = #define USE_NINEPATCH -mode_primitive = #define USE_PRIMITIVE -mode_attributes = #define USE_ATTRIBUTES -mode_instanced = #define USE_ATTRIBUTES \n#define USE_INSTANCING +mode_default = #[specializations] DISABLE_LIGHTING = true USE_RGBA_SHADOWS = false -SINGLE_INSTANCE = false +USE_NINEPATCH = false +USE_PRIMITIVE = false +USE_ATTRIBUTES = false +USE_INSTANCING = false #[vertex] @@ -111,6 +110,9 @@ layout(std140) uniform MaterialUniforms{ //ubo:4 }; #endif + +uniform mediump uint batch_flags; + /* clang-format on */ #include "canvas_uniforms_inc.glsl" @@ -180,13 +182,13 @@ void main() { vec2 uv = uv_attrib; #ifdef USE_INSTANCING - if (bool(read_draw_data_flags & FLAGS_INSTANCING_HAS_COLORS)) { + if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_COLORS)) { vec4 instance_color; instance_color.xy = unpackHalf2x16(uint(instance_color_custom_data.x)); instance_color.zw = unpackHalf2x16(uint(instance_color_custom_data.y)); color *= instance_color; } - if (bool(read_draw_data_flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { + if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { instance_custom.xy = unpackHalf2x16(instance_color_custom_data.z); instance_custom.zw = unpackHalf2x16(instance_color_custom_data.w); } @@ -219,7 +221,7 @@ void main() { else if (vertex_id == 5) vertex_base = vec2(1.0, 1.0); - vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy); + vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy); vec4 color = read_draw_data_modulation; vec2 vertex = read_draw_data_dst_rect.xy + abs(read_draw_data_dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(read_draw_data_src_rect.zw, vec2(0.0, 0.0))); @@ -337,6 +339,8 @@ uniform sampler2D specular_texture; //texunit:-7 uniform sampler2D color_texture; //texunit:0 +uniform mediump uint batch_flags; + layout(location = 0) out vec4 frag_color; /* clang-format off */ @@ -520,7 +524,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo } else if (pixel >= draw_size - margin_end) { return (tex_size - (draw_size - pixel)) * tex_pixel_size; } else { - if (!bool(read_draw_data_flags & FLAGS_NINEPACH_DRAW_CENTER)) { + if (!bool(read_draw_data_flags & INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER)) { draw_center--; } @@ -568,8 +572,8 @@ void main() { int draw_center = 2; uv = vec2( - map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center), - map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center)); + map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center), + map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center)); if (draw_center == 0) { color.a = 0.0; @@ -578,7 +582,7 @@ void main() { uv = uv * read_draw_data_src_rect.zw + read_draw_data_src_rect.xy; //apply region if needed #endif - if (bool(read_draw_data_flags & FLAGS_CLIP_RECT_UV)) { + if (bool(read_draw_data_flags & INSTANCE_FLAGS_CLIP_RECT_UV)) { vec2 half_texpixel = read_draw_data_color_texture_pixel_size * 0.5; uv = clamp(uv, read_draw_data_src_rect.xy + half_texpixel, read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) - half_texpixel); } @@ -586,7 +590,7 @@ void main() { #endif #ifndef USE_PRIMITIVE - if (bool(read_draw_data_flags & FLAGS_USE_MSDF)) { + if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_MSDF)) { float px_range = read_draw_data_ninepatch_margins.x; float outline_thickness = read_draw_data_ninepatch_margins.y; @@ -604,7 +608,7 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - } else if (bool(read_draw_data_flags & FLAGS_USE_LCD)) { + } else if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_LCD)) { vec4 lcd_sample = texture(color_texture, uv); if (lcd_sample.a == 1.0) { color.rgb = lcd_sample.rgb * color.a; @@ -618,7 +622,7 @@ void main() { color *= texture(color_texture, uv); } - uint light_count = (read_draw_data_flags >> uint(FLAGS_LIGHT_COUNT_SHIFT)) & uint(0xF); //max 16 lights + uint light_count = read_draw_data_flags & uint(0xF); // Max 16 lights. bool using_light = light_count > 0u || directional_light_count > 0u; vec3 normal; @@ -629,17 +633,16 @@ void main() { bool normal_used = false; #endif - if (normal_used || (using_light && bool(read_draw_data_flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { + if (normal_used || (using_light && bool(batch_flags & BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED))) { normal.xy = texture(normal_texture, uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); - if (bool(read_draw_data_flags & FLAGS_TRANSPOSE_RECT)) { + +#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) + if (bool(read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT)) { normal.xy = normal.yx; } - if (bool(read_draw_data_flags & FLAGS_FLIP_H)) { - normal.x = -normal.x; - } - if (bool(read_draw_data_flags & FLAGS_FLIP_V)) { - normal.y = -normal.y; - } + normal.xy *= sign(read_draw_data_src_rect.zw); +#endif + normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy))); normal_used = true; } else { @@ -655,7 +658,7 @@ void main() { bool specular_shininess_used = false; #endif - if (specular_shininess_used || (using_light && normal_used && bool(read_draw_data_flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { + if (specular_shininess_used || (using_light && normal_used && bool(batch_flags & BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(specular_texture, uv); specular_shininess *= godot_unpackUnorm4x8(read_draw_data_specular_shininess); specular_shininess_used = true; @@ -728,7 +731,7 @@ void main() { } #endif - if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(read_draw_data_flags & uint(INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec4 shadow_uv = vec4(shadow_pos.x, light_array[light_base].shadow_y_ofs, shadow_pos.y * light_array[light_base].shadow_zfar_inv, 1.0); @@ -803,7 +806,7 @@ void main() { } #endif - if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(read_draw_data_flags & uint(INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec2 pos_norm = normalize(shadow_pos); diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl index f6ad2b730a..94cbbdd8a7 100644 --- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl +++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl @@ -1,33 +1,32 @@ - #define MAX_LIGHTS_PER_ITEM uint(16) #define M_PI 3.14159265359 #define SDF_MAX_LENGTH 16384.0 -//1 means enabled, 2+ means trails in use -#define FLAGS_INSTANCING_MASK uint(0x7F) -#define FLAGS_INSTANCING_HAS_COLORS uint(1 << 7) -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA uint(1 << 8) - -#define FLAGS_CLIP_RECT_UV uint(1 << 9) -#define FLAGS_TRANSPOSE_RECT uint(1 << 10) -// (1 << 11) is for FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR in RD backends, unused here. -#define FLAGS_NINEPACH_DRAW_CENTER uint(1 << 12) +#define INSTANCE_FLAGS_LIGHT_COUNT_SHIFT 0 // 4 bits. -#define FLAGS_NINEPATCH_H_MODE_SHIFT 16 -#define FLAGS_NINEPATCH_V_MODE_SHIFT 18 +#define INSTANCE_FLAGS_CLIP_RECT_UV uint(1 << 4) +#define INSTANCE_FLAGS_TRANSPOSE_RECT uint(1 << 5) +#define INSTANCE_FLAGS_USE_MSDF uint(1 << 6) +#define INSTANCE_FLAGS_USE_LCD uint(1 << 7) -#define FLAGS_LIGHT_COUNT_SHIFT 20 +#define INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER uint(1 << 8) +#define INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT 9 +#define INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT 11 -#define FLAGS_DEFAULT_NORMAL_MAP_USED uint(1 << 26) -#define FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 27) +#define INSTANCE_FLAGS_SHADOW_MASKED_SHIFT 13u // 16 bits. +#define INSTANCE_FLAGS_SHADOW_MASKED uint(1 << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT) -#define FLAGS_USE_MSDF uint(1 << 28) -#define FLAGS_USE_LCD uint(1 << 29) +// 1 means enabled, 2+ means trails in use +#define BATCH_FLAGS_INSTANCING_MASK uint(0x7F) +#define BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT 7 +#define BATCH_FLAGS_INSTANCING_HAS_COLORS uint(1 << BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT) +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8 +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA uint(1 << BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT) -#define FLAGS_FLIP_H uint(1 << 30) -#define FLAGS_FLIP_V uint(1 << 31) +#define BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED uint(1 << 9) +#define BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 10) layout(std140) uniform GlobalShaderUniformData { //ubo:1 vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; diff --git a/drivers/gles3/shaders/feed.glsl b/drivers/gles3/shaders/feed.glsl new file mode 100644 index 0000000000..9d89fc699d --- /dev/null +++ b/drivers/gles3/shaders/feed.glsl @@ -0,0 +1,39 @@ +/* clang-format off */ +#[modes] + +mode_default = + +#[specializations] + +USE_EXTERNAL_SAMPLER = false + +#[vertex] + +layout(location = 0) in vec2 vertex_attrib; + +out vec2 uv_interp; + + +void main() { + uv_interp = vertex_attrib * 0.5 + 0.5; + gl_Position = vec4(vertex_attrib, 1.0, 1.0); +} + +/* clang-format off */ +#[fragment] + +layout(location = 0) out vec4 frag_color; +in vec2 uv_interp; + +/* clang-format on */ +#ifdef USE_EXTERNAL_SAMPLER +uniform samplerExternalOES sourceFeed; // texunit:0 +#else +uniform sampler2D sourceFeed; // texunit:0 +#endif + +void main() { + vec4 color = texture(sourceFeed, uv_interp); + + frag_color = color; +} diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index fcfbeddb9e..2022c8ee43 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1259,7 +1259,7 @@ float SchlickFresnel(float u) { return m2 * m2 * m; // pow(m,5) } -void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, float roughness, float metallic, float specular_amount, vec3 albedo, inout float alpha, +void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, float roughness, float metallic, float specular_amount, vec3 albedo, inout float alpha, vec2 screen_uv, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -1423,7 +1423,7 @@ float get_omni_spot_attenuation(float distance, float inv_range, float decay) { } #if !defined(DISABLE_LIGHT_OMNI) || defined(ADDITIVE_OMNI) -void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, +void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, vec2 screen_uv, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -1450,7 +1450,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f omni_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1469,7 +1469,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f #endif // !DISABLE_LIGHT_OMNI #if !defined(DISABLE_LIGHT_SPOT) || defined(ADDITIVE_SPOT) -void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, +void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, vec2 screen_uv, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -1506,7 +1506,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f spot_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2114,7 +2114,7 @@ void main() { continue; } #endif - light_compute(normal, normalize(directional_lights[i].direction), normalize(view), directional_lights[i].size, directional_lights[i].color * directional_lights[i].energy, true, 1.0, f0, roughness, metallic, 1.0, albedo, alpha, + light_compute(normal, normalize(directional_lights[i].direction), normalize(view), directional_lights[i].size, directional_lights[i].color * directional_lights[i].energy, true, 1.0, f0, roughness, metallic, 1.0, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2143,7 +2143,7 @@ void main() { continue; } #endif - light_process_omni(omni_light_indices[i], vertex, view, normal, f0, roughness, metallic, 1.0, albedo, alpha, + light_process_omni(omni_light_indices[i], vertex, view, normal, f0, roughness, metallic, 1.0, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2171,7 +2171,7 @@ void main() { continue; } #endif - light_process_spot(spot_light_indices[i], vertex, view, normal, f0, roughness, metallic, 1.0, albedo, alpha, + light_process_spot(spot_light_indices[i], vertex, view, normal, f0, roughness, metallic, 1.0, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2389,7 +2389,7 @@ void main() { #endif // SHADOWS_DISABLED #ifndef USE_VERTEX_LIGHTING - light_compute(normal, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].size, directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, directional_shadow, f0, roughness, metallic, 1.0, albedo, alpha, + light_compute(normal, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].size, directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, directional_shadow, f0, roughness, metallic, 1.0, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2421,7 +2421,7 @@ void main() { #endif // SHADOWS_DISABLED #ifndef USE_VERTEX_LIGHTING - light_process_omni(omni_light_index, vertex, view, normal, f0, roughness, metallic, omni_shadow, albedo, alpha, + light_process_omni(omni_light_index, vertex, view, normal, f0, roughness, metallic, omni_shadow, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2451,7 +2451,7 @@ void main() { #endif // SHADOWS_DISABLED #ifndef USE_VERTEX_LIGHTING - light_process_spot(spot_light_index, vertex, view, normal, f0, roughness, metallic, spot_shadow, albedo, alpha, + light_process_spot(spot_light_index, vertex, view, normal, f0, roughness, metallic, spot_shadow, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 186b630bc8..043023aee0 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -2,17 +2,15 @@ #[modes] mode_background = -mode_half_res = #define USE_HALF_RES_PASS -mode_quarter_res = #define USE_QUARTER_RES_PASS mode_cubemap = #define USE_CUBEMAP_PASS -mode_cubemap_half_res = #define USE_CUBEMAP_PASS \n#define USE_HALF_RES_PASS -mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PASS #[specializations] USE_MULTIVIEW = false USE_INVERTED_Y = true APPLY_TONEMAPPING = true +USE_QUARTER_RES_PASS = false +USE_HALF_RES_PASS = false #[vertex] diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl index f88c218506..004db9e5d0 100644 --- a/drivers/gles3/shaders/stdlib_inc.glsl +++ b/drivers/gles3/shaders/stdlib_inc.glsl @@ -1,25 +1,28 @@ - // Compatibility renames. These are exposed with the "godot_" prefix // to work around two distinct Adreno bugs: // 1. Some Adreno devices expose ES310 functions in ES300 shaders. // Internally, we must use the "godot_" prefix, but user shaders // will be mapped automatically. // 2. Adreno 3XX devices have poor implementations of the other packing -// functions, so we just use our own everywhere to keep it simple. +// functions, so we just use our own there to keep it simple. +#ifdef USE_HALF2FLOAT // Floating point pack/unpack functions are part of the GLSL ES 300 specification used by web and mobile. +// It appears to be safe to expose these on mobile, but when running through ANGLE this appears to break. uint float2half(uint f) { - uint b = f + uint(0x00001000); - uint e = (b & uint(0x7F800000)) >> 23; - uint m = b & uint(0x007FFFFF); - return (b & uint(0x80000000)) >> uint(16) | uint(e > uint(112)) * ((((e - uint(112)) << uint(10)) & uint(0x7C00)) | m >> uint(13)) | (uint(e < uint(113)) & uint(e > uint(101))) * ((((uint(0x007FF000) + m) >> (uint(125) - e)) + uint(1)) >> uint(1)) | uint(e > uint(143)) * uint(0x7FFF); + uint e = f & uint(0x7f800000); + if (e <= uint(0x38000000)) { + return uint(0); + } else { + return ((f >> uint(16)) & uint(0x8000)) | + (((e - uint(0x38000000)) >> uint(13)) & uint(0x7c00)) | + ((f >> uint(13)) & uint(0x03ff)); + } } uint half2float(uint h) { - uint e = (h & uint(0x7C00)) >> uint(10); - uint m = (h & uint(0x03FF)) << uint(13); - uint v = m >> uint(23); - return (h & uint(0x8000)) << uint(16) | uint(e != uint(0)) * ((e + uint(112)) << uint(23) | m) | (uint(e == uint(0)) & uint(m != uint(0))) * ((v - uint(37)) << uint(23) | ((m << (uint(150) - v)) & uint(0x007FE000))); + uint h_e = h & uint(0x7c00); + return ((h & uint(0x8000)) << uint(16)) | uint((h_e >> uint(10)) != uint(0)) * (((h_e + uint(0x1c000)) << uint(13)) | ((h & uint(0x03ff)) << uint(13))); } uint godot_packHalf2x16(vec2 v) { @@ -50,6 +53,17 @@ vec2 godot_unpackSnorm2x16(uint p) { return clamp((v - 32767.0) * vec2(0.00003051851), vec2(-1.0), vec2(1.0)); } +#define packHalf2x16 godot_packHalf2x16 +#define unpackHalf2x16 godot_unpackHalf2x16 +#define packUnorm2x16 godot_packUnorm2x16 +#define unpackUnorm2x16 godot_unpackUnorm2x16 +#define packSnorm2x16 godot_packSnorm2x16 +#define unpackSnorm2x16 godot_unpackSnorm2x16 + +#endif // USE_HALF2FLOAT + +// Always expose these as they are ES310 functions and not available in ES300 or GLSL 330. + uint godot_packUnorm4x8(vec4 v) { uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0)); return uv.x | (uv.y << uint(8)) | (uv.z << uint(16)) | (uv.w << uint(24)); @@ -73,9 +87,3 @@ vec4 godot_unpackSnorm4x8(uint p) { #define unpackUnorm4x8 godot_unpackUnorm4x8 #define packSnorm4x8 godot_packSnorm4x8 #define unpackSnorm4x8 godot_unpackSnorm4x8 -#define packHalf2x16 godot_packHalf2x16 -#define unpackHalf2x16 godot_unpackHalf2x16 -#define packUnorm2x16 godot_packUnorm2x16 -#define unpackUnorm2x16 godot_unpackUnorm2x16 -#define packSnorm2x16 godot_packSnorm2x16 -#define unpackSnorm2x16 godot_unpackSnorm2x16 diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index 209b7dd7d2..07dd5f58c1 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -231,6 +231,13 @@ Config::Config() { } else if (rendering_device_name == "PowerVR Rogue GE8320") { disable_transform_feedback_shader_cache = true; } + + if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3_angle") { + polyfill_half2float = false; + } +#ifdef WEB_ENABLED + polyfill_half2float = false; +#endif } Config::~Config() { diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index d60f295d66..51f6714320 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -95,13 +95,16 @@ public: bool multiview_supported = false; bool external_texture_supported = false; - // Adreno 3XX compatibility - bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles' + // Adreno 3XX compatibility. + bool disable_particles_workaround = false; // Set to 'true' to disable 'GPUParticles'. bool flip_xy_workaround = false; - // PowerVR GE 8320 workaround + // PowerVR GE 8320 workaround. bool disable_transform_feedback_shader_cache = false; + // ANGLE shader workaround. + bool polyfill_half2float = true; + #ifdef ANDROID_ENABLED PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr; PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr; @@ -110,7 +113,7 @@ public: PFNEGLIMAGETARGETTEXTURE2DOESPROC eglEGLImageTargetTexture2DOES = nullptr; #endif - static Config *get_singleton() { return singleton; }; + static Config *get_singleton() { return singleton; } Config(); ~Config(); diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index 9b976c2206..9b81430d45 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -213,6 +213,23 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) { light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } +void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_NULL(light); + + light->shadow_caster_mask = p_caster_mask; + + light->version++; + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); +} + +uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_NULL_V(light, 0); + + return light->shadow_caster_mask; +} + void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) { Light *light = light_owner.get_or_null(p_light); ERR_FAIL_NULL(light); diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index ed00dd235f..0695102640 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/drivers/gles3/storage/light_storage.h @@ -59,6 +59,7 @@ struct Light { RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; uint32_t max_sdfgi_cascade = 2; uint32_t cull_mask = 0xFFFFFFFF; + uint32_t shadow_caster_mask = 0xFFFFFFFF; bool distance_fade = false; real_t distance_fade_begin = 40.0; real_t distance_fade_shadow = 50.0; @@ -305,8 +306,8 @@ public: /* Light API */ - Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); }; - bool owns_light(RID p_rid) { return light_owner.owns(p_rid); }; + Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); } + bool owns_light(RID p_rid) { return light_owner.owns(p_rid); } void _light_initialize(RID p_rid, RS::LightType p_type); @@ -327,6 +328,8 @@ public: virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override; virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override; + virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override; + virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override; virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override; virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {} @@ -431,8 +434,8 @@ public: /* LIGHT INSTANCE API */ - LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); }; - bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }; + LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); } + bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); } virtual RID light_instance_create(RID p_light) override; virtual void light_instance_free(RID p_light_instance) override; @@ -630,8 +633,8 @@ public: /* PROBE API */ - ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); }; - bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }; + ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); } + bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); } virtual RID reflection_probe_allocate() override; virtual void reflection_probe_initialize(RID p_rid) override; @@ -712,8 +715,8 @@ public: /* LIGHTMAP CAPTURE */ - Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); }; - bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }; + Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); } + bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); } virtual RID lightmap_allocate() override; virtual void lightmap_initialize(RID p_rid) override; @@ -736,15 +739,15 @@ public: /* LIGHTMAP INSTANCE */ - LightmapInstance *get_lightmap_instance(RID p_rid) { return lightmap_instance_owner.get_or_null(p_rid); }; - bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }; + LightmapInstance *get_lightmap_instance(RID p_rid) { return lightmap_instance_owner.get_or_null(p_rid); } + bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); } virtual RID lightmap_instance_create(RID p_lightmap) override; virtual void lightmap_instance_free(RID p_lightmap) override; virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override; /* SHADOW ATLAS API */ - bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }; + bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); } virtual RID shadow_atlas_create() override; virtual void shadow_atlas_free(RID p_atlas) override; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 684f179492..04cbf7f2cd 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1237,6 +1237,8 @@ MaterialStorage::MaterialStorage() { actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); + actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR"; actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; @@ -1276,8 +1278,6 @@ MaterialStorage::MaterialStorage() { actions.renames["CUSTOM1"] = "custom1_attrib"; actions.renames["CUSTOM2"] = "custom2_attrib"; actions.renames["CUSTOM3"] = "custom3_attrib"; - actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR"; actions.renames["LIGHT_VERTEX"] = "light_vertex"; actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz"; diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 392ebcc570..6c21abc276 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -576,8 +576,8 @@ public: /* SHADER API */ - Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }; - bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; + Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); } + bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); } void _shader_make_dirty(Shader *p_shader); @@ -598,8 +598,8 @@ public: /* MATERIAL API */ - Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; - bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); } + bool owns_material(RID p_rid) { return material_owner.owns(p_rid); } void _material_queue_update(Material *material, bool p_uniform, bool p_texture); void _update_queued_materials(); diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 73d95d75ba..630bfdf1b7 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -1974,6 +1974,10 @@ void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_ } } +RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const { + ERR_FAIL_V_MSG(RID(), "GLES3 does not contain a Rid for the multimesh buffer."); +} + Vector<float> MeshStorage::_multimesh_get_buffer(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_NULL_V(multimesh, Vector<float>()); diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index 8615b89a30..5e3a56366e 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -280,8 +280,8 @@ public: /* MESH API */ - Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); }; - bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); } + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); } virtual RID mesh_allocate() override; virtual void mesh_initialize(RID p_rid) override; @@ -443,8 +443,8 @@ public: /* MESH INSTANCE API */ - MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); }; - bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); }; + MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); } + bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); } virtual RID mesh_instance_create(RID p_base) override; virtual void mesh_instance_free(RID p_rid) override; @@ -492,8 +492,8 @@ public: /* MULTIMESH API */ - MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); }; - bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; + MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); } + bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); } virtual RID _multimesh_allocate() override; virtual void _multimesh_initialize(RID p_rid) override; @@ -517,6 +517,7 @@ public: virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override; virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override; virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override; + virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override; virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override; virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) override; @@ -571,8 +572,8 @@ public: /* SKELETON API */ - Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); }; - bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); }; + Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); } + bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); } virtual RID skeleton_allocate() override; virtual void skeleton_initialize(RID p_rid) override; diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h index 086f5f7936..0552a5324f 100644 --- a/drivers/gles3/storage/particles_storage.h +++ b/drivers/gles3/storage/particles_storage.h @@ -396,7 +396,7 @@ public: _FORCE_INLINE_ bool particles_has_collision(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_NULL_V(particles, 0); + ERR_FAIL_NULL_V(particles, false); return particles->has_collision_cache; } diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index d7b4d6911d..14bbe635a4 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -230,6 +230,32 @@ TextureStorage::TextureStorage() { sdf_shader.shader_version = sdf_shader.shader.version_create(); } + // Initialize texture placeholder data for the `texture_*_placeholder_initialize()` methods. + + constexpr int placeholder_size = 4; + texture_2d_placeholder = Image::create_empty(placeholder_size, placeholder_size, false, Image::FORMAT_RGBA8); + // Draw a magenta/black checkerboard pattern. + for (int i = 0; i < placeholder_size * placeholder_size; i++) { + const int x = i % placeholder_size; + const int y = i / placeholder_size; + texture_2d_placeholder->set_pixel(x, y, (x + y) % 2 == 0 ? Color(1, 0, 1) : Color(0, 0, 0)); + } + + texture_2d_array_placeholder.push_back(texture_2d_placeholder); + + for (int i = 0; i < 6; i++) { + cubemap_placeholder.push_back(texture_2d_placeholder); + } + + Ref<Image> texture_2d_placeholder_rotated; + texture_2d_placeholder_rotated.instantiate(); + texture_2d_placeholder_rotated->copy_from(texture_2d_placeholder); + texture_2d_placeholder_rotated->rotate_90(CLOCKWISE); + for (int i = 0; i < 4; i++) { + // Alternate checkerboard pattern on odd layers (by using a copy that is rotated 90 degrees). + texture_3d_placeholder.push_back(i % 2 == 0 ? texture_2d_placeholder : texture_2d_placeholder_rotated); + } + #ifdef GL_API_ENABLED if (RasterizerGLES3::is_gles_over_gl()) { glEnable(GL_PROGRAM_POINT_SIZE); @@ -1014,46 +1040,19 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { } void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - texture_2d_initialize(p_texture, image); + texture_2d_initialize(p_texture, texture_2d_placeholder); } -void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; +void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { - images.push_back(image); + texture_2d_layered_initialize(p_texture, texture_2d_array_placeholder, p_layered_type); } else { - //cube - for (int i = 0; i < 6; i++) { - images.push_back(image); - } + texture_2d_layered_initialize(p_texture, cubemap_placeholder, p_layered_type); } - - texture_2d_layered_initialize(p_texture, images, p_layered_type); } void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - //cube - for (int i = 0; i < 4; i++) { - images.push_back(image); - } - - texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); + texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, texture_3d_placeholder); } Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { @@ -2453,7 +2452,7 @@ Point2i TextureStorage::render_target_get_position(RID p_render_target) const { ERR_FAIL_NULL_V(rt, Point2i()); return rt->position; -}; +} void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 3786c8c690..916662dcd6 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -36,6 +36,7 @@ #include "platform_gl.h" #include "config.h" +#include "core/io/image.h" #include "core/os/os.h" #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_compositor.h" @@ -477,8 +478,8 @@ public: /* Canvas Texture API */ - CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; - bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); } + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); } virtual RID canvas_texture_allocate() override; virtual void canvas_texture_initialize(RID p_rid) override; @@ -498,8 +499,8 @@ public: return texture_owner.get_or_null(texture->proxy_to); } return texture; - }; - bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + } + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); } void texture_2d_initialize_from_texture(RID p_texture, Texture &p_tex) { texture_owner.initialize_rid(p_texture, p_tex); @@ -521,6 +522,11 @@ public: virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override; virtual void texture_proxy_update(RID p_proxy, RID p_base) override; + Ref<Image> texture_2d_placeholder; + Vector<Ref<Image>> texture_2d_array_placeholder; + Vector<Ref<Image>> cubemap_placeholder; + Vector<Ref<Image>> texture_3d_placeholder; + //these two APIs can be used together or in combination with the others. virtual void texture_2d_placeholder_initialize(RID p_texture) override; virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; @@ -612,8 +618,8 @@ public: static GLuint system_fbo; - RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }; - bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }; + RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); } + bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); } void check_backbuffer(RenderTarget *rt, const bool uses_screen_texture, const bool uses_depth_texture); diff --git a/drivers/gles3/storage/utilities.h b/drivers/gles3/storage/utilities.h index 7c3b08717e..88ac802018 100644 --- a/drivers/gles3/storage/utilities.h +++ b/drivers/gles3/storage/utilities.h @@ -165,8 +165,8 @@ public: /* VISIBILITY NOTIFIER */ - VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }; - bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }; + VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); } + bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); } virtual RID visibility_notifier_allocate() override; virtual void visibility_notifier_initialize(RID p_notifier) override; diff --git a/drivers/metal/metal_objects.h b/drivers/metal/metal_objects.h index 030b353ee8..5eda826d2a 100644 --- a/drivers/metal/metal_objects.h +++ b/drivers/metal/metal_objects.h @@ -82,6 +82,9 @@ MTL_CLASS(Texture) } //namespace MTL +/// Metal buffer index for the view mask when rendering multi-view. +const uint32_t VIEW_MASK_BUFFER_INDEX = 24; + enum ShaderStageUsage : uint32_t { None = 0, Vertex = RDD::SHADER_STAGE_VERTEX_BIT, @@ -96,6 +99,22 @@ _FORCE_INLINE_ ShaderStageUsage &operator|=(ShaderStageUsage &p_a, int p_b) { return p_a; } +enum StageResourceUsage : uint32_t { + VertexRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_VERTEX * 2), + VertexWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_VERTEX * 2), + FragmentRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_FRAGMENT * 2), + FragmentWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_FRAGMENT * 2), + TesselationControlRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2), + TesselationControlWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2), + TesselationEvaluationRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2), + TesselationEvaluationWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2), + ComputeRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_COMPUTE * 2), + ComputeWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_COMPUTE * 2), +}; + +typedef LocalVector<__unsafe_unretained id<MTLResource>> ResourceVector; +typedef HashMap<StageResourceUsage, ResourceVector> ResourceUsageMap; + enum class MDCommandBufferStateType { None, Render, @@ -126,6 +145,12 @@ struct ClearAttKey { const static uint32_t STENCIL_INDEX = DEPTH_INDEX + 1; const static uint32_t ATTACHMENT_COUNT = STENCIL_INDEX + 1; + enum Flags : uint16_t { + CLEAR_FLAGS_NONE = 0, + CLEAR_FLAGS_LAYERED = 1 << 0, + }; + + Flags flags = CLEAR_FLAGS_NONE; uint16_t sample_count = 0; uint16_t pixel_formats[ATTACHMENT_COUNT] = { 0 }; @@ -134,19 +159,22 @@ struct ClearAttKey { _FORCE_INLINE_ void set_stencil_format(MTLPixelFormat p_fmt) { pixel_formats[STENCIL_INDEX] = p_fmt; } _FORCE_INLINE_ MTLPixelFormat depth_format() const { return (MTLPixelFormat)pixel_formats[DEPTH_INDEX]; } _FORCE_INLINE_ MTLPixelFormat stencil_format() const { return (MTLPixelFormat)pixel_formats[STENCIL_INDEX]; } + _FORCE_INLINE_ void enable_layered_rendering() { flags::set(flags, CLEAR_FLAGS_LAYERED); } _FORCE_INLINE_ bool is_enabled(uint32_t p_idx) const { return pixel_formats[p_idx] != 0; } _FORCE_INLINE_ bool is_depth_enabled() const { return pixel_formats[DEPTH_INDEX] != 0; } _FORCE_INLINE_ bool is_stencil_enabled() const { return pixel_formats[STENCIL_INDEX] != 0; } + _FORCE_INLINE_ bool is_layered_rendering_enabled() const { return flags::any(flags, CLEAR_FLAGS_LAYERED); } _FORCE_INLINE_ bool operator==(const ClearAttKey &p_rhs) const { return memcmp(this, &p_rhs, sizeof(ClearAttKey)) == 0; } uint32_t hash() const { - uint32_t h = hash_murmur3_one_32(sample_count); + uint32_t h = hash_murmur3_one_32(flags); + h = hash_murmur3_one_32(sample_count, h); h = hash_murmur3_buffer(pixel_formats, ATTACHMENT_COUNT * sizeof(pixel_formats[0]), h); - return h; + return hash_fmix32(h); } }; @@ -190,6 +218,97 @@ public: ~MDResourceCache() = default; }; +enum class MDAttachmentType : uint8_t { + None = 0, + Color = 1 << 0, + Depth = 1 << 1, + Stencil = 1 << 2, +}; + +_FORCE_INLINE_ MDAttachmentType &operator|=(MDAttachmentType &p_a, MDAttachmentType p_b) { + flags::set(p_a, p_b); + return p_a; +} + +_FORCE_INLINE_ bool operator&(MDAttachmentType p_a, MDAttachmentType p_b) { + return uint8_t(p_a) & uint8_t(p_b); +} + +struct MDSubpass { + uint32_t subpass_index = 0; + uint32_t view_count = 0; + LocalVector<RDD::AttachmentReference> input_references; + LocalVector<RDD::AttachmentReference> color_references; + RDD::AttachmentReference depth_stencil_reference; + LocalVector<RDD::AttachmentReference> resolve_references; + + MTLFmtCaps getRequiredFmtCapsForAttachmentAt(uint32_t p_index) const; +}; + +struct API_AVAILABLE(macos(11.0), ios(14.0)) MDAttachment { +private: + uint32_t index = 0; + uint32_t firstUseSubpassIndex = 0; + uint32_t lastUseSubpassIndex = 0; + +public: + MTLPixelFormat format = MTLPixelFormatInvalid; + MDAttachmentType type = MDAttachmentType::None; + MTLLoadAction loadAction = MTLLoadActionDontCare; + MTLStoreAction storeAction = MTLStoreActionDontCare; + MTLLoadAction stencilLoadAction = MTLLoadActionDontCare; + MTLStoreAction stencilStoreAction = MTLStoreActionDontCare; + uint32_t samples = 1; + + /*! + * @brief Returns true if this attachment is first used in the given subpass. + * @param p_subpass + * @return + */ + _FORCE_INLINE_ bool isFirstUseOf(MDSubpass const &p_subpass) const { + return p_subpass.subpass_index == firstUseSubpassIndex; + } + + /*! + * @brief Returns true if this attachment is last used in the given subpass. + * @param p_subpass + * @return + */ + _FORCE_INLINE_ bool isLastUseOf(MDSubpass const &p_subpass) const { + return p_subpass.subpass_index == lastUseSubpassIndex; + } + + void linkToSubpass(MDRenderPass const &p_pass); + + MTLStoreAction getMTLStoreAction(MDSubpass const &p_subpass, + bool p_is_rendering_entire_area, + bool p_has_resolve, + bool p_can_resolve, + bool p_is_stencil) const; + bool configureDescriptor(MTLRenderPassAttachmentDescriptor *p_desc, + PixelFormats &p_pf, + MDSubpass const &p_subpass, + id<MTLTexture> p_attachment, + bool p_is_rendering_entire_area, + bool p_has_resolve, + bool p_can_resolve, + bool p_is_stencil) const; + /** Returns whether this attachment should be cleared in the subpass. */ + bool shouldClear(MDSubpass const &p_subpass, bool p_is_stencil) const; +}; + +class API_AVAILABLE(macos(11.0), ios(14.0)) MDRenderPass { +public: + Vector<MDAttachment> attachments; + Vector<MDSubpass> subpasses; + + uint32_t get_sample_count() const { + return attachments.is_empty() ? 1 : attachments[0].samples; + } + + MDRenderPass(Vector<MDAttachment> &p_attachments, Vector<MDSubpass> &p_subpasses); +}; + class API_AVAILABLE(macos(11.0), ios(14.0)) MDCommandBuffer { private: RenderingDeviceDriverMetal *device_driver = nullptr; @@ -204,8 +323,8 @@ private: void _render_set_dirty_state(); void _render_bind_uniform_sets(); - static void _populate_vertices(simd::float4 *p_vertices, Size2i p_fb_size, VectorView<Rect2i> p_rects); - static uint32_t _populate_vertices(simd::float4 *p_vertices, uint32_t p_index, Rect2i const &p_rect, Size2i p_fb_size); + void _populate_vertices(simd::float4 *p_vertices, Size2i p_fb_size, VectorView<Rect2i> p_rects); + uint32_t _populate_vertices(simd::float4 *p_vertices, uint32_t p_index, Rect2i const &p_rect, Size2i p_fb_size); void _end_render_pass(); void _render_clear_render_area(); @@ -230,6 +349,7 @@ public: uint32_t index_offset = 0; LocalVector<id<MTLBuffer> __unsafe_unretained> vertex_buffers; LocalVector<NSUInteger> vertex_offsets; + ResourceUsageMap resource_usage; // clang-format off enum DirtyFlag: uint8_t { DIRTY_NONE = 0b0000'0000, @@ -251,26 +371,12 @@ public: // Bit mask of the uniform sets that are dirty, to prevent redundant binding. uint64_t uniform_set_mask = 0; - _FORCE_INLINE_ void reset() { - pass = nil; - frameBuffer = nil; - pipeline = nil; - current_subpass = UINT32_MAX; - render_area = {}; - is_rendering_entire_area = false; - desc = nil; - encoder = nil; - index_buffer = nil; - index_type = MTLIndexTypeUInt16; - dirty = DIRTY_NONE; - uniform_sets.clear(); - uniform_set_mask = 0; - clear_values.clear(); - viewports.clear(); - scissors.clear(); - blend_constants.reset(); - vertex_buffers.clear(); - vertex_offsets.clear(); + _FORCE_INLINE_ void reset(); + void end_encoding(); + + _ALWAYS_INLINE_ const MDSubpass &get_subpass() const { + DEV_ASSERT(pass != nullptr); + return pass->subpasses[current_subpass]; } _FORCE_INLINE_ void mark_viewport_dirty() { @@ -356,13 +462,20 @@ public: } render; // State specific for a compute pass. - struct { + struct ComputeState { MDComputePipeline *pipeline = nullptr; id<MTLComputeCommandEncoder> encoder = nil; + ResourceUsageMap resource_usage; _FORCE_INLINE_ void reset() { pipeline = nil; encoder = nil; + // Keep the keys, as they are likely to be used again. + for (KeyValue<StageResourceUsage, LocalVector<__unsafe_unretained id<MTLResource>>> &kv : resource_usage) { + kv.value.clear(); + } } + + void end_encoding(); } compute; // State specific to a blit pass. @@ -619,6 +732,7 @@ public: uint32_t size = 0; } frag; } push_constants; + bool needs_view_mask_buffer = false; MDLibrary *vert; MDLibrary *frag; @@ -629,20 +743,10 @@ public: void encode_push_constant_data(VectorView<uint32_t> p_data, MDCommandBuffer *p_cb) final; - MDRenderShader(CharString p_name, Vector<UniformSet> p_sets, MDLibrary *p_vert, MDLibrary *p_frag); -}; - -enum StageResourceUsage : uint32_t { - VertexRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_VERTEX * 2), - VertexWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_VERTEX * 2), - FragmentRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_FRAGMENT * 2), - FragmentWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_FRAGMENT * 2), - TesselationControlRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2), - TesselationControlWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2), - TesselationEvaluationRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2), - TesselationEvaluationWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2), - ComputeRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_COMPUTE * 2), - ComputeWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_COMPUTE * 2), + MDRenderShader(CharString p_name, + bool p_needs_view_mask_buffer, + Vector<UniformSet> p_sets, + MDLibrary *p_vert, MDLibrary *p_frag); }; _FORCE_INLINE_ StageResourceUsage &operator|=(StageResourceUsage &p_a, uint32_t p_b) { @@ -667,7 +771,13 @@ struct HashMapComparatorDefault<RDD::ShaderID> { struct BoundUniformSet { id<MTLBuffer> buffer; - HashMap<id<MTLResource>, StageResourceUsage> bound_resources; + ResourceUsageMap usage_to_resources; + + /// Perform a 2-way merge each key of `ResourceVector` resources from this set into the + /// destination set. + /// + /// Assumes the vectors of resources are sorted. + void merge_into(ResourceUsageMap &p_dst) const; }; class API_AVAILABLE(macos(11.0), ios(14.0)) MDUniformSet { @@ -679,96 +789,6 @@ public: BoundUniformSet &boundUniformSetForShader(MDShader *p_shader, id<MTLDevice> p_device); }; -enum class MDAttachmentType : uint8_t { - None = 0, - Color = 1 << 0, - Depth = 1 << 1, - Stencil = 1 << 2, -}; - -_FORCE_INLINE_ MDAttachmentType &operator|=(MDAttachmentType &p_a, MDAttachmentType p_b) { - flags::set(p_a, p_b); - return p_a; -} - -_FORCE_INLINE_ bool operator&(MDAttachmentType p_a, MDAttachmentType p_b) { - return uint8_t(p_a) & uint8_t(p_b); -} - -struct MDSubpass { - uint32_t subpass_index = 0; - LocalVector<RDD::AttachmentReference> input_references; - LocalVector<RDD::AttachmentReference> color_references; - RDD::AttachmentReference depth_stencil_reference; - LocalVector<RDD::AttachmentReference> resolve_references; - - MTLFmtCaps getRequiredFmtCapsForAttachmentAt(uint32_t p_index) const; -}; - -struct API_AVAILABLE(macos(11.0), ios(14.0)) MDAttachment { -private: - uint32_t index = 0; - uint32_t firstUseSubpassIndex = 0; - uint32_t lastUseSubpassIndex = 0; - -public: - MTLPixelFormat format = MTLPixelFormatInvalid; - MDAttachmentType type = MDAttachmentType::None; - MTLLoadAction loadAction = MTLLoadActionDontCare; - MTLStoreAction storeAction = MTLStoreActionDontCare; - MTLLoadAction stencilLoadAction = MTLLoadActionDontCare; - MTLStoreAction stencilStoreAction = MTLStoreActionDontCare; - uint32_t samples = 1; - - /*! - * @brief Returns true if this attachment is first used in the given subpass. - * @param p_subpass - * @return - */ - _FORCE_INLINE_ bool isFirstUseOf(MDSubpass const &p_subpass) const { - return p_subpass.subpass_index == firstUseSubpassIndex; - } - - /*! - * @brief Returns true if this attachment is last used in the given subpass. - * @param p_subpass - * @return - */ - _FORCE_INLINE_ bool isLastUseOf(MDSubpass const &p_subpass) const { - return p_subpass.subpass_index == lastUseSubpassIndex; - } - - void linkToSubpass(MDRenderPass const &p_pass); - - MTLStoreAction getMTLStoreAction(MDSubpass const &p_subpass, - bool p_is_rendering_entire_area, - bool p_has_resolve, - bool p_can_resolve, - bool p_is_stencil) const; - bool configureDescriptor(MTLRenderPassAttachmentDescriptor *p_desc, - PixelFormats &p_pf, - MDSubpass const &p_subpass, - id<MTLTexture> p_attachment, - bool p_is_rendering_entire_area, - bool p_has_resolve, - bool p_can_resolve, - bool p_is_stencil) const; - /** Returns whether this attachment should be cleared in the subpass. */ - bool shouldClear(MDSubpass const &p_subpass, bool p_is_stencil) const; -}; - -class API_AVAILABLE(macos(11.0), ios(14.0)) MDRenderPass { -public: - Vector<MDAttachment> attachments; - Vector<MDSubpass> subpasses; - - uint32_t get_sample_count() const { - return attachments.is_empty() ? 1 : attachments[0].samples; - } - - MDRenderPass(Vector<MDAttachment> &p_attachments, Vector<MDSubpass> &p_subpasses); -}; - class API_AVAILABLE(macos(11.0), ios(14.0)) MDPipeline { public: MDPipelineType type; @@ -818,7 +838,7 @@ public: if (!enabled) return; [p_enc setStencilFrontReferenceValue:front_reference backReferenceValue:back_reference]; - }; + } } stencil; struct { @@ -832,7 +852,7 @@ public: //if (!enabled) // return; [p_enc setBlendColorRed:r green:g blue:b alpha:a]; - }; + } } blend; _FORCE_INLINE_ void apply(id<MTLRenderCommandEncoder> __unsafe_unretained p_enc) const { @@ -869,13 +889,39 @@ public: }; class API_AVAILABLE(macos(11.0), ios(14.0)) MDFrameBuffer { -public: Vector<MTL::Texture> textures; + +public: Size2i size; MDFrameBuffer(Vector<MTL::Texture> p_textures, Size2i p_size) : textures(p_textures), size(p_size) {} MDFrameBuffer() {} + /// Returns the texture at the given index. + _ALWAYS_INLINE_ MTL::Texture get_texture(uint32_t p_idx) const { + return textures[p_idx]; + } + + /// Returns true if the texture at the given index is not nil. + _ALWAYS_INLINE_ bool has_texture(uint32_t p_idx) const { + return textures[p_idx] != nil; + } + + /// Set the texture at the given index. + _ALWAYS_INLINE_ void set_texture(uint32_t p_idx, MTL::Texture p_texture) { + textures.write[p_idx] = p_texture; + } + + /// Unset or nil the texture at the given index. + _ALWAYS_INLINE_ void unset_texture(uint32_t p_idx) { + textures.write[p_idx] = nil; + } + + /// Resizes buffers to the specified size. + _ALWAYS_INLINE_ void set_texture_count(uint32_t p_size) { + textures.resize(p_size); + } + virtual ~MDFrameBuffer() = default; }; diff --git a/drivers/metal/metal_objects.mm b/drivers/metal/metal_objects.mm index 596728212a..11ab209d60 100644 --- a/drivers/metal/metal_objects.mm +++ b/drivers/metal/metal_objects.mm @@ -58,7 +58,7 @@ void MDCommandBuffer::begin() { DEV_ASSERT(commandBuffer == nil); - commandBuffer = queue.commandBuffer; + commandBuffer = queue.commandBufferWithUnretainedReferences; } void MDCommandBuffer::end() { @@ -96,6 +96,9 @@ void MDCommandBuffer::bind_pipeline(RDD::PipelineID p_pipeline) { MDRenderPipeline *rp = (MDRenderPipeline *)p; if (render.encoder == nil) { + // This error would happen if the render pass failed. + ERR_FAIL_NULL_MSG(render.desc, "Render pass descriptor is null."); + // This condition occurs when there are no attachments when calling render_next_subpass() // and is due to the SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS flag. render.desc.defaultRasterSampleCount = static_cast<NSUInteger>(rp->sample_count); @@ -223,8 +226,9 @@ void MDCommandBuffer::render_bind_uniform_set(RDD::UniformSetID p_uniform_set, R void MDCommandBuffer::render_clear_attachments(VectorView<RDD::AttachmentClear> p_attachment_clears, VectorView<Rect2i> p_rects) { DEV_ASSERT(type == MDCommandBufferStateType::Render); - uint32_t vertex_count = p_rects.size() * 6; + const MDSubpass &subpass = render.get_subpass(); + uint32_t vertex_count = p_rects.size() * 6 * subpass.view_count; simd::float4 vertices[vertex_count]; simd::float4 clear_colors[ClearAttKey::ATTACHMENT_COUNT]; @@ -235,6 +239,9 @@ void MDCommandBuffer::render_clear_attachments(VectorView<RDD::AttachmentClear> ClearAttKey key; key.sample_count = render.pass->get_sample_count(); + if (subpass.view_count > 1) { + key.enable_layered_rendering(); + } float depth_value = 0; uint32_t stencil_value = 0; @@ -245,7 +252,7 @@ void MDCommandBuffer::render_clear_attachments(VectorView<RDD::AttachmentClear> if (attClear.aspect.has_flag(RDD::TEXTURE_ASPECT_COLOR_BIT)) { attachment_index = attClear.color_attachment; } else { - attachment_index = render.pass->subpasses[render.current_subpass].depth_stencil_reference.attachment; + attachment_index = subpass.depth_stencil_reference.attachment; } MDAttachment const &mda = render.pass->attachments[attachment_index]; @@ -310,6 +317,13 @@ void MDCommandBuffer::render_clear_attachments(VectorView<RDD::AttachmentClear> void MDCommandBuffer::_render_set_dirty_state() { _render_bind_uniform_sets(); + MDSubpass const &subpass = render.get_subpass(); + if (subpass.view_count > 1) { + uint32_t view_range[2] = { 0, subpass.view_count }; + [render.encoder setVertexBytes:view_range length:sizeof(view_range) atIndex:VIEW_MASK_BUFFER_INDEX]; + [render.encoder setFragmentBytes:view_range length:sizeof(view_range) atIndex:VIEW_MASK_BUFFER_INDEX]; + } + if (render.dirty.has_flag(RenderState::DIRTY_PIPELINE)) { [render.encoder setRenderPipelineState:render.pipeline->state]; } @@ -390,6 +404,38 @@ void MDCommandBuffer::render_set_blend_constants(const Color &p_constants) { } } +void BoundUniformSet::merge_into(ResourceUsageMap &p_dst) const { + for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : usage_to_resources) { + ResourceVector *resources = p_dst.getptr(keyval.key); + if (resources == nullptr) { + resources = &p_dst.insert(keyval.key, ResourceVector())->value; + } + // Reserve space for the new resources, assuming they are all added. + resources->reserve(resources->size() + keyval.value.size()); + + uint32_t i = 0, j = 0; + __unsafe_unretained id<MTLResource> *resources_ptr = resources->ptr(); + const __unsafe_unretained id<MTLResource> *keyval_ptr = keyval.value.ptr(); + // 2-way merge. + while (i < resources->size() && j < keyval.value.size()) { + if (resources_ptr[i] < keyval_ptr[j]) { + i++; + } else if (resources_ptr[i] > keyval_ptr[j]) { + resources->insert(i, keyval_ptr[j]); + i++; + j++; + } else { + i++; + j++; + } + } + // Append the remaining resources. + for (; j < keyval.value.size(); j++) { + resources->push_back(keyval_ptr[j]); + } + } +} + void MDCommandBuffer::_render_bind_uniform_sets() { DEV_ASSERT(type == MDCommandBufferStateType::Render); if (!render.dirty.has_flag(RenderState::DIRTY_UNIFORMS)) { @@ -408,7 +454,7 @@ void MDCommandBuffer::_render_bind_uniform_sets() { // Find the index of the next set bit. int index = __builtin_ctzll(set_uniforms); // Clear the set bit. - set_uniforms &= ~(1ULL << index); + set_uniforms &= (set_uniforms - 1); MDUniformSet *set = render.uniform_sets[index]; if (set == nullptr || set->index >= (uint32_t)shader->sets.size()) { continue; @@ -416,17 +462,7 @@ void MDCommandBuffer::_render_bind_uniform_sets() { UniformSet const &set_info = shader->sets[set->index]; BoundUniformSet &bus = set->boundUniformSetForShader(shader, device); - - for (KeyValue<id<MTLResource>, StageResourceUsage> const &keyval : bus.bound_resources) { - MTLResourceUsage usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_VERTEX); - if (usage != 0) { - [enc useResource:keyval.key usage:usage stages:MTLRenderStageVertex]; - } - usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_FRAGMENT); - if (usage != 0) { - [enc useResource:keyval.key usage:usage stages:MTLRenderStageFragment]; - } - } + bus.merge_into(render.resource_usage); // Set the buffer for the vertex stage. { @@ -470,36 +506,40 @@ uint32_t MDCommandBuffer::_populate_vertices(simd::float4 *p_vertices, uint32_t simd::float4 vtx; uint32_t idx = p_index; - vtx.z = 0.0; - vtx.w = (float)1; + uint32_t endLayer = render.get_subpass().view_count; - // Top left vertex - First triangle. - vtx.y = topPos; - vtx.x = leftPos; - p_vertices[idx++] = vtx; + for (uint32_t layer = 0; layer < endLayer; layer++) { + vtx.z = 0.0; + vtx.w = (float)layer; - // Bottom left vertex. - vtx.y = bottomPos; - vtx.x = leftPos; - p_vertices[idx++] = vtx; + // Top left vertex - First triangle. + vtx.y = topPos; + vtx.x = leftPos; + p_vertices[idx++] = vtx; - // Bottom right vertex. - vtx.y = bottomPos; - vtx.x = rightPos; - p_vertices[idx++] = vtx; + // Bottom left vertex. + vtx.y = bottomPos; + vtx.x = leftPos; + p_vertices[idx++] = vtx; - // Bottom right vertex - Second triangle. - p_vertices[idx++] = vtx; + // Bottom right vertex. + vtx.y = bottomPos; + vtx.x = rightPos; + p_vertices[idx++] = vtx; - // Top right vertex. - vtx.y = topPos; - vtx.x = rightPos; - p_vertices[idx++] = vtx; + // Bottom right vertex - Second triangle. + p_vertices[idx++] = vtx; - // Top left vertex. - vtx.y = topPos; - vtx.x = leftPos; - p_vertices[idx++] = vtx; + // Top right vertex. + vtx.y = topPos; + vtx.x = rightPos; + p_vertices[idx++] = vtx; + + // Top left vertex. + vtx.y = topPos; + vtx.x = leftPos; + p_vertices[idx++] = vtx; + } return idx; } @@ -526,8 +566,7 @@ void MDCommandBuffer::render_begin_pass(RDD::RenderPassID p_render_pass, RDD::Fr void MDCommandBuffer::_end_render_pass() { MDFrameBuffer const &fb_info = *render.frameBuffer; - MDRenderPass const &pass_info = *render.pass; - MDSubpass const &subpass = pass_info.subpasses[render.current_subpass]; + MDSubpass const &subpass = render.get_subpass(); PixelFormats &pf = device_driver->get_pixel_formats(); @@ -535,23 +574,22 @@ void MDCommandBuffer::_end_render_pass() { uint32_t color_index = subpass.color_references[i].attachment; uint32_t resolve_index = subpass.resolve_references[i].attachment; DEV_ASSERT((color_index == RDD::AttachmentReference::UNUSED) == (resolve_index == RDD::AttachmentReference::UNUSED)); - if (color_index == RDD::AttachmentReference::UNUSED || !fb_info.textures[color_index]) { + if (color_index == RDD::AttachmentReference::UNUSED || !fb_info.has_texture(color_index)) { continue; } - id<MTLTexture> resolve_tex = fb_info.textures[resolve_index]; + id<MTLTexture> resolve_tex = fb_info.get_texture(resolve_index); CRASH_COND_MSG(!flags::all(pf.getCapabilities(resolve_tex.pixelFormat), kMTLFmtCapsResolve), "not implemented: unresolvable texture types"); // see: https://github.com/KhronosGroup/MoltenVK/blob/d20d13fe2735adb845636a81522df1b9d89c0fba/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm#L407 } - [render.encoder endEncoding]; - render.encoder = nil; + render.end_encoding(); } void MDCommandBuffer::_render_clear_render_area() { MDRenderPass const &pass = *render.pass; - MDSubpass const &subpass = pass.subpasses[render.current_subpass]; + MDSubpass const &subpass = render.get_subpass(); // First determine attachments that should be cleared. LocalVector<RDD::AttachmentClear> clears; @@ -598,9 +636,14 @@ void MDCommandBuffer::render_next_subpass() { MDFrameBuffer const &fb = *render.frameBuffer; MDRenderPass const &pass = *render.pass; - MDSubpass const &subpass = pass.subpasses[render.current_subpass]; + MDSubpass const &subpass = render.get_subpass(); MTLRenderPassDescriptor *desc = MTLRenderPassDescriptor.renderPassDescriptor; + + if (subpass.view_count > 1) { + desc.renderTargetArrayLength = subpass.view_count; + } + PixelFormats &pf = device_driver->get_pixel_formats(); uint32_t attachmentCount = 0; @@ -617,7 +660,7 @@ void MDCommandBuffer::render_next_subpass() { bool has_resolve = resolveIdx != RDD::AttachmentReference::UNUSED; bool can_resolve = true; if (resolveIdx != RDD::AttachmentReference::UNUSED) { - id<MTLTexture> resolve_tex = fb.textures[resolveIdx]; + id<MTLTexture> resolve_tex = fb.get_texture(resolveIdx); can_resolve = flags::all(pf.getCapabilities(resolve_tex.pixelFormat), kMTLFmtCapsResolve); if (can_resolve) { ca.resolveTexture = resolve_tex; @@ -628,7 +671,9 @@ void MDCommandBuffer::render_next_subpass() { MDAttachment const &attachment = pass.attachments[idx]; - id<MTLTexture> tex = fb.textures[idx]; + id<MTLTexture> tex = fb.get_texture(idx); + ERR_FAIL_NULL_MSG(tex, "Frame buffer color texture is null."); + if ((attachment.type & MDAttachmentType::Color)) { if (attachment.configureDescriptor(ca, pf, subpass, tex, render.is_rendering_entire_area, has_resolve, can_resolve, false)) { Color clearColor = render.clear_values[idx].color; @@ -641,7 +686,8 @@ void MDCommandBuffer::render_next_subpass() { attachmentCount += 1; uint32_t idx = subpass.depth_stencil_reference.attachment; MDAttachment const &attachment = pass.attachments[idx]; - id<MTLTexture> tex = fb.textures[idx]; + id<MTLTexture> tex = fb.get_texture(idx); + ERR_FAIL_NULL_MSG(tex, "Frame buffer depth / stencil texture is null."); if (attachment.type & MDAttachmentType::Depth) { MTLRenderPassDepthAttachmentDescriptor *da = desc.depthAttachment; if (attachment.configureDescriptor(da, pf, subpass, tex, render.is_rendering_entire_area, false, false, false)) { @@ -681,8 +727,15 @@ void MDCommandBuffer::render_draw(uint32_t p_vertex_count, uint32_t p_base_vertex, uint32_t p_first_instance) { DEV_ASSERT(type == MDCommandBufferStateType::Render); + ERR_FAIL_NULL_MSG(render.pipeline, "No pipeline set for render command buffer."); + _render_set_dirty_state(); + MDSubpass const &subpass = render.get_subpass(); + if (subpass.view_count > 1) { + p_instance_count *= subpass.view_count; + } + DEV_ASSERT(render.dirty == 0); id<MTLRenderCommandEncoder> enc = render.encoder; @@ -730,8 +783,15 @@ void MDCommandBuffer::render_draw_indexed(uint32_t p_index_count, int32_t p_vertex_offset, uint32_t p_first_instance) { DEV_ASSERT(type == MDCommandBufferStateType::Render); + ERR_FAIL_NULL_MSG(render.pipeline, "No pipeline set for render command buffer."); + _render_set_dirty_state(); + MDSubpass const &subpass = render.get_subpass(); + if (subpass.view_count > 1) { + p_instance_count *= subpass.view_count; + } + id<MTLRenderCommandEncoder> enc = render.encoder; uint32_t index_offset = render.index_offset; @@ -749,6 +809,8 @@ void MDCommandBuffer::render_draw_indexed(uint32_t p_index_count, void MDCommandBuffer::render_draw_indexed_indirect(RDD::BufferID p_indirect_buffer, uint64_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { DEV_ASSERT(type == MDCommandBufferStateType::Render); + ERR_FAIL_NULL_MSG(render.pipeline, "No pipeline set for render command buffer."); + _render_set_dirty_state(); id<MTLRenderCommandEncoder> enc = render.encoder; @@ -773,6 +835,8 @@ void MDCommandBuffer::render_draw_indexed_indirect_count(RDD::BufferID p_indirec void MDCommandBuffer::render_draw_indirect(RDD::BufferID p_indirect_buffer, uint64_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { DEV_ASSERT(type == MDCommandBufferStateType::Render); + ERR_FAIL_NULL_MSG(render.pipeline, "No pipeline set for render command buffer."); + _render_set_dirty_state(); id<MTLRenderCommandEncoder> enc = render.encoder; @@ -795,11 +859,90 @@ void MDCommandBuffer::render_draw_indirect_count(RDD::BufferID p_indirect_buffer void MDCommandBuffer::render_end_pass() { DEV_ASSERT(type == MDCommandBufferStateType::Render); - [render.encoder endEncoding]; + render.end_encoding(); render.reset(); type = MDCommandBufferStateType::None; } +#pragma mark - RenderState + +void MDCommandBuffer::RenderState::reset() { + pass = nil; + frameBuffer = nil; + pipeline = nil; + current_subpass = UINT32_MAX; + render_area = {}; + is_rendering_entire_area = false; + desc = nil; + encoder = nil; + index_buffer = nil; + index_type = MTLIndexTypeUInt16; + dirty = DIRTY_NONE; + uniform_sets.clear(); + uniform_set_mask = 0; + clear_values.clear(); + viewports.clear(); + scissors.clear(); + blend_constants.reset(); + vertex_buffers.clear(); + vertex_offsets.clear(); + // Keep the keys, as they are likely to be used again. + for (KeyValue<StageResourceUsage, LocalVector<__unsafe_unretained id<MTLResource>>> &kv : resource_usage) { + kv.value.clear(); + } +} + +void MDCommandBuffer::RenderState::end_encoding() { + if (encoder == nil) { + return; + } + + // Bind all resources. + for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : resource_usage) { + if (keyval.value.is_empty()) { + continue; + } + + MTLResourceUsage vert_usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_VERTEX); + MTLResourceUsage frag_usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_FRAGMENT); + if (vert_usage == frag_usage) { + [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:vert_usage stages:MTLRenderStageVertex | MTLRenderStageFragment]; + } else { + if (vert_usage != 0) { + [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:vert_usage stages:MTLRenderStageVertex]; + } + if (frag_usage != 0) { + [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:frag_usage stages:MTLRenderStageFragment]; + } + } + } + + [encoder endEncoding]; + encoder = nil; +} + +#pragma mark - ComputeState + +void MDCommandBuffer::ComputeState::end_encoding() { + if (encoder == nil) { + return; + } + + // Bind all resources. + for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : resource_usage) { + if (keyval.value.is_empty()) { + continue; + } + MTLResourceUsage usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_COMPUTE); + if (usage != 0) { + [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:usage]; + } + } + + [encoder endEncoding]; + encoder = nil; +} + #pragma mark - Compute void MDCommandBuffer::compute_bind_uniform_set(RDD::UniformSetID p_uniform_set, RDD::ShaderID p_shader, uint32_t p_set_index) { @@ -813,13 +956,7 @@ void MDCommandBuffer::compute_bind_uniform_set(RDD::UniformSetID p_uniform_set, MDUniformSet *set = (MDUniformSet *)(p_uniform_set.id); BoundUniformSet &bus = set->boundUniformSetForShader(shader, device); - - for (KeyValue<id<MTLResource>, StageResourceUsage> &keyval : bus.bound_resources) { - MTLResourceUsage usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_COMPUTE); - if (usage != 0) { - [enc useResource:keyval.key usage:usage]; - } - } + bus.merge_into(compute.resource_usage); uint32_t const *offset = set_info.offsets.getptr(RDD::SHADER_STAGE_COMPUTE); if (offset) { @@ -848,7 +985,7 @@ void MDCommandBuffer::compute_dispatch_indirect(RDD::BufferID p_indirect_buffer, void MDCommandBuffer::_end_compute_dispatch() { DEV_ASSERT(type == MDCommandBufferStateType::Compute); - [compute.encoder endEncoding]; + compute.end_encoding(); compute.reset(); type = MDCommandBufferStateType::None; } @@ -879,8 +1016,11 @@ void MDComputeShader::encode_push_constant_data(VectorView<uint32_t> p_data, MDC [enc setBytes:ptr length:length atIndex:push_constants.binding]; } -MDRenderShader::MDRenderShader(CharString p_name, Vector<UniformSet> p_sets, MDLibrary *_Nonnull p_vert, MDLibrary *_Nonnull p_frag) : - MDShader(p_name, p_sets), vert(p_vert), frag(p_frag) { +MDRenderShader::MDRenderShader(CharString p_name, + bool p_needs_view_mask_buffer, + Vector<UniformSet> p_sets, + MDLibrary *_Nonnull p_vert, MDLibrary *_Nonnull p_frag) : + MDShader(p_name, p_sets), needs_view_mask_buffer(p_needs_view_mask_buffer), vert(p_vert), frag(p_frag) { } void MDRenderShader::encode_push_constant_data(VectorView<uint32_t> p_data, MDCommandBuffer *p_cb) { @@ -1052,7 +1192,20 @@ BoundUniformSet &MDUniformSet::boundUniformSetForShader(MDShader *p_shader, id<M } } - BoundUniformSet bs = { .buffer = enc_buffer, .bound_resources = bound_resources }; + SearchArray<__unsafe_unretained id<MTLResource>> search; + ResourceUsageMap usage_to_resources; + for (KeyValue<id<MTLResource>, StageResourceUsage> const &keyval : bound_resources) { + ResourceVector *resources = usage_to_resources.getptr(keyval.value); + if (resources == nullptr) { + resources = &usage_to_resources.insert(keyval.value, ResourceVector())->value; + } + int64_t pos = search.bisect(resources->ptr(), resources->size(), keyval.key, true); + if (pos == resources->size() || (*resources)[pos] != keyval.key) { + resources->insert(pos, keyval.key); + } + } + + BoundUniformSet bs = { .buffer = enc_buffer, .usage_to_resources = usage_to_resources }; bound_uniforms.insert(p_shader, bs); return bound_uniforms.get(p_shader); } @@ -1202,7 +1355,7 @@ typedef struct { typedef struct { float4 v_position [[position]]; - uint layer; + uint layer%s; } VaryingsPos; vertex VaryingsPos vertClear(AttributesPos attributes [[stage_in]], constant ClearColorsIn& ccIn [[buffer(0)]]) { @@ -1211,8 +1364,7 @@ vertex VaryingsPos vertClear(AttributesPos attributes [[stage_in]], constant Cle varyings.layer = uint(attributes.a_position.w); return varyings; } -)", - ClearAttKey::DEPTH_INDEX]; +)", p_key.is_layered_rendering_enabled() ? " [[render_target_array_index]]" : "", ClearAttKey::DEPTH_INDEX]; return new_func(msl, @"vertClear", nil); } @@ -1502,7 +1654,7 @@ void ShaderCacheEntry::notify_free() const { self->_library = library; self->_error = error; if (error) { - ERR_PRINT(String(U"Error compiling shader %s: %s").format(entry->name.get_data(), error.localizedDescription.UTF8String)); + ERR_PRINT(vformat(U"Error compiling shader %s: %s", entry->name.get_data(), error.localizedDescription.UTF8String)); } { diff --git a/drivers/metal/rendering_context_driver_metal.h b/drivers/metal/rendering_context_driver_metal.h index 7e0b09186d..1fdc255f93 100644 --- a/drivers/metal/rendering_context_driver_metal.h +++ b/drivers/metal/rendering_context_driver_metal.h @@ -107,6 +107,7 @@ public: uint32_t height = 0; DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED; bool needs_resize = false; + double present_minimum_duration = 0.0; Surface( #ifdef __OBJC__ @@ -123,6 +124,7 @@ public: virtual Error resize(uint32_t p_desired_framebuffer_count) = 0; virtual RDD::FramebufferID acquire_next_frame_buffer() = 0; virtual void present(MDCommandBuffer *p_cmd_buffer) = 0; + void set_max_fps(int p_max_fps) { present_minimum_duration = p_max_fps ? 1.0 / p_max_fps : 0.0; } }; #ifdef __OBJC__ diff --git a/drivers/metal/rendering_context_driver_metal.mm b/drivers/metal/rendering_context_driver_metal.mm index b97b586352..199ec25d79 100644 --- a/drivers/metal/rendering_context_driver_metal.mm +++ b/drivers/metal/rendering_context_driver_metal.mm @@ -134,7 +134,7 @@ public: frame_buffers.resize(p_desired_framebuffer_count); for (uint32_t i = 0; i < p_desired_framebuffer_count; i++) { // Reserve space for the drawable texture. - frame_buffers[i].textures.resize(1); + frame_buffers[i].set_texture_count(1); } return OK; @@ -154,7 +154,7 @@ public: id<CAMetalDrawable> drawable = layer.nextDrawable; ERR_FAIL_NULL_V_MSG(drawable, RDD::FramebufferID(), "no drawable available"); drawables[rear] = drawable; - frame_buffer.textures.write[0] = drawable.texture; + frame_buffer.set_texture(0, drawable.texture); return RDD::FramebufferID(&frame_buffer); } @@ -165,14 +165,14 @@ public: } // Release texture and drawable. - frame_buffers[front].textures.write[0] = nil; + frame_buffers[front].unset_texture(0); id<MTLDrawable> drawable = drawables[front]; drawables[front] = nil; count--; front = (front + 1) % frame_buffers.size(); - [p_cmd_buffer->get_command_buffer() presentDrawable:drawable]; + [p_cmd_buffer->get_command_buffer() presentDrawable:drawable afterMinimumDuration:present_minimum_duration]; } }; diff --git a/drivers/metal/rendering_device_driver_metal.h b/drivers/metal/rendering_device_driver_metal.h index 7c23624e43..09ab7601e9 100644 --- a/drivers/metal/rendering_device_driver_metal.h +++ b/drivers/metal/rendering_device_driver_metal.h @@ -220,6 +220,7 @@ public: virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) override final; virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) override final; virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override final; + virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) override final; virtual void swap_chain_free(SwapChainID p_swap_chain) override final; #pragma mark - Frame Buffer @@ -239,7 +240,13 @@ private: friend struct PushConstantData; private: - Error _reflect_spirv16(VectorView<ShaderStageSPIRVData> p_spirv, ShaderReflection &r_reflection); + /// Contains additional metadata about the shader. + struct ShaderMeta { + /// Indicates whether the shader uses multiview. + bool has_multiview = false; + }; + + Error _reflect_spirv16(VectorView<ShaderStageSPIRVData> p_spirv, ShaderReflection &r_reflection, ShaderMeta &r_shader_meta); public: virtual String shader_get_binary_cache_key() override final; @@ -410,7 +417,7 @@ public: virtual uint64_t api_trait_get(ApiTrait p_trait) override final; virtual bool has_feature(Features p_feature) override final; virtual const MultiviewCapabilities &get_multiview_capabilities() override final; - virtual String get_api_name() const override final { return "Metal"; }; + virtual String get_api_name() const override final { return "Metal"; } virtual String get_api_version() const override final; virtual String get_pipeline_cache_uuid() const override final; virtual const Capabilities &get_capabilities() const override final; diff --git a/drivers/metal/rendering_device_driver_metal.mm b/drivers/metal/rendering_device_driver_metal.mm index a4a408356a..784c9d5ae8 100644 --- a/drivers/metal/rendering_device_driver_metal.mm +++ b/drivers/metal/rendering_device_driver_metal.mm @@ -982,6 +982,12 @@ RDD::DataFormat RenderingDeviceDriverMetal::swap_chain_get_format(SwapChainID p_ return swap_chain->data_format; } +void RenderingDeviceDriverMetal::swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) { + SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id); + RenderingContextDriverMetal::Surface *metal_surface = (RenderingContextDriverMetal::Surface *)(swap_chain->surface); + metal_surface->set_max_fps(p_max_fps); +} + void RenderingDeviceDriverMetal::swap_chain_free(SwapChainID p_swap_chain) { SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id); _swap_chain_release(swap_chain); @@ -1026,7 +1032,7 @@ void RenderingDeviceDriverMetal::framebuffer_free(FramebufferID p_framebuffer) { #pragma mark - Shader -const uint32_t SHADER_BINARY_VERSION = 1; +const uint32_t SHADER_BINARY_VERSION = 3; // region Serialization @@ -1330,23 +1336,32 @@ struct ComputeSize { struct ShaderStageData { RD::ShaderStage stage = RD::ShaderStage::SHADER_STAGE_MAX; + uint32_t is_position_invariant = UINT32_MAX; + uint32_t supports_fast_math = UINT32_MAX; CharString entry_point_name; CharString source; size_t serialize_size() const { int comp_size = Compression::get_max_compressed_buffer_size(source.length(), Compression::MODE_ZSTD); return sizeof(uint32_t) // Stage. - + sizeof(uint32_t) /* entry_point_name.utf8().length */ + entry_point_name.length() + sizeof(uint32_t) /* uncompressed size */ + sizeof(uint32_t) /* compressed size */ + comp_size; + + sizeof(uint32_t) // is_position_invariant + + sizeof(uint32_t) // supports_fast_math + + sizeof(uint32_t) /* entry_point_name.utf8().length */ + + entry_point_name.length() + sizeof(uint32_t) /* uncompressed size */ + sizeof(uint32_t) /* compressed size */ + comp_size; } void serialize(BufWriter &p_writer) const { p_writer.write((uint32_t)stage); + p_writer.write(is_position_invariant); + p_writer.write(supports_fast_math); p_writer.write(entry_point_name); p_writer.write_compressed(source); } void deserialize(BufReader &p_reader) { p_reader.read((uint32_t &)stage); + p_reader.read(is_position_invariant); + p_reader.read(supports_fast_math); p_reader.read(entry_point_name); p_reader.read_compressed(source); } @@ -1503,6 +1518,7 @@ struct API_AVAILABLE(macos(11.0), ios(14.0)) ShaderBinaryData { uint32_t fragment_output_mask = UINT32_MAX; uint32_t spirv_specialization_constants_ids_mask = UINT32_MAX; uint32_t is_compute = UINT32_MAX; + uint32_t needs_view_mask_buffer = UINT32_MAX; ComputeSize compute_local_size; PushConstantData push_constant; LocalVector<ShaderStageData> stages; @@ -1523,6 +1539,7 @@ struct API_AVAILABLE(macos(11.0), ios(14.0)) ShaderBinaryData { size += sizeof(uint32_t); // fragment_output_mask size += sizeof(uint32_t); // spirv_specialization_constants_ids_mask size += sizeof(uint32_t); // is_compute + size += sizeof(uint32_t); // needs_view_mask_buffer size += compute_local_size.serialize_size(); // compute_local_size size += push_constant.serialize_size(); // push_constant size += sizeof(uint32_t); // stages.size() @@ -1547,6 +1564,7 @@ struct API_AVAILABLE(macos(11.0), ios(14.0)) ShaderBinaryData { p_writer.write(fragment_output_mask); p_writer.write(spirv_specialization_constants_ids_mask); p_writer.write(is_compute); + p_writer.write(needs_view_mask_buffer); p_writer.write(compute_local_size); p_writer.write(push_constant); p_writer.write(VectorView(stages)); @@ -1561,6 +1579,7 @@ struct API_AVAILABLE(macos(11.0), ios(14.0)) ShaderBinaryData { p_reader.read(fragment_output_mask); p_reader.read(spirv_specialization_constants_ids_mask); p_reader.read(is_compute); + p_reader.read(needs_view_mask_buffer); p_reader.read(compute_local_size); p_reader.read(push_constant); p_reader.read(stages); @@ -1572,14 +1591,16 @@ struct API_AVAILABLE(macos(11.0), ios(14.0)) ShaderBinaryData { // endregion String RenderingDeviceDriverMetal::shader_get_binary_cache_key() { - return "Metal-SV" + uitos(SHADER_BINARY_VERSION); + static const String cache_key = "Metal-SV" + uitos(SHADER_BINARY_VERSION); + return cache_key; } -Error RenderingDeviceDriverMetal::_reflect_spirv16(VectorView<ShaderStageSPIRVData> p_spirv, ShaderReflection &r_reflection) { +Error RenderingDeviceDriverMetal::_reflect_spirv16(VectorView<ShaderStageSPIRVData> p_spirv, ShaderReflection &r_reflection, ShaderMeta &r_shader_meta) { using namespace spirv_cross; using spirv_cross::Resource; r_reflection = {}; + r_shader_meta = {}; for (uint32_t i = 0; i < p_spirv.size(); i++) { ShaderStageSPIRVData const &v = p_spirv[i]; @@ -1811,6 +1832,20 @@ Error RenderingDeviceDriverMetal::_reflect_spirv16(VectorView<ShaderStageSPIRVDa } } + for (const BuiltInResource &res : resources.builtin_inputs) { + if (res.builtin == spv::BuiltInViewIndex || res.builtin == spv::BuiltInViewportIndex) { + r_shader_meta.has_multiview = true; + } + } + + if (!r_shader_meta.has_multiview) { + for (const BuiltInResource &res : resources.builtin_outputs) { + if (res.builtin == spv::BuiltInViewIndex || res.builtin == spv::BuiltInViewportIndex) { + r_shader_meta.has_multiview = true; + } + } + } + // Specialization constants. for (SpecializationConstant const &constant : compiler.get_specialization_constants()) { int32_t existing = -1; @@ -1874,7 +1909,8 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec using spirv_cross::Resource; ShaderReflection spirv_data; - ERR_FAIL_COND_V(_reflect_spirv16(p_spirv, spirv_data), Result()); + ShaderMeta shader_meta; + ERR_FAIL_COND_V(_reflect_spirv16(p_spirv, spirv_data, shader_meta), Result()); ShaderBinaryData bin_data{}; if (!p_shader_name.is_empty()) { @@ -1893,6 +1929,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec bin_data.is_compute = spirv_data.is_compute; bin_data.push_constant.size = spirv_data.push_constant_size; bin_data.push_constant.stages = (ShaderStageUsage)(uint8_t)spirv_data.push_constant_stages; + bin_data.needs_view_mask_buffer = shader_meta.has_multiview ? 1 : 0; for (uint32_t i = 0; i < spirv_data.uniform_sets.size(); i++) { const ::Vector<ShaderUniform> &spirv_set = spirv_data.uniform_sets[i]; @@ -1947,6 +1984,11 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec msl_options.pad_fragment_output_components = true; msl_options.r32ui_alignment_constant_id = R32UI_ALIGNMENT_CONSTANT_ID; msl_options.agx_manual_cube_grad_fixup = true; + if (shader_meta.has_multiview) { + msl_options.multiview = true; + msl_options.multiview_layered_rendering = true; + msl_options.view_mask_buffer_index = VIEW_MASK_BUFFER_INDEX; + } CompilerGLSL::Options options{}; options.vertex.flip_vert_y = true; @@ -1978,7 +2020,8 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec ERR_FAIL_COND_V_MSG(compiler.get_entry_points_and_stages().size() != 1, Result(), "Expected a single entry point and stage."); - EntryPoint &entry_point_stage = compiler.get_entry_points_and_stages().front(); + SmallVector<EntryPoint> entry_pts_stages = compiler.get_entry_points_and_stages(); + EntryPoint &entry_point_stage = entry_pts_stages.front(); SPIREntryPoint &entry_point = compiler.get_entry_point(entry_point_stage.name, entry_point_stage.execution_model); // Process specialization constants. @@ -2060,6 +2103,10 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec case BT::Sampler: { primary.dataType = MTLDataTypeSampler; + primary.arrayLength = 1; + for (uint32_t const &a : a_type.array) { + primary.arrayLength *= a; + } } break; default: { @@ -2067,7 +2114,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec } break; } - // Find array length. + // Find array length of image. if (basetype == BT::Image || basetype == BT::SampledImage) { primary.arrayLength = 1; for (uint32_t const &a : a_type.array) { @@ -2256,6 +2303,8 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec ShaderStageData stage_data; stage_data.stage = v.shader_stage; + stage_data.is_position_invariant = compiler.is_position_invariant(); + stage_data.supports_fast_math = !entry_point.flags.get(spv::ExecutionModeSignedZeroInfNanPreserve); stage_data.entry_point_name = entry_point.name.c_str(); stage_data.source = source.c_str(); bin_data.stages.push_back(stage_data); @@ -2328,7 +2377,8 @@ RDD::ShaderID RenderingDeviceDriverMetal::shader_create_from_bytecode(const Vect ShaderCacheEntry *cd = memnew(ShaderCacheEntry(*this, key)); cd->name = binary_data.shader_name; cd->stage = shader_data.stage; - + options.preserveInvariance = shader_data.is_position_invariant; + options.fastMathEnabled = YES; MDLibrary *library = [MDLibrary newLibraryWithCacheEntry:cd device:device source:source @@ -2444,7 +2494,7 @@ RDD::ShaderID RenderingDeviceDriverMetal::shader_create_from_bytecode(const Vect #endif shader = cs; } else { - MDRenderShader *rs = new MDRenderShader(binary_data.shader_name, uniform_sets, libraries[ShaderStage::SHADER_STAGE_VERTEX], libraries[ShaderStage::SHADER_STAGE_FRAGMENT]); + MDRenderShader *rs = new MDRenderShader(binary_data.shader_name, (bool)binary_data.needs_view_mask_buffer, uniform_sets, libraries[ShaderStage::SHADER_STAGE_VERTEX], libraries[ShaderStage::SHADER_STAGE_FRAGMENT]); uint32_t *vert_binding = binary_data.push_constant.msl_binding.getptr(SHADER_STAGE_VERTEX); if (vert_binding) { @@ -2952,6 +3002,7 @@ RDD::RenderPassID RenderingDeviceDriverMetal::render_pass_create(VectorView<Atta for (uint32_t i = 0; i < subpass_count; i++) { MDSubpass &subpass = subpasses.write[i]; subpass.subpass_index = i; + subpass.view_count = p_view_count; subpass.input_references = p_subpasses[i].input_references; subpass.color_references = p_subpasses[i].color_references; subpass.depth_stencil_reference = p_subpasses[i].depth_stencil_reference; @@ -3671,8 +3722,7 @@ void RenderingDeviceDriverMetal::set_object_name(ObjectType p_type, ID p_driver_ uint64_t RenderingDeviceDriverMetal::get_resource_native_handle(DriverResource p_type, ID p_driver_id) { switch (p_type) { case DRIVER_RESOURCE_LOGICAL_DEVICE: { - uintptr_t devicePtr = (uintptr_t)(__bridge void *)device; - return (uint64_t)devicePtr; + return (uint64_t)(uintptr_t)(__bridge void *)device; } case DRIVER_RESOURCE_PHYSICAL_DEVICE: { return 0; @@ -3681,7 +3731,7 @@ uint64_t RenderingDeviceDriverMetal::get_resource_native_handle(DriverResource p return 0; } case DRIVER_RESOURCE_COMMAND_QUEUE: { - return 0; + return (uint64_t)(uintptr_t)(__bridge void *)device_queue; } case DRIVER_RESOURCE_QUEUE_FAMILY: { return 0; @@ -3698,15 +3748,20 @@ uint64_t RenderingDeviceDriverMetal::get_resource_native_handle(DriverResource p case DRIVER_RESOURCE_SAMPLER: { return p_driver_id.id; } - case DRIVER_RESOURCE_UNIFORM_SET: + case DRIVER_RESOURCE_UNIFORM_SET: { return 0; + } case DRIVER_RESOURCE_BUFFER: { return p_driver_id.id; } - case DRIVER_RESOURCE_COMPUTE_PIPELINE: - return 0; - case DRIVER_RESOURCE_RENDER_PIPELINE: - return 0; + case DRIVER_RESOURCE_COMPUTE_PIPELINE: { + MDComputePipeline *pipeline = (MDComputePipeline *)(p_driver_id.id); + return (uint64_t)(uintptr_t)(__bridge void *)pipeline->state; + } + case DRIVER_RESOURCE_RENDER_PIPELINE: { + MDRenderPipeline *pipeline = (MDRenderPipeline *)(p_driver_id.id); + return (uint64_t)(uintptr_t)(__bridge void *)pipeline->state; + } default: { return 0; } @@ -3838,7 +3893,7 @@ uint64_t RenderingDeviceDriverMetal::api_trait_get(ApiTrait p_trait) { bool RenderingDeviceDriverMetal::has_feature(Features p_feature) { switch (p_feature) { case SUPPORTS_MULTIVIEW: - return false; + return multiview_capabilities.is_supported; case SUPPORTS_FSR_HALF_FLOAT: return true; case SUPPORTS_ATTACHMENT_VRS: @@ -3947,6 +4002,18 @@ Error RenderingDeviceDriverMetal::initialize(uint32_t p_device_index, uint32_t p metal_device_properties = memnew(MetalDeviceProperties(device)); pixel_formats = memnew(PixelFormats(device)); + if (metal_device_properties->features.layeredRendering) { + multiview_capabilities.is_supported = true; + multiview_capabilities.max_view_count = metal_device_properties->limits.maxViewports; + // NOTE: I'm not sure what the limit is as I don't see it referenced anywhere + multiview_capabilities.max_instance_count = UINT32_MAX; + + print_verbose("- Metal multiview supported:"); + print_verbose(" max view count: " + itos(multiview_capabilities.max_view_count)); + print_verbose(" max instances: " + itos(multiview_capabilities.max_instance_count)); + } else { + print_verbose("- Metal multiview not supported"); + } // Check required features and abort if any of them is missing. if (!metal_device_properties->features.imageCubeArray) { diff --git a/drivers/png/SCsub b/drivers/png/SCsub index fce37257b1..4268a66475 100644 --- a/drivers/png/SCsub +++ b/drivers/png/SCsub @@ -46,18 +46,18 @@ if env["builtin_libpng"]: if "S_compiler" in env: env_neon["CC"] = env["S_compiler"] neon_sources = [] - neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/arm_init.c")) - neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon_intrinsics.c")) - neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon.S")) - neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/palette_neon_intrinsics.c")) + neon_sources.append(env_neon.Object(thirdparty_dir + "arm/arm_init.c")) + neon_sources.append(env_neon.Object(thirdparty_dir + "arm/filter_neon_intrinsics.c")) + neon_sources.append(env_neon.Object(thirdparty_dir + "arm/filter_neon.S")) + neon_sources.append(env_neon.Object(thirdparty_dir + "arm/palette_neon_intrinsics.c")) thirdparty_obj += neon_sources elif env["arch"].startswith("x86"): env_thirdparty.Append(CPPDEFINES=["PNG_INTEL_SSE"]) - env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/intel/intel_init.c") - env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/intel/filter_sse2_intrinsics.c") + env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "intel/intel_init.c") + env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "intel/filter_sse2_intrinsics.c") elif env["arch"] == "ppc64": - env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/powerpc/powerpc_init.c") - env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/powerpc/filter_vsx_intrinsics.c") + env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "powerpc/powerpc_init.c") + env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "powerpc/filter_vsx_intrinsics.c") env.drivers_sources += thirdparty_obj diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 585e882059..6456467cb9 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -100,7 +100,7 @@ class AudioDriverPulseAudio : public AudioDriver { public: virtual const char *get_name() const override { return "PulseAudio"; - }; + } virtual Error init() override; virtual void start() override; diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 3d584341ed..4b92e5f8a1 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -41,6 +41,11 @@ #include <sys/types.h> #include <unistd.h> +#if defined(TOOLS_ENABLED) +#include <limits.h> +#include <stdlib.h> +#endif + void FileAccessUnix::check_errors() const { ERR_FAIL_NULL_MSG(f, "File must be opened before use."); @@ -87,6 +92,22 @@ Error FileAccessUnix::open_internal(const String &p_path, int p_mode_flags) { } } +#if defined(TOOLS_ENABLED) + if (p_mode_flags & READ) { + String real_path = get_real_path(); + if (real_path != path) { + // Don't warn on symlinks, since they can be used to simply share addons on multiple projects. + if (real_path.to_lower() == path.to_lower()) { + // The File system is case insensitive, but other platforms can be sensitive to it + // To ease cross-platform development, we issue a warning if users try to access + // a file using the wrong case (which *works* on Windows and macOS, but won't on other + // platforms). + WARN_PRINT(vformat("Case mismatch opening requested file '%s', stored as '%s' in the filesystem. This file will not open when exported to other case-sensitive platforms.", path, real_path)); + } + } + } +#endif + if (is_backup_save_enabled() && (p_mode_flags == WRITE)) { save_path = path; // Create a temporary file in the same directory as the target file. @@ -97,7 +118,7 @@ Error FileAccessUnix::open_internal(const String &p_path, int p_mode_flags) { last_error = ERR_FILE_CANT_OPEN; return last_error; } - fchmod(fd, 0666); + fchmod(fd, 0644); path = String::utf8(cs.ptr()); f = fdopen(fd, mode_string); @@ -173,6 +194,26 @@ String FileAccessUnix::get_path_absolute() const { return path; } +#if defined(TOOLS_ENABLED) +String FileAccessUnix::get_real_path() const { + char *resolved_path = ::realpath(path.utf8().get_data(), nullptr); + + if (!resolved_path) { + return path; + } + + String result; + Error parse_ok = result.parse_utf8(resolved_path); + ::free(resolved_path); + + if (parse_ok != OK) { + return path; + } + + return result.simplify_path(); +} +#endif + void FileAccessUnix::seek(uint64_t p_position) { ERR_FAIL_NULL_MSG(f, "File must be opened before use."); diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 76f629f7c2..7caf8a14d7 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -51,6 +51,10 @@ class FileAccessUnix : public FileAccess { void _close(); +#if defined(TOOLS_ENABLED) + String get_real_path() const; // Returns the resolved real path for the current open file. +#endif + public: static CloseNotificationFunc close_notification_func; diff --git a/drivers/unix/file_access_unix_pipe.cpp b/drivers/unix/file_access_unix_pipe.cpp index 0a78429dec..fd60bec9d0 100644 --- a/drivers/unix/file_access_unix_pipe.cpp +++ b/drivers/unix/file_access_unix_pipe.cpp @@ -70,7 +70,7 @@ Error FileAccessUnixPipe::open_internal(const String &p_path, int p_mode_flags) struct stat st = {}; int err = stat(path.utf8().get_data(), &st); if (err) { - if (mkfifo(path.utf8().get_data(), 0666) != 0) { + if (mkfifo(path.utf8().get_data(), 0600) != 0) { last_error = ERR_FILE_CANT_OPEN; return last_error; } diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 5987c1675d..5a1a26e874 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -28,22 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#include "ip_unix.h" - -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) - -#ifdef WINDOWS_ENABLED - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <winsock2.h> -#include <ws2tcpip.h> - -#include <iphlpapi.h> - -#include <stdio.h> +#if defined(UNIX_ENABLED) -#else // UNIX +#include "ip_unix.h" #include <netdb.h> @@ -67,8 +54,6 @@ #include <net/if.h> // Order is important on OpenBSD, leave as last. -#endif // UNIX - #include <string.h> static IPAddress _sockaddr2ip(struct sockaddr *p_addr) { @@ -108,7 +93,7 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos } if (result == nullptr || result->ai_addr == nullptr) { - print_verbose("Invalid response from getaddrinfo"); + print_verbose("Invalid response from getaddrinfo."); if (result) { freeaddrinfo(result); } @@ -132,56 +117,6 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos freeaddrinfo(result); } -#if defined(WINDOWS_ENABLED) - -void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const { - ULONG buf_size = 1024; - IP_ADAPTER_ADDRESSES *addrs; - - while (true) { - addrs = (IP_ADAPTER_ADDRESSES *)memalloc(buf_size); - int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, - nullptr, addrs, &buf_size); - if (err == NO_ERROR) { - break; - } - memfree(addrs); - if (err == ERROR_BUFFER_OVERFLOW) { - continue; // will go back and alloc the right size - } - - ERR_FAIL_MSG("Call to GetAdaptersAddresses failed with error " + itos(err) + "."); - } - - IP_ADAPTER_ADDRESSES *adapter = addrs; - - while (adapter != nullptr) { - Interface_Info info; - info.name = adapter->AdapterName; - info.name_friendly = adapter->FriendlyName; - info.index = String::num_uint64(adapter->IfIndex); - - IP_ADAPTER_UNICAST_ADDRESS *address = adapter->FirstUnicastAddress; - while (address != nullptr) { - int family = address->Address.lpSockaddr->sa_family; - if (family != AF_INET && family != AF_INET6) { - continue; - } - info.ip_addresses.push_front(_sockaddr2ip(address->Address.lpSockaddr)); - address = address->Next; - } - adapter = adapter->Next; - // Only add interface if it has at least one IP - if (info.ip_addresses.size() > 0) { - r_interfaces->insert(info.name, info); - } - } - - memfree(addrs); -} - -#else // UNIX - void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const { struct ifaddrs *ifAddrStruct = nullptr; struct ifaddrs *ifa = nullptr; @@ -219,8 +154,6 @@ void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) } } -#endif // UNIX - void IPUnix::make_default() { _create = _create_unix; } @@ -232,4 +165,4 @@ IP *IPUnix::_create_unix() { IPUnix::IPUnix() { } -#endif // UNIX_ENABLED || WINDOWS_ENABLED +#endif // UNIX_ENABLED diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index 274b7c561e..7e496629ef 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -31,9 +31,9 @@ #ifndef IP_UNIX_H #define IP_UNIX_H -#include "core/io/ip.h" +#if defined(UNIX_ENABLED) -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#include "core/io/ip.h" class IPUnix : public IP { GDCLASS(IPUnix, IP); @@ -49,6 +49,6 @@ public: IPUnix(); }; -#endif +#endif // UNIX_ENABLED #endif // IP_UNIX_H diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_unix.cpp index 5caa33100e..3eaf1b2885 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_unix.cpp @@ -1,5 +1,5 @@ /**************************************************************************/ -/* net_socket_posix.cpp */ +/* net_socket_unix.cpp */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#include "net_socket_posix.h" - // Some proprietary Unix-derived platforms don't expose Unix sockets // so this allows skipping this file to reimplement this API differently. -#ifndef UNIX_SOCKET_UNAVAILABLE +#if defined(UNIX_ENABLED) && !defined(UNIX_SOCKET_UNAVAILABLE) -#if defined(UNIX_ENABLED) +#include "net_socket_unix.h" #include <errno.h> #include <fcntl.h> @@ -62,44 +60,11 @@ #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP #endif -// Some custom defines to minimize ifdefs -#define SOCK_EMPTY -1 -#define SOCK_BUF(x) x -#define SOCK_CBUF(x) x -#define SOCK_IOCTL ioctl -#define SOCK_FIONREAD_LEN_TYPE int -#define SOCK_CLOSE ::close -#define SOCK_CONNECT(p_sock, p_addr, p_addr_len) ::connect(p_sock, p_addr, p_addr_len) - -/* Windows */ -#elif defined(WINDOWS_ENABLED) -#include <winsock2.h> -#include <ws2tcpip.h> - -#include <mswsock.h> -// Some custom defines to minimize ifdefs -#define SOCK_EMPTY INVALID_SOCKET -#define SOCK_BUF(x) (char *)(x) -#define SOCK_CBUF(x) (const char *)(x) -#define SOCK_IOCTL ioctlsocket -#define SOCK_FIONREAD_LEN_TYPE unsigned long -#define SOCK_CLOSE closesocket -// connect is broken on windows under certain conditions, reasons unknown: -// See https://github.com/godotengine/webrtc-native/issues/6 -#define SOCK_CONNECT(p_sock, p_addr, p_addr_len) ::WSAConnect(p_sock, p_addr, p_addr_len, nullptr, nullptr, nullptr, nullptr) - -// Workaround missing flag in MinGW -#if defined(__MINGW32__) && !defined(SIO_UDP_NETRESET) -#define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15) -#endif - -#endif // UNIX_ENABLED - -size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) { +size_t NetSocketUnix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); - if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket + if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket. - // IPv6 only socket with IPv4 address + // IPv6 only socket with IPv4 address. ERR_FAIL_COND_V(!p_ip.is_wildcard() && p_ip_type == IP::TYPE_IPV6 && p_ip.is_ipv4(), 0); struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr; @@ -111,14 +76,14 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const addr6->sin6_addr = in6addr_any; } return sizeof(sockaddr_in6); - } else { // IPv4 socket + } else { // IPv4 socket. - // IPv4 socket with IPv6 address + // IPv4 socket with IPv6 address. ERR_FAIL_COND_V(!p_ip.is_wildcard() && !p_ip.is_ipv4(), 0); struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; addr4->sin_family = AF_INET; - addr4->sin_port = htons(p_port); // short, network byte order + addr4->sin_port = htons(p_port); // Short, network byte order. if (p_ip.is_valid()) { memcpy(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4); @@ -130,7 +95,7 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const } } -void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port) { +void NetSocketUnix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port) { if (p_addr->ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; if (r_ip) { @@ -150,34 +115,21 @@ void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ } } -NetSocket *NetSocketPosix::_create_func() { - return memnew(NetSocketPosix); +NetSocket *NetSocketUnix::_create_func() { + return memnew(NetSocketUnix); } -void NetSocketPosix::make_default() { -#if defined(WINDOWS_ENABLED) - if (_create == nullptr) { - WSADATA data; - WSAStartup(MAKEWORD(2, 2), &data); - } -#endif +void NetSocketUnix::make_default() { _create = _create_func; } -void NetSocketPosix::cleanup() { -#if defined(WINDOWS_ENABLED) - if (_create != nullptr) { - WSACleanup(); - } - _create = nullptr; -#endif +void NetSocketUnix::cleanup() { } -NetSocketPosix::NetSocketPosix() : - _sock(SOCK_EMPTY) { +NetSocketUnix::NetSocketUnix() { } -NetSocketPosix::~NetSocketPosix() { +NetSocketUnix::~NetSocketUnix() { close(); } @@ -188,30 +140,7 @@ NetSocketPosix::~NetSocketPosix() { #pragma GCC diagnostic ignored "-Wlogical-op" #endif -NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const { -#if defined(WINDOWS_ENABLED) - int err = WSAGetLastError(); - if (err == WSAEISCONN) { - return ERR_NET_IS_CONNECTED; - } - if (err == WSAEINPROGRESS || err == WSAEALREADY) { - return ERR_NET_IN_PROGRESS; - } - if (err == WSAEWOULDBLOCK) { - return ERR_NET_WOULD_BLOCK; - } - if (err == WSAEADDRINUSE || err == WSAEADDRNOTAVAIL) { - return ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE; - } - if (err == WSAEACCES) { - return ERR_NET_UNAUTHORIZED; - } - if (err == WSAEMSGSIZE || err == WSAENOBUFS) { - return ERR_NET_BUFFER_TOO_SMALL; - } - print_verbose("Socket error: " + itos(err)); - return ERR_NET_OTHER; -#else +NetSocketUnix::NetError NetSocketUnix::_get_socket_error() const { if (errno == EISCONN) { return ERR_NET_IS_CONNECTED; } @@ -230,16 +159,15 @@ NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const { if (errno == ENOBUFS) { return ERR_NET_BUFFER_TOO_SMALL; } - print_verbose("Socket error: " + itos(errno)); + print_verbose("Socket error: " + itos(errno) + "."); return ERR_NET_OTHER; -#endif } #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif -bool NetSocketPosix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const { +bool NetSocketUnix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const { if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) { return false; } else if (!p_for_bind && !p_ip.is_valid()) { @@ -250,11 +178,11 @@ bool NetSocketPosix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) c return !(_ip_type != IP::TYPE_ANY && !p_ip.is_wildcard() && _ip_type != type); } -_FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add) { +_FORCE_INLINE_ Error NetSocketUnix::_change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_ip, false), ERR_INVALID_PARAMETER); - // Need to force level and af_family to IP(v4) when using dual stacking and provided multicast group is IPv4 + // Need to force level and af_family to IP(v4) when using dual stacking and provided multicast group is IPv4. IP::Type type = _ip_type == IP::TYPE_ANY && p_ip.is_ipv4() ? IP::TYPE_IPV4 : _ip_type; // This needs to be the proper level for the multicast group, no matter if the socket is dual stacking. int level = type == IP::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; @@ -277,7 +205,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, Str for (const IPAddress &F : c.ip_addresses) { if (!F.is_ipv4()) { - continue; // Wrong IP type + continue; // Wrong IP type. } if_ip = F; break; @@ -304,7 +232,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, Str return OK; } -void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream) { +void NetSocketUnix::_set_socket(int p_sock, IP::Type p_ip_type, bool p_is_stream) { _sock = p_sock; _ip_type = p_ip_type; _is_stream = p_is_stream; @@ -312,15 +240,13 @@ void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_ _set_close_exec_enabled(true); } -void NetSocketPosix::_set_close_exec_enabled(bool p_enabled) { -#ifndef WINDOWS_ENABLED +void NetSocketUnix::_set_close_exec_enabled(bool p_enabled) { // Enable close on exec to avoid sharing with subprocesses. Off by default on Windows. int opts = fcntl(_sock, F_GETFD); fcntl(_sock, F_SETFD, opts | FD_CLOEXEC); -#endif } -Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { +Error NetSocketUnix::open(Type p_sock_type, IP::Type &ip_type) { ERR_FAIL_COND_V(is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(ip_type > IP::TYPE_ANY || ip_type < IP::TYPE_NONE, ERR_INVALID_PARAMETER); @@ -336,7 +262,7 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { int type = p_sock_type == TYPE_TCP ? SOCK_STREAM : SOCK_DGRAM; _sock = socket(family, type, protocol); - if (_sock == SOCK_EMPTY && ip_type == IP::TYPE_ANY) { + if (_sock == -1 && ip_type == IP::TYPE_ANY) { // Careful here, changing the referenced parameter so the caller knows that we are using an IPv4 socket // in place of a dual stack one, and further calls to _set_sock_addr will work as expected. ip_type = IP::TYPE_IPV4; @@ -344,11 +270,11 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { _sock = socket(family, type, protocol); } - ERR_FAIL_COND_V(_sock == SOCK_EMPTY, FAILED); + ERR_FAIL_COND_V(_sock == -1, FAILED); _ip_type = ip_type; if (family == AF_INET6) { - // Select IPv4 over IPv6 mapping + // Select IPv4 over IPv6 mapping. set_ipv6_only_enabled(ip_type != IP::TYPE_ANY); } @@ -363,41 +289,27 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { // Disable descriptor sharing with subprocesses. _set_close_exec_enabled(true); -#if defined(WINDOWS_ENABLED) - if (!_is_stream) { - // Disable windows feature/bug reporting WSAECONNRESET/WSAENETRESET when - // recv/recvfrom and an ICMP reply was received from a previous send/sendto. - unsigned long disable = 0; - if (ioctlsocket(_sock, SIO_UDP_CONNRESET, &disable) == SOCKET_ERROR) { - print_verbose("Unable to turn off UDP WSAECONNRESET behavior on Windows"); - } - if (ioctlsocket(_sock, SIO_UDP_NETRESET, &disable) == SOCKET_ERROR) { - // This feature seems not to be supported on wine. - print_verbose("Unable to turn off UDP WSAENETRESET behavior on Windows"); - } - } -#endif #if defined(SO_NOSIGPIPE) - // Disable SIGPIPE (should only be relevant to stream sockets, but seems to affect UDP too on iOS) + // Disable SIGPIPE (should only be relevant to stream sockets, but seems to affect UDP too on iOS). int par = 1; - if (setsockopt(_sock, SOL_SOCKET, SO_NOSIGPIPE, SOCK_CBUF(&par), sizeof(int)) != 0) { - print_verbose("Unable to turn off SIGPIPE on socket"); + if (setsockopt(_sock, SOL_SOCKET, SO_NOSIGPIPE, &par, sizeof(int)) != 0) { + print_verbose("Unable to turn off SIGPIPE on socket."); } #endif return OK; } -void NetSocketPosix::close() { - if (_sock != SOCK_EMPTY) { - SOCK_CLOSE(_sock); +void NetSocketUnix::close() { + if (_sock != -1) { + ::close(_sock); } - _sock = SOCK_EMPTY; + _sock = -1; _ip_type = IP::TYPE_NONE; _is_stream = false; } -Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) { +Error NetSocketUnix::bind(IPAddress p_addr, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_addr, true), ERR_INVALID_PARAMETER); @@ -406,7 +318,7 @@ Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) { if (::bind(_sock, (struct sockaddr *)&addr, addr_size) != 0) { NetError err = _get_socket_error(); - print_verbose("Failed to bind socket. Error: " + itos(err)); + print_verbose("Failed to bind socket. Error: " + itos(err) + "."); close(); return ERR_UNAVAILABLE; } @@ -414,7 +326,7 @@ Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) { return OK; } -Error NetSocketPosix::listen(int p_max_pending) { +Error NetSocketUnix::listen(int p_max_pending) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); if (::listen(_sock, p_max_pending) != 0) { @@ -427,26 +339,26 @@ Error NetSocketPosix::listen(int p_max_pending) { return OK; } -Error NetSocketPosix::connect_to_host(IPAddress p_host, uint16_t p_port) { +Error NetSocketUnix::connect_to_host(IPAddress p_host, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_host, false), ERR_INVALID_PARAMETER); struct sockaddr_storage addr; size_t addr_size = _set_addr_storage(&addr, p_host, p_port, _ip_type); - if (SOCK_CONNECT(_sock, (struct sockaddr *)&addr, addr_size) != 0) { + if (::connect(_sock, (struct sockaddr *)&addr, addr_size) != 0) { NetError err = _get_socket_error(); switch (err) { - // We are already connected + // We are already connected. case ERR_NET_IS_CONNECTED: return OK; - // Still waiting to connect, try again in a while + // Still waiting to connect, try again in a while. case ERR_NET_WOULD_BLOCK: case ERR_NET_IN_PROGRESS: return ERR_BUSY; default: - print_verbose("Connection to remote host failed!"); + print_verbose("Connection to remote host failed."); close(); return FAILED; } @@ -455,66 +367,9 @@ Error NetSocketPosix::connect_to_host(IPAddress p_host, uint16_t p_port) { return OK; } -Error NetSocketPosix::poll(PollType p_type, int p_timeout) const { +Error NetSocketUnix::poll(PollType p_type, int p_timeout) const { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); -#if defined(WINDOWS_ENABLED) - bool ready = false; - fd_set rd, wr, ex; - fd_set *rdp = nullptr; - fd_set *wrp = nullptr; - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_ZERO(&ex); - FD_SET(_sock, &ex); - struct timeval timeout = { p_timeout / 1000, (p_timeout % 1000) * 1000 }; - // For blocking operation, pass nullptr timeout pointer to select. - struct timeval *tp = nullptr; - if (p_timeout >= 0) { - // If timeout is non-negative, we want to specify the timeout instead. - tp = &timeout; - } - - switch (p_type) { - case POLL_TYPE_IN: - FD_SET(_sock, &rd); - rdp = &rd; - break; - case POLL_TYPE_OUT: - FD_SET(_sock, &wr); - wrp = ≀ - break; - case POLL_TYPE_IN_OUT: - FD_SET(_sock, &rd); - FD_SET(_sock, &wr); - rdp = &rd; - wrp = ≀ - } - int ret = select(1, rdp, wrp, &ex, tp); - - if (ret == SOCKET_ERROR) { - return FAILED; - } - - if (ret == 0) { - return ERR_BUSY; - } - - if (FD_ISSET(_sock, &ex)) { - _get_socket_error(); - print_verbose("Exception when polling socket."); - return FAILED; - } - - if (rdp && FD_ISSET(_sock, rdp)) { - ready = true; - } - if (wrp && FD_ISSET(_sock, wrp)) { - ready = true; - } - - return ready ? OK : ERR_BUSY; -#else struct pollfd pfd; pfd.fd = _sock; pfd.events = POLLIN; @@ -544,13 +399,12 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const { } return OK; -#endif } -Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) { +Error NetSocketUnix::recv(uint8_t *p_buffer, int p_len, int &r_read) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); - r_read = ::recv(_sock, SOCK_BUF(p_buffer), p_len, 0); + r_read = ::recv(_sock, p_buffer, p_len, 0); if (r_read < 0) { NetError err = _get_socket_error(); @@ -568,14 +422,14 @@ Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) { return OK; } -Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek) { +Error NetSocketUnix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); struct sockaddr_storage from; socklen_t len = sizeof(struct sockaddr_storage); memset(&from, 0, len); - r_read = ::recvfrom(_sock, SOCK_BUF(p_buffer), p_len, p_peek ? MSG_PEEK : 0, (struct sockaddr *)&from, &len); + r_read = ::recvfrom(_sock, p_buffer, p_len, p_peek ? MSG_PEEK : 0, (struct sockaddr *)&from, &len); if (r_read < 0) { NetError err = _get_socket_error(); @@ -606,7 +460,7 @@ Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddr return OK; } -Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { +Error NetSocketUnix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); int flags = 0; @@ -615,7 +469,7 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { flags = MSG_NOSIGNAL; } #endif - r_sent = ::send(_sock, SOCK_CBUF(p_buffer), p_len, flags); + r_sent = ::send(_sock, p_buffer, p_len, flags); if (r_sent < 0) { NetError err = _get_socket_error(); @@ -632,12 +486,12 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { return OK; } -Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { +Error NetSocketUnix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); struct sockaddr_storage addr; size_t addr_size = _set_addr_storage(&addr, p_ip, p_port, _ip_type); - r_sent = ::sendto(_sock, SOCK_CBUF(p_buffer), p_len, 0, (struct sockaddr *)&addr, addr_size); + r_sent = ::sendto(_sock, p_buffer, p_len, 0, (struct sockaddr *)&addr, addr_size); if (r_sent < 0) { NetError err = _get_socket_error(); @@ -654,7 +508,7 @@ Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP return OK; } -Error NetSocketPosix::set_broadcasting_enabled(bool p_enabled) { +Error NetSocketUnix::set_broadcasting_enabled(bool p_enabled) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); // IPv6 has no broadcast support. if (_ip_type == IP::TYPE_IPV6) { @@ -662,90 +516,68 @@ Error NetSocketPosix::set_broadcasting_enabled(bool p_enabled) { } int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, SOL_SOCKET, SO_BROADCAST, SOCK_CBUF(&par), sizeof(int)) != 0) { - WARN_PRINT("Unable to change broadcast setting"); + if (setsockopt(_sock, SOL_SOCKET, SO_BROADCAST, &par, sizeof(int)) != 0) { + WARN_PRINT("Unable to change broadcast setting."); return FAILED; } return OK; } -void NetSocketPosix::set_blocking_enabled(bool p_enabled) { +void NetSocketUnix::set_blocking_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); int ret = 0; -#if defined(WINDOWS_ENABLED) - unsigned long par = p_enabled ? 0 : 1; - ret = SOCK_IOCTL(_sock, FIONBIO, &par); -#else int opts = fcntl(_sock, F_GETFL); if (p_enabled) { ret = fcntl(_sock, F_SETFL, opts & ~O_NONBLOCK); } else { ret = fcntl(_sock, F_SETFL, opts | O_NONBLOCK); } -#endif if (ret != 0) { - WARN_PRINT("Unable to change non-block mode"); + WARN_PRINT("Unable to change non-block mode."); } } -void NetSocketPosix::set_ipv6_only_enabled(bool p_enabled) { +void NetSocketUnix::set_ipv6_only_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); // This option is only available in IPv6 sockets. ERR_FAIL_COND(_ip_type == IP::TYPE_IPV4); int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, IPPROTO_IPV6, IPV6_V6ONLY, SOCK_CBUF(&par), sizeof(int)) != 0) { - WARN_PRINT("Unable to change IPv4 address mapping over IPv6 option"); + if (setsockopt(_sock, IPPROTO_IPV6, IPV6_V6ONLY, &par, sizeof(int)) != 0) { + WARN_PRINT("Unable to change IPv4 address mapping over IPv6 option."); } } -void NetSocketPosix::set_tcp_no_delay_enabled(bool p_enabled) { +void NetSocketUnix::set_tcp_no_delay_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); - ERR_FAIL_COND(!_is_stream); // Not TCP + ERR_FAIL_COND(!_is_stream); // Not TCP. int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, SOCK_CBUF(&par), sizeof(int)) < 0) { - ERR_PRINT("Unable to set TCP no delay option"); + if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, &par, sizeof(int)) < 0) { + WARN_PRINT("Unable to set TCP no delay option."); } } -void NetSocketPosix::set_reuse_address_enabled(bool p_enabled) { +void NetSocketUnix::set_reuse_address_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); -// On Windows, enabling SO_REUSEADDR actually would also enable reuse port, very bad on TCP. Denying... -// Windows does not have this option, SO_REUSEADDR in this magical world means SO_REUSEPORT -#ifndef WINDOWS_ENABLED - int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, SOCK_CBUF(&par), sizeof(int)) < 0) { - WARN_PRINT("Unable to set socket REUSEADDR option!"); - } -#endif -} - -void NetSocketPosix::set_reuse_port_enabled(bool p_enabled) { - ERR_FAIL_COND(!is_open()); - -// See comment above... -#ifdef WINDOWS_ENABLED -#define SO_REUSEPORT SO_REUSEADDR -#endif int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, SOL_SOCKET, SO_REUSEPORT, SOCK_CBUF(&par), sizeof(int)) < 0) { - WARN_PRINT("Unable to set socket REUSEPORT option!"); + if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &par, sizeof(int)) < 0) { + WARN_PRINT("Unable to set socket REUSEADDR option."); } } -bool NetSocketPosix::is_open() const { - return _sock != SOCK_EMPTY; +bool NetSocketUnix::is_open() const { + return _sock != -1; } -int NetSocketPosix::get_available_bytes() const { +int NetSocketUnix::get_available_bytes() const { ERR_FAIL_COND_V(!is_open(), -1); - SOCK_FIONREAD_LEN_TYPE len; - int ret = SOCK_IOCTL(_sock, FIONREAD, &len); + int len; + int ret = ioctl(_sock, FIONREAD, &len); if (ret == -1) { _get_socket_error(); print_verbose("Error when checking available bytes on socket."); @@ -754,7 +586,7 @@ int NetSocketPosix::get_available_bytes() const { return len; } -Error NetSocketPosix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) const { +Error NetSocketUnix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) const { ERR_FAIL_COND_V(!is_open(), FAILED); struct sockaddr_storage saddr; @@ -768,14 +600,14 @@ Error NetSocketPosix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) cons return OK; } -Ref<NetSocket> NetSocketPosix::accept(IPAddress &r_ip, uint16_t &r_port) { +Ref<NetSocket> NetSocketUnix::accept(IPAddress &r_ip, uint16_t &r_port) { Ref<NetSocket> out; ERR_FAIL_COND_V(!is_open(), out); struct sockaddr_storage their_addr; socklen_t size = sizeof(their_addr); - SOCKET_TYPE fd = ::accept(_sock, (struct sockaddr *)&their_addr, &size); - if (fd == SOCK_EMPTY) { + int fd = ::accept(_sock, (struct sockaddr *)&their_addr, &size); + if (fd == -1) { _get_socket_error(); print_verbose("Error when accepting socket connection."); return out; @@ -783,18 +615,18 @@ Ref<NetSocket> NetSocketPosix::accept(IPAddress &r_ip, uint16_t &r_port) { _set_ip_port(&their_addr, &r_ip, &r_port); - NetSocketPosix *ns = memnew(NetSocketPosix); + NetSocketUnix *ns = memnew(NetSocketUnix); ns->_set_socket(fd, _ip_type, _is_stream); ns->set_blocking_enabled(false); return Ref<NetSocket>(ns); } -Error NetSocketPosix::join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { +Error NetSocketUnix::join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { return _change_multicast_group(p_multi_address, p_if_name, true); } -Error NetSocketPosix::leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { +Error NetSocketUnix::leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { return _change_multicast_group(p_multi_address, p_if_name, false); } -#endif // UNIX_SOCKET_UNAVAILABLE +#endif // UNIX_ENABLED && !UNIX_SOCKET_UNAVAILABLE diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_unix.h index aa59ff36ee..08c45f2ac3 100644 --- a/drivers/unix/net_socket_posix.h +++ b/drivers/unix/net_socket_unix.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* net_socket_posix.h */ +/* net_socket_unix.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,25 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef NET_SOCKET_POSIX_H -#define NET_SOCKET_POSIX_H +#ifndef NET_SOCKET_UNIX_H +#define NET_SOCKET_UNIX_H -#include "core/io/net_socket.h" +#if defined(UNIX_ENABLED) && !defined(UNIX_SOCKET_UNAVAILABLE) -#if defined(WINDOWS_ENABLED) -#include <winsock2.h> -#include <ws2tcpip.h> -#define SOCKET_TYPE SOCKET +#include "core/io/net_socket.h" -#else #include <sys/socket.h> -#define SOCKET_TYPE int -#endif - -class NetSocketPosix : public NetSocket { +class NetSocketUnix : public NetSocket { private: - SOCKET_TYPE _sock; // NOLINT - the default value is defined in the .cpp + int _sock = -1; IP::Type _ip_type = IP::TYPE_NONE; bool _is_stream = false; @@ -61,7 +54,7 @@ private: }; NetError _get_socket_error() const; - void _set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream); + void _set_socket(int p_sock, IP::Type p_ip_type, bool p_is_stream); _FORCE_INLINE_ Error _change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add); _FORCE_INLINE_ void _set_close_exec_enabled(bool p_enabled); @@ -76,33 +69,34 @@ public: static void _set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port); static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type); - virtual Error open(Type p_sock_type, IP::Type &ip_type); - virtual void close(); - virtual Error bind(IPAddress p_addr, uint16_t p_port); - virtual Error listen(int p_max_pending); - virtual Error connect_to_host(IPAddress p_host, uint16_t p_port); - virtual Error poll(PollType p_type, int timeout) const; - virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read); - virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false); - virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent); - virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port); - virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port); - - virtual bool is_open() const; - virtual int get_available_bytes() const; - virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const; - - virtual Error set_broadcasting_enabled(bool p_enabled); - virtual void set_blocking_enabled(bool p_enabled); - virtual void set_ipv6_only_enabled(bool p_enabled); - virtual void set_tcp_no_delay_enabled(bool p_enabled); - virtual void set_reuse_address_enabled(bool p_enabled); - virtual void set_reuse_port_enabled(bool p_enabled); - virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name); - virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name); - - NetSocketPosix(); - ~NetSocketPosix(); + virtual Error open(Type p_sock_type, IP::Type &ip_type) override; + virtual void close() override; + virtual Error bind(IPAddress p_addr, uint16_t p_port) override; + virtual Error listen(int p_max_pending) override; + virtual Error connect_to_host(IPAddress p_host, uint16_t p_port) override; + virtual Error poll(PollType p_type, int timeout) const override; + virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) override; + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) override; + virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) override; + virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) override; + virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port) override; + + virtual bool is_open() const override; + virtual int get_available_bytes() const override; + virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const override; + + virtual Error set_broadcasting_enabled(bool p_enabled) override; + virtual void set_blocking_enabled(bool p_enabled) override; + virtual void set_ipv6_only_enabled(bool p_enabled) override; + virtual void set_tcp_no_delay_enabled(bool p_enabled) override; + virtual void set_reuse_address_enabled(bool p_enabled) override; + virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override; + virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override; + + NetSocketUnix(); + ~NetSocketUnix() override; }; -#endif // NET_SOCKET_POSIX_H +#endif // UNIX_ENABLED && !UNIX_SOCKET_UNAVAILABLE + +#endif // NET_SOCKET_UNIX_H diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 8a9b130068..ffc270cd36 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -38,7 +38,7 @@ #include "drivers/unix/dir_access_unix.h" #include "drivers/unix/file_access_unix.h" #include "drivers/unix/file_access_unix_pipe.h" -#include "drivers/unix/net_socket_posix.h" +#include "drivers/unix/net_socket_unix.h" #include "drivers/unix/thread_posix.h" #include "servers/rendering_server.h" @@ -77,6 +77,7 @@ #include <stdlib.h> #include <string.h> #include <sys/resource.h> +#include <sys/stat.h> #include <sys/time.h> #include <sys/wait.h> #include <time.h> @@ -166,7 +167,9 @@ void OS_Unix::initialize_core() { DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA); DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM); - NetSocketPosix::make_default(); +#ifndef UNIX_SOCKET_UNAVAILABLE + NetSocketUnix::make_default(); +#endif IPUnix::make_default(); process_map = memnew((HashMap<ProcessID, ProcessInfo>)); @@ -175,16 +178,96 @@ void OS_Unix::initialize_core() { void OS_Unix::finalize_core() { memdelete(process_map); - NetSocketPosix::cleanup(); +#ifndef UNIX_SOCKET_UNAVAILABLE + NetSocketUnix::cleanup(); +#endif } Vector<String> OS_Unix::get_video_adapter_driver_info() const { return Vector<String>(); } -String OS_Unix::get_stdin_string() { - char buff[1024]; - return String::utf8(fgets(buff, 1024, stdin)); +String OS_Unix::get_stdin_string(int64_t p_buffer_size) { + Vector<uint8_t> data; + data.resize(p_buffer_size); + if (fgets((char *)data.ptrw(), data.size(), stdin)) { + return String::utf8((char *)data.ptr()); + } + return String(); +} + +PackedByteArray OS_Unix::get_stdin_buffer(int64_t p_buffer_size) { + Vector<uint8_t> data; + data.resize(p_buffer_size); + size_t sz = fread((void *)data.ptrw(), 1, data.size(), stdin); + if (sz > 0) { + data.resize(sz); + return data; + } + return PackedByteArray(); +} + +OS_Unix::StdHandleType OS_Unix::get_stdin_type() const { + int h = fileno(stdin); + if (h == -1) { + return STD_HANDLE_INVALID; + } + + if (isatty(h)) { + return STD_HANDLE_CONSOLE; + } + struct stat statbuf; + if (fstat(h, &statbuf) < 0) { + return STD_HANDLE_UNKNOWN; + } + if (S_ISFIFO(statbuf.st_mode)) { + return STD_HANDLE_PIPE; + } else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { + return STD_HANDLE_FILE; + } + return STD_HANDLE_UNKNOWN; +} + +OS_Unix::StdHandleType OS_Unix::get_stdout_type() const { + int h = fileno(stdout); + if (h == -1) { + return STD_HANDLE_INVALID; + } + + if (isatty(h)) { + return STD_HANDLE_CONSOLE; + } + struct stat statbuf; + if (fstat(h, &statbuf) < 0) { + return STD_HANDLE_UNKNOWN; + } + if (S_ISFIFO(statbuf.st_mode)) { + return STD_HANDLE_PIPE; + } else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { + return STD_HANDLE_FILE; + } + return STD_HANDLE_UNKNOWN; +} + +OS_Unix::StdHandleType OS_Unix::get_stderr_type() const { + int h = fileno(stderr); + if (h == -1) { + return STD_HANDLE_INVALID; + } + + if (isatty(h)) { + return STD_HANDLE_CONSOLE; + } + struct stat statbuf; + if (fstat(h, &statbuf) < 0) { + return STD_HANDLE_UNKNOWN; + } + if (S_ISFIFO(statbuf.st_mode)) { + return STD_HANDLE_PIPE; + } else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { + return STD_HANDLE_FILE; + } + return STD_HANDLE_UNKNOWN; } Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) { @@ -777,7 +860,7 @@ String OS_Unix::get_locale() const { } String locale = get_environment("LANG"); - int tp = locale.find("."); + int tp = locale.find_char('.'); if (tp != -1) { locale = locale.substr(0, tp); } diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 3add5df055..2c7920c142 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -58,7 +58,11 @@ public: virtual Vector<String> get_video_adapter_driver_info() const override; - virtual String get_stdin_string() override; + virtual String get_stdin_string(int64_t p_buffer_size = 1024) override; + virtual PackedByteArray get_stdin_buffer(int64_t p_buffer_size = 1024) override; + virtual StdHandleType get_stdin_type() const override; + virtual StdHandleType get_stdout_type() const override; + virtual StdHandleType get_stderr_type() const override; virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index 154095552b..b6e5ed0287 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -35,6 +35,16 @@ #include "thirdparty/misc/smolv.h" #include "vulkan_hooks.h" +#if defined(ANDROID_ENABLED) +#include "platform/android/java_godot_wrapper.h" +#include "platform/android/os_android.h" +#include "platform/android/thread_jandroid.h" +#endif + +#if defined(SWAPPY_FRAME_PACING_ENABLED) +#include "thirdparty/swappy-frame-pacing/swappyVk.h" +#endif + #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define PRINT_NATIVE_COMMANDS 0 @@ -43,6 +53,10 @@ /**** GENERIC ****/ /*****************/ +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) +static const uint32_t BREADCRUMB_BUFFER_ENTRIES = 512u; +#endif + static const VkFormat RD_TO_VK_FORMAT[RDD::DATA_FORMAT_MAX] = { VK_FORMAT_R4G4_UNORM_PACK8, VK_FORMAT_R4G4B4A4_UNORM_PACK16, @@ -534,6 +548,37 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() { err = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_count, device_extensions.ptr()); ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); +#if defined(SWAPPY_FRAME_PACING_ENABLED) + if (swappy_frame_pacer_enable) { + char **swappy_required_extensions; + uint32_t swappy_required_extensions_count = 0; + // Determine number of extensions required by Swappy frame pacer. + SwappyVk_determineDeviceExtensions(physical_device, device_extension_count, device_extensions.ptr(), &swappy_required_extensions_count, nullptr); + + if (swappy_required_extensions_count < device_extension_count) { + // Determine the actual extensions. + swappy_required_extensions = (char **)malloc(swappy_required_extensions_count * sizeof(char *)); + char *pRequiredExtensionsData = (char *)malloc(swappy_required_extensions_count * (VK_MAX_EXTENSION_NAME_SIZE + 1)); + for (uint32_t i = 0; i < swappy_required_extensions_count; i++) { + swappy_required_extensions[i] = &pRequiredExtensionsData[i * (VK_MAX_EXTENSION_NAME_SIZE + 1)]; + } + SwappyVk_determineDeviceExtensions(physical_device, device_extension_count, + device_extensions.ptr(), &swappy_required_extensions_count, swappy_required_extensions); + + // Enable extensions requested by Swappy. + for (uint32_t i = 0; i < swappy_required_extensions_count; i++) { + CharString extension_name(swappy_required_extensions[i]); + if (requested_device_extensions.has(extension_name)) { + enabled_device_extension_names.insert(extension_name); + } + } + + free(pRequiredExtensionsData); + free(swappy_required_extensions); + } + } +#endif + #ifdef DEV_ENABLED for (uint32_t i = 0; i < device_extension_count; i++) { print_verbose(String("VULKAN: Found device extension ") + String::utf8(device_extensions[i].extensionName)); @@ -1370,7 +1415,22 @@ Error RenderingDeviceDriverVulkan::initialize(uint32_t p_device_index, uint32_t ERR_FAIL_COND_V(err != OK, err); max_descriptor_sets_per_pool = GLOBAL_GET("rendering/rendering_device/vulkan/max_descriptors_per_pool"); - breadcrumb_buffer = buffer_create(sizeof(uint32_t), BufferUsageBits::BUFFER_USAGE_TRANSFER_TO_BIT, MemoryAllocationType::MEMORY_ALLOCATION_TYPE_CPU); + +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) + breadcrumb_buffer = buffer_create(2u * sizeof(uint32_t) * BREADCRUMB_BUFFER_ENTRIES, BufferUsageBits::BUFFER_USAGE_TRANSFER_TO_BIT, MemoryAllocationType::MEMORY_ALLOCATION_TYPE_CPU); +#endif + +#if defined(SWAPPY_FRAME_PACING_ENABLED) + swappy_frame_pacer_enable = GLOBAL_GET("display/window/frame_pacing/android/enable_frame_pacing"); + swappy_mode = GLOBAL_GET("display/window/frame_pacing/android/swappy_mode"); + + if (VulkanHooks::get_singleton() != nullptr) { + // Hooks control device creation & possibly presentation + // (e.g. OpenXR) thus it's too risky to use Swappy. + swappy_frame_pacer_enable = false; + OS::get_singleton()->print("VulkanHooks detected (e.g. OpenXR): Force-disabling Swappy Frame Pacing.\n"); + } +#endif return OK; } @@ -1459,7 +1519,7 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); err = vmaAllocateMemoryForBuffer(allocator, vk_buffer, &alloc_create_info, &allocation, &alloc_info); ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't allocate memory for buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); - err = vmaBindBufferMemory2(allocator, allocation, 0, vk_buffer, NULL); + err = vmaBindBufferMemory2(allocator, allocation, 0, vk_buffer, nullptr); ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't bind memory to buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); // Bookkeep. @@ -1685,7 +1745,7 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat & ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImage failed with error " + itos(err) + "."); err = vmaAllocateMemoryForImage(allocator, vk_image, &alloc_create_info, &allocation, &alloc_info); ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't allocate memory for image, error: " + itos(err) + "."); - err = vmaBindImageMemory2(allocator, allocation, 0, vk_image, NULL); + err = vmaBindImageMemory2(allocator, allocation, 0, vk_image, nullptr); ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't bind memory to image, error: " + itos(err) + "."); // Create view. @@ -2332,7 +2392,9 @@ RDD::CommandQueueFamilyID RenderingDeviceDriverVulkan::command_queue_family_get( } } - ERR_FAIL_COND_V_MSG(picked_family_index >= queue_family_properties.size(), CommandQueueFamilyID(), "A queue family with the requested bits could not be found."); + if (picked_family_index >= queue_family_properties.size()) { + return CommandQueueFamilyID(); + } // Since 0 is a valid index and we use 0 as the error case, we make the index start from 1 instead. return CommandQueueFamilyID(picked_family_index + 1); @@ -2357,6 +2419,14 @@ RDD::CommandQueueID RenderingDeviceDriverVulkan::command_queue_create(CommandQue ERR_FAIL_COND_V_MSG(picked_queue_index >= queue_family.size(), CommandQueueID(), "A queue in the picked family could not be found."); +#if defined(SWAPPY_FRAME_PACING_ENABLED) + if (swappy_frame_pacer_enable) { + VkQueue selected_queue; + vkGetDeviceQueue(vk_device, family_index, picked_queue_index, &selected_queue); + SwappyVk_setQueueFamilyIndex(vk_device, selected_queue, family_index); + } +#endif + // Create the virtual queue. CommandQueue *command_queue = memnew(CommandQueue); command_queue->queue_family = family_index; @@ -2502,7 +2572,16 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu present_info.pResults = results.ptr(); device_queue.submit_mutex.lock(); +#if defined(SWAPPY_FRAME_PACING_ENABLED) + if (swappy_frame_pacer_enable) { + err = SwappyVk_queuePresent(device_queue.queue, &present_info); + } else { + err = device_functions.QueuePresentKHR(device_queue.queue, &present_info); + } +#else err = device_functions.QueuePresentKHR(device_queue.queue, &present_info); +#endif + device_queue.submit_mutex.unlock(); // Set the index to an invalid value. If any of the swap chains returned out of date, indicate it should be resized the next time it's acquired. @@ -2534,7 +2613,10 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu // it'll lead to very low performance in Android by entering an endless loop where it'll always resize the swap chain // every frame. - ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR, FAILED); + ERR_FAIL_COND_V_MSG( + err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR, + FAILED, + "QueuePresentKHR failed with error: " + get_vulkan_result(err)); } return OK; @@ -2637,11 +2719,13 @@ bool RenderingDeviceDriverVulkan::command_buffer_begin(CommandBufferID p_cmd_buf bool RenderingDeviceDriverVulkan::command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) { // Reset is implicit (VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT). + Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id); + VkCommandBufferInheritanceInfo inheritance_info = {}; inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; inheritance_info.renderPass = (VkRenderPass)p_render_pass.id; inheritance_info.subpass = p_subpass; - inheritance_info.framebuffer = (VkFramebuffer)p_framebuffer.id; + inheritance_info.framebuffer = framebuffer->vk_framebuffer; VkCommandBufferBeginInfo cmd_buf_begin_info = {}; cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -2682,6 +2766,14 @@ void RenderingDeviceDriverVulkan::_swap_chain_release(SwapChain *swap_chain) { swap_chain->framebuffers.clear(); if (swap_chain->vk_swapchain != VK_NULL_HANDLE) { +#if defined(SWAPPY_FRAME_PACING_ENABLED) + if (swappy_frame_pacer_enable) { + // Swappy has a bug where the ANativeWindow will be leaked if we call + // SwappyVk_destroySwapchain, so we must release it by hand. + SwappyVk_setWindow(vk_device, swap_chain->vk_swapchain, nullptr); + SwappyVk_destroySwapchain(vk_device, swap_chain->vk_swapchain); + } +#endif device_functions.DestroySwapchainKHR(vk_device, swap_chain->vk_swapchain, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SWAPCHAIN_KHR)); swap_chain->vk_swapchain = VK_NULL_HANDLE; } @@ -2798,9 +2890,30 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, VkResult err = functions.GetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface->vk_surface, &surface_capabilities); ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + // No swapchain yet, this is the first time we're creating it. + if (!swap_chain->vk_swapchain) { + if (surface_capabilities.currentExtent.width == 0xFFFFFFFF) { + // The current extent is currently undefined, so the current surface width and height will be clamped to the surface's capabilities. + // We make sure to overwrite surface_capabilities.currentExtent.width so that the same check further below + // does not set extent.width = CLAMP( surface->width, ... ) on the first run of this function, because + // that'd be potentially unswapped. + surface_capabilities.currentExtent.width = CLAMP(surface->width, surface_capabilities.minImageExtent.width, surface_capabilities.maxImageExtent.width); + surface_capabilities.currentExtent.height = CLAMP(surface->height, surface_capabilities.minImageExtent.height, surface_capabilities.maxImageExtent.height); + } + + // We must SWAP() only once otherwise we'll keep ping-ponging between + // the right and wrong resolutions after multiple calls to swap_chain_resize(). + if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR || + surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { + // Swap to get identity width and height. + SWAP(surface_capabilities.currentExtent.width, surface_capabilities.currentExtent.height); + } + } + VkExtent2D extent; if (surface_capabilities.currentExtent.width == 0xFFFFFFFF) { // The current extent is currently undefined, so the current surface width and height will be clamped to the surface's capabilities. + // We can only be here on the second call to swap_chain_resize(), by which time surface->width & surface->height should already be swapped if needed. extent.width = CLAMP(surface->width, surface_capabilities.minImageExtent.width, surface_capabilities.maxImageExtent.width); extent.height = CLAMP(surface->height, surface_capabilities.minImageExtent.height, surface_capabilities.maxImageExtent.height); } else { @@ -2848,9 +2961,7 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, } bool present_mode_available = present_modes.has(present_mode); - if (present_mode_available) { - print_verbose("Using present mode: " + present_mode_name); - } else { + if (!present_mode_available) { // Present mode is not available, fall back to FIFO which is guaranteed to be supported. WARN_PRINT(vformat("The requested V-Sync mode %s is not available. Falling back to V-Sync mode Enabled.", present_mode_name)); surface->vsync_mode = DisplayServer::VSYNC_ENABLED; @@ -2864,15 +2975,8 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, desired_swapchain_images = MIN(desired_swapchain_images, surface_capabilities.maxImageCount); } - // Prefer identity transform if it's supported, use the current transform otherwise. - // This behavior is intended as Godot does not supported native rotation in platforms that use these bits. // Refer to the comment in command_queue_present() for more details. - VkSurfaceTransformFlagBitsKHR surface_transform_bits; - if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { - surface_transform_bits = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - } else { - surface_transform_bits = surface_capabilities.currentTransform; - } + VkSurfaceTransformFlagBitsKHR surface_transform_bits = surface_capabilities.currentTransform; VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; if (OS::get_singleton()->is_layered_allowed() || !(surface_capabilities.supportedCompositeAlpha & composite_alpha)) { @@ -2904,12 +3008,60 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, swap_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swap_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swap_create_info.preTransform = surface_transform_bits; + switch (swap_create_info.preTransform) { + case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: + swap_chain->pre_transform_rotation_degrees = 0; + break; + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + swap_chain->pre_transform_rotation_degrees = 90; + break; + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + swap_chain->pre_transform_rotation_degrees = 180; + break; + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + swap_chain->pre_transform_rotation_degrees = 270; + break; + default: + WARN_PRINT("Unexpected swap_create_info.preTransform = " + itos(swap_create_info.preTransform) + "."); + swap_chain->pre_transform_rotation_degrees = 0; + break; + } swap_create_info.compositeAlpha = composite_alpha; swap_create_info.presentMode = present_mode; swap_create_info.clipped = true; err = device_functions.CreateSwapchainKHR(vk_device, &swap_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SWAPCHAIN_KHR), &swap_chain->vk_swapchain); ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); +#if defined(SWAPPY_FRAME_PACING_ENABLED) + if (swappy_frame_pacer_enable) { + SwappyVk_initAndGetRefreshCycleDuration(get_jni_env(), static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity(), physical_device, + vk_device, swap_chain->vk_swapchain, &swap_chain->refresh_duration); + SwappyVk_setWindow(vk_device, swap_chain->vk_swapchain, static_cast<OS_Android *>(OS::get_singleton())->get_native_window()); + SwappyVk_setSwapIntervalNS(vk_device, swap_chain->vk_swapchain, swap_chain->refresh_duration); + + enum SwappyModes { + PIPELINE_FORCED_ON, + AUTO_FPS_PIPELINE_FORCED_ON, + AUTO_FPS_AUTO_PIPELINE, + }; + + switch (swappy_mode) { + case PIPELINE_FORCED_ON: + SwappyVk_setAutoSwapInterval(true); + SwappyVk_setAutoPipelineMode(true); + break; + case AUTO_FPS_PIPELINE_FORCED_ON: + SwappyVk_setAutoSwapInterval(true); + SwappyVk_setAutoPipelineMode(false); + break; + case AUTO_FPS_AUTO_PIPELINE: + SwappyVk_setAutoSwapInterval(false); + SwappyVk_setAutoPipelineMode(false); + break; + } + } +#endif + uint32_t image_count = 0; err = device_functions.GetSwapchainImagesKHR(vk_device, swap_chain->vk_swapchain, &image_count, nullptr); ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); @@ -2951,12 +3103,16 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, fb_create_info.height = surface->height; fb_create_info.layers = 1; - VkFramebuffer framebuffer; + VkFramebuffer vk_framebuffer; for (uint32_t i = 0; i < image_count; i++) { fb_create_info.pAttachments = &swap_chain->image_views[i]; - err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &framebuffer); + err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer); ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + Framebuffer *framebuffer = memnew(Framebuffer); + framebuffer->vk_framebuffer = vk_framebuffer; + framebuffer->swap_chain_image = swap_chain->images[i]; + framebuffer->swap_chain_image_subresource_range = view_create_info.subresourceRange; swap_chain->framebuffers.push_back(RDD::FramebufferID(framebuffer)); } @@ -3025,7 +3181,10 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(C command_queue->pending_semaphores_for_fence.push_back(semaphore_index); // Return the corresponding framebuffer to the new current image. - return swap_chain->framebuffers[swap_chain->image_index]; + FramebufferID framebuffer_id = swap_chain->framebuffers[swap_chain->image_index]; + Framebuffer *framebuffer = (Framebuffer *)(framebuffer_id.id); + framebuffer->swap_chain_acquired = true; + return framebuffer_id; } RDD::RenderPassID RenderingDeviceDriverVulkan::swap_chain_get_render_pass(SwapChainID p_swap_chain) { @@ -3035,6 +3194,13 @@ RDD::RenderPassID RenderingDeviceDriverVulkan::swap_chain_get_render_pass(SwapCh return swap_chain->render_pass; } +int RenderingDeviceDriverVulkan::swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) { + DEV_ASSERT(p_swap_chain.id != 0); + + SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id); + return swap_chain->pre_transform_rotation_degrees; +} + RDD::DataFormat RenderingDeviceDriverVulkan::swap_chain_get_format(SwapChainID p_swap_chain) { DEV_ASSERT(p_swap_chain.id != 0); @@ -3050,6 +3216,22 @@ RDD::DataFormat RenderingDeviceDriverVulkan::swap_chain_get_format(SwapChainID p } } +void RenderingDeviceDriverVulkan::swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) { + DEV_ASSERT(p_swap_chain.id != 0); + +#ifdef SWAPPY_FRAME_PACING_ENABLED + if (!swappy_frame_pacer_enable) { + return; + } + + SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id); + if (swap_chain->vk_swapchain != VK_NULL_HANDLE) { + const uint64_t max_time = p_max_fps > 0 ? uint64_t((1000.0 * 1000.0 * 1000.0) / p_max_fps) : 0; + SwappyVk_setSwapIntervalNS(vk_device, swap_chain->vk_swapchain, MAX(swap_chain->refresh_duration, max_time)); + } +#endif +} + void RenderingDeviceDriverVulkan::swap_chain_free(SwapChainID p_swap_chain) { DEV_ASSERT(p_swap_chain.id != 0); @@ -3094,11 +3276,15 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::framebuffer_create(RenderPassID } #endif - return FramebufferID(vk_framebuffer); + Framebuffer *framebuffer = memnew(Framebuffer); + framebuffer->vk_framebuffer = vk_framebuffer; + return FramebufferID(framebuffer); } void RenderingDeviceDriverVulkan::framebuffer_free(FramebufferID p_framebuffer) { - vkDestroyFramebuffer(vk_device, (VkFramebuffer)p_framebuffer.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER)); + Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id); + vkDestroyFramebuffer(vk_device, framebuffer->vk_framebuffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER)); + memdelete(framebuffer); } /****************/ @@ -3865,7 +4051,7 @@ RDD::UniformSetID RenderingDeviceDriverVulkan::uniform_set_create(VectorView<Bou } // Need a descriptor pool. - DescriptorSetPools::Iterator pool_sets_it = {}; + DescriptorSetPools::Iterator pool_sets_it; VkDescriptorPool vk_pool = _descriptor_set_pool_find_or_create(pool_key, &pool_sets_it); DEV_ASSERT(vk_pool); pool_sets_it->value[vk_pool]++; @@ -4316,10 +4502,25 @@ void RenderingDeviceDriverVulkan::render_pass_free(RenderPassID p_render_pass) { static_assert(ARRAYS_COMPATIBLE_FIELDWISE(RDD::RenderPassClearValue, VkClearValue)); void RenderingDeviceDriverVulkan::command_begin_render_pass(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, FramebufferID p_framebuffer, CommandBufferType p_cmd_buffer_type, const Rect2i &p_rect, VectorView<RenderPassClearValue> p_clear_values) { + Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id); + if (framebuffer->swap_chain_acquired) { + // Insert a barrier to wait for the acquisition of the framebuffer before the render pass begins. + VkImageMemoryBarrier image_barrier = {}; + image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + image_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_barrier.image = framebuffer->swap_chain_image; + image_barrier.subresourceRange = framebuffer->swap_chain_image_subresource_range; + vkCmdPipelineBarrier((VkCommandBuffer)p_cmd_buffer.id, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_barrier); + framebuffer->swap_chain_acquired = false; + } + VkRenderPassBeginInfo render_pass_begin = {}; render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin.renderPass = (VkRenderPass)p_render_pass.id; - render_pass_begin.framebuffer = (VkFramebuffer)p_framebuffer.id; + render_pass_begin.framebuffer = framebuffer->vk_framebuffer; render_pass_begin.renderArea.offset.x = p_rect.position.x; render_pass_begin.renderArea.offset.y = p_rect.position.y; @@ -4976,10 +5177,65 @@ void RenderingDeviceDriverVulkan::command_end_label(CommandBufferID p_cmd_buffer /**** DEBUG *****/ /****************/ void RenderingDeviceDriverVulkan::command_insert_breadcrumb(CommandBufferID p_cmd_buffer, uint32_t p_data) { +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) if (p_data == BreadcrumbMarker::NONE) { return; } - vkCmdFillBuffer((VkCommandBuffer)p_cmd_buffer.id, ((BufferInfo *)breadcrumb_buffer.id)->vk_buffer, 0, sizeof(uint32_t), p_data); + + if (Engine::get_singleton()->is_accurate_breadcrumbs_enabled()) { + // Force a full barrier so commands are not executed in parallel. + // This will mean that the last breadcrumb to see was actually the + // last (group of) command to be executed (hence, the one causing the crash). + VkMemoryBarrier memoryBarrier; + memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memoryBarrier.pNext = nullptr; + memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT | + VK_ACCESS_INDEX_READ_BIT | + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | + VK_ACCESS_UNIFORM_READ_BIT | + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | + VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_READ_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT | + VK_ACCESS_HOST_READ_BIT | + VK_ACCESS_HOST_WRITE_BIT; + memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT | + VK_ACCESS_INDEX_READ_BIT | + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | + VK_ACCESS_UNIFORM_READ_BIT | + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | + VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_READ_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT | + VK_ACCESS_HOST_READ_BIT | + VK_ACCESS_HOST_WRITE_BIT; + + vkCmdPipelineBarrier( + (VkCommandBuffer)p_cmd_buffer.id, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, 1u, &memoryBarrier, 0u, nullptr, 0u, nullptr); + } + + // We write to a circular buffer. If you're getting barrier sync errors here, + // increase the value of BREADCRUMB_BUFFER_ENTRIES. + vkCmdFillBuffer((VkCommandBuffer)p_cmd_buffer.id, ((BufferInfo *)breadcrumb_buffer.id)->vk_buffer, breadcrumb_offset, sizeof(uint32_t), breadcrumb_id++); + vkCmdFillBuffer((VkCommandBuffer)p_cmd_buffer.id, ((BufferInfo *)breadcrumb_buffer.id)->vk_buffer, breadcrumb_offset + sizeof(uint32_t), sizeof(uint32_t), p_data); + breadcrumb_offset += sizeof(uint32_t) * 2u; + if (breadcrumb_offset >= BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u) { + breadcrumb_offset = 0u; + } +#endif } void RenderingDeviceDriverVulkan::on_device_lost() const { @@ -5061,68 +5317,142 @@ void RenderingDeviceDriverVulkan::on_device_lost() const { void RenderingDeviceDriverVulkan::print_lost_device_info() { #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) - void *breadcrumb_ptr; - vmaFlushAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, sizeof(uint32_t)); - vmaInvalidateAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, sizeof(uint32_t)); - - vmaMapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, &breadcrumb_ptr); - uint32_t last_breadcrumb = *(uint32_t *)breadcrumb_ptr; - vmaUnmapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle); - uint32_t phase = last_breadcrumb & uint32_t(~((1 << 16) - 1)); - uint32_t user_data = last_breadcrumb & ((1 << 16) - 1); - String error_msg = "Last known breadcrumb: "; - - switch (phase) { - case BreadcrumbMarker::ALPHA_PASS: - error_msg += "ALPHA_PASS"; - break; - case BreadcrumbMarker::BLIT_PASS: - error_msg += "BLIT_PASS"; - break; - case BreadcrumbMarker::DEBUG_PASS: - error_msg += "DEBUG_PASS"; - break; - case BreadcrumbMarker::LIGHTMAPPER_PASS: - error_msg += "LIGHTMAPPER_PASS"; - break; - case BreadcrumbMarker::OPAQUE_PASS: - error_msg += "OPAQUE_PASS"; - break; - case BreadcrumbMarker::POST_PROCESSING_PASS: - error_msg += "POST_PROCESSING_PASS"; - break; - case BreadcrumbMarker::REFLECTION_PROBES: - error_msg += "REFLECTION_PROBES"; - break; - case BreadcrumbMarker::SHADOW_PASS_CUBE: - error_msg += "SHADOW_PASS_CUBE"; - break; - case BreadcrumbMarker::SHADOW_PASS_DIRECTIONAL: - error_msg += "SHADOW_PASS_DIRECTIONAL"; - break; - case BreadcrumbMarker::SKY_PASS: - error_msg += "SKY_PASS"; - break; - case BreadcrumbMarker::TRANSPARENT_PASS: - error_msg += "TRANSPARENT_PASS"; - break; - case BreadcrumbMarker::UI_PASS: - error_msg += "UI_PASS"; - break; - default: - error_msg += "UNKNOWN_BREADCRUMB(" + itos((uint32_t)phase) + ')'; - break; + { + String error_msg = "Printing last known breadcrumbs in reverse order (last executed first)."; + if (!Engine::get_singleton()->is_accurate_breadcrumbs_enabled()) { + error_msg += "\nSome of them might be inaccurate. Try running with --accurate-breadcrumbs for precise information."; + } + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, error_msg); } - if (user_data != 0) { - error_msg += " | User data: " + itos(user_data); - } + uint8_t *breadcrumb_ptr = nullptr; + VkResult map_result = VK_SUCCESS; + + vmaFlushAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u); + vmaInvalidateAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u); + { + void *ptr = nullptr; + map_result = vmaMapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, &ptr); + breadcrumb_ptr = reinterpret_cast<uint8_t *>(ptr); + } + + if (breadcrumb_ptr && map_result == VK_SUCCESS) { + uint32_t last_breadcrumb_offset = 0; + { + _err_print_error_asap("Searching last breadcrumb. We've sent up to ID: " + itos(breadcrumb_id - 1u)); + + // Scan the whole buffer to find the offset with the highest ID. + // That means that was the last one to be written. + // + // We use "breadcrumb_id - id" to account for wraparound. + // e.g. breadcrumb_id = 2 and id = 4294967294; then 2 - 4294967294 = 4. + // The one with the smallest difference is the closest to breadcrumb_id, which means it's + // the last written command. + uint32_t biggest_id = 0u; + uint32_t smallest_id_diff = std::numeric_limits<uint32_t>::max(); + const uint32_t *breadcrumb_ptr32 = reinterpret_cast<const uint32_t *>(breadcrumb_ptr); + for (size_t i = 0u; i < BREADCRUMB_BUFFER_ENTRIES; ++i) { + const uint32_t id = breadcrumb_ptr32[i * 2u]; + const uint32_t id_diff = breadcrumb_id - id; + if (id_diff < smallest_id_diff) { + biggest_id = i; + smallest_id_diff = id_diff; + } + } - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, error_msg); + _err_print_error_asap("Last breadcrumb ID found: " + itos(breadcrumb_ptr32[biggest_id * 2u])); + + last_breadcrumb_offset = biggest_id * sizeof(uint32_t) * 2u; + } + + const size_t entries_to_print = 8u; // Note: The value is arbitrary. + for (size_t i = 0u; i < entries_to_print; ++i) { + const uint32_t last_breadcrumb = *reinterpret_cast<uint32_t *>(breadcrumb_ptr + last_breadcrumb_offset + sizeof(uint32_t)); + const uint32_t phase = last_breadcrumb & uint32_t(~((1 << 16) - 1)); + const uint32_t user_data = last_breadcrumb & ((1 << 16) - 1); + String error_msg = "Last known breadcrumb: "; + + switch (phase) { + case BreadcrumbMarker::ALPHA_PASS: + error_msg += "ALPHA_PASS"; + break; + case BreadcrumbMarker::BLIT_PASS: + error_msg += "BLIT_PASS"; + break; + case BreadcrumbMarker::DEBUG_PASS: + error_msg += "DEBUG_PASS"; + break; + case BreadcrumbMarker::LIGHTMAPPER_PASS: + error_msg += "LIGHTMAPPER_PASS"; + break; + case BreadcrumbMarker::OPAQUE_PASS: + error_msg += "OPAQUE_PASS"; + break; + case BreadcrumbMarker::POST_PROCESSING_PASS: + error_msg += "POST_PROCESSING_PASS"; + break; + case BreadcrumbMarker::REFLECTION_PROBES: + error_msg += "REFLECTION_PROBES"; + break; + case BreadcrumbMarker::SHADOW_PASS_CUBE: + error_msg += "SHADOW_PASS_CUBE"; + break; + case BreadcrumbMarker::SHADOW_PASS_DIRECTIONAL: + error_msg += "SHADOW_PASS_DIRECTIONAL"; + break; + case BreadcrumbMarker::SKY_PASS: + error_msg += "SKY_PASS"; + break; + case BreadcrumbMarker::TRANSPARENT_PASS: + error_msg += "TRANSPARENT_PASS"; + break; + case BreadcrumbMarker::UI_PASS: + error_msg += "UI_PASS"; + break; + default: + error_msg += "UNKNOWN_BREADCRUMB(" + itos((uint32_t)phase) + ')'; + break; + } + + if (user_data != 0) { + error_msg += " | User data: " + itos(user_data); + } + + _err_print_error_asap(error_msg); + + if (last_breadcrumb_offset == 0u) { + // Decrement last_breadcrumb_idx, wrapping underflow. + last_breadcrumb_offset = BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u; + } + last_breadcrumb_offset -= sizeof(uint32_t) * 2u; + } + + vmaUnmapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle); + breadcrumb_ptr = nullptr; + } else { + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Couldn't map breadcrumb buffer. VkResult = " + itos(map_result)); + } #endif on_device_lost(); } +inline String RenderingDeviceDriverVulkan::get_vulkan_result(VkResult err) { +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) + if (err == VK_ERROR_OUT_OF_HOST_MEMORY) { + return "VK_ERROR_OUT_OF_HOST_MEMORY"; + } else if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY) { + return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + } else if (err == VK_ERROR_DEVICE_LOST) { + return "VK_ERROR_DEVICE_LOST"; + } else if (err == VK_ERROR_SURFACE_LOST_KHR) { + return "VK_ERROR_SURFACE_LOST_KHR"; + } else if (err == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) { + return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; + } +#endif + return itos(err); +} + /********************/ /**** SUBMISSION ****/ /********************/ @@ -5389,7 +5719,9 @@ RenderingDeviceDriverVulkan::RenderingDeviceDriverVulkan(RenderingContextDriverV } RenderingDeviceDriverVulkan::~RenderingDeviceDriverVulkan() { +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) buffer_free(breadcrumb_buffer); +#endif while (small_allocs_pools.size()) { HashMap<uint32_t, VmaPool>::Iterator E = small_allocs_pools.begin(); diff --git a/drivers/vulkan/rendering_device_driver_vulkan.h b/drivers/vulkan/rendering_device_driver_vulkan.h index 58f7a97ec0..06cd2a31be 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.h +++ b/drivers/vulkan/rendering_device_driver_vulkan.h @@ -143,6 +143,11 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver { #if defined(VK_TRACK_DEVICE_MEMORY) bool device_memory_report_support = false; #endif +#if defined(SWAPPY_FRAME_PACING_ENABLED) + // Swappy frame pacer for Android. + bool swappy_frame_pacer_enable = false; + uint8_t swappy_mode = 2; // See default value for display/window/frame_pacing/android/swappy_mode. +#endif DeviceFunctions device_functions; void _register_requested_device_extension(const CharString &p_extension_name, bool p_required); @@ -172,7 +177,12 @@ private: VmaPool _find_or_create_small_allocs_pool(uint32_t p_mem_type_index); private: +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) + // It's a circular buffer. BufferID breadcrumb_buffer; + uint32_t breadcrumb_offset = 0u; + uint32_t breadcrumb_id = 0u; +#endif public: /*****************/ @@ -349,7 +359,11 @@ private: LocalVector<CommandQueue *> command_queues_acquired; LocalVector<uint32_t> command_queues_acquired_semaphores; RenderPassID render_pass; + int pre_transform_rotation_degrees = 0; uint32_t image_index = 0; +#ifdef ANDROID_ENABLED + uint64_t refresh_duration = 0; +#endif }; void _swap_chain_release(SwapChain *p_swap_chain); @@ -359,13 +373,24 @@ public: virtual Error swap_chain_resize(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, uint32_t p_desired_framebuffer_count) override final; virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) override final; virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) override final; + virtual int swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) override final; virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override final; + virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) override final; virtual void swap_chain_free(SwapChainID p_swap_chain) override final; /*********************/ /**** FRAMEBUFFER ****/ /*********************/ + struct Framebuffer { + VkFramebuffer vk_framebuffer = VK_NULL_HANDLE; + + // Only filled in by a framebuffer created by a swap chain. Unused otherwise. + VkImage swap_chain_image = VK_NULL_HANDLE; + VkImageSubresourceRange swap_chain_image_subresource_range = {}; + bool swap_chain_acquired = false; + }; + virtual FramebufferID framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height) override final; virtual void framebuffer_free(FramebufferID p_framebuffer) override final; @@ -463,7 +488,7 @@ private: struct UniformSetInfo { VkDescriptorSet vk_descriptor_set = VK_NULL_HANDLE; VkDescriptorPool vk_descriptor_pool = VK_NULL_HANDLE; - DescriptorSetPools::Iterator pool_sets_it = {}; + DescriptorSetPools::Iterator pool_sets_it; }; public: @@ -630,6 +655,7 @@ public: virtual void command_insert_breadcrumb(CommandBufferID p_cmd_buffer, uint32_t p_data) override final; void print_lost_device_info(); void on_device_lost() const; + static String get_vulkan_result(VkResult err); /********************/ /**** SUBMISSION ****/ diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index 4e7c9695a5..b800e5f1f4 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -85,7 +85,7 @@ public: _In_ const WAVEFORMATEX *pFormat, /* [annotation][in] */ _In_opt_ LPCGUID AudioSessionGuid) = 0; -}; +} __CRT_UUID_DECL(IAudioClient3, 0x7ED4EE07, 0x8E67, 0x4CD4, 0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42) #endif // __IAudioClient3_INTERFACE_DEFINED__ diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index f7632842ed..3ddbde72c4 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -230,7 +230,7 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) const { return cdir; } else { if (_get_root_string().is_empty()) { - int pos = cdir.find(":"); + int pos = cdir.find_char(':'); if (pos != -1) { return cdir.substr(pos + 1); } @@ -282,7 +282,7 @@ Error DirAccessWindows::rename(String p_path, String p_new_path) { uint64_t id = OS::get_singleton()->get_ticks_usec(); while (true) { tmpfile_utf16 = (path + itos(id++) + ".tmp").utf16(); - HANDLE handle = CreateFileW((LPCWSTR)tmpfile_utf16.get_data(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + HANDLE handle = CreateFileW((LPCWSTR)tmpfile_utf16.get_data(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); if (handle != INVALID_HANDLE_VALUE) { CloseHandle(handle); break; @@ -344,7 +344,7 @@ String DirAccessWindows::get_filesystem_type() const { return "Network Share"; } - int unit_end = path.find(":"); + int unit_end = path.find_char(':'); ERR_FAIL_COND_V(unit_end == -1, String()); String unit = path.substr(0, unit_end + 1) + "\\"; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index a8a2ea6b5e..4a0e5e5f49 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -64,7 +64,7 @@ bool FileAccessWindows::is_path_invalid(const String &p_path) { // Check for invalid operating system file. String fname = p_path.get_file().to_lower(); - int dot = fname.find("."); + int dot = fname.find_char('.'); if (dot != -1) { fname = fname.substr(0, dot); } @@ -127,7 +127,7 @@ Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) { } #ifdef TOOLS_ENABLED - // Windows is case insensitive, but all other platforms are sensitive to it + // Windows is case insensitive in the default configuration, but other platforms can be sensitive to it // To ease cross-platform development, we issue a warning if users try to access // a file using the wrong case (which *works* on Windows, but won't on other // platforms), we only check for relative paths, or paths in res:// or user://, @@ -193,7 +193,7 @@ Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) { uint64_t id = OS::get_singleton()->get_ticks_usec(); while (true) { tmpfile = path + itos(id++) + ".tmp"; - HANDLE handle = CreateFileW((LPCWSTR)tmpfile.utf16().get_data(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + HANDLE handle = CreateFileW((LPCWSTR)tmpfile.utf16().get_data(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); if (handle != INVALID_HANDLE_VALUE) { CloseHandle(handle); break; diff --git a/drivers/windows/file_access_windows_pipe.cpp b/drivers/windows/file_access_windows_pipe.cpp index 9bf0f4d852..7348b29a92 100644 --- a/drivers/windows/file_access_windows_pipe.cpp +++ b/drivers/windows/file_access_windows_pipe.cpp @@ -40,7 +40,7 @@ Error FileAccessWindowsPipe::open_existing(HANDLE p_rfd, HANDLE p_wfd, bool p_bl _close(); path_src = String(); - ERR_FAIL_COND_V_MSG(fd[0] != 0 || fd[1] != 0, ERR_ALREADY_IN_USE, "Pipe is already in use."); + ERR_FAIL_COND_V_MSG(fd[0] != nullptr || fd[1] != nullptr, ERR_ALREADY_IN_USE, "Pipe is already in use."); fd[0] = p_rfd; fd[1] = p_wfd; @@ -58,18 +58,18 @@ Error FileAccessWindowsPipe::open_internal(const String &p_path, int p_mode_flag _close(); path_src = p_path; - ERR_FAIL_COND_V_MSG(fd[0] != 0 || fd[1] != 0, ERR_ALREADY_IN_USE, "Pipe is already in use."); + ERR_FAIL_COND_V_MSG(fd[0] != nullptr || fd[1] != nullptr, ERR_ALREADY_IN_USE, "Pipe is already in use."); path = String("\\\\.\\pipe\\LOCAL\\") + p_path.replace("pipe://", "").replace("/", "_"); - HANDLE h = CreateFileW((LPCWSTR)path.utf16().get_data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE h = CreateFileW((LPCWSTR)path.utf16().get_data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (h == INVALID_HANDLE_VALUE) { h = CreateNamedPipeW((LPCWSTR)path.utf16().get_data(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 4096, 4096, 0, nullptr); if (h == INVALID_HANDLE_VALUE) { last_error = ERR_FILE_CANT_OPEN; return last_error; } - ConnectNamedPipe(h, NULL); + ConnectNamedPipe(h, nullptr); } fd[0] = h; fd[1] = h; @@ -79,19 +79,19 @@ Error FileAccessWindowsPipe::open_internal(const String &p_path, int p_mode_flag } void FileAccessWindowsPipe::_close() { - if (fd[0] == 0) { + if (fd[0] == nullptr) { return; } if (fd[1] != fd[0]) { CloseHandle(fd[1]); } CloseHandle(fd[0]); - fd[0] = 0; - fd[1] = 0; + fd[0] = nullptr; + fd[1] = nullptr; } bool FileAccessWindowsPipe::is_open() const { - return (fd[0] != 0 || fd[1] != 0); + return (fd[0] != nullptr || fd[1] != nullptr); } String FileAccessWindowsPipe::get_path() const { @@ -103,7 +103,7 @@ String FileAccessWindowsPipe::get_path_absolute() const { } uint64_t FileAccessWindowsPipe::get_buffer(uint8_t *p_dst, uint64_t p_length) const { - ERR_FAIL_COND_V_MSG(fd[0] == 0, -1, "Pipe must be opened before use."); + ERR_FAIL_COND_V_MSG(fd[0] == nullptr, -1, "Pipe must be opened before use."); ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); DWORD read = 0; @@ -120,7 +120,7 @@ Error FileAccessWindowsPipe::get_error() const { } void FileAccessWindowsPipe::store_buffer(const uint8_t *p_src, uint64_t p_length) { - ERR_FAIL_COND_MSG(fd[1] == 0, "Pipe must be opened before use."); + ERR_FAIL_COND_MSG(fd[1] == nullptr, "Pipe must be opened before use."); ERR_FAIL_COND(!p_src && p_length > 0); DWORD read = -1; diff --git a/drivers/windows/file_access_windows_pipe.h b/drivers/windows/file_access_windows_pipe.h index 1eb3c6ef2f..5edf0500a5 100644 --- a/drivers/windows/file_access_windows_pipe.h +++ b/drivers/windows/file_access_windows_pipe.h @@ -39,7 +39,7 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> class FileAccessWindowsPipe : public FileAccess { - HANDLE fd[2] = { 0, 0 }; + HANDLE fd[2] = { nullptr, nullptr }; mutable Error last_error = OK; diff --git a/drivers/windows/ip_windows.cpp b/drivers/windows/ip_windows.cpp new file mode 100644 index 0000000000..4ff368d3f4 --- /dev/null +++ b/drivers/windows/ip_windows.cpp @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* ip_windows.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. */ +/**************************************************************************/ + +#if defined(WINDOWS_ENABLED) + +#include "ip_windows.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winsock2.h> +#include <ws2tcpip.h> + +#include <iphlpapi.h> + +#include <stdio.h> + +#include <string.h> + +static IPAddress _sockaddr2ip(struct sockaddr *p_addr) { + IPAddress ip; + + if (p_addr->sa_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *)p_addr; + ip.set_ipv4((uint8_t *)&(addr->sin_addr)); + } else if (p_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr; + ip.set_ipv6(addr6->sin6_addr.s6_addr); + } + + return ip; +} + +void IPWindows::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type) const { + struct addrinfo hints; + struct addrinfo *result = nullptr; + + memset(&hints, 0, sizeof(struct addrinfo)); + if (p_type == TYPE_IPV4) { + hints.ai_family = AF_INET; + } else if (p_type == TYPE_IPV6) { + hints.ai_family = AF_INET6; + hints.ai_flags = 0; + } else { + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; + } + hints.ai_flags &= ~AI_NUMERICHOST; + + int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result); + if (s != 0) { + print_verbose("getaddrinfo failed! Cannot resolve hostname."); + return; + } + + if (result == nullptr || result->ai_addr == nullptr) { + print_verbose("Invalid response from getaddrinfo."); + if (result) { + freeaddrinfo(result); + } + return; + } + + struct addrinfo *next = result; + + do { + if (next->ai_addr == nullptr) { + next = next->ai_next; + continue; + } + IPAddress ip = _sockaddr2ip(next->ai_addr); + if (ip.is_valid() && !r_addresses.find(ip)) { + r_addresses.push_back(ip); + } + next = next->ai_next; + } while (next); + + freeaddrinfo(result); +} + +void IPWindows::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const { + ULONG buf_size = 1024; + IP_ADAPTER_ADDRESSES *addrs; + + while (true) { + addrs = (IP_ADAPTER_ADDRESSES *)memalloc(buf_size); + int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, + nullptr, addrs, &buf_size); + if (err == NO_ERROR) { + break; + } + memfree(addrs); + if (err == ERROR_BUFFER_OVERFLOW) { + continue; // Will go back and alloc the right size. + } + + ERR_FAIL_MSG("Call to GetAdaptersAddresses failed with error " + itos(err) + "."); + } + + IP_ADAPTER_ADDRESSES *adapter = addrs; + + while (adapter != nullptr) { + Interface_Info info; + info.name = adapter->AdapterName; + info.name_friendly = adapter->FriendlyName; + info.index = String::num_uint64(adapter->IfIndex); + + IP_ADAPTER_UNICAST_ADDRESS *address = adapter->FirstUnicastAddress; + while (address != nullptr) { + int family = address->Address.lpSockaddr->sa_family; + if (family != AF_INET && family != AF_INET6) { + continue; + } + info.ip_addresses.push_front(_sockaddr2ip(address->Address.lpSockaddr)); + address = address->Next; + } + adapter = adapter->Next; + // Only add interface if it has at least one IP. + if (info.ip_addresses.size() > 0) { + r_interfaces->insert(info.name, info); + } + } + + memfree(addrs); +} + +void IPWindows::make_default() { + _create = _create_unix; +} + +IP *IPWindows::_create_unix() { + return memnew(IPWindows); +} + +IPWindows::IPWindows() { +} + +#endif // WINDOWS_ENABLED diff --git a/drivers/windows/ip_windows.h b/drivers/windows/ip_windows.h new file mode 100644 index 0000000000..5788d33ee2 --- /dev/null +++ b/drivers/windows/ip_windows.h @@ -0,0 +1,54 @@ +/**************************************************************************/ +/* ip_windows.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef IP_WINDOWS_H +#define IP_WINDOWS_H + +#if defined(WINDOWS_ENABLED) + +#include "core/io/ip.h" + +class IPWindows : public IP { + GDCLASS(IPWindows, IP); + + virtual void _resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type = TYPE_ANY) const override; + + static IP *_create_unix(); + +public: + virtual void get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const override; + + static void make_default(); + IPWindows(); +}; + +#endif // WINDOWS_ENABLED + +#endif // IP_WINDOWS_H diff --git a/drivers/windows/net_socket_winsock.cpp b/drivers/windows/net_socket_winsock.cpp new file mode 100644 index 0000000000..3fe7fc619e --- /dev/null +++ b/drivers/windows/net_socket_winsock.cpp @@ -0,0 +1,613 @@ +/**************************************************************************/ +/* net_socket_winsock.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 WINDOWS_ENABLED + +#include "net_socket_winsock.h" + +#include <winsock2.h> +#include <ws2tcpip.h> + +#include <mswsock.h> +// Workaround missing flag in MinGW +#if defined(__MINGW32__) && !defined(SIO_UDP_NETRESET) +#define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15) +#endif + +size_t NetSocketWinSock::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) { + memset(p_addr, 0, sizeof(struct sockaddr_storage)); + if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket. + + // IPv6 only socket with IPv4 address. + ERR_FAIL_COND_V(!p_ip.is_wildcard() && p_ip_type == IP::TYPE_IPV6 && p_ip.is_ipv4(), 0); + + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(p_port); + if (p_ip.is_valid()) { + memcpy(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16); + } else { + addr6->sin6_addr = in6addr_any; + } + return sizeof(sockaddr_in6); + } else { // IPv4 socket. + + // IPv4 socket with IPv6 address. + ERR_FAIL_COND_V(!p_ip.is_wildcard() && !p_ip.is_ipv4(), 0); + + struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(p_port); // Short, network byte order. + + if (p_ip.is_valid()) { + memcpy(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4); + } else { + addr4->sin_addr.s_addr = INADDR_ANY; + } + + return sizeof(sockaddr_in); + } +} + +void NetSocketWinSock::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port) { + if (p_addr->ss_family == AF_INET) { + struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; + if (r_ip) { + r_ip->set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr)); + } + if (r_port) { + *r_port = ntohs(addr4->sin_port); + } + } else if (p_addr->ss_family == AF_INET6) { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr; + if (r_ip) { + r_ip->set_ipv6(addr6->sin6_addr.s6_addr); + } + if (r_port) { + *r_port = ntohs(addr6->sin6_port); + } + } +} + +NetSocket *NetSocketWinSock::_create_func() { + return memnew(NetSocketWinSock); +} + +void NetSocketWinSock::make_default() { + ERR_FAIL_COND(_create != nullptr); + + WSADATA data; + WSAStartup(MAKEWORD(2, 2), &data); + _create = _create_func; +} + +void NetSocketWinSock::cleanup() { + ERR_FAIL_COND(_create == nullptr); + + WSACleanup(); + _create = nullptr; +} + +NetSocketWinSock::NetSocketWinSock() { +} + +NetSocketWinSock::~NetSocketWinSock() { + close(); +} + +NetSocketWinSock::NetError NetSocketWinSock::_get_socket_error() const { + int err = WSAGetLastError(); + if (err == WSAEISCONN) { + return ERR_NET_IS_CONNECTED; + } + if (err == WSAEINPROGRESS || err == WSAEALREADY) { + return ERR_NET_IN_PROGRESS; + } + if (err == WSAEWOULDBLOCK) { + return ERR_NET_WOULD_BLOCK; + } + if (err == WSAEADDRINUSE || err == WSAEADDRNOTAVAIL) { + return ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE; + } + if (err == WSAEACCES) { + return ERR_NET_UNAUTHORIZED; + } + if (err == WSAEMSGSIZE || err == WSAENOBUFS) { + return ERR_NET_BUFFER_TOO_SMALL; + } + print_verbose("Socket error: " + itos(err) + "."); + return ERR_NET_OTHER; +} + +bool NetSocketWinSock::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const { + if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) { + return false; + } else if (!p_for_bind && !p_ip.is_valid()) { + return false; + } + // Check if socket support this IP type. + IP::Type type = p_ip.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + return !(_ip_type != IP::TYPE_ANY && !p_ip.is_wildcard() && _ip_type != type); +} + +_FORCE_INLINE_ Error NetSocketWinSock::_change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + ERR_FAIL_COND_V(!_can_use_ip(p_ip, false), ERR_INVALID_PARAMETER); + + // Need to force level and af_family to IP(v4) when using dual stacking and provided multicast group is IPv4. + IP::Type type = _ip_type == IP::TYPE_ANY && p_ip.is_ipv4() ? IP::TYPE_IPV4 : _ip_type; + // This needs to be the proper level for the multicast group, no matter if the socket is dual stacking. + int level = type == IP::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; + int ret = -1; + + IPAddress if_ip; + uint32_t if_v6id = 0; + HashMap<String, IP::Interface_Info> if_info; + IP::get_singleton()->get_local_interfaces(&if_info); + for (KeyValue<String, IP::Interface_Info> &E : if_info) { + IP::Interface_Info &c = E.value; + if (c.name != p_if_name) { + continue; + } + + if_v6id = (uint32_t)c.index.to_int(); + if (type == IP::TYPE_IPV6) { + break; // IPv6 uses index. + } + + for (const IPAddress &F : c.ip_addresses) { + if (!F.is_ipv4()) { + continue; // Wrong IP type. + } + if_ip = F; + break; + } + break; + } + + if (level == IPPROTO_IP) { + ERR_FAIL_COND_V(!if_ip.is_valid(), ERR_INVALID_PARAMETER); + struct ip_mreq greq; + int sock_opt = p_add ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; + memcpy(&greq.imr_multiaddr, p_ip.get_ipv4(), 4); + memcpy(&greq.imr_interface, if_ip.get_ipv4(), 4); + ret = setsockopt(_sock, level, sock_opt, (const char *)&greq, sizeof(greq)); + } else { + struct ipv6_mreq greq; + int sock_opt = p_add ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP; + memcpy(&greq.ipv6mr_multiaddr, p_ip.get_ipv6(), 16); + greq.ipv6mr_interface = if_v6id; + ret = setsockopt(_sock, level, sock_opt, (const char *)&greq, sizeof(greq)); + } + ERR_FAIL_COND_V(ret != 0, FAILED); + + return OK; +} + +void NetSocketWinSock::_set_socket(SOCKET p_sock, IP::Type p_ip_type, bool p_is_stream) { + _sock = p_sock; + _ip_type = p_ip_type; + _is_stream = p_is_stream; +} + +Error NetSocketWinSock::open(Type p_sock_type, IP::Type &ip_type) { + ERR_FAIL_COND_V(is_open(), ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(ip_type > IP::TYPE_ANY || ip_type < IP::TYPE_NONE, ERR_INVALID_PARAMETER); + + int family = ip_type == IP::TYPE_IPV4 ? AF_INET : AF_INET6; + int protocol = p_sock_type == TYPE_TCP ? IPPROTO_TCP : IPPROTO_UDP; + int type = p_sock_type == TYPE_TCP ? SOCK_STREAM : SOCK_DGRAM; + _sock = socket(family, type, protocol); + + if (_sock == INVALID_SOCKET && ip_type == IP::TYPE_ANY) { + // Careful here, changing the referenced parameter so the caller knows that we are using an IPv4 socket + // in place of a dual stack one, and further calls to _set_sock_addr will work as expected. + ip_type = IP::TYPE_IPV4; + family = AF_INET; + _sock = socket(family, type, protocol); + } + + ERR_FAIL_COND_V(_sock == INVALID_SOCKET, FAILED); + _ip_type = ip_type; + + if (family == AF_INET6) { + // Select IPv4 over IPv6 mapping. + set_ipv6_only_enabled(ip_type != IP::TYPE_ANY); + } + + if (protocol == IPPROTO_UDP) { + // Make sure to disable broadcasting for UDP sockets. + // Depending on the OS, this option might or might not be enabled by default. Let's normalize it. + set_broadcasting_enabled(false); + } + + _is_stream = p_sock_type == TYPE_TCP; + + if (!_is_stream) { + // Disable windows feature/bug reporting WSAECONNRESET/WSAENETRESET when + // recv/recvfrom and an ICMP reply was received from a previous send/sendto. + unsigned long disable = 0; + if (ioctlsocket(_sock, SIO_UDP_CONNRESET, &disable) == SOCKET_ERROR) { + print_verbose("Unable to turn off UDP WSAECONNRESET behavior on Windows."); + } + if (ioctlsocket(_sock, SIO_UDP_NETRESET, &disable) == SOCKET_ERROR) { + // This feature seems not to be supported on wine. + print_verbose("Unable to turn off UDP WSAENETRESET behavior on Windows."); + } + } + return OK; +} + +void NetSocketWinSock::close() { + if (_sock != INVALID_SOCKET) { + closesocket(_sock); + } + + _sock = INVALID_SOCKET; + _ip_type = IP::TYPE_NONE; + _is_stream = false; +} + +Error NetSocketWinSock::bind(IPAddress p_addr, uint16_t p_port) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + ERR_FAIL_COND_V(!_can_use_ip(p_addr, true), ERR_INVALID_PARAMETER); + + sockaddr_storage addr; + size_t addr_size = _set_addr_storage(&addr, p_addr, p_port, _ip_type); + + if (::bind(_sock, (struct sockaddr *)&addr, addr_size) != 0) { + NetError err = _get_socket_error(); + print_verbose("Failed to bind socket. Error: " + itos(err) + "."); + close(); + return ERR_UNAVAILABLE; + } + + return OK; +} + +Error NetSocketWinSock::listen(int p_max_pending) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + + if (::listen(_sock, p_max_pending) != 0) { + _get_socket_error(); + print_verbose("Failed to listen from socket."); + close(); + return FAILED; + } + + return OK; +} + +Error NetSocketWinSock::connect_to_host(IPAddress p_host, uint16_t p_port) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + ERR_FAIL_COND_V(!_can_use_ip(p_host, false), ERR_INVALID_PARAMETER); + + struct sockaddr_storage addr; + size_t addr_size = _set_addr_storage(&addr, p_host, p_port, _ip_type); + + if (::WSAConnect(_sock, (struct sockaddr *)&addr, addr_size, nullptr, nullptr, nullptr, nullptr) != 0) { + NetError err = _get_socket_error(); + + switch (err) { + // We are already connected. + case ERR_NET_IS_CONNECTED: + return OK; + // Still waiting to connect, try again in a while. + case ERR_NET_WOULD_BLOCK: + case ERR_NET_IN_PROGRESS: + return ERR_BUSY; + default: + print_verbose("Connection to remote host failed."); + close(); + return FAILED; + } + } + + return OK; +} + +Error NetSocketWinSock::poll(PollType p_type, int p_timeout) const { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + + bool ready = false; + fd_set rd, wr, ex; + fd_set *rdp = nullptr; + fd_set *wrp = nullptr; + FD_ZERO(&rd); + FD_ZERO(&wr); + FD_ZERO(&ex); + FD_SET(_sock, &ex); + struct timeval timeout = { p_timeout / 1000, (p_timeout % 1000) * 1000 }; + // For blocking operation, pass nullptr timeout pointer to select. + struct timeval *tp = nullptr; + if (p_timeout >= 0) { + // If timeout is non-negative, we want to specify the timeout instead. + tp = &timeout; + } + + switch (p_type) { + case POLL_TYPE_IN: + FD_SET(_sock, &rd); + rdp = &rd; + break; + case POLL_TYPE_OUT: + FD_SET(_sock, &wr); + wrp = ≀ + break; + case POLL_TYPE_IN_OUT: + FD_SET(_sock, &rd); + FD_SET(_sock, &wr); + rdp = &rd; + wrp = ≀ + } + // WSAPoll is broken: https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/. + int ret = select(1, rdp, wrp, &ex, tp); + + if (ret == SOCKET_ERROR) { + return FAILED; + } + + if (ret == 0) { + return ERR_BUSY; + } + + if (FD_ISSET(_sock, &ex)) { + _get_socket_error(); + print_verbose("Exception when polling socket."); + return FAILED; + } + + if (rdp && FD_ISSET(_sock, rdp)) { + ready = true; + } + if (wrp && FD_ISSET(_sock, wrp)) { + ready = true; + } + + return ready ? OK : ERR_BUSY; +} + +Error NetSocketWinSock::recv(uint8_t *p_buffer, int p_len, int &r_read) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + + r_read = ::recv(_sock, (char *)p_buffer, p_len, 0); + + if (r_read < 0) { + NetError err = _get_socket_error(); + if (err == ERR_NET_WOULD_BLOCK) { + return ERR_BUSY; + } + + if (err == ERR_NET_BUFFER_TOO_SMALL) { + return ERR_OUT_OF_MEMORY; + } + + return FAILED; + } + + return OK; +} + +Error NetSocketWinSock::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + + struct sockaddr_storage from; + socklen_t len = sizeof(struct sockaddr_storage); + memset(&from, 0, len); + + r_read = ::recvfrom(_sock, (char *)p_buffer, p_len, p_peek ? MSG_PEEK : 0, (struct sockaddr *)&from, &len); + + if (r_read < 0) { + NetError err = _get_socket_error(); + if (err == ERR_NET_WOULD_BLOCK) { + return ERR_BUSY; + } + + if (err == ERR_NET_BUFFER_TOO_SMALL) { + return ERR_OUT_OF_MEMORY; + } + + return FAILED; + } + + if (from.ss_family == AF_INET) { + struct sockaddr_in *sin_from = (struct sockaddr_in *)&from; + r_ip.set_ipv4((uint8_t *)&sin_from->sin_addr); + r_port = ntohs(sin_from->sin_port); + } else if (from.ss_family == AF_INET6) { + struct sockaddr_in6 *s6_from = (struct sockaddr_in6 *)&from; + r_ip.set_ipv6((uint8_t *)&s6_from->sin6_addr); + r_port = ntohs(s6_from->sin6_port); + } else { + // Unsupported socket family, should never happen. + ERR_FAIL_V(FAILED); + } + + return OK; +} + +Error NetSocketWinSock::send(const uint8_t *p_buffer, int p_len, int &r_sent) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + + int flags = 0; + r_sent = ::send(_sock, (const char *)p_buffer, p_len, flags); + + if (r_sent < 0) { + NetError err = _get_socket_error(); + if (err == ERR_NET_WOULD_BLOCK) { + return ERR_BUSY; + } + if (err == ERR_NET_BUFFER_TOO_SMALL) { + return ERR_OUT_OF_MEMORY; + } + + return FAILED; + } + + return OK; +} + +Error NetSocketWinSock::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + + struct sockaddr_storage addr; + size_t addr_size = _set_addr_storage(&addr, p_ip, p_port, _ip_type); + r_sent = ::sendto(_sock, (const char *)p_buffer, p_len, 0, (struct sockaddr *)&addr, addr_size); + + if (r_sent < 0) { + NetError err = _get_socket_error(); + if (err == ERR_NET_WOULD_BLOCK) { + return ERR_BUSY; + } + if (err == ERR_NET_BUFFER_TOO_SMALL) { + return ERR_OUT_OF_MEMORY; + } + + return FAILED; + } + + return OK; +} + +Error NetSocketWinSock::set_broadcasting_enabled(bool p_enabled) { + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + // IPv6 has no broadcast support. + if (_ip_type == IP::TYPE_IPV6) { + return ERR_UNAVAILABLE; + } + + int par = p_enabled ? 1 : 0; + if (setsockopt(_sock, SOL_SOCKET, SO_BROADCAST, (const char *)&par, sizeof(int)) != 0) { + WARN_PRINT("Unable to change broadcast setting."); + return FAILED; + } + return OK; +} + +void NetSocketWinSock::set_blocking_enabled(bool p_enabled) { + ERR_FAIL_COND(!is_open()); + + int ret = 0; + unsigned long par = p_enabled ? 0 : 1; + ret = ioctlsocket(_sock, FIONBIO, &par); + if (ret != 0) { + WARN_PRINT("Unable to change non-block mode."); + } +} + +void NetSocketWinSock::set_ipv6_only_enabled(bool p_enabled) { + ERR_FAIL_COND(!is_open()); + // This option is only available in IPv6 sockets. + ERR_FAIL_COND(_ip_type == IP::TYPE_IPV4); + + int par = p_enabled ? 1 : 0; + if (setsockopt(_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&par, sizeof(int)) != 0) { + WARN_PRINT("Unable to change IPv4 address mapping over IPv6 option."); + } +} + +void NetSocketWinSock::set_tcp_no_delay_enabled(bool p_enabled) { + ERR_FAIL_COND(!is_open()); + ERR_FAIL_COND(!_is_stream); // Not TCP. + + int par = p_enabled ? 1 : 0; + if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&par, sizeof(int)) < 0) { + WARN_PRINT("Unable to set TCP no delay option."); + } +} + +void NetSocketWinSock::set_reuse_address_enabled(bool p_enabled) { + ERR_FAIL_COND(!is_open()); + + // On Windows, enabling SO_REUSEADDR actually would also enable reuse port, very bad on TCP. Denying... + // Windows does not have this option, SO_REUSEADDR in this magical world means SO_REUSEPORT +} + +bool NetSocketWinSock::is_open() const { + return _sock != INVALID_SOCKET; +} + +int NetSocketWinSock::get_available_bytes() const { + ERR_FAIL_COND_V(!is_open(), -1); + + unsigned long len; + int ret = ioctlsocket(_sock, FIONREAD, &len); + if (ret == -1) { + _get_socket_error(); + print_verbose("Error when checking available bytes on socket."); + return -1; + } + return len; +} + +Error NetSocketWinSock::get_socket_address(IPAddress *r_ip, uint16_t *r_port) const { + ERR_FAIL_COND_V(!is_open(), FAILED); + + struct sockaddr_storage saddr; + socklen_t len = sizeof(saddr); + if (getsockname(_sock, (struct sockaddr *)&saddr, &len) != 0) { + _get_socket_error(); + print_verbose("Error when reading local socket address."); + return FAILED; + } + _set_ip_port(&saddr, r_ip, r_port); + return OK; +} + +Ref<NetSocket> NetSocketWinSock::accept(IPAddress &r_ip, uint16_t &r_port) { + Ref<NetSocket> out; + ERR_FAIL_COND_V(!is_open(), out); + + struct sockaddr_storage their_addr; + socklen_t size = sizeof(their_addr); + SOCKET fd = ::accept(_sock, (struct sockaddr *)&their_addr, &size); + if (fd == INVALID_SOCKET) { + _get_socket_error(); + print_verbose("Error when accepting socket connection."); + return out; + } + + _set_ip_port(&their_addr, &r_ip, &r_port); + + NetSocketWinSock *ns = memnew(NetSocketWinSock); + ns->_set_socket(fd, _ip_type, _is_stream); + ns->set_blocking_enabled(false); + return Ref<NetSocket>(ns); +} + +Error NetSocketWinSock::join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { + return _change_multicast_group(p_multi_address, p_if_name, true); +} + +Error NetSocketWinSock::leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { + return _change_multicast_group(p_multi_address, p_if_name, false); +} + +#endif // WINDOWS_ENABLED diff --git a/drivers/windows/net_socket_winsock.h b/drivers/windows/net_socket_winsock.h new file mode 100644 index 0000000000..5c3445b8cb --- /dev/null +++ b/drivers/windows/net_socket_winsock.h @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* net_socket_winsock.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef NET_SOCKET_WINSOCK_H +#define NET_SOCKET_WINSOCK_H + +#ifdef WINDOWS_ENABLED + +#include "core/io/net_socket.h" + +#include <winsock2.h> +#include <ws2tcpip.h> + +class NetSocketWinSock : public NetSocket { +private: + SOCKET _sock = INVALID_SOCKET; + IP::Type _ip_type = IP::TYPE_NONE; + bool _is_stream = false; + + enum NetError { + ERR_NET_WOULD_BLOCK, + ERR_NET_IS_CONNECTED, + ERR_NET_IN_PROGRESS, + ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE, + ERR_NET_UNAUTHORIZED, + ERR_NET_BUFFER_TOO_SMALL, + ERR_NET_OTHER, + }; + + NetError _get_socket_error() const; + void _set_socket(SOCKET p_sock, IP::Type p_ip_type, bool p_is_stream); + _FORCE_INLINE_ Error _change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add); + +protected: + static NetSocket *_create_func(); + + bool _can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const; + +public: + static void make_default(); + static void cleanup(); + static void _set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port); + static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type); + + virtual Error open(Type p_sock_type, IP::Type &ip_type) override; + virtual void close() override; + virtual Error bind(IPAddress p_addr, uint16_t p_port) override; + virtual Error listen(int p_max_pending) override; + virtual Error connect_to_host(IPAddress p_host, uint16_t p_port) override; + virtual Error poll(PollType p_type, int timeout) const override; + virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) override; + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) override; + virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) override; + virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) override; + virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port) override; + + virtual bool is_open() const override; + virtual int get_available_bytes() const override; + virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const override; + + virtual Error set_broadcasting_enabled(bool p_enabled) override; + virtual void set_blocking_enabled(bool p_enabled) override; + virtual void set_ipv6_only_enabled(bool p_enabled) override; + virtual void set_tcp_no_delay_enabled(bool p_enabled) override; + virtual void set_reuse_address_enabled(bool p_enabled) override; + virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override; + virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override; + + NetSocketWinSock(); + ~NetSocketWinSock() override; +}; + +#endif // WINDOWS_ENABLED + +#endif // NET_SOCKET_WINSOCK_H diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 0d89f37dd2..cf5b18ce3c 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -358,7 +358,7 @@ void ActionMapEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { action_list_search->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); if (!actions_cache.is_empty()) { update_action_list(); } diff --git a/editor/add_metadata_dialog.cpp b/editor/add_metadata_dialog.cpp index 0a070e37b6..66a7b820f5 100644 --- a/editor/add_metadata_dialog.cpp +++ b/editor/add_metadata_dialog.cpp @@ -64,7 +64,6 @@ AddMetadataDialog::AddMetadataDialog() { } void AddMetadataDialog::_complete_init(const StringName &p_title) { - add_meta_name->grab_focus(); add_meta_name->set_text(""); validation_panel->update(); @@ -90,6 +89,7 @@ void AddMetadataDialog::open(const StringName p_title, List<StringName> &p_exist this->_existing_metas = p_existing_metas; _complete_init(p_title); popup_centered(); + add_meta_name->grab_focus(); } StringName AddMetadataDialog::get_meta_name() { diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 8d7c6a1f16..36ca417638 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -275,7 +275,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { } String base_path = animation->track_get_path(i); - int end = base_path.find(":"); + int end = base_path.find_char(':'); if (end != -1) { base_path = base_path.substr(0, end + 1); } @@ -1650,7 +1650,7 @@ void AnimationBezierTrackEdit::_zoom_callback(float p_zoom_factor, Vector2 p_ori Ref<InputEventWithModifiers> iewm = p_event; if (iewm.is_valid() && iewm->is_alt_pressed()) { // Alternate zoom (doesn't affect timeline). - timeline_v_zoom = CLAMP(timeline_v_zoom * p_zoom_factor, 0.000001, 100000); + timeline_v_zoom = CLAMP(timeline_v_zoom / p_zoom_factor, 0.000001, 100000); } else { float zoom_factor = p_zoom_factor > 1.0 ? AnimationTimelineEdit::SCROLL_ZOOM_FACTOR_IN : AnimationTimelineEdit::SCROLL_ZOOM_FACTOR_OUT; timeline->_zoom_callback(zoom_factor, p_origin, p_event); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 741d127ea2..19e0647fb7 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -63,7 +63,6 @@ constexpr double FPS_DECIMAL = 1.0; constexpr double SECOND_DECIMAL = 0.0001; -constexpr double FPS_STEP_FRACTION = 0.0625; void AnimationTrackKeyEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_obj"), &AnimationTrackKeyEdit::_update_obj); @@ -1440,8 +1439,8 @@ void AnimationTimelineEdit::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - add_track->set_icon(get_editor_theme_icon(SNAME("Add"))); - loop->set_icon(get_editor_theme_icon(SNAME("Loop"))); + add_track->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + loop->set_button_icon(get_editor_theme_icon(SNAME("Loop"))); time_icon->set_texture(get_editor_theme_icon(SNAME("Time"))); add_track->get_popup()->clear(); @@ -1818,15 +1817,15 @@ void AnimationTimelineEdit::update_values() { switch (animation->get_loop_mode()) { case Animation::LOOP_NONE: { - loop->set_icon(get_editor_theme_icon(SNAME("Loop"))); + loop->set_button_icon(get_editor_theme_icon(SNAME("Loop"))); loop->set_pressed(false); } break; case Animation::LOOP_LINEAR: { - loop->set_icon(get_editor_theme_icon(SNAME("Loop"))); + loop->set_button_icon(get_editor_theme_icon(SNAME("Loop"))); loop->set_pressed(true); } break; case Animation::LOOP_PINGPONG: { - loop->set_icon(get_editor_theme_icon(SNAME("PingPongLoop"))); + loop->set_button_icon(get_editor_theme_icon(SNAME("PingPongLoop"))); loop->set_pressed(true); } break; default: @@ -2192,7 +2191,7 @@ void AnimationTrackEdit::_notification(int p_what) { offset = offset * scale + limit; Color marker_color = animation->get_marker_color(marker); marker_color.a = 0.2; - draw_line(Point2(offset, 0), Point2(offset, get_size().height), marker_color); + draw_line(Point2(offset, 0), Point2(offset, get_size().height), marker_color, Math::round(EDSCALE)); } } } @@ -3313,7 +3312,7 @@ Variant AnimationTrackEdit::get_drag_data(const Point2 &p_point) { Button *tb = memnew(Button); tb->set_flat(true); tb->set_text(path_cache); - tb->set_icon(icon_cache); + tb->set_button_icon(icon_cache); tb->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tb->add_theme_constant_override("icon_max_width", get_theme_constant("class_icon_size", EditorStringName(Editor))); set_drag_preview(tb); @@ -3648,7 +3647,7 @@ void AnimationTrackEditGroup::_notification(int p_what) { offset = offset * scale + limit; Color marker_color = editor->get_current_animation()->get_marker_color(marker); marker_color.a = 0.2; - draw_line(Point2(offset, 0), Point2(offset, get_size().height), marker_color); + draw_line(Point2(offset, 0), Point2(offset, get_size().height), marker_color, Math::round(EDSCALE)); } } } @@ -3776,6 +3775,7 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re step->set_read_only(false); snap_keys->set_disabled(false); snap_timeline->set_disabled(false); + fps_compat->set_disabled(false); snap_mode->set_disabled(false); auto_fit->set_disabled(false); auto_fit_bezier->set_disabled(false); @@ -3798,6 +3798,7 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re step->set_read_only(true); snap_keys->set_disabled(true); snap_timeline->set_disabled(true); + fps_compat->set_disabled(true); snap_mode->set_disabled(true); bezier_edit_icon->set_disabled(true); auto_fit->set_disabled(true); @@ -4339,7 +4340,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p if (track_path == np) { actual_value = value; // All good. } else { - int sep = track_path.rfind(":"); + int sep = track_path.rfind_char(':'); if (sep != -1) { String base_path = track_path.substr(0, sep); if (base_path == np) { @@ -5029,7 +5030,12 @@ void AnimationTrackEditor::_snap_mode_changed(int p_mode) { } marker_edit->set_use_fps(use_fps); // To ensure that the conversion results are consistent between serialization and load, the value is snapped with 0.0625 to be a rational number when FPS mode is used. - step->set_step(use_fps ? FPS_STEP_FRACTION : SECOND_DECIMAL); + step->set_step(use_fps ? FPS_DECIMAL : SECOND_DECIMAL); + if (use_fps) { + fps_compat->hide(); + } else { + fps_compat->show(); + } _update_step_spinbox(); } @@ -5045,7 +5051,6 @@ void AnimationTrackEditor::_update_step_spinbox() { } else { step->set_value(1.0 / animation->get_step()); } - } else { step->set_value(animation->get_step()); } @@ -5054,6 +5059,20 @@ void AnimationTrackEditor::_update_step_spinbox() { _update_snap_unit(); } +void AnimationTrackEditor::_update_fps_compat_mode(bool p_enabled) { + _update_snap_unit(); +} + +void AnimationTrackEditor::_update_nearest_fps_label() { + bool is_fps_invalid = nearest_fps == 0; + if (is_fps_invalid) { + nearest_fps_label->hide(); + } else { + nearest_fps_label->show(); + nearest_fps_label->set_text("Nearest FPS: " + itos(nearest_fps)); + } +} + void AnimationTrackEditor::_animation_update() { timeline->queue_redraw(); timeline->update_values(); @@ -5112,18 +5131,19 @@ void AnimationTrackEditor::_notification(int p_what) { } case NOTIFICATION_THEME_CHANGED: { zoom_icon->set_texture(get_editor_theme_icon(SNAME("Zoom"))); - bezier_edit_icon->set_icon(get_editor_theme_icon(SNAME("EditBezier"))); - snap_timeline->set_icon(get_editor_theme_icon(SNAME("SnapTimeline"))); - snap_keys->set_icon(get_editor_theme_icon(SNAME("SnapKeys"))); - view_group->set_icon(get_editor_theme_icon(view_group->is_pressed() ? SNAME("AnimationTrackList") : SNAME("AnimationTrackGroup"))); - selected_filter->set_icon(get_editor_theme_icon(SNAME("AnimationFilter"))); - imported_anim_warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); - dummy_player_warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); - inactive_player_warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); + bezier_edit_icon->set_button_icon(get_editor_theme_icon(SNAME("EditBezier"))); + snap_timeline->set_button_icon(get_editor_theme_icon(SNAME("SnapTimeline"))); + snap_keys->set_button_icon(get_editor_theme_icon(SNAME("SnapKeys"))); + fps_compat->set_button_icon(get_editor_theme_icon(SNAME("FPS"))); + view_group->set_button_icon(get_editor_theme_icon(view_group->is_pressed() ? SNAME("AnimationTrackList") : SNAME("AnimationTrackGroup"))); + selected_filter->set_button_icon(get_editor_theme_icon(SNAME("AnimationFilter"))); + imported_anim_warning->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning"))); + dummy_player_warning->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning"))); + inactive_player_warning->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning"))); main_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_editor_theme_icon(SNAME("Reload"))); - auto_fit->set_icon(get_editor_theme_icon(SNAME("AnimationAutoFit"))); - auto_fit_bezier->set_icon(get_editor_theme_icon(SNAME("AnimationAutoFitBezier"))); + auto_fit->set_button_icon(get_editor_theme_icon(SNAME("AnimationAutoFit"))); + auto_fit_bezier->set_button_icon(get_editor_theme_icon(SNAME("AnimationAutoFitBezier"))); const int timeline_separation = get_theme_constant(SNAME("timeline_v_separation"), SNAME("AnimationTrackEditor")); timeline_vbox->add_theme_constant_override("separation", timeline_separation); @@ -5160,9 +5180,8 @@ void AnimationTrackEditor::_update_step(double p_new_step) { double step_value = p_new_step; if (timeline->is_using_fps()) { if (step_value != 0.0) { - // step_value must also be less than or equal to 1000 to ensure that no error accumulates due to interactions with retrieving values from inner range. + // A step_value should be less than or equal to 1000 to ensure that no error accumulates due to interactions with retrieving values from inner range. step_value = 1.0 / MIN(1000.0, p_new_step); - ; } timeline->queue_redraw(); } @@ -5297,6 +5316,28 @@ void AnimationTrackEditor::_add_track(int p_type) { return; } adding_track_type = p_type; + Vector<StringName> valid_types; + switch (adding_track_type) { + case Animation::TYPE_BLEND_SHAPE: { + // Blend Shape is a property of MeshInstance3D. + valid_types.push_back(SNAME("MeshInstance3D")); + } break; + case Animation::TYPE_POSITION_3D: + case Animation::TYPE_ROTATION_3D: + case Animation::TYPE_SCALE_3D: { + // 3D Properties come from nodes inheriting Node3D. + valid_types.push_back(SNAME("Node3D")); + } break; + case Animation::TYPE_AUDIO: { + valid_types.push_back(SNAME("AudioStreamPlayer")); + valid_types.push_back(SNAME("AudioStreamPlayer2D")); + valid_types.push_back(SNAME("AudioStreamPlayer3D")); + } break; + case Animation::TYPE_ANIMATION: { + valid_types.push_back(SNAME("AnimationPlayer")); + } break; + } + pick_track->set_valid_types(valid_types); pick_track->popup_scenetree_dialog(nullptr, root_node); pick_track->get_filter_line_edit()->clear(); pick_track->get_filter_line_edit()->grab_focus(); @@ -6337,8 +6378,9 @@ bool AnimationTrackEditor::_is_track_compatible(int p_target_track_idx, Variant: } if (path_valid) { - if (is_source_bezier) + if (is_source_bezier) { p_source_value_type = Variant::FLOAT; + } return property_type == p_source_value_type; } else { if (animation->track_get_key_count(p_target_track_idx) > 0) { @@ -6453,7 +6495,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { path = NodePath(node->get_path().get_names(), path.get_subnames(), true); // Store full path instead for copying. } else { text = path; - int sep = text.find(":"); + int sep = text.find_char(':'); if (sep != -1) { text = text.substr(sep + 1, text.length()); } @@ -7279,7 +7321,7 @@ void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) { void AnimationTrackEditor::_view_group_toggle() { _update_tracks(); - view_group->set_icon(get_editor_theme_icon(view_group->is_pressed() ? SNAME("AnimationTrackList") : SNAME("AnimationTrackGroup"))); + view_group->set_button_icon(get_editor_theme_icon(view_group->is_pressed() ? SNAME("AnimationTrackList") : SNAME("AnimationTrackGroup"))); bezier_edit->set_filtered(selected_filter->is_pressed()); } @@ -7313,39 +7355,54 @@ void AnimationTrackEditor::_selection_changed() { } void AnimationTrackEditor::_update_snap_unit() { + nearest_fps = 0; + if (step->get_value() <= 0) { snap_unit = 0; + _update_nearest_fps_label(); return; // Avoid zero div. } if (timeline->is_using_fps()) { snap_unit = 1.0 / step->get_value(); } else { - double integer; - double fraction = Math::modf(step->get_value(), &integer); - fraction = 1.0 / Math::round(1.0 / fraction); - snap_unit = integer + fraction; + if (fps_compat->is_pressed()) { + snap_unit = CLAMP(step->get_value(), 0.0, 1.0); + if (!Math::is_zero_approx(snap_unit)) { + real_t fps = Math::round(1.0 / snap_unit); + nearest_fps = int(fps); + snap_unit = 1.0 / fps; + } + } else { + snap_unit = step->get_value(); + } } + _update_nearest_fps_label(); } float AnimationTrackEditor::snap_time(float p_value, bool p_relative) { if (is_snap_keys_enabled()) { + double current_snap = snap_unit; if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { // Use more precise snapping when holding Shift. - snap_unit *= 0.25; + current_snap *= 0.25; } if (p_relative) { - double rel = Math::fmod(timeline->get_value(), snap_unit); - p_value = Math::snapped(p_value + rel, snap_unit) - rel; + double rel = Math::fmod(timeline->get_value(), current_snap); + p_value = Math::snapped(p_value + rel, current_snap) - rel; } else { - p_value = Math::snapped(p_value, snap_unit); + p_value = Math::snapped(p_value, current_snap); } } return p_value; } +float AnimationTrackEditor::get_snap_unit() { + return snap_unit; +} + void AnimationTrackEditor::_show_imported_anim_warning() { // It looks terrible on a single line but the TTR extractor doesn't support line breaks yet. EditorNode::get_singleton()->show_warning( @@ -7599,6 +7656,18 @@ AnimationTrackEditor::AnimationTrackEditor() { snap_keys->set_pressed(true); snap_keys->set_tooltip_text(TTR("Apply snapping to selected key(s).")); + fps_compat = memnew(Button); + fps_compat->set_flat(true); + bottom_hb->add_child(fps_compat); + fps_compat->set_disabled(true); + fps_compat->set_toggle_mode(true); + fps_compat->set_pressed(true); + fps_compat->set_tooltip_text(TTR("Apply snapping to the nearest integer FPS.")); + fps_compat->connect(SceneStringName(toggled), callable_mp(this, &AnimationTrackEditor::_update_fps_compat_mode)); + + nearest_fps_label = memnew(Label); + bottom_hb->add_child(nearest_fps_label); + step = memnew(EditorSpinSlider); step->set_min(0); step->set_max(1000000); @@ -7913,6 +7982,11 @@ AnimationTrackEditor::~AnimationTrackEditor() { // AnimationTrackKeyEditEditorPlugin. +void AnimationTrackKeyEditEditor::_time_edit_spun() { + _time_edit_entered(); + _time_edit_exited(); +} + void AnimationTrackKeyEditEditor::_time_edit_entered() { int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX); if (key == -1) { @@ -7940,7 +8014,7 @@ void AnimationTrackKeyEditEditor::_time_edit_exited() { int existing = animation->track_find_key(track, new_time, Animation::FIND_MODE_APPROX); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Animation Change Keyframe Time"), UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Animation Change Keyframe Time")); if (existing != -1) { undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", track, animation->track_get_key_time(track, existing)); @@ -7987,6 +8061,7 @@ AnimationTrackKeyEditEditor::AnimationTrackKeyEditEditor(Ref<Animation> p_animat spinner->set_min(0); spinner->set_allow_greater(true); spinner->set_allow_lesser(true); + add_child(spinner); if (use_fps) { spinner->set_step(FPS_DECIMAL); @@ -7995,14 +8070,13 @@ AnimationTrackKeyEditEditor::AnimationTrackKeyEditEditor(Ref<Animation> p_animat fps = 1.0 / fps; } spinner->set_value(key_ofs * fps); + spinner->connect("updown_pressed", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_spun), CONNECT_DEFERRED); } else { spinner->set_step(SECOND_DECIMAL); spinner->set_value(key_ofs); spinner->set_max(animation->get_length()); } - add_child(spinner); - spinner->connect("grabbed", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_entered), CONNECT_DEFERRED); spinner->connect("ungrabbed", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_exited), CONNECT_DEFERRED); spinner->connect("value_focus_entered", callable_mp(this, &AnimationTrackKeyEditEditor::_time_edit_entered), CONNECT_DEFERRED); @@ -8237,9 +8311,6 @@ void AnimationMarkerEdit::_notification(int p_what) { Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label")); Color color = get_theme_color(SceneStringName(font_color), SNAME("Label")); - int hsep = get_theme_constant(SNAME("h_separation"), SNAME("ItemList")); - Color linecolor = color; - linecolor.a = 0.2; // SECTION PREVIEW // @@ -8298,31 +8369,21 @@ void AnimationMarkerEdit::_notification(int p_what) { draw_key(name, scale, int(offset), is_selected, limit, limit_end); - const int font_size = 16; + const int font_size = 12 * EDSCALE; Size2 string_size = font->get_string_size(name, HORIZONTAL_ALIGNMENT_LEFT, -1.0, font_size); if (int(offset) <= limit_end && int(offset) >= limit && should_show_all_marker_names) { float bottom = get_size().height + string_size.y - font->get_descent(font_size); float extrusion = MAX(0, offset + string_size.x - limit_end); // How much the string would extrude outside limit_end if unadjusted. Color marker_color = animation->get_marker_color(name); - draw_string(font, Point2(offset - extrusion, bottom), name, HORIZONTAL_ALIGNMENT_LEFT, -1.0, font_size, marker_color); - draw_string_outline(font, Point2(offset - extrusion, bottom), name, HORIZONTAL_ALIGNMENT_LEFT, -1.0, font_size, 1, color); + float margin = 4 * EDSCALE; + Point2 pos = Point2(offset - extrusion + margin, bottom + margin); + draw_string(font, pos, name, HORIZONTAL_ALIGNMENT_LEFT, -1.0, font_size, marker_color); + draw_string_outline(font, pos, name, HORIZONTAL_ALIGNMENT_LEFT, -1.0, font_size, 1, color); } } } draw_fg(limit, get_size().width - timeline->get_buttons_width()); - - // BUTTONS // - - { - int ofs = get_size().width - timeline->get_buttons_width(); - - draw_line(Point2(ofs, 0), Point2(ofs, get_size().height), linecolor, Math::round(EDSCALE)); - - ofs += hsep; - } - - draw_line(Vector2(0, get_size().height), get_size(), linecolor, Math::round(EDSCALE)); } break; case NOTIFICATION_MOUSE_ENTER: @@ -9123,9 +9184,6 @@ void AnimationMultiMarkerKeyEdit::_get_property_list(List<PropertyInfo> *p_list) // AnimationMarkerKeyEditEditorPlugin -void AnimationMarkerKeyEditEditor::_time_edit_entered() { -} - void AnimationMarkerKeyEditEditor::_time_edit_exited() { real_t new_time = spinner->get_value(); @@ -9144,7 +9202,7 @@ void AnimationMarkerKeyEditEditor::_time_edit_exited() { } EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Animation Change Marker Time"), UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Animation Change Marker Time")); Color color = animation->get_marker_color(marker_name); undo_redo->add_do_method(animation.ptr(), "add_marker", marker_name, new_time); @@ -9185,6 +9243,7 @@ AnimationMarkerKeyEditEditor::AnimationMarkerKeyEditEditor(Ref<Animation> p_anim spinner->set_min(0); spinner->set_allow_greater(true); spinner->set_allow_lesser(true); + add_child(spinner); float time = animation->get_marker_time(marker_name); @@ -9195,17 +9254,14 @@ AnimationMarkerKeyEditEditor::AnimationMarkerKeyEditEditor(Ref<Animation> p_anim fps = 1.0 / fps; } spinner->set_value(time * fps); + spinner->connect("updown_pressed", callable_mp(this, &AnimationMarkerKeyEditEditor::_time_edit_exited), CONNECT_DEFERRED); } else { spinner->set_step(SECOND_DECIMAL); spinner->set_value(time); spinner->set_max(animation->get_length()); } - add_child(spinner); - - spinner->connect("grabbed", callable_mp(this, &AnimationMarkerKeyEditEditor::_time_edit_entered), CONNECT_DEFERRED); spinner->connect("ungrabbed", callable_mp(this, &AnimationMarkerKeyEditEditor::_time_edit_exited), CONNECT_DEFERRED); - spinner->connect("value_focus_entered", callable_mp(this, &AnimationMarkerKeyEditEditor::_time_edit_entered), CONNECT_DEFERRED); spinner->connect("value_focus_exited", callable_mp(this, &AnimationMarkerKeyEditEditor::_time_edit_exited), CONNECT_DEFERRED); } diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 0da474afd4..f17386b0c9 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -600,6 +600,8 @@ class AnimationTrackEditor : public VBoxContainer { AnimationMarkerEdit *marker_edit = nullptr; HSlider *zoom = nullptr; EditorSpinSlider *step = nullptr; + Button *fps_compat = nullptr; + Label *nearest_fps_label = nullptr; TextureRect *zoom_icon = nullptr; Button *snap_keys = nullptr; Button *snap_timeline = nullptr; @@ -637,6 +639,8 @@ class AnimationTrackEditor : public VBoxContainer { void _track_grab_focus(int p_track); void _update_scroll(double); + void _update_nearest_fps_label(); + void _update_fps_compat_mode(bool p_enabled); void _update_step(double p_new_step); void _update_length(double p_new_len); void _dropped_track(int p_from_track, int p_to_track); @@ -716,7 +720,7 @@ class AnimationTrackEditor : public VBoxContainer { struct SelectedKey { int track = 0; int key = 0; - bool operator<(const SelectedKey &p_key) const { return track == p_key.track ? key < p_key.key : track < p_key.track; }; + bool operator<(const SelectedKey &p_key) const { return track == p_key.track ? key < p_key.key : track < p_key.track; } }; struct KeyInfo { @@ -853,6 +857,8 @@ class AnimationTrackEditor : public VBoxContainer { void _pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates); double snap_unit; + bool fps_compatible = true; + int nearest_fps = 0; void _update_snap_unit(); protected: @@ -935,6 +941,7 @@ public: bool can_add_reset_key() const; float get_moving_selection_offset() const; float snap_time(float p_value, bool p_relative = false); + float get_snap_unit(); bool is_grouping_tracks(); PackedStringArray get_selected_section() const; bool is_marker_selected(const StringName &p_marker) const; @@ -970,6 +977,7 @@ class AnimationTrackKeyEditEditor : public EditorProperty { Variant value; } key_data_cache; + void _time_edit_spun(); void _time_edit_entered(); void _time_edit_exited(); @@ -989,7 +997,6 @@ class AnimationMarkerKeyEditEditor : public EditorProperty { EditorSpinSlider *spinner = nullptr; - void _time_edit_entered(); void _time_edit_exited(); public: diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 88a32b1a6d..05eeef4fc9 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -104,8 +104,8 @@ void FindReplaceBar::_notification(int p_what) { [[fallthrough]]; } case NOTIFICATION_READY: { - find_prev->set_icon(get_editor_theme_icon(SNAME("MoveUp"))); - find_next->set_icon(get_editor_theme_icon(SNAME("MoveDown"))); + find_prev->set_button_icon(get_editor_theme_icon(SNAME("MoveUp"))); + find_next->set_button_icon(get_editor_theme_icon(SNAME("MoveDown"))); hide_button->set_texture_normal(get_editor_theme_icon(SNAME("Close"))); hide_button->set_texture_hover(get_editor_theme_icon(SNAME("Close"))); hide_button->set_texture_pressed(get_editor_theme_icon(SNAME("Close"))); @@ -549,7 +549,7 @@ void FindReplaceBar::_update_toggle_replace_button(bool p_replace_visible) { String shortcut = ED_GET_SHORTCUT(p_replace_visible ? "script_text_editor/find" : "script_text_editor/replace")->get_as_text(); toggle_replace_button->set_tooltip_text(vformat("%s (%s)", tooltip, shortcut)); StringName rtl_compliant_arrow = is_layout_rtl() ? SNAME("GuiTreeArrowLeft") : SNAME("GuiTreeArrowRight"); - toggle_replace_button->set_icon(get_editor_theme_icon(p_replace_visible ? SNAME("GuiTreeArrowDown") : rtl_compliant_arrow)); + toggle_replace_button->set_button_icon(get_editor_theme_icon(p_replace_visible ? SNAME("GuiTreeArrowDown") : rtl_compliant_arrow)); } void FindReplaceBar::_show_search(bool p_with_replace, bool p_show_only) { @@ -1493,8 +1493,8 @@ void CodeTextEditor::goto_error() { void CodeTextEditor::_update_text_editor_theme() { emit_signal(SNAME("load_theme_settings")); - error_button->set_icon(get_editor_theme_icon(SNAME("StatusError"))); - warning_button->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); + error_button->set_button_icon(get_editor_theme_icon(SNAME("StatusError"))); + warning_button->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning"))); Ref<Font> status_bar_font = get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)); int status_bar_font_size = get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)); @@ -1771,7 +1771,7 @@ void CodeTextEditor::show_toggle_scripts_button() { void CodeTextEditor::update_toggle_scripts_button() { ERR_FAIL_NULL(toggle_scripts_list); bool forward = toggle_scripts_list->is_visible() == is_layout_rtl(); - toggle_scripts_button->set_icon(get_editor_theme_icon(forward ? SNAME("Forward") : SNAME("Back"))); + toggle_scripts_button->set_button_icon(get_editor_theme_icon(forward ? SNAME("Forward") : SNAME("Back"))); toggle_scripts_button->set_tooltip_text(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); } diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 1c269a62c5..d76c324be0 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -488,7 +488,7 @@ void ConnectDialog::_notification(int p_what) { } method_search->set_right_icon(get_editor_theme_icon("Search")); - open_method_tree->set_icon(get_editor_theme_icon("Edit")); + open_method_tree->set_button_icon(get_editor_theme_icon("Edit")); } break; } } @@ -524,7 +524,7 @@ void ConnectDialog::set_dst_node(Node *p_node) { StringName ConnectDialog::get_dst_method_name() const { String txt = dst_method->get_text(); if (txt.contains("(")) { - txt = txt.left(txt.find("(")).strip_edges(); + txt = txt.left(txt.find_char('(')).strip_edges(); } return txt; } @@ -1079,17 +1079,17 @@ void ConnectionsDock::_tree_item_selected() { TreeItem *item = tree->get_selected(); if (item && _get_item_type(*item) == TREE_ITEM_TYPE_SIGNAL) { connect_button->set_text(TTR("Connect...")); - connect_button->set_icon(get_editor_theme_icon(SNAME("Instance"))); + connect_button->set_button_icon(get_editor_theme_icon(SNAME("Instance"))); connect_button->set_disabled(false); } else if (item && _get_item_type(*item) == TREE_ITEM_TYPE_CONNECTION) { connect_button->set_text(TTR("Disconnect")); - connect_button->set_icon(get_editor_theme_icon(SNAME("Unlinked"))); + connect_button->set_button_icon(get_editor_theme_icon(SNAME("Unlinked"))); Object::Connection connection = item->get_metadata(0); connect_button->set_disabled(_is_connection_inherited(connection)); } else { connect_button->set_text(TTR("Connect...")); - connect_button->set_icon(get_editor_theme_icon(SNAME("Instance"))); + connect_button->set_button_icon(get_editor_theme_icon(SNAME("Instance"))); connect_button->set_disabled(true); } } @@ -1586,7 +1586,7 @@ void ConnectionsDock::update_tree() { } connect_button->set_text(TTR("Connect...")); - connect_button->set_icon(get_editor_theme_icon(SNAME("Instance"))); + connect_button->set_button_icon(get_editor_theme_icon(SNAME("Instance"))); connect_button->set_disabled(true); } diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 330ac3b437..2273014f72 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -160,13 +160,13 @@ bool CreateDialog::_should_hide_type(const StringName &p_type) const { String script_path = ScriptServer::get_global_class_path(p_type); if (script_path.begins_with("res://addons/")) { - int i = script_path.find("/", 13); // 13 is length of "res://addons/". + int i = script_path.find_char('/', 13); // 13 is length of "res://addons/". while (i > -1) { const String plugin_path = script_path.substr(0, i).path_join("plugin.cfg"); if (FileAccess::exists(plugin_path)) { return !EditorNode::get_singleton()->is_addon_plugin_enabled(plugin_path); } - i = script_path.find("/", i + 1); + i = script_path.find_char('/', i + 1); } } } @@ -468,7 +468,7 @@ void CreateDialog::_notification(int p_what) { recent->set_fixed_icon_size(Size2(icon_width, icon_width)); search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - favorite->set_icon(get_editor_theme_icon(SNAME("Favorites"))); + favorite->set_button_icon(get_editor_theme_icon(SNAME("Favorites"))); } break; } } @@ -613,7 +613,7 @@ Variant CreateDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { Button *tb = memnew(Button); tb->set_flat(true); - tb->set_icon(ti->get_icon(0)); + tb->set_button_icon(ti->get_icon(0)); tb->set_text(ti->get_text(0)); tb->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); favorites->set_drag_preview(tb); diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp index 2af629676a..904085630b 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp @@ -147,7 +147,7 @@ Dictionary DebugAdapterParser::req_initialize(const Dictionary &p_params) const for (List<String>::Element *E = breakpoints.front(); E; E = E->next()) { String breakpoint = E->get(); - String path = breakpoint.left(breakpoint.find(":", 6)); // Skip initial part of path, aka "res://" + String path = breakpoint.left(breakpoint.find_char(':', 6)); // Skip initial part of path, aka "res://" int line = breakpoint.substr(path.size()).to_int(); DebugAdapterProtocol::get_singleton()->on_debug_breakpoint_toggled(path, line, true); diff --git a/editor/debugger/editor_debugger_inspector.h b/editor/debugger/editor_debugger_inspector.h index fac9525943..860c2bf582 100644 --- a/editor/debugger/editor_debugger_inspector.h +++ b/editor/debugger/editor_debugger_inspector.h @@ -48,7 +48,7 @@ public: List<PropertyInfo> prop_list; HashMap<StringName, Variant> prop_values; - ObjectID get_remote_object_id() { return remote_object_id; }; + ObjectID get_remote_object_id() { return remote_object_id; } String get_title(); Variant get_variant(const StringName &p_name); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index b4265f9fc0..f06d9be78f 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -105,6 +105,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { node->connect("breakpoint_selected", callable_mp(this, &EditorDebuggerNode::_error_selected).bind(id)); node->connect("clear_execution", callable_mp(this, &EditorDebuggerNode::_clear_execution)); node->connect("breaked", callable_mp(this, &EditorDebuggerNode::_breaked).bind(id)); + node->connect("remote_tree_select_requested", callable_mp(this, &EditorDebuggerNode::_remote_tree_select_requested).bind(id)); node->connect("remote_tree_updated", callable_mp(this, &EditorDebuggerNode::_remote_tree_updated).bind(id)); node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated).bind(id)); node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated).bind(id)); @@ -119,7 +120,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { tabs->add_child(node); - node->set_name("Session " + itos(tabs->get_tab_count())); + node->set_name(vformat(TTR("Session %d"), tabs->get_tab_count())); if (tabs->get_tab_count() > 1) { node->clear_style(); tabs->set_tabs_visible(true); @@ -159,9 +160,9 @@ void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_d } else { // If the script is built-in, it can be opened only if the scene is loaded in memory. int i = file.find("::"); - int j = file.rfind("(", i); + int j = file.rfind_char('(', i); if (j > -1) { // If the script is named, the string is "name (file)", so we need to extract the path. - file = file.substr(j + 1, file.find(")", i) - j - 1); + file = file.substr(j + 1, file.find_char(')', i) - j - 1); } Ref<PackedScene> ps = ResourceLoader::load(file.get_slice("::", 0)); stack_script = ResourceLoader::load(file); @@ -182,9 +183,9 @@ void EditorDebuggerNode::_text_editor_stack_clear(const ScriptEditorDebugger *p_ } else { // If the script is built-in, it can be opened only if the scene is loaded in memory. int i = file.find("::"); - int j = file.rfind("(", i); + int j = file.rfind_char('(', i); if (j > -1) { // If the script is named, the string is "name (file)", so we need to extract the path. - file = file.substr(j + 1, file.find(")", i) - j - 1); + file = file.substr(j + 1, file.find_char(')', i) - j - 1); } Ref<PackedScene> ps = ResourceLoader::load(file.get_slice("::", 0)); stack_script = ResourceLoader::load(file); @@ -417,18 +418,18 @@ void EditorDebuggerNode::_update_errors() { if (error_count == 0 && warning_count == 0) { debugger_button->set_text(TTR("Debugger")); debugger_button->remove_theme_color_override(SceneStringName(font_color)); - debugger_button->set_icon(Ref<Texture2D>()); + debugger_button->set_button_icon(Ref<Texture2D>()); } else { debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count + warning_count) + ")"); if (error_count >= 1 && warning_count >= 1) { - debugger_button->set_icon(get_editor_theme_icon(SNAME("ErrorWarning"))); + debugger_button->set_button_icon(get_editor_theme_icon(SNAME("ErrorWarning"))); // Use error color to represent the highest level of severity reported. debugger_button->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); } else if (error_count >= 1) { - debugger_button->set_icon(get_editor_theme_icon(SNAME("Error"))); + debugger_button->set_button_icon(get_editor_theme_icon(SNAME("Error"))); debugger_button->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); } else { - debugger_button->set_icon(get_editor_theme_icon(SNAME("Warning"))); + debugger_button->set_button_icon(get_editor_theme_icon(SNAME("Warning"))); debugger_button->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } } @@ -637,6 +638,13 @@ void EditorDebuggerNode::request_remote_tree() { get_current_debugger()->request_remote_tree(); } +void EditorDebuggerNode::_remote_tree_select_requested(ObjectID p_id, int p_debugger) { + if (p_debugger != tabs->get_current_tab()) { + return; + } + remote_scene_tree->select_node(p_id); +} + void EditorDebuggerNode::_remote_tree_updated(int p_debugger) { if (p_debugger != tabs->get_current_tab()) { return; diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index 12e097f652..12c0d30c42 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -51,11 +51,8 @@ class EditorDebuggerNode : public MarginContainer { public: enum CameraOverride { OVERRIDE_NONE, - OVERRIDE_2D, - OVERRIDE_3D_1, // 3D Viewport 1 - OVERRIDE_3D_2, // 3D Viewport 2 - OVERRIDE_3D_3, // 3D Viewport 3 - OVERRIDE_3D_4 // 3D Viewport 4 + OVERRIDE_INGAME, + OVERRIDE_EDITORS, }; private: @@ -132,6 +129,7 @@ protected: void _debugger_stopped(int p_id); void _debugger_wants_stop(int p_id); void _debugger_changed(int p_tab); + void _remote_tree_select_requested(ObjectID p_id, int p_debugger); void _remote_tree_updated(int p_debugger); void _remote_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); void _remote_object_updated(ObjectID p_id, int p_debugger); diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp index a900842651..a9e4adf674 100644 --- a/editor/debugger/editor_debugger_tree.cpp +++ b/editor/debugger/editor_debugger_tree.cpp @@ -30,6 +30,7 @@ #include "editor_debugger_tree.h" +#include "editor/debugger/editor_debugger_node.h" #include "editor/editor_node.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" @@ -148,7 +149,8 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int updating_scene_tree = true; const String last_path = get_selected_path(); const String filter = SceneTreeDock::get_singleton()->get_filter(); - bool filter_changed = filter != last_filter; + bool should_scroll = scrolling_to_item || filter != last_filter; + scrolling_to_item = false; TreeItem *scroll_item = nullptr; // Nodes are in a flatten list, depth first. Use a stack of parents, avoid recursion. @@ -185,8 +187,18 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int // Select previously selected node. if (debugger_id == p_debugger) { // Can use remote id. if (node.id == inspected_object_id) { + if (selection_uncollapse_all) { + selection_uncollapse_all = false; + + // Temporarily set to `false`, to allow caching the unfolds. + updating_scene_tree = false; + item->uncollapse_tree(); + updating_scene_tree = true; + } + item->select(0); - if (filter_changed) { + + if (should_scroll) { scroll_item = item; } } @@ -194,7 +206,7 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int if (last_path == _get_path(item)) { updating_scene_tree = false; // Force emission of new selection. item->select(0); - if (filter_changed) { + if (should_scroll) { scroll_item = item; } updating_scene_tree = true; @@ -258,14 +270,30 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int } } } - debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree + + debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree. if (scroll_item) { - callable_mp((Tree *)this, &Tree::scroll_to_item).call_deferred(scroll_item, false); + scroll_to_item(scroll_item, false); } last_filter = filter; updating_scene_tree = false; } +void EditorDebuggerTree::select_node(ObjectID p_id) { + // Manually select, as the tree control may be out-of-date for some reason (e.g. not shown yet). + selection_uncollapse_all = true; + inspected_object_id = uint64_t(p_id); + scrolling_to_item = true; + emit_signal(SNAME("object_selected"), inspected_object_id, debugger_id); + + if (!updating_scene_tree) { + // Request a tree refresh. + EditorDebuggerNode::get_singleton()->request_remote_tree(); + } + // Set the value immediately, so no update flooding happens and causes a crash. + updating_scene_tree = true; +} + Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) { if (get_button_id_at_position(p_point) != -1) { return Variant(); @@ -354,7 +382,7 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) { text = "."; } else { text = text.replace("/root/", ""); - int slash = text.find("/"); + int slash = text.find_char('/'); if (slash < 0) { text = "."; } else { diff --git a/editor/debugger/editor_debugger_tree.h b/editor/debugger/editor_debugger_tree.h index 705df17baf..d048688cad 100644 --- a/editor/debugger/editor_debugger_tree.h +++ b/editor/debugger/editor_debugger_tree.h @@ -49,6 +49,8 @@ private: ObjectID inspected_object_id; int debugger_id = 0; bool updating_scene_tree = false; + bool scrolling_to_item = false; + bool selection_uncollapse_all = false; HashSet<ObjectID> unfold_cache; PopupMenu *item_menu = nullptr; EditorFileDialog *file_dialog = nullptr; @@ -78,6 +80,7 @@ public: ObjectID get_selected_object(); int get_current_debugger(); // Would love to have one tree for every debugger. void update_scene_tree(const SceneDebuggerTree *p_tree, int p_debugger); + void select_node(ObjectID p_id); EditorDebuggerTree(); }; diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index d244b6b4cd..33fa208f70 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -30,6 +30,7 @@ #include "editor_profiler.h" +#include "core/io/image.h" #include "core/os/os.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" @@ -389,10 +390,10 @@ void EditorProfiler::_update_frame() { void EditorProfiler::_update_button_text() { if (activate->is_pressed()) { - activate->set_icon(get_editor_theme_icon(SNAME("Stop"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Stop"))); activate->set_text(TTR("Stop")); } else { - activate->set_icon(get_editor_theme_icon(SNAME("Play"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Play"))); activate->set_text(TTR("Start")); } } @@ -427,8 +428,8 @@ void EditorProfiler::_notification(int p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { - activate->set_icon(get_editor_theme_icon(SNAME("Play"))); - clear_button->set_icon(get_editor_theme_icon(SNAME("Clear"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Play"))); + clear_button->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); theme_cache.seek_line_color = get_theme_color(SceneStringName(font_color), EditorStringName(Editor)); theme_cache.seek_line_color.a = 0.8; diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index 7b831a1c8b..9a83277e99 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -30,6 +30,7 @@ #include "editor_visual_profiler.h" +#include "core/io/image.h" #include "core/os/os.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" @@ -410,12 +411,12 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) { void EditorVisualProfiler::_activate_pressed() { if (activate->is_pressed()) { - activate->set_icon(get_editor_theme_icon(SNAME("Stop"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Stop"))); activate->set_text(TTR("Stop")); _clear_pressed(); //always clear on start clear_button->set_disabled(false); } else { - activate->set_icon(get_editor_theme_icon(SNAME("Play"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Play"))); activate->set_text(TTR("Start")); } emit_signal(SNAME("enable_profiling"), activate->is_pressed()); @@ -437,8 +438,8 @@ void EditorVisualProfiler::_notification(int p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { - activate->set_icon(get_editor_theme_icon(SNAME("Play"))); - clear_button->set_icon(get_editor_theme_icon(SNAME("Clear"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Play"))); + clear_button->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); } break; } } @@ -656,10 +657,10 @@ void EditorVisualProfiler::_bind_methods() { void EditorVisualProfiler::_update_button_text() { if (activate->is_pressed()) { - activate->set_icon(get_editor_theme_icon(SNAME("Stop"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Stop"))); activate->set_text(TTR("Stop")); } else { - activate->set_icon(get_editor_theme_icon(SNAME("Play"))); + activate->set_button_icon(get_editor_theme_icon(SNAME("Play"))); activate->set_text(TTR("Start")); } } diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index cbe7910518..da59450dd0 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -95,9 +95,9 @@ void ScriptEditorDebugger::debug_copy() { void ScriptEditorDebugger::debug_skip_breakpoints() { skip_breakpoints_value = !skip_breakpoints_value; if (skip_breakpoints_value) { - skip_breakpoints->set_icon(get_editor_theme_icon(SNAME("DebugSkipBreakpointsOn"))); + skip_breakpoints->set_button_icon(get_editor_theme_icon(SNAME("DebugSkipBreakpointsOn"))); } else { - skip_breakpoints->set_icon(get_editor_theme_icon(SNAME("DebugSkipBreakpointsOff"))); + skip_breakpoints->set_button_icon(get_editor_theme_icon(SNAME("DebugSkipBreakpointsOff"))); } Array msg; @@ -806,6 +806,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread } else if (p_msg == "request_quit") { emit_signal(SNAME("stop_requested")); _stop_and_notify(); + } else if (p_msg == "remote_node_clicked") { + if (!p_data.is_empty()) { + emit_signal(SNAME("remote_tree_select_requested"), p_data[0]); + } } else if (p_msg == "performance:profile_names") { Vector<StringName> monitors; monitors.resize(p_data.size()); @@ -827,7 +831,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread bool parsed = EditorDebuggerNode::get_singleton()->plugins_capture(this, p_msg, p_data); if (!parsed) { - WARN_PRINT("unknown message " + p_msg); + WARN_PRINT("Unknown message: " + p_msg); } } } @@ -870,14 +874,14 @@ void ScriptEditorDebugger::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { tabs->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("DebuggerPanel"), EditorStringName(EditorStyles))); - skip_breakpoints->set_icon(get_editor_theme_icon(skip_breakpoints_value ? SNAME("DebugSkipBreakpointsOn") : SNAME("DebugSkipBreakpointsOff"))); - copy->set_icon(get_editor_theme_icon(SNAME("ActionCopy"))); - step->set_icon(get_editor_theme_icon(SNAME("DebugStep"))); - next->set_icon(get_editor_theme_icon(SNAME("DebugNext"))); - dobreak->set_icon(get_editor_theme_icon(SNAME("Pause"))); - docontinue->set_icon(get_editor_theme_icon(SNAME("DebugContinue"))); - vmem_refresh->set_icon(get_editor_theme_icon(SNAME("Reload"))); - vmem_export->set_icon(get_editor_theme_icon(SNAME("Save"))); + skip_breakpoints->set_button_icon(get_editor_theme_icon(skip_breakpoints_value ? SNAME("DebugSkipBreakpointsOn") : SNAME("DebugSkipBreakpointsOff"))); + copy->set_button_icon(get_editor_theme_icon(SNAME("ActionCopy"))); + step->set_button_icon(get_editor_theme_icon(SNAME("DebugStep"))); + next->set_button_icon(get_editor_theme_icon(SNAME("DebugNext"))); + dobreak->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); + docontinue->set_button_icon(get_editor_theme_icon(SNAME("DebugContinue"))); + vmem_refresh->set_button_icon(get_editor_theme_icon(SNAME("Reload"))); + vmem_export->set_button_icon(get_editor_theme_icon(SNAME("Save"))); search->set_right_icon(get_editor_theme_icon(SNAME("Search"))); reason->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); @@ -905,37 +909,42 @@ void ScriptEditorDebugger::_notification(int p_what) { if (is_session_active()) { peer->poll(); - if (camera_override == CameraOverride::OVERRIDE_2D) { - Dictionary state = CanvasItemEditor::get_singleton()->get_state(); - float zoom = state["zoom"]; - Point2 offset = state["ofs"]; - Transform2D transform; - - transform.scale_basis(Size2(zoom, zoom)); - transform.columns[2] = -offset * zoom; - - Array msg; - msg.push_back(transform); - _put_msg("scene:override_camera_2D:transform", msg); - - } else if (camera_override >= CameraOverride::OVERRIDE_3D_1) { - int viewport_idx = camera_override - CameraOverride::OVERRIDE_3D_1; - Node3DEditorViewport *viewport = Node3DEditor::get_singleton()->get_editor_viewport(viewport_idx); - Camera3D *const cam = viewport->get_camera_3d(); - - Array msg; - msg.push_back(cam->get_camera_transform()); - if (cam->get_projection() == Camera3D::PROJECTION_ORTHOGONAL) { - msg.push_back(false); - msg.push_back(cam->get_size()); - } else { - msg.push_back(true); - msg.push_back(cam->get_fov()); + if (camera_override == CameraOverride::OVERRIDE_EDITORS) { + // CanvasItem Editor + { + Dictionary state = CanvasItemEditor::get_singleton()->get_state(); + float zoom = state["zoom"]; + Point2 offset = state["ofs"]; + Transform2D transform; + + transform.scale_basis(Size2(zoom, zoom)); + transform.columns[2] = -offset * zoom; + + Array msg; + msg.push_back(transform); + _put_msg("scene:transform_camera_2d", msg); + } + + // Node3D Editor + { + Node3DEditorViewport *viewport = Node3DEditor::get_singleton()->get_last_used_viewport(); + const Camera3D *cam = viewport->get_camera_3d(); + + Array msg; + msg.push_back(cam->get_camera_transform()); + if (cam->get_projection() == Camera3D::PROJECTION_ORTHOGONAL) { + msg.push_back(false); + msg.push_back(cam->get_size()); + } else { + msg.push_back(true); + msg.push_back(cam->get_fov()); + } + msg.push_back(cam->get_near()); + msg.push_back(cam->get_far()); + _put_msg("scene:transform_camera_3d", msg); } - msg.push_back(cam->get_near()); - msg.push_back(cam->get_far()); - _put_msg("scene:override_camera_3D:transform", msg); } + if (is_breaked() && can_request_idle_draw) { _put_msg("servers:draw", Array()); can_request_idle_draw = false; @@ -1024,6 +1033,9 @@ void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) { _update_buttons_state(); emit_signal(SNAME("started")); + Array quit_keys = DebuggerMarshalls::serialize_key_shortcut(ED_GET_SHORTCUT("editor/stop_running_project")); + _put_msg("scene:setup_scene", quit_keys); + if (EditorSettings::get_singleton()->get_project_metadata("debug_options", "autostart_profiler", false)) { profiler->set_profiling(true); } @@ -1161,6 +1173,12 @@ String ScriptEditorDebugger::get_var_value(const String &p_var) const { return inspector->get_stack_variable(p_var); } +void ScriptEditorDebugger::_resources_reimported(const PackedStringArray &p_resources) { + Array msg; + msg.push_back(p_resources); + _put_msg("scene:reload_cached_files", msg); +} + int ScriptEditorDebugger::_get_node_path_cache(const NodePath &p_path) { const int *r = node_path_cache.getptr(p_path); if (r) { @@ -1469,23 +1487,10 @@ CameraOverride ScriptEditorDebugger::get_camera_override() const { } void ScriptEditorDebugger::set_camera_override(CameraOverride p_override) { - if (p_override == CameraOverride::OVERRIDE_2D && camera_override != CameraOverride::OVERRIDE_2D) { - Array msg; - msg.push_back(true); - _put_msg("scene:override_camera_2D:set", msg); - } else if (p_override != CameraOverride::OVERRIDE_2D && camera_override == CameraOverride::OVERRIDE_2D) { - Array msg; - msg.push_back(false); - _put_msg("scene:override_camera_2D:set", msg); - } else if (p_override >= CameraOverride::OVERRIDE_3D_1 && camera_override < CameraOverride::OVERRIDE_3D_1) { - Array msg; - msg.push_back(true); - _put_msg("scene:override_camera_3D:set", msg); - } else if (p_override < CameraOverride::OVERRIDE_3D_1 && camera_override >= CameraOverride::OVERRIDE_3D_1) { - Array msg; - msg.push_back(false); - _put_msg("scene:override_camera_3D:set", msg); - } + Array msg; + msg.push_back(p_override != CameraOverride::OVERRIDE_NONE); + msg.push_back(p_override == CameraOverride::OVERRIDE_EDITORS); + _put_msg("scene:override_cameras", msg); camera_override = p_override; } @@ -1776,6 +1781,7 @@ void ScriptEditorDebugger::_bind_methods() { ADD_SIGNAL(MethodInfo("remote_object_updated", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("remote_object_property_updated", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "property"))); ADD_SIGNAL(MethodInfo("remote_tree_updated")); + ADD_SIGNAL(MethodInfo("remote_tree_select_requested", PropertyInfo(Variant::NODE_PATH, "path"))); ADD_SIGNAL(MethodInfo("output", PropertyInfo(Variant::STRING, "msg"), PropertyInfo(Variant::INT, "level"))); ADD_SIGNAL(MethodInfo("stack_dump", PropertyInfo(Variant::ARRAY, "stack_dump"))); ADD_SIGNAL(MethodInfo("stack_frame_vars", PropertyInfo(Variant::INT, "num_vars"))); @@ -1821,6 +1827,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() { tabs->connect("tab_changed", callable_mp(this, &ScriptEditorDebugger::_tab_changed)); InspectorDock::get_inspector_singleton()->connect("object_id_selected", callable_mp(this, &ScriptEditorDebugger::_remote_object_selected)); + EditorFileSystem::get_singleton()->connect("resources_reimported", callable_mp(this, &ScriptEditorDebugger::_resources_reimported)); { //debugger VBoxContainer *vbc = memnew(VBoxContainer); diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index 1908b1e5a7..06a968e141 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -198,6 +198,8 @@ private: void _video_mem_request(); void _video_mem_export(); + void _resources_reimported(const PackedStringArray &p_resources); + int _get_node_path_cache(const NodePath &p_path); int _get_res_path_cache(const String &p_path); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 8ba5811ffa..9ca12070fe 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -471,7 +471,7 @@ void DependencyRemoveDialog::_find_localization_remaps_of_removed_files(Vector<R for (int j = 0; j < remap_keys.size(); j++) { PackedStringArray remapped_files = remaps[remap_keys[j]]; for (int k = 0; k < remapped_files.size(); k++) { - int splitter_pos = remapped_files[k].rfind(":"); + int splitter_pos = remapped_files[k].rfind_char(':'); String res_path = remapped_files[k].substr(0, splitter_pos); if (res_path == path) { String locale_name = remapped_files[k].substr(splitter_pos + 1); diff --git a/editor/directory_create_dialog.cpp b/editor/directory_create_dialog.cpp index ee03d5a7f6..d68af88fc8 100644 --- a/editor/directory_create_dialog.cpp +++ b/editor/directory_create_dialog.cpp @@ -142,7 +142,7 @@ void DirectoryCreateDialog::config(const String &p_base_dir, const Callable &p_a validation_panel->update(); if (p_mode == MODE_FILE) { - int extension_pos = p_default_name.rfind("."); + int extension_pos = p_default_name.rfind_char('.'); if (extension_pos > -1) { dir_path->select(0, extension_pos); return; diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 79e0c7ebd1..842c4acce0 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -908,6 +908,23 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) { c.properties.sort(); + List<StringName> enums; + Variant::get_enums_for_type(Variant::Type(i), &enums); + + for (const StringName &E : enums) { + List<StringName> enumerations; + Variant::get_enumerations_for_enum(Variant::Type(i), E, &enumerations); + + for (const StringName &F : enumerations) { + DocData::ConstantDoc constant; + constant.name = F; + constant.value = itos(Variant::get_enum_value(Variant::Type(i), E, F)); + constant.is_value_valid = true; + constant.enumeration = E; + c.constants.push_back(constant); + } + } + List<StringName> constants; Variant::get_constants_for_type(Variant::Type(i), &constants); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 1e44a9bdc9..72755e8943 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -130,14 +130,14 @@ void EditorAssetInstaller::open_asset(const String &p_path, bool p_autoskip_topl // Create intermediate directories if they aren't reported by unzip. // We are only interested in subfolders, so skip the root slash. - int separator = source_name.find("/", 1); + int separator = source_name.find_char('/', 1); while (separator != -1) { String dir_name = source_name.substr(0, separator + 1); if (!dir_name.is_empty() && !asset_files.has(dir_name)) { asset_files.insert(dir_name); } - separator = source_name.find("/", separator + 1); + separator = source_name.find_char('/', separator + 1); } if (!source_name.is_empty() && !asset_files.has(source_name)) { @@ -214,7 +214,7 @@ void EditorAssetInstaller::_rebuild_source_tree() { TreeItem *parent_item; - int separator = path.rfind("/"); + int separator = path.rfind_char('/'); if (separator == -1) { parent_item = root; } else { @@ -313,7 +313,7 @@ void EditorAssetInstaller::_rebuild_destination_tree() { TreeItem *parent_item; - int separator = path.rfind("/"); + int separator = path.rfind_char('/'); if (separator == -1) { parent_item = root; } else { @@ -411,9 +411,9 @@ void EditorAssetInstaller::_toggle_source_tree(bool p_visible, bool p_scroll_to_ show_source_files_button->set_pressed_no_signal(p_visible); // To keep in sync if triggered by something else. if (p_visible) { - show_source_files_button->set_icon(get_editor_theme_icon(SNAME("Back"))); + show_source_files_button->set_button_icon(get_editor_theme_icon(SNAME("Back"))); } else { - show_source_files_button->set_icon(get_editor_theme_icon(SNAME("Forward"))); + show_source_files_button->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); } if (p_visible && p_scroll_to_error && first_file_conflict) { @@ -597,9 +597,9 @@ void EditorAssetInstaller::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { if (show_source_files_button->is_pressed()) { - show_source_files_button->set_icon(get_editor_theme_icon(SNAME("Back"))); + show_source_files_button->set_button_icon(get_editor_theme_icon(SNAME("Back"))); } else { - show_source_files_button->set_icon(get_editor_theme_icon(SNAME("Forward"))); + show_source_files_button->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); } asset_conflicts_link->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 24fc7a9c2b..0649272216 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -91,19 +91,28 @@ void EditorAudioBus::_notification(int p_what) { Color mute_color = EditorThemeManager::is_dark_theme() ? Color(1.0, 0.16, 0.16) : Color(2.35, 1.03, 1.03); Color bypass_color = EditorThemeManager::is_dark_theme() ? Color(0.13, 0.8, 1.0) : Color(1.03, 2.04, 2.35); float darkening_factor = EditorThemeManager::is_dark_theme() ? 0.15 : 0.65; - - Ref<StyleBoxFlat>(solo->get_theme_stylebox(SceneStringName(pressed)))->set_border_color(solo_color.darkened(darkening_factor)); - Ref<StyleBoxFlat>(mute->get_theme_stylebox(SceneStringName(pressed)))->set_border_color(mute_color.darkened(darkening_factor)); - Ref<StyleBoxFlat>(bypass->get_theme_stylebox(SceneStringName(pressed)))->set_border_color(bypass_color.darkened(darkening_factor)); - - solo->set_icon(get_editor_theme_icon(SNAME("AudioBusSolo"))); + Color solo_color_darkened = solo_color.darkened(darkening_factor); + Color mute_color_darkened = mute_color.darkened(darkening_factor); + Color bypass_color_darkened = bypass_color.darkened(darkening_factor); + + Ref<StyleBoxFlat>(solo->get_theme_stylebox(SceneStringName(pressed)))->set_border_color(solo_color_darkened); + Ref<StyleBoxFlat>(mute->get_theme_stylebox(SceneStringName(pressed)))->set_border_color(mute_color_darkened); + Ref<StyleBoxFlat>(bypass->get_theme_stylebox(SceneStringName(pressed)))->set_border_color(bypass_color_darkened); + Ref<StyleBoxFlat>(solo->get_theme_stylebox("hover_pressed"))->set_border_color(solo_color_darkened); + Ref<StyleBoxFlat>(mute->get_theme_stylebox("hover_pressed"))->set_border_color(mute_color_darkened); + Ref<StyleBoxFlat>(bypass->get_theme_stylebox("hover_pressed"))->set_border_color(bypass_color_darkened); + + solo->set_button_icon(get_editor_theme_icon(SNAME("AudioBusSolo"))); solo->add_theme_color_override("icon_pressed_color", solo_color); - mute->set_icon(get_editor_theme_icon(SNAME("AudioBusMute"))); + solo->add_theme_color_override("icon_hover_pressed_color", solo_color_darkened); + mute->set_button_icon(get_editor_theme_icon(SNAME("AudioBusMute"))); mute->add_theme_color_override("icon_pressed_color", mute_color); - bypass->set_icon(get_editor_theme_icon(SNAME("AudioBusBypass"))); + mute->add_theme_color_override("icon_hover_pressed_color", mute_color_darkened); + bypass->set_button_icon(get_editor_theme_icon(SNAME("AudioBusBypass"))); bypass->add_theme_color_override("icon_pressed_color", bypass_color); + bypass->add_theme_color_override("icon_hover_pressed_color", bypass_color_darkened); - bus_options->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + bus_options->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); audio_value_preview_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SceneStringName(font_color), SNAME("TooltipLabel"))); audio_value_preview_label->add_theme_color_override("font_shadow_color", get_theme_color(SNAME("font_shadow_color"), SNAME("TooltipLabel"))); @@ -841,13 +850,18 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { child->begin_bulk_theme_override(); child->add_theme_style_override(CoreStringName(normal), sbempty); child->add_theme_style_override("hover", sbempty); + child->add_theme_style_override("hover_mirrored", sbempty); child->add_theme_style_override("focus", sbempty); + child->add_theme_style_override("focus_mirrored", sbempty); Ref<StyleBoxFlat> sbflat = memnew(StyleBoxFlat); sbflat->set_content_margin_all(0); sbflat->set_bg_color(Color(1, 1, 1, 0)); sbflat->set_border_width(Side::SIDE_BOTTOM, Math::round(3 * EDSCALE)); child->add_theme_style_override(SceneStringName(pressed), sbflat); + child->add_theme_style_override("pressed_mirrored", sbflat); + child->add_theme_style_override("hover_pressed", sbflat); + child->add_theme_style_override("hover_pressed_mirrored", sbflat); child->end_bulk_theme_override(); } diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 1613d1d62f..23a2f5b13c 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -55,12 +55,12 @@ void EditorAutoloadSettings::_notification(int p_what) { file_dialog->add_filter("*." + E); } - browse_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); + browse_button->set_button_icon(get_editor_theme_icon(SNAME("Folder"))); } break; case NOTIFICATION_THEME_CHANGED: { - browse_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); - add_autoload->set_icon(get_editor_theme_icon(SNAME("Add"))); + browse_button->set_button_icon(get_editor_theme_icon(SNAME("Folder"))); + add_autoload->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index ee16c61c89..bb02172b1a 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -547,6 +547,7 @@ Variant EditorData::instantiate_custom_type(const String &p_type, const String & if (n) { n->set_name(p_type); } + n->set_meta(SceneStringName(_custom_type_script), script); ((Object *)ob)->set_script(script); return ob; } @@ -1008,6 +1009,7 @@ Variant EditorData::script_class_instance(const String &p_class) { // Store in a variant to initialize the refcount if needed. Variant obj = ClassDB::instantiate(script->get_instance_base_type()); if (obj) { + Object::cast_to<Object>(obj)->set_meta(SceneStringName(_custom_type_script), script); obj.operator Object *()->set_script(script); } return obj; diff --git a/editor/editor_dock_manager.cpp b/editor/editor_dock_manager.cpp index 0bdda41f26..1db073ec81 100644 --- a/editor/editor_dock_manager.cpp +++ b/editor/editor_dock_manager.cpp @@ -852,21 +852,21 @@ void DockContextPopup::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { if (make_float_button) { - make_float_button->set_icon(get_editor_theme_icon(SNAME("MakeFloating"))); + make_float_button->set_button_icon(get_editor_theme_icon(SNAME("MakeFloating"))); } if (is_layout_rtl()) { - tab_move_left_button->set_icon(get_editor_theme_icon(SNAME("Forward"))); - tab_move_right_button->set_icon(get_editor_theme_icon(SNAME("Back"))); + tab_move_left_button->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); + tab_move_right_button->set_button_icon(get_editor_theme_icon(SNAME("Back"))); tab_move_left_button->set_tooltip_text(TTR("Move this dock right one tab.")); tab_move_right_button->set_tooltip_text(TTR("Move this dock left one tab.")); } else { - tab_move_left_button->set_icon(get_editor_theme_icon(SNAME("Back"))); - tab_move_right_button->set_icon(get_editor_theme_icon(SNAME("Forward"))); + tab_move_left_button->set_button_icon(get_editor_theme_icon(SNAME("Back"))); + tab_move_right_button->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); tab_move_left_button->set_tooltip_text(TTR("Move this dock left one tab.")); tab_move_right_button->set_tooltip_text(TTR("Move this dock right one tab.")); } - dock_to_bottom_button->set_icon(get_editor_theme_icon(SNAME("ControlAlignBottomWide"))); - close_button->set_icon(get_editor_theme_icon(SNAME("Close"))); + dock_to_bottom_button->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignBottomWide"))); + close_button->set_button_icon(get_editor_theme_icon(SNAME("Close"))); } break; } } diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 44fc9e3702..9cf10c0ecb 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -49,6 +49,7 @@ const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = { TTRC("FileSystem Dock"), TTRC("Import Dock"), TTRC("History Dock"), + TTRC("Game View"), }; const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = { @@ -60,6 +61,7 @@ const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = { TTRC("Allows to browse the local file system via a dedicated dock."), TTRC("Allows to configure import settings for individual assets. Requires the FileSystem dock to function."), TTRC("Provides an overview of the editor's and each scene's undo history."), + TTRC("Provides tools for selecting and debugging nodes at runtime."), }; const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = { @@ -71,6 +73,7 @@ const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = { "filesystem_dock", "import_dock", "history_dock", + "game", }; void EditorFeatureProfile::set_disable_class(const StringName &p_class, bool p_disabled) { @@ -307,6 +310,7 @@ void EditorFeatureProfile::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_FILESYSTEM_DOCK); BIND_ENUM_CONSTANT(FEATURE_IMPORT_DOCK); BIND_ENUM_CONSTANT(FEATURE_HISTORY_DOCK); + BIND_ENUM_CONSTANT(FEATURE_GAME); BIND_ENUM_CONSTANT(FEATURE_MAX); } diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h index 7458a04e19..e84936dd34 100644 --- a/editor/editor_feature_profile.h +++ b/editor/editor_feature_profile.h @@ -55,6 +55,7 @@ public: FEATURE_FILESYSTEM_DOCK, FEATURE_IMPORT_DOCK, FEATURE_HISTORY_DOCK, + FEATURE_GAME, FEATURE_MAX }; diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 2d1a914120..b5306154ba 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -248,11 +248,16 @@ void EditorFileSystem::_first_scan_filesystem() { ep.step(TTR("Scanning file structure..."), 0, true); nb_files_total = _scan_new_dir(first_scan_root_dir, d); + // Preloading GDExtensions file extensions to prevent looping on all the resource loaders + // for each files in _first_scan_process_scripts. + List<String> gdextension_extensions; + ResourceLoader::get_recognized_extensions_for_type("GDExtension", &gdextension_extensions); + // This loads the global class names from the scripts and ensures that even if the // global_script_class_cache.cfg was missing or invalid, the global class names are valid in ScriptServer. // At the same time, to prevent looping multiple times in all files, it looks for extensions. ep.step(TTR("Loading global class names..."), 1, true); - _first_scan_process_scripts(first_scan_root_dir, existing_class_names, extensions); + _first_scan_process_scripts(first_scan_root_dir, gdextension_extensions, existing_class_names, extensions); // Removing invalid global class to prevent having invalid paths in ScriptServer. _remove_invalid_global_class_names(existing_class_names); @@ -276,16 +281,16 @@ void EditorFileSystem::_first_scan_filesystem() { ep.step(TTR("Starting file scan..."), 5, true); } -void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_scan_dir, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions) { +void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_scan_dir, List<String> &p_gdextension_extensions, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions) { for (ScannedDirectory *scan_sub_dir : p_scan_dir->subdirs) { - _first_scan_process_scripts(scan_sub_dir, p_existing_class_names, p_extensions); + _first_scan_process_scripts(scan_sub_dir, p_gdextension_extensions, p_existing_class_names, p_extensions); } for (const String &scan_file : p_scan_dir->files) { // Optimization to skip the ResourceLoader::get_resource_type for files // that are not scripts. Some loader get_resource_type methods read the file // which can be very slow on large projects. - String ext = scan_file.get_extension().to_lower(); + const String ext = scan_file.get_extension().to_lower(); bool is_script = false; for (int i = 0; i < ScriptServer::get_language_count(); i++) { if (ScriptServer::get_language(i)->get_extension() == ext) { @@ -293,24 +298,29 @@ void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_sca break; } } - if (!is_script) { - continue; // Not a script. - } + if (is_script) { + const String path = p_scan_dir->full_path.path_join(scan_file); + const String type = ResourceLoader::get_resource_type(path); - String path = p_scan_dir->full_path.path_join(scan_file); - String type = ResourceLoader::get_resource_type(path); + if (ClassDB::is_parent_class(type, SNAME("Script"))) { + String script_class_extends; + String script_class_icon_path; + String script_class_name = _get_global_script_class(type, path, &script_class_extends, &script_class_icon_path); + _register_global_class_script(path, path, type, script_class_name, script_class_extends, script_class_icon_path); - if (ClassDB::is_parent_class(type, SNAME("Script"))) { - String script_class_extends; - String script_class_icon_path; - String script_class_name = _get_global_script_class(type, path, &script_class_extends, &script_class_icon_path); - _register_global_class_script(path, path, type, script_class_name, script_class_extends, script_class_icon_path); + if (!script_class_name.is_empty()) { + p_existing_class_names.insert(script_class_name); + } + } + } - if (!script_class_name.is_empty()) { - p_existing_class_names.insert(script_class_name); + // Check for GDExtensions. + if (p_gdextension_extensions.find(ext)) { + const String path = p_scan_dir->full_path.path_join(scan_file); + const String type = ResourceLoader::get_resource_type(path); + if (type == SNAME("GDExtension")) { + p_extensions.insert(path); } - } else if (type == SNAME("GDExtension")) { - p_extensions.insert(path); } } } @@ -1017,7 +1027,9 @@ void EditorFileSystem::scan() { void EditorFileSystem::ScanProgress::increment() { current++; float ratio = current / MAX(hi, 1.0f); - progress->step(ratio * 1000.0f); + if (progress) { + progress->step(ratio * 1000.0f); + } EditorFileSystem::singleton->scan_total = ratio; } @@ -1247,6 +1259,15 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir, } } } + + if (fi->uid == ResourceUID::INVALID_ID && ResourceLoader::exists(path) && !ResourceLoader::has_custom_uid_support(path) && !FileAccess::exists(path + ".uid")) { + // Create a UID. + Ref<FileAccess> f = FileAccess::open(path + ".uid", FileAccess::WRITE); + if (f.is_valid()) { + fi->uid = ResourceUID::get_singleton()->create_id(); + f->store_line(ResourceUID::get_singleton()->id_to_text(fi->uid)); + } + } } if (fi->uid != ResourceUID::INVALID_ID) { @@ -1283,7 +1304,7 @@ void EditorFileSystem::_process_removed_files(const HashSet<String> &p_processed } } -void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanProgress &p_progress) { +void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanProgress &p_progress, bool p_recursive) { uint64_t current_mtime = FileAccess::get_modified_time(p_dir->get_path()); bool updated_dir = false; @@ -1477,7 +1498,9 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanPr scan_actions.push_back(ia); continue; } - _scan_fs_changes(p_dir->get_subdir(i), p_progress); + if (p_recursive) { + _scan_fs_changes(p_dir->get_subdir(i), p_progress); + } } nb_files_total = MAX(nb_files_total + diff_nb_files, 0); @@ -1493,6 +1516,9 @@ void EditorFileSystem::_delete_internal_files(const String &p_file) { } da->remove(p_file + ".import"); } + if (FileAccess::exists(p_file + ".uid")) { + DirAccess::remove_absolute(p_file + ".uid"); + } } int EditorFileSystem::_insert_actions_delete_files_directory(EditorFileSystemDirectory *p_dir) { @@ -2362,10 +2388,18 @@ void EditorFileSystem::update_files(const Vector<String> &p_script_paths) { if (!is_scanning()) { _process_update_pending(); } - call_deferred(SNAME("emit_signal"), "filesystem_changed"); // Update later + if (!filesystem_changed_queued) { + filesystem_changed_queued = true; + callable_mp(this, &EditorFileSystem::_notify_filesystem_changed).call_deferred(); + } } } +void EditorFileSystem::_notify_filesystem_changed() { + emit_signal("filesystem_changed"); + filesystem_changed_queued = false; +} + HashSet<String> EditorFileSystem::get_valid_extensions() const { return valid_extensions; } @@ -2559,7 +2593,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector EditorFileSystemDirectory *fs = nullptr; int cpos = -1; bool found = _find_file(file, &fs, cpos); - ERR_FAIL_COND_V_MSG(!found, ERR_UNCONFIGURED, "Can't find file '" + file + "'."); + ERR_FAIL_COND_V_MSG(!found, ERR_UNCONFIGURED, vformat("Can't find file '%s' during group reimport.", file)); //update modified times, to avoid reimport fs->files[cpos]->modified_time = FileAccess::get_modified_time(file); @@ -2609,7 +2643,7 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin int cpos = -1; if (p_update_file_system) { bool found = _find_file(p_file, &fs, cpos); - ERR_FAIL_COND_V_MSG(!found, ERR_FILE_NOT_FOUND, "Can't find file '" + p_file + "'."); + ERR_FAIL_COND_V_MSG(!found, ERR_FILE_NOT_FOUND, vformat("Can't find file '%s' during file reimport.", p_file)); } //try to obtain existing params @@ -2718,13 +2752,17 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin } } + if (uid == ResourceUID::INVALID_ID) { + uid = ResourceUID::get_singleton()->create_id(); + } + //finally, perform import!! String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_file); List<String> import_variants; List<String> gen_files; Variant meta; - Error err = importer->import(p_file, base_path, params, &import_variants, &gen_files, &meta); + Error err = importer->import(uid, p_file, base_path, params, &import_variants, &gen_files, &meta); // As import is complete, save the .import file. @@ -2745,10 +2783,6 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin f->store_line("type=\"" + importer->get_resource_type() + "\""); } - if (uid == ResourceUID::INVALID_ID) { - uid = ResourceUID::get_singleton()->create_id(); - } - f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); // Store in readable format. if (err == OK) { @@ -2902,6 +2936,96 @@ void EditorFileSystem::reimport_file_with_custom_parameters(const String &p_file emit_signal(SNAME("resources_reimported"), reloads); } +Error EditorFileSystem::_copy_file(const String &p_from, const String &p_to) { + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (FileAccess::exists(p_from + ".import")) { + Error err = da->copy(p_from, p_to); + if (err != OK) { + return err; + } + + // Remove uid from .import file to avoid conflict. + Ref<ConfigFile> cfg; + cfg.instantiate(); + cfg->load(p_from + ".import"); + cfg->erase_section_key("remap", "uid"); + err = cfg->save(p_to + ".import"); + if (err != OK) { + return err; + } + } else if (ResourceLoader::get_resource_uid(p_from) == ResourceUID::INVALID_ID) { + // Files which do not use an uid can just be copied. + Error err = da->copy(p_from, p_to); + if (err != OK) { + return err; + } + } else { + // Load the resource and save it again in the new location (this generates a new UID). + Error err; + Ref<Resource> res = ResourceLoader::load(p_from, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); + if (err == OK && res.is_valid()) { + err = ResourceSaver::save(res, p_to, ResourceSaver::FLAG_COMPRESS); + if (err != OK) { + return err; + } + } else if (err != OK) { + // When loading files like text files the error is OK but the resource is still null. + // We can ignore such files. + return err; + } + } + return OK; +} + +bool EditorFileSystem::_copy_directory(const String &p_from, const String &p_to, List<CopiedFile> *p_files) { + Ref<DirAccess> old_dir = DirAccess::open(p_from); + ERR_FAIL_COND_V(old_dir.is_null(), false); + + Error err = make_dir_recursive(p_to); + if (err != OK && err != ERR_ALREADY_EXISTS) { + return false; + } + + bool success = true; + old_dir->set_include_navigational(false); + old_dir->list_dir_begin(); + + for (String F = old_dir->_get_next(); !F.is_empty(); F = old_dir->_get_next()) { + if (old_dir->current_is_dir()) { + success = _copy_directory(p_from.path_join(F), p_to.path_join(F), p_files) && success; + } else if (F.get_extension() != "import") { + CopiedFile copy; + copy.from = p_from.path_join(F); + copy.to = p_to.path_join(F); + p_files->push_back(copy); + } + } + return success; +} + +void EditorFileSystem::_queue_refresh_filesystem() { + if (refresh_queued) { + return; + } + refresh_queued = true; + get_tree()->connect(SNAME("process_frame"), callable_mp(this, &EditorFileSystem::_refresh_filesystem), CONNECT_ONE_SHOT); +} + +void EditorFileSystem::_refresh_filesystem() { + for (const ObjectID &id : folders_to_sort) { + EditorFileSystemDirectory *dir = Object::cast_to<EditorFileSystemDirectory>(ObjectDB::get_instance(id)); + if (dir) { + dir->subdirs.sort_custom<DirectoryComparator>(); + } + } + folders_to_sort.clear(); + + _update_scan_actions(); + + emit_signal(SNAME("filesystem_changed")); + refresh_queued = false; +} + void EditorFileSystem::_reimport_thread(uint32_t p_index, ImportThreadData *p_import_data) { int current_max = p_import_data->reimport_from + int(p_index); p_import_data->max_index.exchange_if_greater(current_max); @@ -3225,10 +3349,9 @@ Error EditorFileSystem::make_dir_recursive(const String &p_path, const String &p const String path = da->get_current_dir(); EditorFileSystemDirectory *parent = get_filesystem_path(path); ERR_FAIL_NULL_V(parent, ERR_FILE_NOT_FOUND); + folders_to_sort.insert(parent->get_instance_id()); const PackedStringArray folders = p_path.trim_prefix(path).trim_suffix("/").split("/"); - bool first = true; - for (const String &folder : folders) { const int current = parent->find_dir_index(folder); if (current > -1) { @@ -3240,18 +3363,59 @@ Error EditorFileSystem::make_dir_recursive(const String &p_path, const String &p efd->parent = parent; efd->name = folder; parent->subdirs.push_back(efd); - - if (first) { - parent->subdirs.sort_custom<DirectoryComparator>(); - first = false; - } parent = efd; } - emit_signal(SNAME("filesystem_changed")); + _queue_refresh_filesystem(); + return OK; +} + +Error EditorFileSystem::copy_file(const String &p_from, const String &p_to) { + _copy_file(p_from, p_to); + + EditorFileSystemDirectory *parent = get_filesystem_path(p_to.get_base_dir()); + ERR_FAIL_NULL_V(parent, ERR_FILE_NOT_FOUND); + + ScanProgress sp; + _scan_fs_changes(parent, sp, false); + + _queue_refresh_filesystem(); return OK; } +Error EditorFileSystem::copy_directory(const String &p_from, const String &p_to) { + List<CopiedFile> files; + bool success = _copy_directory(p_from, p_to, &files); + + EditorProgress *ep = nullptr; + if (files.size() > 10) { + ep = memnew(EditorProgress("_copy_files", TTR("Copying files..."), files.size())); + } + + int i = 0; + for (const CopiedFile &F : files) { + if (_copy_file(F.from, F.to) != OK) { + success = false; + } + if (ep) { + ep->step(F.from.get_file(), i++, false); + } + } + memdelete_notnull(ep); + + EditorFileSystemDirectory *efd = get_filesystem_path(p_to); + ERR_FAIL_NULL_V(efd, FAILED); + ERR_FAIL_NULL_V(efd->get_parent(), FAILED); + + folders_to_sort.insert(efd->get_parent()->get_instance_id()); + + ScanProgress sp; + _scan_fs_changes(efd, sp); + + _queue_refresh_filesystem(); + return success ? OK : FAILED; +} + ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate) { if (!p_path.is_resource_file() || p_path.begins_with(ProjectSettings::get_singleton()->get_project_data_path())) { // Saved externally (configuration file) or internal file, do not assign an ID. diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 7aa0137f4e..11573ef0d7 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -180,6 +180,7 @@ class EditorFileSystem : public Node { EditorFileSystemDirectory *new_filesystem = nullptr; ScannedDirectory *first_scan_root_dir = nullptr; + bool filesystem_changed_queued = false; bool scanning = false; bool importing = false; bool first_scan = true; @@ -189,9 +190,10 @@ class EditorFileSystem : public Node { bool revalidate_import_files = false; int nb_files_total = 0; + void _notify_filesystem_changed(); void _scan_filesystem(); void _first_scan_filesystem(); - void _first_scan_process_scripts(const ScannedDirectory *p_scan_dir, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions); + void _first_scan_process_scripts(const ScannedDirectory *p_scan_dir, List<String> &p_gdextension_extensions, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions); HashSet<String> late_update_files; @@ -239,7 +241,7 @@ class EditorFileSystem : public Node { bool _find_file(const String &p_file, EditorFileSystemDirectory **r_d, int &r_file_pos) const; - void _scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanProgress &p_progress); + void _scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanProgress &p_progress, bool p_recursive = true); void _delete_internal_files(const String &p_file); int _insert_actions_delete_files_directory(EditorFileSystemDirectory *p_dir); @@ -324,6 +326,19 @@ class EditorFileSystem : public Node { HashSet<String> group_file_cache; HashMap<String, String> file_icon_cache; + struct CopiedFile { + String from; + String to; + }; + + bool refresh_queued = false; + HashSet<ObjectID> folders_to_sort; + + Error _copy_file(const String &p_from, const String &p_to); + bool _copy_directory(const String &p_from, const String &p_to, List<CopiedFile> *p_files); + void _queue_refresh_filesystem(); + void _refresh_filesystem(); + struct ImportThreadData { const ImportFile *reimport_files; int reimport_from; @@ -378,6 +393,8 @@ public: void move_group_file(const String &p_path, const String &p_new_path); Error make_dir_recursive(const String &p_path, const String &p_base_path = String()); + Error copy_file(const String &p_from, const String &p_to); + Error copy_directory(const String &p_from, const String &p_to); static bool _should_skip_directory(const String &p_path); diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index 18f5610655..5cb38fa875 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -249,7 +249,7 @@ void EditorFolding::_do_object_unfolds(Object *p_object, HashSet<Ref<Resource>> } } } else { //path - int last = E.name.rfind("/"); + int last = E.name.rfind_char('/'); if (last != -1) { bool can_revert = EditorPropertyRevert::can_property_revert(p_object, E.name); if (can_revert) { diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index cfe257fcfc..f0c54b9edd 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -148,7 +148,7 @@ static String _contextualize_class_specifier(const String &p_class_specifier, co // Here equal length + begins_with from above implies p_class_specifier == p_edited_class :) if (p_class_specifier.length() == p_edited_class.length()) { - int rfind = p_class_specifier.rfind("."); + int rfind = p_class_specifier.rfind_char('.'); if (rfind == -1) { // Single identifier return p_class_specifier; } @@ -234,7 +234,7 @@ void EditorHelp::_class_desc_select(const String &p_select) { enum_class_name = "@GlobalScope"; enum_name = link; } else { - const int dot_pos = link.rfind("."); + const int dot_pos = link.rfind_char('.'); if (dot_pos >= 0) { enum_class_name = link.left(dot_pos); enum_name = link.substr(dot_pos + 1); @@ -3109,9 +3109,9 @@ void EditorHelp::set_scroll(int p_scroll) { void EditorHelp::update_toggle_scripts_button() { if (is_layout_rtl()) { - toggle_scripts_button->set_icon(get_editor_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Forward") : SNAME("Back"))); + toggle_scripts_button->set_button_icon(get_editor_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Forward") : SNAME("Back"))); } else { - toggle_scripts_button->set_icon(get_editor_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"))); + toggle_scripts_button->set_button_icon(get_editor_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"))); } toggle_scripts_button->set_tooltip_text(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); } @@ -3252,7 +3252,7 @@ EditorHelpBit::HelpData EditorHelpBit::_get_property_help_data(const StringName enum_class_name = "@GlobalScope"; enum_name = property.enumeration; } else { - const int dot_pos = property.enumeration.rfind("."); + const int dot_pos = property.enumeration.rfind_char('.'); if (dot_pos >= 0) { enum_class_name = property.enumeration.left(dot_pos); enum_name = property.enumeration.substr(dot_pos + 1); @@ -3619,7 +3619,7 @@ void EditorHelpBit::_meta_clicked(const String &p_select) { enum_class_name = "@GlobalScope"; enum_name = link; } else { - const int dot_pos = link.rfind("."); + const int dot_pos = link.rfind_char('.'); if (dot_pos >= 0) { enum_class_name = link.left(dot_pos); enum_name = link.substr(dot_pos + 1); @@ -3868,7 +3868,7 @@ void EditorHelpBitTooltip::show_tooltip(EditorHelpBit *p_help_bit, Control *p_ta EditorHelpBitTooltip *tooltip = memnew(EditorHelpBitTooltip(p_target)); p_help_bit->connect("request_hide", callable_mp(tooltip, &EditorHelpBitTooltip::_safe_queue_free)); tooltip->add_child(p_help_bit); - p_target->get_viewport()->add_child(tooltip); + p_target->add_child(tooltip); p_help_bit->update_content_height(); tooltip->popup_under_cursor(); } @@ -4153,8 +4153,8 @@ void FindBar::popup_search() { void FindBar::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - find_prev->set_icon(get_editor_theme_icon(SNAME("MoveUp"))); - find_next->set_icon(get_editor_theme_icon(SNAME("MoveDown"))); + find_prev->set_button_icon(get_editor_theme_icon(SNAME("MoveUp"))); + find_next->set_button_icon(get_editor_theme_icon(SNAME("MoveDown"))); hide_button->set_texture_normal(get_editor_theme_icon(SNAME("Close"))); hide_button->set_texture_hover(get_editor_theme_icon(SNAME("Close"))); hide_button->set_texture_pressed(get_editor_theme_icon(SNAME("Close"))); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 47f16f219f..0fc7052a2b 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -151,7 +151,7 @@ void EditorHelpSearch::_update_results() { search_flags |= SEARCH_SHOW_HIERARCHY; } - search = Ref<Runner>(memnew(Runner(results_tree, results_tree, &tree_cache, term, search_flags))); + search.instantiate(results_tree, results_tree, &tree_cache, term, search_flags); // Clear old search flags to force rebuild on short term. old_search_flags = 0; @@ -162,7 +162,7 @@ void EditorHelpSearch::_update_results() { hierarchy_button->set_disabled(true); // Always show hierarchy for short searches. - search = Ref<Runner>(memnew(Runner(results_tree, results_tree, &tree_cache, term, search_flags | SEARCH_SHOW_HIERARCHY))); + search.instantiate(results_tree, results_tree, &tree_cache, term, search_flags | SEARCH_SHOW_HIERARCHY); old_search_flags = search_flags; set_process(true); @@ -244,8 +244,8 @@ void EditorHelpSearch::_notification(int p_what) { search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); search_box->add_theme_icon_override("right_icon", get_editor_theme_icon(SNAME("Search"))); - case_sensitive_button->set_icon(get_editor_theme_icon(SNAME("MatchCase"))); - hierarchy_button->set_icon(get_editor_theme_icon(SNAME("ClassList"))); + case_sensitive_button->set_button_icon(get_editor_theme_icon(SNAME("MatchCase"))); + hierarchy_button->set_button_icon(get_editor_theme_icon(SNAME("ClassList"))); if (is_visible()) { _update_results(); @@ -1166,7 +1166,7 @@ TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const if (p_matching_keyword.is_empty()) { item->set_text(0, p_doc->name); } else { - item->set_text(0, p_doc->name + " - " + TTR(vformat("Matches the \"%s\" keyword.", p_matching_keyword))); + item->set_text(0, p_doc->name + " - " + vformat(TTR("Matches the \"%s\" keyword."), p_matching_keyword)); } if (!term.is_empty()) { @@ -1272,7 +1272,7 @@ TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, cons text = p_class_name + "." + p_text; } if (!p_matching_keyword.is_empty()) { - text += " - " + TTR(vformat("Matches the \"%s\" keyword.", p_matching_keyword)); + text += " - " + vformat(TTR("Matches the \"%s\" keyword."), p_matching_keyword); } item->set_text(0, text); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index e6553cc92b..1a973d7b77 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -931,10 +931,19 @@ float EditorProperty::get_name_split_ratio() const { return split_ratio; } +void EditorProperty::set_favoritable(bool p_favoritable) { + can_favorite = p_favoritable; +} + +bool EditorProperty::is_favoritable() const { + return can_favorite; +} + void EditorProperty::set_object_and_property(Object *p_object, const StringName &p_property) { object = p_object; property = p_property; - _update_pin_flags(); + + _update_flags(); } static bool _is_value_potential_override(Node *p_node, const String &p_property) { @@ -953,12 +962,14 @@ static bool _is_value_potential_override(Node *p_node, const String &p_property) } } -void EditorProperty::_update_pin_flags() { +void EditorProperty::_update_flags() { can_pin = false; pin_hidden = true; + if (read_only) { return; } + if (Node *node = Object::cast_to<Node>(object)) { // Avoid errors down the road by ignoring nodes which are not part of a scene if (!node->get_owner()) { @@ -1034,6 +1045,10 @@ void EditorProperty::menu_option(int p_option) { case MENU_COPY_PROPERTY_PATH: { DisplayServer::get_singleton()->clipboard_set(property_path); } break; + case MENU_FAVORITE_PROPERTY: { + emit_signal(SNAME("property_favorited"), property, !favorited); + queue_redraw(); + } break; case MENU_PIN_VALUE: { emit_signal(SNAME("property_pinned"), property, !pinned); queue_redraw(); @@ -1091,6 +1106,7 @@ void EditorProperty::_bind_methods() { ADD_SIGNAL(MethodInfo("property_deleted", PropertyInfo(Variant::STRING_NAME, "property"))); ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "checked"))); + ADD_SIGNAL(MethodInfo("property_favorited", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "favorited"))); ADD_SIGNAL(MethodInfo("property_pinned", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "pinned"))); ADD_SIGNAL(MethodInfo("property_can_revert_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "can_revert"))); ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); @@ -1129,8 +1145,21 @@ void EditorProperty::_update_popup() { menu->set_item_disabled(MENU_PASTE_VALUE, is_read_only()); menu->set_item_disabled(MENU_COPY_PROPERTY_PATH, internal); - if (!pin_hidden) { + if (can_favorite || !pin_hidden) { menu->add_separator(); + } + + if (can_favorite) { + if (favorited) { + menu->add_icon_item(get_editor_theme_icon(SNAME("Unfavorite")), TTR("Unfavorite Property"), MENU_FAVORITE_PROPERTY); + menu->set_item_tooltip(menu->get_item_index(MENU_FAVORITE_PROPERTY), TTR("Make this property be put back at its original place.")); + } else { + menu->add_icon_item(get_editor_theme_icon(SNAME("Favorites")), TTR("Favorite Property"), MENU_FAVORITE_PROPERTY); + menu->set_item_tooltip(menu->get_item_index(MENU_FAVORITE_PROPERTY), TTR("Make this property be placed at the top for all objects of this class.")); + } + } + + if (!pin_hidden) { if (can_pin) { menu->add_icon_check_item(get_editor_theme_icon(SNAME("Pin")), TTR("Pin Value"), MENU_PIN_VALUE); menu->set_item_checked(menu->get_item_index(MENU_PIN_VALUE), pinned); @@ -1219,9 +1248,14 @@ void EditorInspectorPlugin::_bind_methods() { void EditorInspectorCategory::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - menu->set_item_icon(menu->get_item_index(MENU_OPEN_DOCS), get_editor_theme_icon(SNAME("Help"))); + if (menu) { + if (is_favorite) { + menu->set_item_icon(menu->get_item_index(EditorInspector::MENU_UNFAVORITE_ALL), get_editor_theme_icon(SNAME("Unfavorite"))); + } else { + menu->set_item_icon(menu->get_item_index(MENU_OPEN_DOCS), get_editor_theme_icon(SNAME("Help"))); + } + } } break; case NOTIFICATION_DRAW: { Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg")); @@ -1278,6 +1312,15 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons return memnew(Control); // Make the standard tooltip invisible. } +void EditorInspectorCategory::set_as_favorite(EditorInspector *p_for_inspector) { + is_favorite = true; + + menu = memnew(PopupMenu); + menu->add_item(TTR("Unfavorite All"), EditorInspector::MENU_UNFAVORITE_ALL); + add_child(menu); + menu->connect(SceneStringName(id_pressed), callable_mp(p_for_inspector, &EditorInspector::_handle_menu_option)); +} + Size2 EditorInspectorCategory::get_minimum_size() const { Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts)); int font_size = get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)); @@ -1306,7 +1349,7 @@ void EditorInspectorCategory::_handle_menu_option(int p_option) { } void EditorInspectorCategory::gui_input(const Ref<InputEvent> &p_event) { - if (doc_class_name.is_empty()) { + if (!is_favorite && doc_class_name.is_empty()) { return; } @@ -1315,20 +1358,21 @@ void EditorInspectorCategory::gui_input(const Ref<InputEvent> &p_event) { return; } - menu->set_item_disabled(menu->get_item_index(MENU_OPEN_DOCS), !EditorHelp::get_doc_data()->class_list.has(doc_class_name)); + if (!is_favorite) { + if (!menu) { + menu = memnew(PopupMenu); + menu->add_icon_item(get_editor_theme_icon(SNAME("Help")), TTR("Open Documentation"), MENU_OPEN_DOCS); + add_child(menu); + menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorInspectorCategory::_handle_menu_option)); + } + menu->set_item_disabled(menu->get_item_index(MENU_OPEN_DOCS), !EditorHelp::get_doc_data()->class_list.has(doc_class_name)); + } menu->set_position(get_screen_position() + mb_event->get_position()); menu->reset_size(); menu->popup(); } -EditorInspectorCategory::EditorInspectorCategory() { - menu = memnew(PopupMenu); - menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorInspectorCategory::_handle_menu_option)); - menu->add_item(TTR("Open Documentation"), MENU_OPEN_DOCS); - add_child(menu); -} - //////////////////////////////////////////////// //////////////////////////////////////////////// @@ -1622,6 +1666,10 @@ void EditorInspectorSection::gui_input(const Ref<InputEvent> &p_event) { } } +String EditorInspectorSection::get_section() const { + return section; +} + VBoxContainer *EditorInspectorSection::get_vbox() { return vbox; } @@ -2234,7 +2282,7 @@ void EditorInspectorArray::_setup() { if (element_position > 0) { ae.move_up = memnew(Button); - ae.move_up->set_icon(get_editor_theme_icon(SNAME("MoveUp"))); + ae.move_up->set_button_icon(get_editor_theme_icon(SNAME("MoveUp"))); ae.move_up->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorArray::_move_element).bind(element_position, element_position - 1)); move_vbox->add_child(ae.move_up); } @@ -2250,7 +2298,7 @@ void EditorInspectorArray::_setup() { if (element_position < count - 1) { ae.move_down = memnew(Button); - ae.move_down->set_icon(get_editor_theme_icon(SNAME("MoveDown"))); + ae.move_down->set_button_icon(get_editor_theme_icon(SNAME("MoveDown"))); ae.move_down->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorArray::_move_element).bind(element_position, element_position + 2)); move_vbox->add_child(ae.move_down); } @@ -2273,7 +2321,7 @@ void EditorInspectorArray::_setup() { ae.hbox->add_child(ae.vbox); ae.erase = memnew(Button); - ae.erase->set_icon(get_editor_theme_icon(SNAME("Remove"))); + ae.erase->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); ae.erase->set_v_size_flags(SIZE_SHRINK_CENTER); ae.erase->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorArray::_remove_item).bind(element_position)); ae.hbox->add_child(ae.erase); @@ -2355,10 +2403,10 @@ void EditorInspectorArray::_notification(int p_what) { ae.move_texture_rect->set_texture(get_editor_theme_icon(SNAME("TripleBar"))); } if (ae.move_up) { - ae.move_up->set_icon(get_editor_theme_icon(SNAME("MoveUp"))); + ae.move_up->set_button_icon(get_editor_theme_icon(SNAME("MoveUp"))); } if (ae.move_down) { - ae.move_down->set_icon(get_editor_theme_icon(SNAME("MoveDown"))); + ae.move_down->set_button_icon(get_editor_theme_icon(SNAME("MoveDown"))); } Size2 min_size = get_theme_stylebox(SNAME("Focus"), EditorStringName(EditorStyles))->get_minimum_size(); ae.margin->begin_bulk_theme_override(); @@ -2369,11 +2417,11 @@ void EditorInspectorArray::_notification(int p_what) { ae.margin->end_bulk_theme_override(); if (ae.erase) { - ae.erase->set_icon(get_editor_theme_icon(SNAME("Remove"))); + ae.erase->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); } } - add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); update_minimum_size(); } break; @@ -2542,10 +2590,10 @@ void EditorPaginator::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - first_page_button->set_icon(get_editor_theme_icon(SNAME("PageFirst"))); - prev_page_button->set_icon(get_editor_theme_icon(SNAME("PagePrevious"))); - next_page_button->set_icon(get_editor_theme_icon(SNAME("PageNext"))); - last_page_button->set_icon(get_editor_theme_icon(SNAME("PageLast"))); + first_page_button->set_button_icon(get_editor_theme_icon(SNAME("PageFirst"))); + prev_page_button->set_button_icon(get_editor_theme_icon(SNAME("PagePrevious"))); + next_page_button->set_button_icon(get_editor_theme_icon(SNAME("PageNext"))); + last_page_button->set_button_icon(get_editor_theme_icon(SNAME("PageLast"))); } break; } } @@ -2675,7 +2723,13 @@ String EditorInspector::get_selected_path() const { void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped) { for (const EditorInspectorPlugin::AddedEditor &F : ped->added_editors) { EditorProperty *ep = Object::cast_to<EditorProperty>(F.property_editor); - current_vbox->add_child(F.property_editor); + + if (ep && !F.properties.is_empty() && current_favorites.has(F.properties[0])) { + ep->favorited = true; + favorites_vbox->add_child(F.property_editor); + } else { + current_vbox->add_child(F.property_editor); + } if (ep) { ep->object = object; @@ -2684,6 +2738,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorIn ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), CONNECT_DEFERRED); ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value)); ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked)); + ep->connect("property_favorited", callable_mp(this, &EditorInspector::_set_property_favorited), CONNECT_DEFERRED); ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned)); ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected)); ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed)); @@ -2727,7 +2782,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorIn ep->set_read_only(read_only); ep->update_property(); - ep->_update_pin_flags(); + ep->_update_flags(); ep->update_editor_property_status(); ep->set_deletable(deletable_properties); ep->update_cache(); @@ -2837,6 +2892,7 @@ void EditorInspector::update_tree() { String subgroup; String subgroup_base; int section_depth = 0; + bool disable_favorite = false; VBoxContainer *category_vbox = nullptr; List<PropertyInfo> plist; @@ -2844,13 +2900,17 @@ void EditorInspector::update_tree() { HashMap<VBoxContainer *, HashMap<String, VBoxContainer *>> vbox_per_path; HashMap<String, EditorInspectorArray *> editor_inspector_array_per_prefix; + HashMap<String, HashMap<String, LocalVector<EditorProperty *>>> favorites_to_add; Color sscolor = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)); // Get the lists of editors to add the beginning. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_begin(object); - _parse_added_editors(main_vbox, nullptr, ped); + _parse_added_editors(begin_vbox, nullptr, ped); + } + if (begin_vbox->get_child_count()) { + begin_vbox->show(); } StringName doc_name; @@ -2897,6 +2957,7 @@ void EditorInspector::update_tree() { subgroup = ""; subgroup_base = ""; section_depth = 0; + disable_favorite = false; vbox_per_path.clear(); editor_inspector_array_per_prefix.clear(); @@ -2960,6 +3021,11 @@ void EditorInspector::update_tree() { } else { category_icon = EditorNode::get_singleton()->get_object_icon(scr.ptr(), "Object"); } + + // Property favorites aren't compatible with built-in scripts. + if (scr->is_built_in()) { + disable_favorite = true; + } } } @@ -3058,9 +3124,14 @@ void EditorInspector::update_tree() { } } + // Don't allow to favorite array items. + if (!disable_favorite) { + disable_favorite = !array_prefix.is_empty(); + } + if (!array_prefix.is_empty()) { path = path.trim_prefix(array_prefix); - int char_index = path.find("/"); + int char_index = path.find_char('/'); if (char_index >= 0) { path = path.right(-char_index - 1); } else { @@ -3100,10 +3171,10 @@ void EditorInspector::update_tree() { } // Get the property label's string. - String name_override = (path.contains("/")) ? path.substr(path.rfind("/") + 1) : path; + String name_override = (path.contains("/")) ? path.substr(path.rfind_char('/') + 1) : path; String feature_tag; { - const int dot = name_override.find("."); + const int dot = name_override.find_char('.'); if (dot != -1) { feature_tag = name_override.substr(dot); name_override = name_override.substr(0, dot); @@ -3118,7 +3189,7 @@ void EditorInspector::update_tree() { const String property_label_string = EditorPropertyNameProcessor::get_singleton()->process_name(name_override, name_style, p.name, doc_name) + feature_tag; // Remove the property from the path. - int idx = path.rfind("/"); + int idx = path.rfind_char('/'); if (idx > -1) { path = path.left(idx); } else { @@ -3249,7 +3320,7 @@ void EditorInspector::update_tree() { array_element_prefix = class_name_components[0]; editor_inspector_array = memnew(EditorInspectorArray(all_read_only)); - String array_label = path.contains("/") ? path.substr(path.rfind("/") + 1) : path; + String array_label = path.contains("/") ? path.substr(path.rfind_char('/') + 1) : path; array_label = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string, property_name_style, p.name, doc_name); int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0; editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding); @@ -3457,6 +3528,7 @@ void EditorInspector::update_tree() { ep->set_draw_warning(draw_warning); ep->set_use_folding(use_folding); + ep->set_favoritable(can_favorite && !disable_favorite); ep->set_checkable(checkable); ep->set_checked(checked); ep->set_keying(keying); @@ -3472,7 +3544,12 @@ void EditorInspector::update_tree() { } } - current_vbox->add_child(editors[i].property_editor); + if (ep && ep->is_favoritable() && current_favorites.has(p.name)) { + ep->favorited = true; + favorites_to_add[group][subgroup].push_back(ep); + } else { + current_vbox->add_child(editors[i].property_editor); + } if (ep) { // Eventually, set other properties/signals after the property editor got added to the tree. @@ -3481,6 +3558,7 @@ void EditorInspector::update_tree() { ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed)); ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), CONNECT_DEFERRED); ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value)); + ep->connect("property_favorited", callable_mp(this, &EditorInspector::_set_property_favorited), CONNECT_DEFERRED); ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked)); ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned)); ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected)); @@ -3511,7 +3589,7 @@ void EditorInspector::update_tree() { ep->set_internal(p.usage & PROPERTY_USAGE_INTERNAL); ep->update_property(); - ep->_update_pin_flags(); + ep->_update_flags(); ep->update_editor_property_status(); ep->update_cache(); @@ -3522,6 +3600,77 @@ void EditorInspector::update_tree() { } } + if (!current_favorites.is_empty()) { + favorites_section->show(); + + // Organize the favorited properties in their sections, to keep context and differentiate from others with the same name. + bool is_localized = property_name_style == EditorPropertyNameProcessor::STYLE_LOCALIZED; + for (const KeyValue<String, HashMap<String, LocalVector<EditorProperty *>>> &KV : favorites_to_add) { + String section_name = KV.key; + String label; + String tooltip; + VBoxContainer *parent_vbox = favorites_vbox; + if (!section_name.is_empty()) { + if (is_localized) { + label = EditorPropertyNameProcessor::get_singleton()->translate_group_name(section_name); + tooltip = section_name; + } else { + label = section_name; + tooltip = EditorPropertyNameProcessor::get_singleton()->translate_group_name(section_name); + } + + EditorInspectorSection *section = memnew(EditorInspectorSection); + favorites_groups_vbox->add_child(section); + parent_vbox = section->get_vbox(); + section->setup("", section_name, object, sscolor, false); + section->set_tooltip_text(tooltip); + } + + for (const KeyValue<String, LocalVector<EditorProperty *>> &KV2 : KV.value) { + section_name = KV2.key; + VBoxContainer *vbox = parent_vbox; + if (!section_name.is_empty()) { + if (is_localized) { + label = EditorPropertyNameProcessor::get_singleton()->translate_group_name(section_name); + tooltip = section_name; + } else { + label = section_name; + tooltip = EditorPropertyNameProcessor::get_singleton()->translate_group_name(section_name); + } + + EditorInspectorSection *section = memnew(EditorInspectorSection); + vbox->add_child(section); + vbox = section->get_vbox(); + section->setup("", section_name, object, sscolor, false); + section->set_tooltip_text(tooltip); + } + + for (EditorProperty *ep : KV2.value) { + vbox->add_child(ep); + } + } + } + + // Show a separator if there's no category to clearly divide the properties. + favorites_separator->hide(); + if (main_vbox->get_child_count() > 0) { + EditorInspectorCategory *category = Object::cast_to<EditorInspectorCategory>(main_vbox->get_child(0)); + if (!category) { + favorites_separator->show(); + } + } + + // Clean up empty sections. + for (List<EditorInspectorSection *>::Element *I = sections.back(); I; I = I->prev()) { + EditorInspectorSection *section = I->get(); + if (section->get_vbox()->get_child_count() == 0) { + sections.erase(section); + vbox_per_path[main_vbox].erase(section->get_section()); + memdelete(section); + } + } + } + if (!hide_metadata && !object->call("_hide_metadata_from_inspector")) { // Add 4px of spacing between the "Add Metadata" button and the content above it. Control *spacer = memnew(Control); @@ -3529,7 +3678,7 @@ void EditorInspector::update_tree() { main_vbox->add_child(spacer); Button *add_md = EditorInspector::create_inspector_action_button(TTR("Add Metadata")); - add_md->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_md->set_button_icon(get_editor_theme_icon(SNAME("Add"))); add_md->connect(SceneStringName(pressed), callable_mp(this, &EditorInspector::_show_add_meta_dialog)); main_vbox->add_child(add_md); if (all_read_only) { @@ -3564,6 +3713,19 @@ void EditorInspector::update_property(const String &p_prop) { } void EditorInspector::_clear(bool p_hide_plugins) { + begin_vbox->hide(); + while (begin_vbox->get_child_count()) { + memdelete(begin_vbox->get_child(0)); + } + + favorites_section->hide(); + while (favorites_vbox->get_child_count()) { + memdelete(favorites_vbox->get_child(0)); + } + while (favorites_groups_vbox->get_child_count()) { + memdelete(favorites_groups_vbox->get_child(0)); + } + while (main_vbox->get_child_count()) { memdelete(main_vbox->get_child(0)); } @@ -3610,6 +3772,10 @@ void EditorInspector::edit(Object *p_object) { update_scroll_request = scroll_cache[object->get_instance_id()]; //done this way because wait until full size is accommodated } object->connect(CoreStringName(property_list_changed), callable_mp(this, &EditorInspector::_changed_callback)); + + can_favorite = Object::cast_to<Node>(object) || Object::cast_to<Resource>(object); + _update_current_favorites(); + update_tree(); } @@ -4104,10 +4270,164 @@ void EditorInspector::_node_removed(Node *p_node) { } } +void EditorInspector::_update_current_favorites() { + current_favorites.clear(); + if (!can_favorite) { + return; + } + + HashMap<String, PackedStringArray> favorites = EditorSettings::get_singleton()->get_favorite_properties(); + + // Fetch script properties. + Ref<Script> scr = object->get_script(); + if (scr.is_valid()) { + List<PropertyInfo> plist; + // FIXME: Only properties from a saved script will be available, unsaved ones will be ignored. + // Can cause a little wonkiness, while nothing serious, would be nice to find a way to get + // unsaved ones without needing to get the entire property list of an object. + scr->get_script_property_list(&plist); + + String path; + HashMap<String, LocalVector<String>> props; + + for (PropertyInfo &p : plist) { + if (p.usage & PROPERTY_USAGE_CATEGORY) { + path = favorites.has(p.hint_string) ? p.hint_string : String(); + } else if (p.usage & PROPERTY_USAGE_SCRIPT_VARIABLE && !path.is_empty()) { + props[path].push_back(p.name); + } + } + + // Add favorited properties while removing invalid ones. + bool invalid_props = false; + for (const KeyValue<String, LocalVector<String>> &KV : props) { + path = KV.key; + for (int i = 0; i < favorites[path].size(); i++) { + String prop = favorites[path][i]; + if (KV.value.has(prop)) { + current_favorites.append(prop); + } else { + invalid_props = true; + favorites[path].erase(prop); + i--; + } + } + + if (favorites[path].is_empty()) { + favorites.erase(path); + } + } + + if (invalid_props) { + EditorSettings::get_singleton()->set_favorite_properties(favorites); + } + } + + // Fetch built-in properties. + StringName class_name = object->get_class_name(); + for (const KeyValue<String, PackedStringArray> &KV : favorites) { + if (ClassDB::is_parent_class(class_name, KV.key)) { + current_favorites.append_array(KV.value); + } + } +} + +void EditorInspector::_set_property_favorited(const String &p_path, bool p_favorited) { + if (!object) { + return; + } + + StringName class_name = object->get_class_name(); + while (!class_name.is_empty()) { + bool has_prop = ClassDB::has_property(class_name, p_path, true); + if (has_prop) { + break; + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + + if (class_name.is_empty()) { + Ref<Script> scr = object->get_script(); + if (scr.is_valid()) { + List<PropertyInfo> plist; + scr->get_script_property_list(&plist); + + String path; + for (PropertyInfo &p : plist) { + if (p.usage & PROPERTY_USAGE_CATEGORY) { + path = p.hint_string; + } else if (p.usage & PROPERTY_USAGE_SCRIPT_VARIABLE && p.name == p_path) { + class_name = path; + break; + } + } + } + + ERR_FAIL_COND_MSG(class_name.is_empty(), "Can't favorite invalid property. If said property was from a script and recently renamed, try saving it first."); + } + + HashMap<String, PackedStringArray> favorites = EditorSettings::get_singleton()->get_favorite_properties(); + if (p_favorited) { + current_favorites.append(p_path); + favorites[class_name].append(p_path); + } else { + current_favorites.erase(p_path); + + if (favorites.has(class_name) && favorites[class_name].has(p_path)) { + if (favorites[class_name].size() > 1) { + favorites[class_name].erase(p_path); + } else { + favorites.erase(class_name); + } + } + } + EditorSettings::get_singleton()->set_favorite_properties(favorites); + + update_tree(); +} + +void EditorInspector::_clear_current_favorites() { + current_favorites.clear(); + + HashMap<String, PackedStringArray> favorites = EditorSettings::get_singleton()->get_favorite_properties(); + + Ref<Script> scr = object->get_script(); + if (scr.is_valid()) { + List<PropertyInfo> plist; + scr->get_script_property_list(&plist); + + for (PropertyInfo &p : plist) { + if (p.usage & PROPERTY_USAGE_CATEGORY && favorites.has(p.hint_string)) { + favorites.erase(p.hint_string); + } + } + } + + StringName class_name = object->get_class_name(); + while (class_name) { + if (favorites.has(class_name)) { + favorites.erase(class_name); + } + + class_name = ClassDB::get_parent_class(class_name); + } + + EditorSettings::get_singleton()->set_favorite_properties(favorites); + update_tree(); +} + void EditorInspector::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - main_vbox->add_theme_constant_override("separation", get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"))); + favorites_category->icon = get_editor_theme_icon(SNAME("Favorites")); + + int separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector")); + base_vbox->add_theme_constant_override("separation", separation); + begin_vbox->add_theme_constant_override("separation", separation); + favorites_section->add_theme_constant_override("separation", separation); + favorites_groups_vbox->add_theme_constant_override("separation", separation); + main_vbox->add_theme_constant_override("separation", separation); } break; case NOTIFICATION_READY: { @@ -4205,6 +4525,7 @@ void EditorInspector::_notification(int p_what) { void EditorInspector::_changed_callback() { //this is called when property change is notified via notify_property_list_changed() if (object != nullptr) { + _update_current_favorites(); _edit_request_change(object, String()); } } @@ -4294,6 +4615,14 @@ void EditorInspector::_add_meta_confirm() { undo_redo->commit_action(); } +void EditorInspector::_handle_menu_option(int p_option) { + switch (p_option) { + case MENU_UNFAVORITE_ALL: + _clear_current_favorites(); + break; + } +} + void EditorInspector::_bind_methods() { ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change); ClassDB::bind_method("get_selected_path", &EditorInspector::get_selected_path); @@ -4312,9 +4641,36 @@ void EditorInspector::_bind_methods() { EditorInspector::EditorInspector() { object = nullptr; + + base_vbox = memnew(VBoxContainer); + base_vbox->set_h_size_flags(SIZE_EXPAND_FILL); + add_child(base_vbox); + + begin_vbox = memnew(VBoxContainer); + base_vbox->add_child(begin_vbox); + begin_vbox->hide(); + + favorites_section = memnew(VBoxContainer); + base_vbox->add_child(favorites_section); + favorites_section->hide(); + + favorites_category = memnew(EditorInspectorCategory); + favorites_category->set_as_favorite(this); + favorites_section->add_child(favorites_category); + favorites_category->label = TTR("Favorites"); + + favorites_vbox = memnew(VBoxContainer); + favorites_section->add_child(favorites_vbox); + favorites_groups_vbox = memnew(VBoxContainer); + favorites_section->add_child(favorites_groups_vbox); + + favorites_separator = memnew(HSeparator); + favorites_section->add_child(favorites_separator); + favorites_separator->hide(); + main_vbox = memnew(VBoxContainer); - main_vbox->set_h_size_flags(SIZE_EXPAND_FILL); - add_child(main_vbox); + base_vbox->add_child(main_vbox); + set_horizontal_scroll_mode(SCROLL_MODE_DISABLED); set_follow_focus(true); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 0309213b76..2e4633ccea 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -41,6 +41,7 @@ class Button; class ConfirmationDialog; class EditorInspector; class EditorValidationPanel; +class HSeparator; class LineEdit; class MarginContainer; class OptionButton; @@ -64,6 +65,7 @@ public: MENU_COPY_VALUE, MENU_PASTE_VALUE, MENU_COPY_PROPERTY_PATH, + MENU_FAVORITE_PROPERTY, MENU_PIN_VALUE, MENU_OPEN_DOCUMENTATION, }; @@ -112,6 +114,9 @@ private: bool pin_hidden = false; bool pinned = false; + bool can_favorite = false; + bool favorited = false; + bool use_folding = false; bool draw_top_bg = true; @@ -134,7 +139,7 @@ private: GDVIRTUAL0(_update_property) GDVIRTUAL1(_set_read_only, bool) - void _update_pin_flags(); + void _update_flags(); protected: bool has_borders = false; @@ -218,6 +223,9 @@ public: void set_name_split_ratio(float p_ratio); float get_name_split_ratio() const; + void set_favoritable(bool p_favoritable); + bool is_favoritable() const; + void set_object_and_property(Object *p_object, const StringName &p_property); virtual Control *make_custom_tooltip(const String &p_text) const override; @@ -285,6 +293,7 @@ class EditorInspectorCategory : public Control { String label; String doc_class_name; PopupMenu *menu = nullptr; + bool is_favorite = false; void _handle_menu_option(int p_option); @@ -293,10 +302,10 @@ protected: virtual void gui_input(const Ref<InputEvent> &p_event) override; public: + void set_as_favorite(EditorInspector *p_for_inspector); + virtual Size2 get_minimum_size() const override; virtual Control *make_custom_tooltip(const String &p_text) const override; - - EditorInspectorCategory(); }; class EditorInspectorSection : public Container { @@ -331,6 +340,7 @@ public: virtual Size2 get_minimum_size() const override; void setup(const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable, int p_indent_depth = 0, int p_level = 1); + String get_section() const; VBoxContainer *get_vbox(); void unfold(); void fold(); @@ -480,13 +490,31 @@ public: class EditorInspector : public ScrollContainer { GDCLASS(EditorInspector, ScrollContainer); + friend class EditorInspectorCategory; + enum { MAX_PLUGINS = 1024 }; static Ref<EditorInspectorPlugin> inspector_plugins[MAX_PLUGINS]; static int inspector_plugin_count; + // Right-click context menu options. + enum ClassMenuOption { + MENU_UNFAVORITE_ALL, + }; + + bool can_favorite = false; + PackedStringArray current_favorites; + VBoxContainer *favorites_section = nullptr; + EditorInspectorCategory *favorites_category = nullptr; + VBoxContainer *favorites_vbox = nullptr; + VBoxContainer *favorites_groups_vbox = nullptr; + HSeparator *favorites_separator = nullptr; + EditorInspector *root_inspector = nullptr; + + VBoxContainer *base_vbox = nullptr; + VBoxContainer *begin_vbox = nullptr; VBoxContainer *main_vbox = nullptr; // Map used to cache the instantiated editors. @@ -557,6 +585,10 @@ class EditorInspector : public ScrollContainer { void _property_selected(const String &p_path, int p_focusable); void _object_id_selected(const String &p_path, ObjectID p_id); + void _update_current_favorites(); + void _set_property_favorited(const String &p_path, bool p_favorited); + void _clear_current_favorites(); + void _node_removed(Node *p_node); HashMap<StringName, int> per_array_page; @@ -584,6 +616,8 @@ class EditorInspector : public ScrollContainer { void _add_meta_confirm(); void _show_add_meta_dialog(); + void _handle_menu_option(int p_option); + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index 264c80dcbf..e85258df50 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -43,6 +43,7 @@ #include "editor/gui/editor_quick_open_dialog.h" #include "editor/gui/editor_run_bar.h" #include "editor/gui/editor_scene_tabs.h" +#include "editor/gui/editor_toaster.h" #include "editor/gui/scene_tree_editor.h" #include "editor/inspector_dock.h" #include "editor/plugins/node_3d_editor_plugin.h" @@ -89,6 +90,10 @@ Ref<EditorSettings> EditorInterface::get_editor_settings() const { return EditorSettings::get_singleton(); } +EditorToaster *EditorInterface::get_editor_toaster() const { + return EditorToaster::get_singleton(); +} + EditorUndoRedoManager *EditorInterface::get_editor_undo_redo() const { return EditorUndoRedoManager::get_singleton(); } @@ -280,14 +285,10 @@ void EditorInterface::set_current_feature_profile(const String &p_profile_name) // Editor dialogs. void EditorInterface::popup_node_selector(const Callable &p_callback, const TypedArray<StringName> &p_valid_types, Node *p_current_value) { - // TODO: Should reuse dialog instance instead of creating a fresh one, but need to rework set_valid_types first. - if (node_selector) { - node_selector->disconnect(SNAME("selected"), callable_mp(this, &EditorInterface::_node_selected).bind(p_callback)); - node_selector->disconnect(SNAME("canceled"), callable_mp(this, &EditorInterface::_node_selection_canceled).bind(p_callback)); - get_base_control()->remove_child(node_selector); - node_selector->queue_free(); + if (!node_selector) { + node_selector = memnew(SceneTreeDialog); + get_base_control()->add_child(node_selector); } - node_selector = memnew(SceneTreeDialog); Vector<StringName> valid_types; int length = p_valid_types.size(); @@ -296,27 +297,18 @@ void EditorInterface::popup_node_selector(const Callable &p_callback, const Type valid_types.write[i] = p_valid_types[i]; } node_selector->set_valid_types(valid_types); - - get_base_control()->add_child(node_selector); - node_selector->popup_scenetree_dialog(p_current_value); - const Callable selected_callback = callable_mp(this, &EditorInterface::_node_selected).bind(p_callback); - node_selector->connect(SNAME("selected"), selected_callback, CONNECT_DEFERRED); - - const Callable canceled_callback = callable_mp(this, &EditorInterface::_node_selection_canceled).bind(p_callback); - node_selector->connect(SNAME("canceled"), canceled_callback, CONNECT_DEFERRED); + const Callable callback = callable_mp(this, &EditorInterface::_node_selected); + node_selector->connect(SNAME("selected"), callback.bind(p_callback), CONNECT_DEFERRED); + node_selector->connect(SNAME("canceled"), callback.bind(NodePath(), p_callback), CONNECT_DEFERRED); } void EditorInterface::popup_property_selector(Object *p_object, const Callable &p_callback, const PackedInt32Array &p_type_filter, const String &p_current_value) { - // TODO: Should reuse dialog instance instead of creating a fresh one, but need to rework set_type_filter first. - if (property_selector) { - property_selector->disconnect(SNAME("selected"), callable_mp(this, &EditorInterface::_property_selected).bind(p_callback)); - property_selector->disconnect(SNAME("canceled"), callable_mp(this, &EditorInterface::_property_selection_canceled).bind(p_callback)); - get_base_control()->remove_child(property_selector); - property_selector->queue_free(); + if (!property_selector) { + property_selector = memnew(PropertySelector); + get_base_control()->add_child(property_selector); } - property_selector = memnew(PropertySelector); Vector<Variant::Type> type_filter; int length = p_type_filter.size(); @@ -325,16 +317,24 @@ void EditorInterface::popup_property_selector(Object *p_object, const Callable & type_filter.write[i] = (Variant::Type)p_type_filter[i]; } property_selector->set_type_filter(type_filter); + property_selector->select_property_from_instance(p_object, p_current_value); - get_base_control()->add_child(property_selector); + const Callable callback = callable_mp(this, &EditorInterface::_property_selected); + property_selector->connect(SNAME("selected"), callback.bind(p_callback), CONNECT_DEFERRED); + property_selector->connect(SNAME("canceled"), callback.bind(String(), p_callback), CONNECT_DEFERRED); +} - property_selector->select_property_from_instance(p_object, p_current_value); +void EditorInterface::popup_method_selector(Object *p_object, const Callable &p_callback, const String &p_current_value) { + if (!method_selector) { + method_selector = memnew(PropertySelector); + get_base_control()->add_child(method_selector); + } - const Callable selected_callback = callable_mp(this, &EditorInterface::_property_selected).bind(p_callback); - property_selector->connect(SNAME("selected"), selected_callback, CONNECT_DEFERRED); + method_selector->select_method_from_instance(p_object, p_current_value); - const Callable canceled_callback = callable_mp(this, &EditorInterface::_property_selection_canceled).bind(p_callback); - property_selector->connect(SNAME("canceled"), canceled_callback, CONNECT_DEFERRED); + const Callable callback = callable_mp(this, &EditorInterface::_method_selected); + method_selector->connect(SNAME("selected"), callback.bind(p_callback), CONNECT_DEFERRED); + method_selector->connect(SNAME("canceled"), callback.bind(String(), p_callback), CONNECT_DEFERRED); } void EditorInterface::popup_quick_open(const Callable &p_callback, const TypedArray<StringName> &p_base_types) { @@ -356,20 +356,40 @@ void EditorInterface::popup_quick_open(const Callable &p_callback, const TypedAr } void EditorInterface::_node_selected(const NodePath &p_node_path, const Callable &p_callback) { - const NodePath path = get_edited_scene_root()->get_path().rel_path_to(p_node_path); - _call_dialog_callback(p_callback, path, "node selected"); -} + const Callable callback = callable_mp(this, &EditorInterface::_node_selected); + node_selector->disconnect(SNAME("selected"), callback); + node_selector->disconnect(SNAME("canceled"), callback); -void EditorInterface::_node_selection_canceled(const Callable &p_callback) { - _call_dialog_callback(p_callback, NodePath(), "node selection canceled"); + if (p_node_path.is_empty()) { + _call_dialog_callback(p_callback, NodePath(), "node selection canceled"); + } else { + const NodePath path = get_edited_scene_root()->get_path().rel_path_to(p_node_path); + _call_dialog_callback(p_callback, path, "node selected"); + } } void EditorInterface::_property_selected(const String &p_property_name, const Callable &p_callback) { - _call_dialog_callback(p_callback, NodePath(p_property_name).get_as_property_path(), "property selected"); + const Callable callback = callable_mp(this, &EditorInterface::_property_selected); + property_selector->disconnect(SNAME("selected"), callback); + property_selector->disconnect(SNAME("canceled"), callback); + + if (p_property_name.is_empty()) { + _call_dialog_callback(p_callback, NodePath(p_property_name).get_as_property_path(), "property selection canceled"); + } else { + _call_dialog_callback(p_callback, NodePath(p_property_name).get_as_property_path(), "property selected"); + } } -void EditorInterface::_property_selection_canceled(const Callable &p_callback) { - _call_dialog_callback(p_callback, NodePath(), "property selection canceled"); +void EditorInterface::_method_selected(const String &p_method_name, const Callable &p_callback) { + const Callable callback = callable_mp(this, &EditorInterface::_method_selected); + method_selector->disconnect(SNAME("selected"), callback); + method_selector->disconnect(SNAME("canceled"), callback); + + if (p_method_name.is_empty()) { + _call_dialog_callback(p_callback, p_method_name, "method selection canceled"); + } else { + _call_dialog_callback(p_callback, p_method_name, "method selected"); + } } void EditorInterface::_quick_open(const String &p_file_path, const Callable &p_callback) { @@ -556,6 +576,7 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer); ClassDB::bind_method(D_METHOD("get_selection"), &EditorInterface::get_selection); ClassDB::bind_method(D_METHOD("get_editor_settings"), &EditorInterface::get_editor_settings); + ClassDB::bind_method(D_METHOD("get_editor_toaster"), &EditorInterface::get_editor_toaster); ClassDB::bind_method(D_METHOD("get_editor_undo_redo"), &EditorInterface::get_editor_undo_redo); ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews); @@ -593,6 +614,7 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("popup_node_selector", "callback", "valid_types", "current_value"), &EditorInterface::popup_node_selector, DEFVAL(TypedArray<StringName>()), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("popup_property_selector", "object", "callback", "type_filter", "current_value"), &EditorInterface::popup_property_selector, DEFVAL(PackedInt32Array()), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("popup_method_selector", "object", "callback", "current_value"), &EditorInterface::popup_method_selector, DEFVAL(String())); ClassDB::bind_method(D_METHOD("popup_quick_open", "callback", "base_types"), &EditorInterface::popup_quick_open, DEFVAL(TypedArray<StringName>())); // Editor docks. diff --git a/editor/editor_interface.h b/editor/editor_interface.h index 4877444dac..2ae77331b1 100644 --- a/editor/editor_interface.h +++ b/editor/editor_interface.h @@ -45,6 +45,7 @@ class EditorPlugin; class EditorResourcePreview; class EditorSelection; class EditorSettings; +class EditorToaster; class EditorUndoRedoManager; class FileSystemDock; class Mesh; @@ -66,12 +67,12 @@ class EditorInterface : public Object { // Editor dialogs. PropertySelector *property_selector = nullptr; + PropertySelector *method_selector = nullptr; SceneTreeDialog *node_selector = nullptr; void _node_selected(const NodePath &p_node_paths, const Callable &p_callback); - void _node_selection_canceled(const Callable &p_callback); void _property_selected(const String &p_property_name, const Callable &p_callback); - void _property_selection_canceled(const Callable &p_callback); + void _method_selected(const String &p_property_name, const Callable &p_callback); void _quick_open(const String &p_file_path, const Callable &p_callback); void _call_dialog_callback(const Callable &p_callback, const Variant &p_selected, const String &p_context); @@ -102,6 +103,7 @@ public: EditorResourcePreview *get_resource_previewer() const; EditorSelection *get_selection() const; Ref<EditorSettings> get_editor_settings() const; + EditorToaster *get_editor_toaster() const; EditorUndoRedoManager *get_editor_undo_redo() const; Vector<Ref<Texture2D>> make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size); @@ -139,6 +141,7 @@ public: void popup_node_selector(const Callable &p_callback, const TypedArray<StringName> &p_valid_types = TypedArray<StringName>(), Node *p_current_value = nullptr); // Must use Vector<int> because exposing Vector<Variant::Type> is not supported. void popup_property_selector(Object *p_object, const Callable &p_callback, const PackedInt32Array &p_type_filter = PackedInt32Array(), const String &p_current_value = String()); + void popup_method_selector(Object *p_object, const Callable &p_callback, const String &p_current_value = String()); void popup_quick_open(const Callable &p_callback, const TypedArray<StringName> &p_base_types = TypedArray<StringName>()); // Editor docks. diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index aec374929e..db26a75cb8 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -100,20 +100,20 @@ void EditorLog::_update_theme() { log->add_theme_font_size_override("mono_font_size", font_size); log->end_bulk_theme_override(); - type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_editor_theme_icon(SNAME("Popup"))); - type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_editor_theme_icon(SNAME("StatusError"))); - type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_editor_theme_icon(SNAME("StatusWarning"))); - type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_editor_theme_icon(SNAME("Edit"))); + type_filter_map[MSG_TYPE_STD]->toggle_button->set_button_icon(get_editor_theme_icon(SNAME("Popup"))); + type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_button_icon(get_editor_theme_icon(SNAME("StatusError"))); + type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_button_icon(get_editor_theme_icon(SNAME("StatusWarning"))); + type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); type_filter_map[MSG_TYPE_STD]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); - clear_button->set_icon(get_editor_theme_icon(SNAME("Clear"))); - copy_button->set_icon(get_editor_theme_icon(SNAME("ActionCopy"))); - collapse_button->set_icon(get_editor_theme_icon(SNAME("CombineLines"))); - show_search_button->set_icon(get_editor_theme_icon(SNAME("Search"))); + clear_button->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); + copy_button->set_button_icon(get_editor_theme_icon(SNAME("ActionCopy"))); + collapse_button->set_button_icon(get_editor_theme_icon(SNAME("CombineLines"))); + show_search_button->set_button_icon(get_editor_theme_icon(SNAME("Search"))); search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); theme_cache.error_color = get_theme_color(SNAME("error_color"), EditorStringName(Editor)); @@ -204,7 +204,7 @@ void EditorLog::_clear_request() { log->clear(); messages.clear(); _reset_message_counts(); - tool_button->set_icon(Ref<Texture2D>()); + tool_button->set_button_icon(Ref<Texture2D>()); } void EditorLog::_copy_request() { @@ -359,14 +359,14 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) { Ref<Texture2D> icon = theme_cache.error_icon; log->add_image(icon); log->add_text(" "); - tool_button->set_icon(icon); + tool_button->set_button_icon(icon); } break; case MSG_TYPE_WARNING: { log->push_color(theme_cache.warning_color); Ref<Texture2D> icon = theme_cache.warning_icon; log->add_image(icon); log->add_text(" "); - tool_button->set_icon(icon); + tool_button->set_button_icon(icon); } break; case MSG_TYPE_EDITOR: { // Distinguish editor messages from messages printed by the project diff --git a/editor/editor_main_screen.cpp b/editor/editor_main_screen.cpp index 77bbee5a7f..6da2bce60e 100644 --- a/editor/editor_main_screen.cpp +++ b/editor/editor_main_screen.cpp @@ -66,9 +66,9 @@ void EditorMainScreen::_notification(int p_what) { Ref<Texture2D> icon = p_editor->get_icon(); if (icon.is_valid()) { - tb->set_icon(icon); + tb->set_button_icon(icon); } else if (has_theme_icon(p_editor->get_name(), EditorStringName(EditorIcons))) { - tb->set_icon(get_theme_icon(p_editor->get_name(), EditorStringName(EditorIcons))); + tb->set_button_icon(get_theme_icon(p_editor->get_name(), EditorStringName(EditorIcons))); } } } break; @@ -244,7 +244,7 @@ void EditorMainScreen::add_main_plugin(EditorPlugin *p_editor) { icon = get_editor_theme_icon(p_editor->get_name()); } if (icon.is_valid()) { - tb->set_icon(icon); + tb->set_button_icon(icon); // Make sure the control is updated if the icon is reimported. icon->connect_changed(callable_mp((Control *)tb, &Control::update_minimum_size)); } diff --git a/editor/editor_main_screen.h b/editor/editor_main_screen.h index 153a182bc2..ca78ceaa88 100644 --- a/editor/editor_main_screen.h +++ b/editor/editor_main_screen.h @@ -47,6 +47,7 @@ public: EDITOR_2D = 0, EDITOR_3D, EDITOR_SCRIPT, + EDITOR_GAME, EDITOR_ASSETLIB, }; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index dd6c88ef25..f056a477c4 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -35,6 +35,7 @@ #include "core/input/input.h" #include "core/io/config_file.h" #include "core/io/file_access.h" +#include "core/io/image.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/object/class_db.h" @@ -144,6 +145,7 @@ #include "editor/plugins/editor_plugin.h" #include "editor/plugins/editor_preview_plugins.h" #include "editor/plugins/editor_resource_conversion_plugin.h" +#include "editor/plugins/game_view_plugin.h" #include "editor/plugins/gdextension_export_plugin.h" #include "editor/plugins/material_editor_plugin.h" #include "editor/plugins/mesh_library_editor_plugin.h" @@ -251,8 +253,8 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto // append that to yield "folder/foo.tscn". if (difference > 0) { String parent = full_path.substr(0, difference); - int slash_idx = parent.rfind("/"); - slash_idx = parent.rfind("/", slash_idx - 1); + int slash_idx = parent.rfind_char('/'); + slash_idx = parent.rfind_char('/', slash_idx - 1); parent = (slash_idx >= 0 && parent.length() > 1) ? parent.substr(slash_idx + 1) : parent; r_filenames.write[set_idx] = parent + r_filenames[set_idx]; } @@ -356,6 +358,8 @@ void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) { editor_main_screen->select(EditorMainScreen::EDITOR_3D); } else if (ED_IS_SHORTCUT("editor/editor_script", p_event)) { editor_main_screen->select(EditorMainScreen::EDITOR_SCRIPT); + } else if (ED_IS_SHORTCUT("editor/editor_game", p_event)) { + editor_main_screen->select(EditorMainScreen::EDITOR_GAME); } else if (ED_IS_SHORTCUT("editor/editor_help", p_event)) { emit_signal(SNAME("request_help_search"), ""); } else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && AssetLibraryEditorPlugin::is_available()) { @@ -531,7 +535,7 @@ void EditorNode::_update_theme(bool p_skip_creation) { editor_main_screen->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("Content"), EditorStringName(EditorStyles))); bottom_panel->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles))); - distraction_free->set_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons))); + distraction_free->set_button_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons))); distraction_free->add_theme_style_override(SceneStringName(pressed), theme->get_stylebox(CoreStringName(normal), "FlatMenuButton")); help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons))); @@ -620,7 +624,7 @@ void EditorNode::_notification(int p_what) { // Update the icon itself only when the spinner is visible. if (_should_display_update_spinner()) { - update_spinner->set_icon(theme->get_icon("Progress" + itos(update_spinner_step + 1), EditorStringName(EditorIcons))); + update_spinner->set_button_icon(theme->get_icon("Progress" + itos(update_spinner_step + 1), EditorStringName(EditorIcons))); } } @@ -1450,6 +1454,16 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String file->popup_file_dialog(); } +void EditorNode::ensure_uid_file(const String &p_new_resource_path) { + if (ResourceLoader::exists(p_new_resource_path) && !ResourceLoader::has_custom_uid_support(p_new_resource_path) && !FileAccess::exists(p_new_resource_path + ".uid")) { + Ref<FileAccess> f = FileAccess::open(p_new_resource_path + ".uid", FileAccess::WRITE); + if (f.is_valid()) { + const ResourceUID::ID id = ResourceUID::get_singleton()->create_id(); + f->store_line(ResourceUID::get_singleton()->id_to_text(id)); + } + } +} + void EditorNode::_menu_option(int p_option) { _menu_option_confirm(p_option, false); } @@ -2149,7 +2163,7 @@ void EditorNode::_dialog_action(String p_file) { } if (ml.is_null()) { - ml = Ref<MeshLibrary>(memnew(MeshLibrary)); + ml.instantiate(); } MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, merge_with_existing_library, apply_mesh_instance_transforms); @@ -2169,6 +2183,12 @@ void EditorNode::_dialog_action(String p_file) { case RESOURCE_SAVE_AS: { ERR_FAIL_COND(saving_resource.is_null()); save_resource_in_path(saving_resource, p_file); + + if (current_menu_option == RESOURCE_SAVE_AS) { + // Create .uid file when making new Resource. + ensure_uid_file(p_file); + } + saving_resource = Ref<Resource>(); ObjectID current_id = editor_history.get_current(); Object *current_obj = current_id.is_valid() ? ObjectDB::get_instance(current_id) : nullptr; @@ -3378,6 +3398,8 @@ void EditorNode::unload_editor_addons() { remove_editor_plugin(E.value, false); memdelete(E.value); } + + addon_name_to_plugin.clear(); } void EditorNode::_discard_changes(const String &p_str) { @@ -4672,6 +4694,11 @@ void EditorNode::stop_child_process(OS::ProcessID p_pid) { Ref<Script> EditorNode::get_object_custom_type_base(const Object *p_object) const { ERR_FAIL_NULL_V(p_object, nullptr); + const Node *node = Object::cast_to<const Node>(p_object); + if (node && node->has_meta(SceneStringName(_custom_type_script))) { + return node->get_meta(SceneStringName(_custom_type_script)); + } + Ref<Script> scr = p_object->get_script(); if (scr.is_valid()) { @@ -6569,6 +6596,7 @@ void EditorNode::_feature_profile_changed() { editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_3D, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)); editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_SCRIPT, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT)); + editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_GAME, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_GAME)); if (AssetLibraryEditorPlugin::is_available()) { editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_ASSETLIB, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB)); } @@ -6579,6 +6607,7 @@ void EditorNode::_feature_profile_changed() { editor_dock_manager->set_dock_enabled(history_dock, true); editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_3D, true); editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_SCRIPT, true); + editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_GAME, true); if (AssetLibraryEditorPlugin::is_available()) { editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_ASSETLIB, true); } @@ -7489,7 +7518,7 @@ EditorNode::EditorNode() { update_spinner = memnew(MenuButton); right_menu_hb->add_child(update_spinner); - update_spinner->set_icon(theme->get_icon(SNAME("Progress1"), EditorStringName(EditorIcons))); + update_spinner->set_button_icon(theme->get_icon(SNAME("Progress1"), EditorStringName(EditorIcons))); update_spinner->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option)); PopupMenu *p = update_spinner->get_popup(); p->add_radio_check_item(TTR("Update Continuously"), SETTINGS_UPDATE_CONTINUOUSLY); @@ -7677,24 +7706,28 @@ EditorNode::EditorNode() { disk_changed = memnew(ConfirmationDialog); { - disk_changed->set_title(TTR("Files have been modified on disk")); + disk_changed->set_title(TTR("Files have been modified outside Godot")); VBoxContainer *vbc = memnew(VBoxContainer); disk_changed->add_child(vbc); Label *dl = memnew(Label); - dl->set_text(TTR("The following files are newer on disk.\nWhat action should be taken?")); + dl->set_text(TTR("The following files are newer on disk:")); vbc->add_child(dl); disk_changed_list = memnew(Tree); vbc->add_child(disk_changed_list); disk_changed_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + Label *what_action_label = memnew(Label); + what_action_label->set_text(TTR("What action should be taken?")); + vbc->add_child(what_action_label); + disk_changed->connect(SceneStringName(confirmed), callable_mp(this, &EditorNode::_reload_modified_scenes)); disk_changed->connect(SceneStringName(confirmed), callable_mp(this, &EditorNode::_reload_project_settings)); - disk_changed->set_ok_button_text(TTR("Discard local changes and reload")); + disk_changed->set_ok_button_text(TTR("Reload from disk")); - disk_changed->add_button(TTR("Keep local changes and overwrite"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave"); + disk_changed->add_button(TTR("Ignore external changes"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave"); disk_changed->connect("custom_action", callable_mp(this, &EditorNode::_resave_scenes)); } @@ -7706,6 +7739,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(CanvasItemEditorPlugin)); add_editor_plugin(memnew(Node3DEditorPlugin)); add_editor_plugin(memnew(ScriptEditorPlugin)); + add_editor_plugin(memnew(GameViewPlugin)); EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor(); @@ -7888,12 +7922,14 @@ EditorNode::EditorNode() { ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTR("Open 2D Editor"), KeyModifierMask::CTRL | Key::F1); ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KeyModifierMask::CTRL | Key::F2); ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KeyModifierMask::CTRL | Key::F3); - ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KeyModifierMask::CTRL | Key::F4); + ED_SHORTCUT_AND_COMMAND("editor/editor_game", TTR("Open Game View"), KeyModifierMask::CTRL | Key::F4); + ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KeyModifierMask::CTRL | Key::F5); ED_SHORTCUT_OVERRIDE("editor/editor_2d", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_1); ED_SHORTCUT_OVERRIDE("editor/editor_3d", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_2); ED_SHORTCUT_OVERRIDE("editor/editor_script", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_3); - ED_SHORTCUT_OVERRIDE("editor/editor_assetlib", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_4); + ED_SHORTCUT_OVERRIDE("editor/editor_game", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_4); + ED_SHORTCUT_OVERRIDE("editor/editor_assetlib", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_5); ED_SHORTCUT_AND_COMMAND("editor/editor_next", TTR("Open the next Editor")); ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTR("Open the previous Editor")); diff --git a/editor/editor_node.h b/editor/editor_node.h index 696caf857c..4a283983c8 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -747,6 +747,7 @@ public: void save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path); void save_resource(const Ref<Resource> &p_resource); void save_resource_as(const Ref<Resource> &p_resource, const String &p_at_path = String()); + void ensure_uid_file(const String &p_new_resource_path); void show_about() { _menu_option_confirm(HELP_ABOUT, false); } @@ -789,7 +790,7 @@ public: struct AdditiveNodeEntry { Node *node = nullptr; - NodePath parent = NodePath(); + NodePath parent; Node *owner = nullptr; int index = 0; // Used if the original parent node is lost @@ -932,7 +933,7 @@ public: void dim_editor(bool p_dimming); bool is_editor_dimmed() const; - void edit_current() { _edit_current(); }; + void edit_current() { _edit_current(); } bool has_scenes_in_session(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index c5a35e466c..2b2b32eb22 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -192,7 +192,7 @@ void EditorPropertyMultilineText::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { Ref<Texture2D> df = get_editor_theme_icon(SNAME("DistractionFree")); - open_big_text->set_icon(df); + open_big_text->set_button_icon(df); Ref<Font> font; int font_size; @@ -340,9 +340,9 @@ void EditorPropertyTextEnum::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - edit_button->set_icon(get_editor_theme_icon(SNAME("Edit"))); - accept_button->set_icon(get_editor_theme_icon(SNAME("ImportCheck"))); - cancel_button->set_icon(get_editor_theme_icon(SNAME("ImportFail"))); + edit_button->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + accept_button->set_button_icon(get_editor_theme_icon(SNAME("ImportCheck"))); + cancel_button->set_button_icon(get_editor_theme_icon(SNAME("ImportFail"))); } break; } } @@ -428,7 +428,7 @@ void EditorPropertyLocale::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - locale_edit->set_icon(get_editor_theme_icon(SNAME("Translation"))); + locale_edit->set_button_icon(get_editor_theme_icon(SNAME("Translation"))); } break; } } @@ -462,10 +462,28 @@ void EditorPropertyPath::_set_read_only(bool p_read_only) { } void EditorPropertyPath::_path_selected(const String &p_path) { - emit_changed(get_edited_property(), p_path); + String full_path = p_path; + + if (!global) { + const ResourceUID::ID id = ResourceLoader::get_resource_uid(full_path); + if (id != ResourceUID::INVALID_ID) { + full_path = ResourceUID::get_singleton()->id_to_text(id); + } + } + + emit_changed(get_edited_property(), full_path); update_property(); } +String EditorPropertyPath::_get_path_text() { + String full_path = get_edited_property_value(); + if (full_path.begins_with("uid://")) { + full_path = ResourceUID::uid_to_path(full_path); + } + + return full_path; +} + void EditorPropertyPath::_path_pressed() { if (!dialog) { dialog = memnew(EditorFileDialog); @@ -474,7 +492,7 @@ void EditorPropertyPath::_path_pressed() { add_child(dialog); } - String full_path = get_edited_property_value(); + String full_path = _get_path_text(); dialog->clear_filters(); @@ -502,7 +520,7 @@ void EditorPropertyPath::_path_pressed() { } void EditorPropertyPath::update_property() { - String full_path = get_edited_property_value(); + String full_path = _get_path_text(); path->set_text(full_path); path->set_tooltip_text(full_path); } @@ -522,9 +540,9 @@ void EditorPropertyPath::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (folder) { - path_edit->set_icon(get_editor_theme_icon(SNAME("FolderBrowse"))); + path_edit->set_button_icon(get_editor_theme_icon(SNAME("FolderBrowse"))); } else { - path_edit->set_icon(get_editor_theme_icon(SNAME("FileBrowse"))); + path_edit->set_button_icon(get_editor_theme_icon(SNAME("FileBrowse"))); } } break; } @@ -547,8 +565,7 @@ void EditorPropertyPath::_drop_data_fw(const Point2 &p_point, const Variant &p_d return; } - emit_changed(get_edited_property(), filesPaths[0]); - update_property(); + _path_selected(filesPaths[0]); } bool EditorPropertyPath::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { @@ -1343,12 +1360,12 @@ void EditorPropertyObjectID::update_property() { edit->set_text(type + " ID: " + uitos(id)); edit->set_tooltip_text(type + " ID: " + uitos(id)); edit->set_disabled(false); - edit->set_icon(EditorNode::get_singleton()->get_class_icon(type)); + edit->set_button_icon(EditorNode::get_singleton()->get_class_icon(type)); } else { edit->set_text(TTR("<empty>")); edit->set_tooltip_text(""); edit->set_disabled(true); - edit->set_icon(Ref<Texture2D>()); + edit->set_button_icon(Ref<Texture2D>()); } } @@ -1378,7 +1395,7 @@ void EditorPropertySignal::update_property() { edit->set_text("Signal: " + signal.get_name()); edit->set_disabled(false); - edit->set_icon(get_editor_theme_icon(SNAME("Signals"))); + edit->set_button_icon(get_editor_theme_icon(SNAME("Signals"))); } EditorPropertySignal::EditorPropertySignal() { @@ -1397,7 +1414,7 @@ void EditorPropertyCallable::update_property() { edit->set_text("Callable"); edit->set_disabled(true); - edit->set_icon(get_editor_theme_icon(SNAME("Callable"))); + edit->set_button_icon(get_editor_theme_icon(SNAME("Callable"))); } EditorPropertyCallable::EditorPropertyCallable() { @@ -2024,9 +2041,9 @@ void EditorPropertyQuaternion::_notification(int p_what) { for (int i = 0; i < 3; i++) { euler[i]->add_theme_color_override("label_color", colors[i]); } - edit_button->set_icon(get_editor_theme_icon(SNAME("Edit"))); + edit_button->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); euler_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("property_color"), SNAME("EditorProperty"))); - warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); + warning->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning"))); warning->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } break; } @@ -2638,7 +2655,7 @@ EditorPropertyColor::EditorPropertyColor() { void EditorPropertyNodePath::_set_read_only(bool p_read_only) { assign->set_disabled(p_read_only); menu->set_disabled(p_read_only); -}; +} Variant EditorPropertyNodePath::_get_cache_value(const StringName &p_prop, bool &r_valid) const { if (p_prop == get_edited_property()) { @@ -2648,7 +2665,7 @@ Variant EditorPropertyNodePath::_get_cache_value(const StringName &p_prop, bool return Variant(); } -void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { +void EditorPropertyNodePath::_node_selected(const NodePath &p_path, bool p_absolute) { NodePath path = p_path; Node *base_node = get_base_node(); @@ -2658,7 +2675,7 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { path = get_tree()->get_edited_scene_root()->get_path_to(to_node); } - if (base_node) { // for AnimationTrackKeyEdit + if (p_absolute && base_node) { // for AnimationTrackKeyEdit path = base_node->get_path().rel_path_to(p_path); } @@ -2680,7 +2697,7 @@ void EditorPropertyNodePath::_node_assign() { scene_tree->get_scene_tree()->set_show_enabled_subscene(true); scene_tree->set_valid_types(valid_types); add_child(scene_tree); - scene_tree->connect("selected", callable_mp(this, &EditorPropertyNodePath::_node_selected)); + scene_tree->connect("selected", callable_mp(this, &EditorPropertyNodePath::_node_selected).bind(true)); } Variant val = get_edited_property_value(); @@ -2748,7 +2765,7 @@ void EditorPropertyNodePath::_accept_text() { void EditorPropertyNodePath::_text_submitted(const String &p_text) { NodePath np = p_text; - emit_changed(get_edited_property(), np); + _node_selected(np, false); edit->hide(); assign->show(); menu->show(); @@ -2829,7 +2846,7 @@ void EditorPropertyNodePath::update_property() { assign->set_tooltip_text(p); if (p.is_empty()) { - assign->set_icon(Ref<Texture2D>()); + assign->set_button_icon(Ref<Texture2D>()); assign->set_text(TTR("Assign...")); assign->set_flat(false); return; @@ -2837,7 +2854,7 @@ void EditorPropertyNodePath::update_property() { assign->set_flat(true); if (!base_node || !base_node->has_node(p)) { - assign->set_icon(Ref<Texture2D>()); + assign->set_button_icon(Ref<Texture2D>()); assign->set_text(p); return; } @@ -2846,13 +2863,13 @@ void EditorPropertyNodePath::update_property() { ERR_FAIL_NULL(target_node); if (String(target_node->get_name()).contains("@")) { - assign->set_icon(Ref<Texture2D>()); + assign->set_button_icon(Ref<Texture2D>()); assign->set_text(p); return; } assign->set_text(target_node->get_name()); - assign->set_icon(EditorNode::get_singleton()->get_object_icon(target_node, "Node")); + assign->set_button_icon(EditorNode::get_singleton()->get_object_icon(target_node, "Node")); } void EditorPropertyNodePath::setup(const Vector<StringName> &p_valid_types, bool p_use_path_from_scene_root, bool p_editing_node) { @@ -2865,7 +2882,7 @@ void EditorPropertyNodePath::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); menu->get_popup()->set_item_icon(ACTION_CLEAR, get_editor_theme_icon(SNAME("Clear"))); menu->get_popup()->set_item_icon(ACTION_COPY, get_editor_theme_icon(SNAME("ActionCopy"))); menu->get_popup()->set_item_icon(ACTION_EDIT, get_editor_theme_icon(SNAME("Edit"))); @@ -3221,6 +3238,7 @@ void EditorPropertyResource::setup(Object *p_object, const String &p_path, const } resource_picker->set_base_type(p_base_type); + resource_picker->set_resource_owner(p_object); resource_picker->set_editable(true); resource_picker->set_h_size_flags(SIZE_EXPAND_FILL); add_child(resource_picker); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 004630da3e..ae9c454195 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -142,6 +142,8 @@ class EditorPropertyPath : public EditorProperty { LineEdit *path = nullptr; Button *path_edit = nullptr; + String _get_path_text(); + void _path_selected(const String &p_path); void _path_pressed(); void _path_focus_exited(); @@ -628,7 +630,7 @@ class EditorPropertyNodePath : public EditorProperty { bool editing_node = false; Vector<StringName> valid_types; - void _node_selected(const NodePath &p_path); + void _node_selected(const NodePath &p_path, bool p_absolute = true); void _node_assign(); Node *get_base_node(); void _update_menu(); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index f03eef4d4d..3cc3a0f7c2 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -283,7 +283,7 @@ void EditorPropertyArray::_create_new_property_slot() { HBoxContainer *hbox = memnew(HBoxContainer); Button *reorder_button = memnew(Button); - reorder_button->set_icon(get_editor_theme_icon(SNAME("TripleBar"))); + reorder_button->set_button_icon(get_editor_theme_icon(SNAME("TripleBar"))); reorder_button->set_default_cursor_shape(Control::CURSOR_MOVE); reorder_button->set_disabled(is_read_only()); reorder_button->connect(SceneStringName(gui_input), callable_mp(this, &EditorPropertyArray::_reorder_button_gui_input)); @@ -298,13 +298,13 @@ void EditorPropertyArray::_create_new_property_slot() { if (is_untyped_array) { Button *edit_btn = memnew(Button); - edit_btn->set_icon(get_editor_theme_icon(SNAME("Edit"))); + edit_btn->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); edit_btn->set_disabled(is_read_only()); edit_btn->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyArray::_change_type).bind(edit_btn, idx)); hbox->add_child(edit_btn); } else { Button *remove_btn = memnew(Button); - remove_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); + remove_btn->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); remove_btn->set_disabled(is_read_only()); remove_btn->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyArray::_remove_pressed).bind(idx)); hbox->add_child(remove_btn); @@ -395,7 +395,7 @@ void EditorPropertyArray::update_property() { vbox->add_child(property_vbox); button_add_item = EditorInspector::create_inspector_action_button(TTR("Add Element")); - button_add_item->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add_item->set_button_icon(get_editor_theme_icon(SNAME("Add"))); button_add_item->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyArray::_add_element)); button_add_item->set_disabled(is_read_only()); vbox->add_child(button_add_item); @@ -657,7 +657,7 @@ void EditorPropertyArray::_notification(int p_what) { } if (button_add_item) { - button_add_item->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add_item->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } } break; @@ -740,10 +740,10 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint // The format of p_hint_string is: // subType/subTypeHint:nextSubtype ... etc. if (!p_hint_string.is_empty()) { - int hint_subtype_separator = p_hint_string.find(":"); + int hint_subtype_separator = p_hint_string.find_char(':'); if (hint_subtype_separator >= 0) { String subtype_string = p_hint_string.substr(0, hint_subtype_separator); - int slash_pos = subtype_string.find("/"); + int slash_pos = subtype_string.find_char('/'); if (slash_pos >= 0) { subtype_hint = PropertyHint(subtype_string.substr(slash_pos + 1, subtype_string.size() - slash_pos - 1).to_int()); subtype_string = subtype_string.substr(0, slash_pos); @@ -939,13 +939,13 @@ void EditorPropertyDictionary::_create_new_property_slot(int p_idx) { if (is_untyped_dict) { Button *edit_btn = memnew(Button); - edit_btn->set_icon(get_editor_theme_icon(SNAME("Edit"))); + edit_btn->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); edit_btn->set_disabled(is_read_only()); edit_btn->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyDictionary::_change_type).bind(edit_btn, slots.size())); hbox->add_child(edit_btn); } else if (p_idx >= 0) { Button *remove_btn = memnew(Button); - remove_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); + remove_btn->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); remove_btn->set_disabled(is_read_only()); remove_btn->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyDictionary::_remove_pressed).bind(slots.size())); hbox->add_child(remove_btn); @@ -1006,10 +1006,10 @@ void EditorPropertyDictionary::setup(PropertyHint p_hint, const String &p_hint_s PackedStringArray types = p_hint_string.split(";"); if (types.size() > 0 && !types[0].is_empty()) { String key = types[0]; - int hint_key_subtype_separator = key.find(":"); + int hint_key_subtype_separator = key.find_char(':'); if (hint_key_subtype_separator >= 0) { String key_subtype_string = key.substr(0, hint_key_subtype_separator); - int slash_pos = key_subtype_string.find("/"); + int slash_pos = key_subtype_string.find_char('/'); if (slash_pos >= 0) { key_subtype_hint = PropertyHint(key_subtype_string.substr(slash_pos + 1, key_subtype_string.size() - slash_pos - 1).to_int()); key_subtype_string = key_subtype_string.substr(0, slash_pos); @@ -1025,10 +1025,10 @@ void EditorPropertyDictionary::setup(PropertyHint p_hint, const String &p_hint_s } if (types.size() > 1 && !types[1].is_empty()) { String value = types[1]; - int hint_value_subtype_separator = value.find(":"); + int hint_value_subtype_separator = value.find_char(':'); if (hint_value_subtype_separator >= 0) { String value_subtype_string = value.substr(0, hint_value_subtype_separator); - int slash_pos = value_subtype_string.find("/"); + int slash_pos = value_subtype_string.find_char('/'); if (slash_pos >= 0) { value_subtype_hint = PropertyHint(value_subtype_string.substr(slash_pos + 1, value_subtype_string.size() - slash_pos - 1).to_int()); value_subtype_string = value_subtype_string.substr(0, slash_pos); @@ -1122,7 +1122,7 @@ void EditorPropertyDictionary::update_property() { _create_new_property_slot(EditorPropertyDictionaryObject::NEW_VALUE_INDEX); button_add_item = EditorInspector::create_inspector_action_button(TTR("Add Key/Value Pair")); - button_add_item->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); + button_add_item->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); button_add_item->set_disabled(is_read_only()); button_add_item->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyDictionary::_add_key_value)); add_vbox->add_child(button_add_item); @@ -1173,6 +1173,11 @@ void EditorPropertyDictionary::update_property() { new_prop->set_h_size_flags(SIZE_EXPAND_FILL); new_prop->set_read_only(is_read_only()); slot.set_prop(new_prop); + } else if (slot.index != EditorPropertyDictionaryObject::NEW_KEY_INDEX && slot.index != EditorPropertyDictionaryObject::NEW_VALUE_INDEX) { + Variant key = dict.get_key_at_index(slot.index); + String cs = key.get_construct_string(); + slot.prop->set_label(cs); + slot.prop->set_tooltip_text(cs); } // We need to grab the focus of the property that is being changed, even if the type didn't actually changed. @@ -1200,7 +1205,8 @@ void EditorPropertyDictionary::update_property() { void EditorPropertyDictionary::_remove_pressed(int p_slot_index) { Dictionary dict = object->get_dict().duplicate(); - dict.erase(dict.get_key_at_index(p_slot_index)); + int index = slots[p_slot_index].index; + dict.erase(dict.get_key_at_index(index)); emit_changed(get_edited_property(), dict); } @@ -1227,7 +1233,7 @@ void EditorPropertyDictionary::_notification(int p_what) { } if (button_add_item) { - button_add_item->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add_item->set_button_icon(get_editor_theme_icon(SNAME("Add"))); add_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("DictionaryAddItem"))); } } break; @@ -1424,7 +1430,7 @@ void EditorPropertyLocalizableString::update_property() { hbox->add_child(prop); prop->set_h_size_flags(SIZE_EXPAND_FILL); Button *edit_btn = memnew(Button); - edit_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); + edit_btn->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); hbox->add_child(edit_btn); edit_btn->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyLocalizableString::_remove_item).bind(edit_btn, remove_index)); @@ -1433,7 +1439,7 @@ void EditorPropertyLocalizableString::update_property() { if (page_index == max_page) { button_add_item = EditorInspector::create_inspector_action_button(TTR("Add Translation")); - button_add_item->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add_item->set_button_icon(get_editor_theme_icon(SNAME("Add"))); button_add_item->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyLocalizableString::_add_locale_popup)); property_vbox->add_child(button_add_item); } @@ -1459,7 +1465,7 @@ void EditorPropertyLocalizableString::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { if (button_add_item) { - button_add_item->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add_item->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } } break; } diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index e38ab456cb..ca8854f797 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -198,6 +198,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["gi"] = "GI"; capitalize_string_remaps["gl"] = "GL"; capitalize_string_remaps["glb"] = "GLB"; + capitalize_string_remaps["gles"] = "GLES"; capitalize_string_remaps["gles2"] = "GLES2"; capitalize_string_remaps["gles3"] = "GLES3"; capitalize_string_remaps["gltf"] = "glTF"; @@ -231,6 +232,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["kb"] = "(KB)"; // Unit. capitalize_string_remaps["lcd"] = "LCD"; capitalize_string_remaps["ldr"] = "LDR"; + capitalize_string_remaps["linuxbsd"] = "Linux/*BSD"; capitalize_string_remaps["lod"] = "LOD"; capitalize_string_remaps["lods"] = "LODs"; capitalize_string_remaps["lowpass"] = "Low-pass"; @@ -248,6 +250,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["oidn"] = "OIDN"; capitalize_string_remaps["ok"] = "OK"; capitalize_string_remaps["opengl"] = "OpenGL"; + capitalize_string_remaps["opengl3"] = "OpenGL 3"; capitalize_string_remaps["opentype"] = "OpenType"; capitalize_string_remaps["openxr"] = "OpenXR"; capitalize_string_remaps["osslsigncode"] = "osslsigncode"; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 0f0287718c..4c3fc7f8c2 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -61,11 +61,11 @@ void EditorResourcePicker::_update_resource() { assign_button->set_custom_minimum_size(assign_button_min_size); if (edited_resource == Ref<Resource>()) { - assign_button->set_icon(Ref<Texture2D>()); + assign_button->set_button_icon(Ref<Texture2D>()); assign_button->set_text(TTR("<empty>")); assign_button->set_tooltip_text(""); } else { - assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), SNAME("Object"))); + assign_button->set_button_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), SNAME("Object"))); if (!edited_resource->get_name().is_empty()) { assign_button->set_text(edited_resource->get_name()); @@ -103,7 +103,7 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const } if (p_preview.is_valid()) { - preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(CoreStringName(normal))->get_content_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button"))); + preview_rect->set_offset(SIDE_LEFT, assign_button->get_button_icon()->get_width() + assign_button->get_theme_stylebox(CoreStringName(normal))->get_content_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button"))); // Resource-specific stretching. if (Ref<GradientTexture1D>(edited_resource).is_valid() || Ref<Gradient>(edited_resource).is_valid()) { @@ -224,7 +224,9 @@ void EditorResourcePicker::_update_menu_items() { } if (is_editable()) { - edit_menu->add_icon_item(get_editor_theme_icon(SNAME("Clear")), TTR("Clear"), OBJ_MENU_CLEAR); + if (!_is_custom_type_script()) { + edit_menu->add_icon_item(get_editor_theme_icon(SNAME("Clear")), TTR("Clear"), OBJ_MENU_CLEAR); + } edit_menu->add_icon_item(get_editor_theme_icon(SNAME("Duplicate")), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); // Check whether the resource has subresources. @@ -694,6 +696,16 @@ bool EditorResourcePicker::_is_type_valid(const String &p_type_name, const HashS return false; } +bool EditorResourcePicker::_is_custom_type_script() const { + Ref<Script> resource_as_script = edited_resource; + + if (resource_as_script.is_valid() && resource_owner && resource_owner->has_meta(SceneStringName(_custom_type_script))) { + return true; + } + + return false; +} + Variant EditorResourcePicker::get_drag_data_fw(const Point2 &p_point, Control *p_from) { if (edited_resource.is_valid()) { Dictionary drag_data = EditorNode::get_singleton()->drag_resource(edited_resource, p_from); @@ -819,7 +831,7 @@ void EditorResourcePicker::_notification(int p_what) { edit_menu->add_theme_constant_override("icon_max_width", icon_width); } - edit_button->set_icon(get_theme_icon(SNAME("select_arrow"), SNAME("Tree"))); + edit_button->set_button_icon(get_theme_icon(SNAME("select_arrow"), SNAME("Tree"))); } break; case NOTIFICATION_DRAW: { @@ -953,6 +965,10 @@ bool EditorResourcePicker::is_toggle_pressed() const { return assign_button->is_pressed(); } +void EditorResourcePicker::set_resource_owner(Object *p_object) { + resource_owner = p_object; +} + void EditorResourcePicker::set_editable(bool p_editable) { editable = p_editable; assign_button->set_disabled(!editable && !edited_resource.is_valid()); @@ -1098,7 +1114,10 @@ void EditorScriptPicker::set_create_options(Object *p_menu_node) { return; } - menu_node->add_icon_item(get_editor_theme_icon(SNAME("ScriptCreate")), TTR("New Script..."), OBJ_MENU_NEW_SCRIPT); + if (!(script_owner && script_owner->has_meta(SceneStringName(_custom_type_script)))) { + menu_node->add_icon_item(get_editor_theme_icon(SNAME("ScriptCreate")), TTR("New Script..."), OBJ_MENU_NEW_SCRIPT); + } + if (script_owner) { Ref<Script> scr = script_owner->get_script(); if (scr.is_valid()) { diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h index 0a32dea3ed..8fb774a2cb 100644 --- a/editor/editor_resource_picker.h +++ b/editor/editor_resource_picker.h @@ -81,6 +81,8 @@ class EditorResourcePicker : public HBoxContainer { CONVERT_BASE_ID = 1000, }; + Object *resource_owner = nullptr; + PopupMenu *edit_menu = nullptr; void _update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj); @@ -102,6 +104,7 @@ class EditorResourcePicker : public HBoxContainer { void _ensure_allowed_types() const; bool _is_drop_valid(const Dictionary &p_drag_data) const; bool _is_type_valid(const String &p_type_name, const HashSet<StringName> &p_allowed_types) const; + bool _is_custom_type_script() const; Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; @@ -137,6 +140,8 @@ public: void set_toggle_pressed(bool p_pressed); bool is_toggle_pressed() const; + void set_resource_owner(Object *p_object); + void set_editable(bool p_editable); bool is_editable() const; diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index d5135f4198..caed02ae58 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -223,11 +223,6 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) { args.push_back(p_scene); } - // Pass the debugger stop shortcut to the running instance(s). - String shortcut; - VariantWriter::write_to_string(ED_GET_SHORTCUT("editor/stop_running_project"), shortcut); - OS::get_singleton()->set_environment("__GODOT_EDITOR_STOP_SHORTCUT__", shortcut); - String exec = OS::get_singleton()->get_executable_path(); int instance_count = RunInstancesDialog::get_singleton()->get_instance_count(); for (int i = 0; i < instance_count; i++) { diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index e0e1ef6d19..3e7c8466a2 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -39,7 +39,7 @@ void EditorRunNative::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - remote_debug->set_icon(get_editor_theme_icon(SNAME("PlayRemote"))); + remote_debug->set_button_icon(get_editor_theme_icon(SNAME("PlayRemote"))); } break; case NOTIFICATION_PROCESS: { diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp index 27cbb9810c..d88cc4d5fa 100644 --- a/editor/editor_sectioned_inspector.cpp +++ b/editor/editor_sectioned_inspector.cpp @@ -96,7 +96,7 @@ class SectionedInspectorFilter : public Object { List<PropertyInfo> pinfo; edited->get_property_list(&pinfo); for (PropertyInfo &pi : pinfo) { - int sp = pi.name.find("/"); + int sp = pi.name.find_char('/'); if (pi.name == "resource_path" || pi.name == "resource_name" || pi.name == "resource_local_to_scene" || pi.name.begins_with("script/") || pi.name.begins_with("_global_script")) { //skip resource stuff continue; @@ -255,7 +255,7 @@ void SectionedInspector::update_category_list() { continue; } - int sp = pi.name.find("/"); + int sp = pi.name.find_char('/'); if (sp == -1) { pi.name = "global/" + pi.name; } diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 12a7c3a2ff..b0d1c3e6bb 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -602,6 +602,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "filesystem/file_dialog/thumbnail_size", 64, "32,128,16") // Quick Open dialog + EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "filesystem/quick_open_dialog/max_results", 100, "0,10000,1", PROPERTY_USAGE_DEFAULT) + _initial_set("filesystem/quick_open_dialog/show_search_highlight", true); + _initial_set("filesystem/quick_open_dialog/enable_fuzzy_matching", true); + EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "filesystem/quick_open_dialog/max_fuzzy_misses", 2, "0,10,1", PROPERTY_USAGE_DEFAULT) _initial_set("filesystem/quick_open_dialog/include_addons", false); EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "filesystem/quick_open_dialog/default_display_mode", 0, "Adaptive,Last Used") @@ -711,6 +715,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/script_list/sort_members_outline_alphabetically", false, true); _initial_set("text_editor/script_list/script_temperature_enabled", true); _initial_set("text_editor/script_list/script_temperature_history_size", 15); + _initial_set("text_editor/script_list/highlight_scene_scripts", true); _initial_set("text_editor/script_list/group_help_pages", true); EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/script_list/sort_scripts_by", 0, "Name,Path,None"); EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/script_list/list_script_names_as", 0, "Name,Parent Directory And Name,Full Path"); @@ -1225,7 +1230,7 @@ fail: extra_config->set_value("init_projects", "list", list); } - singleton = Ref<EditorSettings>(memnew(EditorSettings)); + singleton.instantiate(); singleton->set_path(config_file_path, true); singleton->save_changed_setting = true; singleton->_load_defaults(extra_config); @@ -1492,10 +1497,26 @@ void EditorSettings::set_favorites(const Vector<String> &p_favorites) { } } +void EditorSettings::set_favorite_properties(const HashMap<String, PackedStringArray> &p_favorite_properties) { + favorite_properties = p_favorite_properties; + String favorite_properties_file = EditorPaths::get_singleton()->get_project_settings_dir().path_join("favorite_properties"); + + Ref<ConfigFile> cf; + cf.instantiate(); + for (const KeyValue<String, PackedStringArray> &kv : p_favorite_properties) { + cf->set_value(kv.key, "properties", kv.value); + } + cf->save(favorite_properties_file); +} + Vector<String> EditorSettings::get_favorites() const { return favorites; } +HashMap<String, PackedStringArray> EditorSettings::get_favorite_properties() const { + return favorite_properties; +} + void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) { recent_dirs = p_recent_dirs; String recent_dirs_file; @@ -1518,23 +1539,51 @@ Vector<String> EditorSettings::get_recent_dirs() const { void EditorSettings::load_favorites_and_recent_dirs() { String favorites_file; + String favorite_properties_file; String recent_dirs_file; if (Engine::get_singleton()->is_project_manager_hint()) { favorites_file = EditorPaths::get_singleton()->get_config_dir().path_join("favorite_dirs"); + favorite_properties_file = EditorPaths::get_singleton()->get_config_dir().path_join("favorite_properties"); recent_dirs_file = EditorPaths::get_singleton()->get_config_dir().path_join("recent_dirs"); } else { favorites_file = EditorPaths::get_singleton()->get_project_settings_dir().path_join("favorites"); + favorite_properties_file = EditorPaths::get_singleton()->get_project_settings_dir().path_join("favorite_properties"); recent_dirs_file = EditorPaths::get_singleton()->get_project_settings_dir().path_join("recent_dirs"); } + + /// File Favorites + Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::READ); if (f.is_valid()) { String line = f->get_line().strip_edges(); while (!line.is_empty()) { - favorites.push_back(line); + favorites.append(line); line = f->get_line().strip_edges(); } } + /// Inspector Favorites + + Ref<ConfigFile> cf; + cf.instantiate(); + if (cf->load(favorite_properties_file) == OK) { + List<String> secs; + cf->get_sections(&secs); + + for (String &E : secs) { + PackedStringArray properties = PackedStringArray(cf->get_value(E, "properties")); + if (EditorNode::get_editor_data().is_type_recognized(E) || ResourceLoader::exists(E, "Script")) { + for (const String &property : properties) { + if (!favorite_properties[E].has(property)) { + favorite_properties[E].push_back(property); + } + } + } + } + } + + /// Recent Directories + f = FileAccess::open(recent_dirs_file, FileAccess::READ); if (f.is_valid()) { String line = f->get_line().strip_edges(); diff --git a/editor/editor_settings.h b/editor/editor_settings.h index d1ccedfe6c..3c8a4de866 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -102,6 +102,7 @@ private: HashMap<String, List<Ref<InputEvent>>> builtin_action_overrides; Vector<String> favorites; + HashMap<String, PackedStringArray> favorite_properties; Vector<String> recent_dirs; bool save_changed_setting = true; @@ -176,6 +177,8 @@ public: void set_favorites(const Vector<String> &p_favorites); Vector<String> get_favorites() const; + void set_favorite_properties(const HashMap<String, PackedStringArray> &p_favorite_properties); + HashMap<String, PackedStringArray> get_favorite_properties() const; void set_recent_dirs(const Vector<String> &p_recent_dirs); Vector<String> get_recent_dirs() const; void load_favorites_and_recent_dirs(); diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index d07608d852..8989b9cf9b 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -106,8 +106,8 @@ void EditorSettingsDialog::update_navigation_preset() { orbit_mod_key_2 = InputEventKey::create_reference(Key::NONE); pan_mod_key_1 = InputEventKey::create_reference(Key::SHIFT); pan_mod_key_2 = InputEventKey::create_reference(Key::NONE); - zoom_mod_key_1 = InputEventKey::create_reference(Key::SHIFT); - zoom_mod_key_2 = InputEventKey::create_reference(Key::CTRL); + zoom_mod_key_1 = InputEventKey::create_reference(Key::CTRL); + zoom_mod_key_2 = InputEventKey::create_reference(Key::NONE); } else if (nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA) { set_preset = true; set_orbit_mouse_button = Node3DEditorViewport::NAVIGATION_LEFT_MOUSE; @@ -285,7 +285,7 @@ void EditorSettingsDialog::_update_icons() { shortcut_search_box->set_right_icon(shortcuts->get_editor_theme_icon(SNAME("Search"))); shortcut_search_box->set_clear_button_enabled(true); - restart_close_button->set_icon(shortcuts->get_editor_theme_icon(SNAME("Close"))); + restart_close_button->set_button_icon(shortcuts->get_editor_theme_icon(SNAME("Close"))); restart_container->add_theme_style_override(SceneStringName(panel), shortcuts->get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); restart_icon->set_texture(shortcuts->get_editor_theme_icon(SNAME("StatusWarning"))); restart_label->add_theme_color_override(SceneStringName(font_color), shortcuts->get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); diff --git a/editor/editor_translation_parser.cpp b/editor/editor_translation_parser.cpp index 8a77ce4a82..d12bbc1af2 100644 --- a/editor/editor_translation_parser.cpp +++ b/editor/editor_translation_parser.cpp @@ -31,7 +31,6 @@ #include "editor_translation_parser.h" #include "core/error/error_macros.h" -#include "core/io/file_access.h" #include "core/object/script_language.h" #include "core/templates/hash_set.h" @@ -65,6 +64,21 @@ Error EditorTranslationParserPlugin::parse_file(const String &p_path, Vector<Str } } +void EditorTranslationParserPlugin::get_comments(Vector<String> *r_ids_comment, Vector<String> *r_ids_ctx_plural_comment) { + TypedArray<String> ids_comment; + TypedArray<String> ids_ctx_plural_comment; + + if (GDVIRTUAL_CALL(_get_comments, ids_comment, ids_ctx_plural_comment)) { + for (int i = 0; i < ids_comment.size(); i++) { + r_ids_comment->append(ids_comment[i]); + } + + for (int i = 0; i < ids_ctx_plural_comment.size(); i++) { + r_ids_ctx_plural_comment->append(ids_ctx_plural_comment[i]); + } + } +} + void EditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { Vector<String> extensions; if (GDVIRTUAL_CALL(_get_recognized_extensions, extensions)) { @@ -78,6 +92,7 @@ void EditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_ex void EditorTranslationParserPlugin::_bind_methods() { GDVIRTUAL_BIND(_parse_file, "path", "msgids", "msgids_context_plural"); + GDVIRTUAL_BIND(_get_comments, "msgids_comment", "msgids_context_plural_comment"); GDVIRTUAL_BIND(_get_recognized_extensions); } diff --git a/editor/editor_translation_parser.h b/editor/editor_translation_parser.h index 78dc726c52..20c8ed7939 100644 --- a/editor/editor_translation_parser.h +++ b/editor/editor_translation_parser.h @@ -43,10 +43,12 @@ protected: static void _bind_methods(); GDVIRTUAL3(_parse_file, String, TypedArray<String>, TypedArray<Array>) + GDVIRTUAL2(_get_comments, TypedArray<String>, TypedArray<String>) GDVIRTUAL0RC(Vector<String>, _get_recognized_extensions) public: virtual Error parse_file(const String &p_path, Vector<String> *r_ids, Vector<Vector<String>> *r_ids_ctx_plural); + virtual void get_comments(Vector<String> *r_ids_comment, Vector<String> *r_ids_ctx_plural_comment); virtual void get_recognized_extensions(List<String> *r_extensions) const; }; diff --git a/editor/engine_update_label.cpp b/editor/engine_update_label.cpp index facbfc7c6b..0d40181257 100644 --- a/editor/engine_update_label.cpp +++ b/editor/engine_update_label.cpp @@ -240,8 +240,8 @@ EngineUpdateLabel::VersionType EngineUpdateLabel::_get_version_type(const String } String EngineUpdateLabel::_extract_sub_string(const String &p_line) const { - int j = p_line.find("\"") + 1; - return p_line.substr(j, p_line.find("\"", j) - j); + int j = p_line.find_char('"') + 1; + return p_line.substr(j, p_line.find_char('"', j) - j); } void EngineUpdateLabel::_notification(int p_what) { diff --git a/editor/export/codesign.cpp b/editor/export/codesign.cpp index 72d496b04d..cc53068d48 100644 --- a/editor/export/codesign.cpp +++ b/editor/export/codesign.cpp @@ -1381,14 +1381,14 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const r_error_msg = TTR("Invalid entitlements file."); ERR_FAIL_V_MSG(FAILED, "CodeSign: Invalid entitlements file."); } - cet = Ref<CodeSignEntitlementsText>(memnew(CodeSignEntitlementsText(entitlements))); - ceb = Ref<CodeSignEntitlementsBinary>(memnew(CodeSignEntitlementsBinary(entitlements))); + cet.instantiate(entitlements); + ceb.instantiate(entitlements); } print_verbose("CodeSign: Generating requirements..."); Ref<CodeSignRequirements> rq; String team_id = ""; - rq = Ref<CodeSignRequirements>(memnew(CodeSignRequirements())); + rq.instantiate(); // Sign executables. for (int i = 0; i < files_to_sign.size(); i++) { @@ -1487,7 +1487,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const print_verbose("CodeSign: Generating signature..."); Ref<CodeSignSignature> cs; - cs = Ref<CodeSignSignature>(memnew(CodeSignSignature())); + cs.instantiate(); print_verbose("CodeSign: Writing signature superblob..."); // Write signature data to the executable. diff --git a/editor/export/codesign.h b/editor/export/codesign.h index 9a858c49ac..92366da0f6 100644 --- a/editor/export/codesign.h +++ b/editor/export/codesign.h @@ -166,7 +166,7 @@ public: virtual int get_size() const override; - virtual uint32_t get_index_type() const override { return 0x00000002; }; + virtual uint32_t get_index_type() const override { return 0x00000002; } virtual void write_to_file(Ref<FileAccess> p_file) const override; }; @@ -188,7 +188,7 @@ public: virtual int get_size() const override; - virtual uint32_t get_index_type() const override { return 0x00000005; }; + virtual uint32_t get_index_type() const override { return 0x00000005; } virtual void write_to_file(Ref<FileAccess> p_file) const override; }; @@ -210,7 +210,7 @@ public: virtual int get_size() const override; - virtual uint32_t get_index_type() const override { return 0x00000007; }; + virtual uint32_t get_index_type() const override { return 0x00000007; } virtual void write_to_file(Ref<FileAccess> p_file) const override; }; @@ -311,7 +311,7 @@ public: virtual PackedByteArray get_hash_sha256() const override; virtual int get_size() const override; - virtual uint32_t get_index_type() const override { return 0x00000000; }; + virtual uint32_t get_index_type() const override { return 0x00000000; } virtual void write_to_file(Ref<FileAccess> p_file) const override; }; @@ -330,7 +330,7 @@ public: virtual PackedByteArray get_hash_sha256() const override; virtual int get_size() const override; - virtual uint32_t get_index_type() const override { return 0x00010000; }; + virtual uint32_t get_index_type() const override { return 0x00010000; } virtual void write_to_file(Ref<FileAccess> p_file) const override; }; diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp index 6ca83c5e25..cddc8173cb 100644 --- a/editor/export/editor_export.cpp +++ b/editor/export/editor_export.cpp @@ -87,6 +87,8 @@ void EditorExport::_save() { config->set_value(section, "encryption_include_filters", preset->get_enc_in_filter()); config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter()); + config->set_value(section, "seed", preset->get_seed()); + config->set_value(section, "encrypt_pck", preset->get_enc_pck()); config->set_value(section, "encrypt_directory", preset->get_enc_directory()); config->set_value(section, "script_export_mode", preset->get_script_export_mode()); @@ -307,6 +309,9 @@ void EditorExport::load_config() { preset->set_script_export_mode(config->get_value(section, "script_export_mode", EditorExportPreset::MODE_SCRIPT_BINARY_TOKENS_COMPRESSED)); preset->set_patches(config->get_value(section, "patches", Vector<String>())); + if (config->has_section_key(section, "seed")) { + preset->set_seed(config->get_value(section, "seed")); + } if (config->has_section_key(section, "encrypt_pck")) { preset->set_enc_pck(config->get_value(section, "encrypt_pck")); } diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 50fa49dc52..27216c2399 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -59,6 +59,17 @@ static int _get_pad(int p_alignment, int p_n) { return pad; } +template <typename T> +static bool _has_pack_path(const T &p_paths, const String &p_path) { + for (const String &E : p_paths) { + if (E.simplify_path().trim_prefix("res://") == p_path) { + return true; + } + } + + return false; +} + #define PCK_PADDING 16 bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) { @@ -205,26 +216,28 @@ void EditorExportPlatform::_unload_patches() { PackedData::get_singleton()->clear(); } -Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export."); PackData *pd = (PackData *)p_userdata; + String simplified_path = p_path.simplify_path(); + SavedData sd; - sd.path_utf8 = p_path.utf8(); + sd.path_utf8 = simplified_path.trim_prefix("res://").utf8(); sd.ofs = pd->f->get_position(); sd.size = p_data.size(); sd.encrypted = false; for (int i = 0; i < p_enc_in_filters.size(); ++i) { - if (p_path.matchn(p_enc_in_filters[i]) || p_path.replace("res://", "").matchn(p_enc_in_filters[i])) { + if (simplified_path.matchn(p_enc_in_filters[i]) || simplified_path.trim_prefix("res://").matchn(p_enc_in_filters[i])) { sd.encrypted = true; break; } } for (int i = 0; i < p_enc_ex_filters.size(); ++i) { - if (p_path.matchn(p_enc_ex_filters[i]) || p_path.replace("res://", "").matchn(p_enc_ex_filters[i])) { + if (simplified_path.matchn(p_enc_ex_filters[i]) || simplified_path.trim_prefix("res://").matchn(p_enc_ex_filters[i])) { sd.encrypted = false; break; } @@ -234,10 +247,27 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa Ref<FileAccess> ftmp = pd->f; if (sd.encrypted) { + Vector<uint8_t> iv; + if (p_seed != 0) { + uint64_t seed = p_seed; + + const uint8_t *ptr = p_data.ptr(); + int64_t len = p_data.size(); + for (int64_t i = 0; i < len; i++) { + seed = ((seed << 5) + seed) ^ ptr[i]; + } + + RandomPCG rng = RandomPCG(seed, RandomPCG::DEFAULT_INC); + iv.resize(16); + for (int i = 0; i < 16; i++) { + iv.write[i] = rng.rand() % 256; + } + } + fae.instantiate(); ERR_FAIL_COND_V(fae.is_null(), ERR_SKIP); - Error err = fae->open_and_parse(ftmp, p_key, FileAccessEncrypted::MODE_WRITE_AES256, false); + Error err = fae->open_and_parse(ftmp, p_key, FileAccessEncrypted::MODE_WRITE_AES256, false, iv); ERR_FAIL_COND_V(err != OK, ERR_SKIP); ftmp = fae; } @@ -275,15 +305,15 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa return OK; } -Error EditorExportPlatform::_save_pack_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error EditorExportPlatform::_save_pack_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { if (_check_hash(PackedData::get_singleton()->get_file_hash(p_path), p_data)) { return OK; } - return _save_pack_file(p_userdata, p_path, p_data, p_file, p_total, p_enc_in_filters, p_enc_ex_filters, p_key); + return _save_pack_file(p_userdata, p_path, p_data, p_file, p_total, p_enc_in_filters, p_enc_ex_filters, p_key, p_seed); } -Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export."); String path = p_path.replace_first("res://", ""); @@ -315,12 +345,12 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat return OK; } -Error EditorExportPlatform::_save_zip_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error EditorExportPlatform::_save_zip_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { if (_check_hash(PackedData::get_singleton()->get_file_hash(p_path), p_data)) { return OK; } - return _save_zip_file(p_userdata, p_path, p_data, p_file, p_total, p_enc_in_filters, p_enc_ex_filters, p_key); + return _save_zip_file(p_userdata, p_path, p_data, p_file, p_total, p_enc_in_filters, p_enc_ex_filters, p_key, p_seed); } Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const { @@ -919,7 +949,7 @@ Vector<String> EditorExportPlatform::get_forced_export_files() { return files; } -Error EditorExportPlatform::_script_save_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error EditorExportPlatform::_script_save_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { Callable cb = ((ScriptCallbackData *)p_userdata)->file_cb; ERR_FAIL_COND_V(!cb.is_valid(), FAILED); @@ -965,10 +995,10 @@ Error EditorExportPlatform::_export_project_files(const Ref<EditorExportPreset> ScriptCallbackData data; data.file_cb = p_save_func; data.so_cb = p_so_func; - return export_project_files(p_preset, p_debug, _script_save_file, &data, _script_add_shared_object); + return export_project_files(p_preset, p_debug, _script_save_file, nullptr, &data, _script_add_shared_object); } -Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { +Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_save_func, EditorExportRemoveFunction p_remove_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { //figure out paths of files that will be exported HashSet<String> paths; Vector<String> path_remaps; @@ -1030,8 +1060,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<String> enc_in_filters; Vector<String> enc_ex_filters; Vector<uint8_t> key; + uint64_t seed = 0; if (enc_pck) { + seed = p_preset->get_seed(); Vector<String> enc_in_split = p_preset->get_enc_in_filter().split(","); for (int i = 0; i < enc_in_split.size(); i++) { String f = enc_in_split[i].strip_edges(); @@ -1082,6 +1114,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Error err = OK; Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + Vector<String> extra_paths; struct SortByName { bool operator()(const Ref<EditorExportPlugin> &left, const Ref<EditorExportPlugin> &right) const { @@ -1102,10 +1135,12 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } + + extra_paths.push_back(export_plugins[i]->extra_files[j].path); } export_plugins.write[i]->_clear(); @@ -1218,7 +1253,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1227,6 +1262,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & path_remaps.push_back(path); path_remaps.push_back(export_plugins[i]->extra_files[j].path); } + + extra_paths.push_back(export_plugins[i]->extra_files[j].path); } if (export_plugins[i]->skipped) { @@ -1248,7 +1285,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & if (importer_type == "keep") { // Just keep file as-is. Vector<uint8_t> array = FileAccess::get_file_as_bytes(path); - err = p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; @@ -1291,13 +1328,13 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & sarr.resize(cs.size()); memcpy(sarr.ptrw(), cs.ptr(), sarr.size()); - err = p_func(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } // Now actual remapped file: sarr = FileAccess::get_file_as_bytes(export_path); - err = p_func(p_udata, export_path, sarr, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, export_path, sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1327,14 +1364,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & if (remap == "path") { String remapped_path = config->get_value("remap", remap); Vector<uint8_t> array = FileAccess::get_file_as_bytes(remapped_path); - err = p_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); } else if (remap.begins_with("path.")) { String feature = remap.get_slice(".", 1); if (remap_features.has(feature)) { String remapped_path = config->get_value("remap", remap); Vector<uint8_t> array = FileAccess::get_file_as_bytes(remapped_path); - err = p_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); } else { // Remove paths if feature not enabled. config->erase_section_key("remap", remap); @@ -1360,7 +1397,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & sarr.resize(cs.size()); memcpy(sarr.ptrw(), cs.ptr(), sarr.size()); - err = p_func(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; @@ -1381,7 +1418,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } Vector<uint8_t> array = FileAccess::get_file_as_bytes(export_path); - err = p_func(p_udata, export_path, array, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, export_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1445,7 +1482,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & new_file.write[j] = utf8[j]; } - err = p_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1458,8 +1495,16 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<String> forced_export = get_forced_export_files(); for (int i = 0; i < forced_export.size(); i++) { - Vector<uint8_t> array = FileAccess::get_file_as_bytes(forced_export[i]); - err = p_func(p_udata, forced_export[i], array, idx, total, enc_in_filters, enc_ex_filters, key); + Vector<uint8_t> array; + if (GDExtension::get_extension_list_config_file() == forced_export[i]) { + array = _filter_extension_list_config_file(forced_export[i], paths); + if (array.size() == 0) { + continue; + } + } else { + array = FileAccess::get_file_as_bytes(forced_export[i]); + } + err = p_save_func(p_udata, forced_export[i], array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1471,7 +1516,46 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<uint8_t> data = FileAccess::get_file_as_bytes(engine_cfb); DirAccess::remove_file_or_error(engine_cfb); - return p_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key); + err = p_save_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key, seed); + if (err != OK) { + return err; + } + + if (p_remove_func) { + for (const String &E : PackedData::get_singleton()->get_file_paths()) { + String simplified_path = E.simplify_path(); + if (simplified_path == config_file) { + continue; + } + + String pack_path = simplified_path.trim_suffix(".remap"); + + if (!_has_pack_path(paths, pack_path) && !_has_pack_path(extra_paths, pack_path) && !_has_pack_path(path_remaps, pack_path) && !_has_pack_path(forced_export, pack_path)) { + err = p_remove_func(p_udata, E); + if (err != OK) { + return err; + } + } + } + } + + return OK; +} + +Vector<uint8_t> EditorExportPlatform::_filter_extension_list_config_file(const String &p_config_path, const HashSet<String> &p_paths) { + Ref<FileAccess> f = FileAccess::open(p_config_path, FileAccess::READ); + if (f.is_null()) { + ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path '" + String(p_config_path) + "'."); + } + Vector<uint8_t> data; + while (!f->eof_reached()) { + String l = f->get_line().strip_edges(); + if (p_paths.has(l)) { + data.append_array(l.to_utf8_buffer()); + data.append('\n'); + } + } + return data; } Error EditorExportPlatform::_pack_add_shared_object(void *p_userdata, const SharedObject &p_so) { @@ -1483,6 +1567,29 @@ Error EditorExportPlatform::_pack_add_shared_object(void *p_userdata, const Shar return OK; } +Error EditorExportPlatform::_remove_pack_file(void *p_userdata, const String &p_path) { + PackData *pd = (PackData *)p_userdata; + + SavedData sd; + sd.path_utf8 = p_path.utf8(); + sd.ofs = pd->f->get_position(); + sd.size = 0; + sd.removal = true; + + // This padding will likely never be added, as we should already be aligned when removals are added. + int pad = _get_pad(PCK_PADDING, pd->f->get_position()); + for (int i = 0; i < pad; i++) { + pd->f->store_8(0); + } + + sd.md5.resize(16); + sd.md5.fill(0); + + pd->file_ofs.push_back(sd); + + return OK; +} + Error EditorExportPlatform::_zip_add_shared_object(void *p_userdata, const SharedObject &p_so) { ZipData *zip_data = (ZipData *)p_userdata; if (zip_data->so_files) { @@ -1613,7 +1720,7 @@ Dictionary EditorExportPlatform::_save_pack(const Ref<EditorExportPreset> &p_pre Vector<SharedObject> so_files; int64_t embedded_start = 0; int64_t embedded_size = 0; - Error err_code = save_pack(p_preset, p_debug, p_path, &so_files, nullptr, p_embed, &embedded_start, &embedded_size); + Error err_code = save_pack(p_preset, p_debug, p_path, &so_files, nullptr, nullptr, p_embed, &embedded_start, &embedded_size); Dictionary ret; ret["result"] = err_code; @@ -1699,7 +1806,7 @@ Dictionary EditorExportPlatform::_save_zip_patch(const Ref<EditorExportPreset> & return ret; } -Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, EditorExportSaveFunction p_save_func, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { +Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, EditorExportSaveFunction p_save_func, EditorExportRemoveFunction p_remove_func, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { EditorProgress ep("savepack", TTR("Packing"), 102, true); if (p_save_func == nullptr) { @@ -1722,7 +1829,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b pd.f = ftmp; pd.so_files = p_so_files; - Error err = export_project_files(p_preset, p_debug, p_save_func, &pd, _pack_add_shared_object); + Error err = export_project_files(p_preset, p_debug, p_save_func, p_remove_func, &pd, _pack_add_shared_object); // Close temp file. pd.f.unref(); @@ -1808,6 +1915,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b Ref<FileAccess> fhead = f; if (enc_pck && enc_directory) { + uint64_t seed = p_preset->get_seed(); String script_key = _get_script_encryption_key(p_preset); Vector<uint8_t> key; key.resize(32); @@ -1842,7 +1950,27 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b return ERR_CANT_CREATE; } - err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_WRITE_AES256, false); + Vector<uint8_t> iv; + if (seed != 0) { + for (int i = 0; i < pd.file_ofs.size(); i++) { + for (int64_t j = 0; j < pd.file_ofs[i].path_utf8.length(); j++) { + seed = ((seed << 5) + seed) ^ pd.file_ofs[i].path_utf8.get_data()[j]; + } + for (int64_t j = 0; j < pd.file_ofs[i].md5.size(); j++) { + seed = ((seed << 5) + seed) ^ pd.file_ofs[i].md5[j]; + } + seed = ((seed << 5) + seed) ^ pd.file_ofs[i].ofs; + seed = ((seed << 5) + seed) ^ pd.file_ofs[i].size; + } + + RandomPCG rng = RandomPCG(seed, RandomPCG::DEFAULT_INC); + iv.resize(16); + for (int i = 0; i < 16; i++) { + iv.write[i] = rng.rand() % 256; + } + } + + err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_WRITE_AES256, false, iv); if (err != OK) { add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), TTR("Can't open encrypted file to write.")); return ERR_CANT_CREATE; @@ -1868,6 +1996,9 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b if (pd.file_ofs[i].encrypted) { flags |= PACK_FILE_ENCRYPTED; } + if (pd.file_ofs[i].removal) { + flags |= PACK_FILE_REMOVAL; + } fhead->store_32(flags); } @@ -1936,7 +2067,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b } Error EditorExportPlatform::save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { - return save_pack(p_preset, p_debug, p_path, p_so_files, _save_pack_patch_file, p_embed, r_embedded_start, r_embedded_size); + return save_pack(p_preset, p_debug, p_path, p_so_files, _save_pack_patch_file, _remove_pack_file, p_embed, r_embedded_start, r_embedded_size); } Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, EditorExportSaveFunction p_save_func) { @@ -1957,7 +2088,7 @@ Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bo zd.zip = zip; zd.so_files = p_so_files; - Error err = export_project_files(p_preset, p_debug, p_save_func, &zd, _zip_add_shared_object); + Error err = export_project_files(p_preset, p_debug, p_save_func, nullptr, &zd, _zip_add_shared_object); if (err != OK && err != ERR_SKIP) { add_message(EXPORT_MESSAGE_ERROR, TTR("Save ZIP"), TTR("Failed to export project files.")); } diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h index ef3274c5e4..a33bdce72a 100644 --- a/editor/export/editor_export_platform.h +++ b/editor/export/editor_export_platform.h @@ -53,7 +53,8 @@ protected: static void _bind_methods(); public: - typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); + typedef Error (*EditorExportRemoveFunction)(void *p_userdata, const String &p_path); typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so); enum DebugFlags { @@ -82,6 +83,7 @@ private: uint64_t ofs = 0; uint64_t size = 0; bool encrypted = false; + bool removal = false; Vector<uint8_t> md5; CharString path_utf8; @@ -112,12 +114,14 @@ private: static bool _check_hash(const uint8_t *p_hash, const Vector<uint8_t> &p_data); - static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); - static Error _save_pack_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); + static Error _save_pack_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); static Error _pack_add_shared_object(void *p_userdata, const SharedObject &p_so); - static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); - static Error _save_zip_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error _remove_pack_file(void *p_userdata, const String &p_path); + + static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); + static Error _save_zip_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); static Error _zip_add_shared_object(void *p_userdata, const SharedObject &p_so); struct ScriptCallbackData { @@ -125,12 +129,14 @@ private: Callable so_cb; }; - static Error _script_save_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error _script_save_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); static Error _script_add_shared_object(void *p_userdata, const SharedObject &p_so); void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude); void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude); + static Vector<uint8_t> _filter_extension_list_config_file(const String &p_config_path, const HashSet<String> &p_paths); + struct FileExportCache { uint64_t source_modified_time = 0; String source_md5; @@ -287,7 +293,7 @@ public: Array get_current_presets() const; Error _export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, const Callable &p_save_func, const Callable &p_so_func); - Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr); + Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_save_func, EditorExportRemoveFunction p_remove_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr); Dictionary _save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, bool p_embed = false); Dictionary _save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); @@ -295,7 +301,7 @@ public: Dictionary _save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); Dictionary _save_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); - Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, EditorExportSaveFunction p_save_func = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); + Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, EditorExportSaveFunction p_save_func = nullptr, EditorExportRemoveFunction p_remove_func = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, EditorExportSaveFunction p_save_func = nullptr); Error save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); diff --git a/editor/export/editor_export_platform_pc.cpp b/editor/export/editor_export_platform_pc.cpp index 52f7a0cee8..15d684cac5 100644 --- a/editor/export/editor_export_platform_pc.cpp +++ b/editor/export/editor_export_platform_pc.cpp @@ -194,7 +194,7 @@ Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> int64_t embedded_pos; int64_t embedded_size; - Error err = save_pack(p_preset, p_debug, pck_path, &so_files, nullptr, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); + Error err = save_pack(p_preset, p_debug, pck_path, &so_files, nullptr, nullptr, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); if (err == OK && p_preset->get("binary_format/embed_pck")) { if (embedded_size >= 0x100000000 && String(p_preset->get("binary_format/architecture")).contains("32")) { add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB.")); @@ -223,13 +223,13 @@ Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> if (err == OK) { err = da->copy_dir(src_path, target_path, -1, true); if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("GDExtension"), TTR(vformat("Failed to copy shared object \"%s\".", src_path))); + add_message(EXPORT_MESSAGE_ERROR, TTR("GDExtension"), vformat(TTR("Failed to copy shared object \"%s\"."), src_path)); } } } else { err = da->copy(src_path, target_path); if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("GDExtension"), TTR(vformat("Failed to copy shared object \"%s\".", src_path))); + add_message(EXPORT_MESSAGE_ERROR, TTR("GDExtension"), vformat(TTR("Failed to copy shared object \"%s\"."), src_path)); } if (err == OK) { err = sign_shared_object(p_preset, p_debug, target_path); diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp index da7059b777..8ff5dd7551 100644 --- a/editor/export/editor_export_preset.cpp +++ b/editor/export/editor_export_preset.cpp @@ -451,6 +451,15 @@ String EditorExportPreset::get_enc_ex_filter() const { return enc_ex_filters; } +void EditorExportPreset::set_seed(uint64_t p_seed) { + seed = p_seed; + EditorExport::singleton->save_presets(); +} + +uint64_t EditorExportPreset::get_seed() const { + return seed; +} + void EditorExportPreset::set_enc_pck(bool p_enabled) { enc_pck = p_enabled; EditorExport::singleton->save_presets(); diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h index af3a23fc50..4834a483eb 100644 --- a/editor/export/editor_export_preset.h +++ b/editor/export/editor_export_preset.h @@ -92,6 +92,7 @@ private: String enc_ex_filters; bool enc_pck = false; bool enc_directory = false; + uint64_t seed = 0; String script_key; int script_mode = MODE_SCRIPT_BINARY_TOKENS_COMPRESSED; @@ -165,6 +166,9 @@ public: void set_enc_ex_filter(const String &p_filter); String get_enc_ex_filter() const; + void set_seed(uint64_t p_seed); + uint64_t get_seed() const; + void set_enc_pck(bool p_enabled); bool get_enc_pck() const; diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp index 2309319376..a90c16f66e 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -889,7 +889,7 @@ void ExportTemplateManager::_notification(int p_what) { current_missing_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); current_installed_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); - mirror_options_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + mirror_options_button->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index f9137082d7..0fc62416af 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -100,15 +100,15 @@ void ProjectExportDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate"))); - delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove"))); - patch_add_btn->set_icon(get_editor_theme_icon(SNAME("Add"))); + duplicate_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Duplicate"))); + delete_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Remove"))); + patch_add_btn->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } break; case NOTIFICATION_READY: { - duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate"))); - delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove"))); - patch_add_btn->set_icon(get_editor_theme_icon(SNAME("Add"))); + duplicate_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Duplicate"))); + delete_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Remove"))); + patch_add_btn->set_button_icon(get_editor_theme_icon(SNAME("Add"))); connect(SceneStringName(confirmed), callable_mp(this, &ProjectExportDialog::_export_pck_zip)); _update_export_all(); } break; @@ -382,10 +382,16 @@ void ProjectExportDialog::_edit_preset(int p_index) { bool enc_pck_mode = current->get_enc_pck(); enc_pck->set_pressed(enc_pck_mode); + uint64_t seed = current->get_seed(); + if (!updating_seed) { + seed_input->set_text(itos(seed)); + } + enc_directory->set_disabled(!enc_pck_mode); enc_in_filters->set_editable(enc_pck_mode); enc_ex_filters->set_editable(enc_pck_mode); script_key->set_editable(enc_pck_mode); + seed_input->set_editable(enc_pck_mode); bool enc_directory_mode = current->get_enc_directory(); enc_directory->set_pressed(enc_directory_mode); @@ -591,6 +597,21 @@ void ProjectExportDialog::_enc_pck_changed(bool p_pressed) { _update_current_preset(); } +void ProjectExportDialog::_seed_input_changed(const String &p_text) { + if (updating) { + return; + } + + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + current->set_seed(seed_input->get_text().to_int()); + + updating_seed = true; + _update_current_preset(); + updating_seed = false; +} + void ProjectExportDialog::_enc_directory_changed(bool p_pressed) { if (updating) { return; @@ -1185,6 +1206,9 @@ void ProjectExportDialog::_export_pck_zip_selected(const String &p_path) { bool export_debug = fd_option.get(TTR("Export With Debug"), true); bool export_as_patch = fd_option.get(TTR("Export As Patch"), true); + EditorSettings::get_singleton()->set_project_metadata("export_options", "export_debug", export_debug); + EditorSettings::get_singleton()->set_project_metadata("export_options", "export_as_patch", export_as_patch); + if (p_path.ends_with(".zip")) { if (export_as_patch) { platform->export_zip_patch(current, export_debug, p_path); @@ -1284,6 +1308,8 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) { Dictionary fd_option = export_project->get_selected_options(); bool export_debug = fd_option.get(TTR("Export With Debug"), true); + EditorSettings::get_singleton()->set_project_metadata("export_options", "export_debug", export_debug); + Error err = platform->export_project(current, export_debug, current->get_export_path(), 0); result_dialog_log->clear(); if (err != ERR_SKIP) { @@ -1623,6 +1649,10 @@ ProjectExportDialog::ProjectExportDialog() { sec_vb->add_child(script_key_error); sections->add_child(sec_scroll_container); + seed_input = memnew(LineEdit); + seed_input->connect(SceneStringName(text_changed), callable_mp(this, &ProjectExportDialog::_seed_input_changed)); + sec_vb->add_margin_child(TTR("Initialization vector seed"), seed_input); + Label *sec_info = memnew(Label); sec_info->set_text(TTR("Note: Encryption key needs to be stored in the binary,\nyou need to build the export templates from source.")); sec_vb->add_child(sec_info); @@ -1749,9 +1779,9 @@ ProjectExportDialog::ProjectExportDialog() { export_project->connect("file_selected", callable_mp(this, &ProjectExportDialog::_export_project_to_path)); export_project->get_line_edit()->connect(SceneStringName(text_changed), callable_mp(this, &ProjectExportDialog::_validate_export_path)); - export_project->add_option(TTR("Export With Debug"), Vector<String>(), true); - export_pck_zip->add_option(TTR("Export With Debug"), Vector<String>(), true); - export_pck_zip->add_option(TTR("Export As Patch"), Vector<String>(), true); + export_project->add_option(TTR("Export With Debug"), Vector<String>(), EditorSettings::get_singleton()->get_project_metadata("export_options", "export_debug", true)); + export_pck_zip->add_option(TTR("Export With Debug"), Vector<String>(), EditorSettings::get_singleton()->get_project_metadata("export_options", "export_debug", true)); + export_pck_zip->add_option(TTR("Export As Patch"), Vector<String>(), EditorSettings::get_singleton()->get_project_metadata("export_options", "export_as_patch", true)); set_hide_on_ok(false); diff --git a/editor/export/project_export.h b/editor/export/project_export.h index e360596be6..68676bfc84 100644 --- a/editor/export/project_export.h +++ b/editor/export/project_export.h @@ -172,6 +172,7 @@ class ProjectExportDialog : public ConfirmationDialog { CheckButton *enc_directory = nullptr; LineEdit *enc_in_filters = nullptr; LineEdit *enc_ex_filters = nullptr; + LineEdit *seed_input = nullptr; OptionButton *script_mode = nullptr; @@ -192,9 +193,11 @@ class ProjectExportDialog : public ConfirmationDialog { bool updating_script_key = false; bool updating_enc_filters = false; + bool updating_seed = false; void _enc_pck_changed(bool p_pressed); void _enc_directory_changed(bool p_pressed); void _enc_filters_changed(const String &p_text); + void _seed_input_changed(const String &p_text); void _script_encryption_key_changed(const String &p_key); bool _validate_script_encryption_key(const String &p_key); @@ -216,7 +219,7 @@ public: Ref<EditorExportPreset> get_current_preset() const; - bool is_exporting() const { return exporting; }; + bool is_exporting() const { return exporting; } ProjectExportDialog(); ~ProjectExportDialog(); diff --git a/editor/fbx_importer_manager.cpp b/editor/fbx_importer_manager.cpp index 2650b642fa..f612c3bd81 100644 --- a/editor/fbx_importer_manager.cpp +++ b/editor/fbx_importer_manager.cpp @@ -40,7 +40,7 @@ void FBXImporterManager::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - fbx_path_browse->set_icon(get_editor_theme_icon(SNAME("FileBrowse"))); + fbx_path_browse->set_button_icon(get_editor_theme_icon(SNAME("FileBrowse"))); } break; case NOTIFICATION_READY: { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 53982b37b9..c7e12d1f3b 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -137,7 +137,7 @@ bool FileSystemList::edit_selected() { String name = get_item_text(s); line_editor->set_text(name); - line_editor->select(0, name.rfind(".")); + line_editor->select(0, name.rfind_char('.')); popup_edit_commited = false; // Start edit popup processing. popup_editor->popup(); @@ -203,9 +203,7 @@ Ref<Texture2D> FileSystemDock::_get_tree_item_icon(bool p_is_valid, const String } } -bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path) { - bool parent_should_expand = false; - +void FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path) { // Create a tree item for the subdirectory. TreeItem *subdirectory_item = tree->create_item(p_parent); String dname = p_dir->get_name(); @@ -213,6 +211,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory if (dname.is_empty()) { dname = "res://"; + resources_item = subdirectory_item; } // Set custom folder color (if applicable). @@ -258,16 +257,13 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory } else { subdirectory_item->set_collapsed(!uncollapsed_paths.has(lpath)); } - if (!searched_tokens.is_empty() && _matches_all_search_tokens(dname)) { - parent_should_expand = true; - } // Create items for all subdirectories. bool reversed = file_sort == FileSortOption::FILE_SORT_NAME_REVERSE; for (int i = reversed ? p_dir->get_subdir_count() - 1 : 0; reversed ? i >= 0 : i < p_dir->get_subdir_count(); reversed ? i-- : i++) { - parent_should_expand = (_create_tree(subdirectory_item, p_dir->get_subdir(i), uncollapsed_paths, p_select_in_favorites, p_unfold_path) || parent_should_expand); + _create_tree(subdirectory_item, p_dir->get_subdir(i), uncollapsed_paths, p_select_in_favorites, p_unfold_path); } // Create all items for the files in the subdirectory. @@ -283,17 +279,6 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory continue; } - String file_name = p_dir->get_file(i); - if (!searched_tokens.is_empty()) { - if (!_matches_all_search_tokens(file_name)) { - // The searched string is not in the file name, we skip it. - continue; - } else { - // We expand all parents. - parent_should_expand = true; - } - } - FileInfo file_info; file_info.name = p_dir->get_file(i); file_info.type = p_dir->get_file_type(i); @@ -346,24 +331,12 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory subdirectory_item->set_as_cursor(0); } } - - if (!searched_tokens.is_empty()) { - if (parent_should_expand) { - subdirectory_item->set_collapsed(false); - } else if (dname != "res://") { - subdirectory_item->get_parent()->remove_child(subdirectory_item); - memdelete(subdirectory_item); - } - } - - return parent_should_expand; } Vector<String> FileSystemDock::get_uncollapsed_paths() const { Vector<String> uncollapsed_paths; TreeItem *root = tree->get_root(); if (root) { - TreeItem *favorites_item = root->get_first_child(); if (!favorites_item->is_collapsed()) { uncollapsed_paths.push_back(favorites_item->get_metadata(0)); } @@ -400,7 +373,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo TreeItem *root = tree->create_item(); // Handles the favorites. - TreeItem *favorites_item = tree->create_item(root); + favorites_item = tree->create_item(root); favorites_item->set_icon(0, get_editor_theme_icon(SNAME("Favorites"))); favorites_item->set_text(0, TTR("Favorites:")); favorites_item->set_metadata(0, "Favorites"); @@ -453,24 +426,22 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo color = Color(1, 1, 1); } - if (searched_tokens.is_empty() || _matches_all_search_tokens(text)) { - TreeItem *ti = tree->create_item(favorites_item); - ti->set_text(0, text); - ti->set_icon(0, icon); - ti->set_icon_modulate(0, color); - ti->set_tooltip_text(0, favorite); - ti->set_selectable(0, true); - ti->set_metadata(0, favorite); - if (p_select_in_favorites && favorite == current_path) { - ti->select(0); - ti->set_as_cursor(0); - } - if (!favorite.ends_with("/")) { - Array udata; - udata.push_back(tree_update_id); - udata.push_back(ti); - EditorResourcePreview::get_singleton()->queue_resource_preview(favorite, this, "_tree_thumbnail_done", udata); - } + TreeItem *ti = tree->create_item(favorites_item); + ti->set_text(0, text); + ti->set_icon(0, icon); + ti->set_icon_modulate(0, color); + ti->set_tooltip_text(0, favorite); + ti->set_selectable(0, true); + ti->set_metadata(0, favorite); + if (p_select_in_favorites && favorite == current_path) { + ti->select(0); + ti->set_as_cursor(0); + } + if (!favorite.ends_with("/")) { + Array udata; + udata.push_back(tree_update_id); + udata.push_back(ti); + EditorResourcePreview::get_singleton()->queue_resource_preview(favorite, this, "_tree_thumbnail_done", udata); } } @@ -495,7 +466,7 @@ void FileSystemDock::_update_display_mode(bool p_force) { if (p_force || old_display_mode != display_mode) { switch (display_mode) { case DISPLAY_MODE_TREE_ONLY: - button_toggle_display_mode->set_icon(get_editor_theme_icon(SNAME("Panels1"))); + button_toggle_display_mode->set_button_icon(get_editor_theme_icon(SNAME("Panels1"))); tree->show(); tree->set_v_size_flags(SIZE_EXPAND_FILL); toolbar2_hbc->show(); @@ -512,7 +483,7 @@ void FileSystemDock::_update_display_mode(bool p_force) { const int actual_offset = is_vertical ? split_box_offset_v : split_box_offset_h; split_box->set_split_offset(actual_offset); const StringName icon = is_vertical ? SNAME("Panels2") : SNAME("Panels2Alt"); - button_toggle_display_mode->set_icon(get_editor_theme_icon(icon)); + button_toggle_display_mode->set_button_icon(get_editor_theme_icon(icon)); tree->show(); tree->set_v_size_flags(SIZE_EXPAND_FILL); @@ -597,7 +568,7 @@ void FileSystemDock::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { _update_display_mode(true); - button_reload->set_icon(get_editor_theme_icon(SNAME("Reload"))); + button_reload->set_button_icon(get_editor_theme_icon(SNAME("Reload"))); StringName mode_icon = "Panels1"; if (display_mode == DISPLAY_MODE_VSPLIT) { @@ -605,28 +576,28 @@ void FileSystemDock::_notification(int p_what) { } else if (display_mode == DISPLAY_MODE_HSPLIT) { mode_icon = "Panels2Alt"; } - button_toggle_display_mode->set_icon(get_editor_theme_icon(mode_icon)); + button_toggle_display_mode->set_button_icon(get_editor_theme_icon(mode_icon)); if (file_list_display_mode == FILE_LIST_DISPLAY_LIST) { - button_file_list_display_mode->set_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); + button_file_list_display_mode->set_button_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); } else { - button_file_list_display_mode->set_icon(get_editor_theme_icon(SNAME("FileList"))); + button_file_list_display_mode->set_button_icon(get_editor_theme_icon(SNAME("FileList"))); } tree_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - tree_button_sort->set_icon(get_editor_theme_icon(SNAME("Sort"))); + tree_button_sort->set_button_icon(get_editor_theme_icon(SNAME("Sort"))); file_list_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - file_list_button_sort->set_icon(get_editor_theme_icon(SNAME("Sort"))); + file_list_button_sort->set_button_icon(get_editor_theme_icon(SNAME("Sort"))); - button_dock_placement->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + button_dock_placement->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); if (is_layout_rtl()) { - button_hist_next->set_icon(get_editor_theme_icon(SNAME("Back"))); - button_hist_prev->set_icon(get_editor_theme_icon(SNAME("Forward"))); + button_hist_next->set_button_icon(get_editor_theme_icon(SNAME("Back"))); + button_hist_prev->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); } else { - button_hist_next->set_icon(get_editor_theme_icon(SNAME("Forward"))); - button_hist_prev->set_icon(get_editor_theme_icon(SNAME("Back"))); + button_hist_next->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); + button_hist_prev->set_button_icon(get_editor_theme_icon(SNAME("Back"))); } overwrite_dialog_scroll->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), "Tree")); @@ -676,7 +647,6 @@ void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_s return; } - TreeItem *favorites_item = tree->get_root()->get_first_child(); if (selected->get_parent() == favorites_item && !String(selected->get_metadata(0)).ends_with("/")) { // Go to the favorites if we click in the favorites and the path has changed. current_path = "Favorites"; @@ -771,6 +741,36 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa } } +bool FileSystemDock::_update_filtered_items(TreeItem *p_tree_item) { + TreeItem *item = p_tree_item; + if (!item) { + item = tree->get_root(); + } + ERR_FAIL_NULL_V(item, false); + + bool keep_visible = false; + for (TreeItem *child = item->get_first_child(); child; child = child->get_next()) { + keep_visible = _update_filtered_items(child) || keep_visible; + } + + if (searched_tokens.is_empty()) { + item->set_visible(true); + // Always uncollapse root (the hidden item above res:// and favorites). + item->set_collapsed(item != tree->get_root() && !uncollapsed_paths_before_search.has(item->get_metadata(0))); + return true; + } + + if (keep_visible) { + item->set_collapsed(false); + } else { + // res:// and favorites are always visible. + keep_visible = item == resources_item || item == favorites_item; + keep_visible = keep_visible || _matches_all_search_tokens(item->get_text(0)); + } + item->set_visible(keep_visible); + return keep_visible; +} + void FileSystemDock::navigate_to_path(const String &p_path) { file_list_search_box->clear(); _navigate_to_path(p_path); @@ -818,11 +818,11 @@ void FileSystemDock::_toggle_file_display() { void FileSystemDock::_set_file_display(bool p_active) { if (p_active) { file_list_display_mode = FILE_LIST_DISPLAY_LIST; - button_file_list_display_mode->set_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); + button_file_list_display_mode->set_button_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); button_file_list_display_mode->set_tooltip_text(TTR("View items as a grid of thumbnails.")); } else { file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; - button_file_list_display_mode->set_icon(get_editor_theme_icon(SNAME("FileList"))); + button_file_list_display_mode->set_button_icon(get_editor_theme_icon(SNAME("FileList"))); button_file_list_display_mode->set_tooltip_text(TTR("View items as a list.")); } @@ -1446,6 +1446,13 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_ } } + if (p_item.is_file && FileAccess::exists(old_path + ".uid")) { + err = da->rename(old_path + ".uid", new_path + ".uid"); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + ".uid\n"); + } + } + // Update scene if it is open. for (int i = 0; i < file_changed_paths.size(); ++i) { String new_item_path = p_item.is_file ? new_path : file_changed_paths[i].replace_first(old_path, new_path); @@ -1491,76 +1498,22 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.") + "\n" + old_path + "\n"); return; } - Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (p_item.is_file) { print_verbose("Duplicating " + old_path + " -> " + new_path); // Create the directory structure. - da->make_dir_recursive(new_path.get_base_dir()); - - if (FileAccess::exists(old_path + ".import")) { - Error err = da->copy(old_path, new_path); - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ": " + error_names[err] + "\n"); - return; - } - - // Remove uid from .import file to avoid conflict. - Ref<ConfigFile> cfg; - cfg.instantiate(); - cfg->load(old_path + ".import"); - cfg->erase_section_key("remap", "uid"); - err = cfg->save(new_path + ".import"); - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ".import: " + error_names[err] + "\n"); - return; - } - } else { - // Files which do not use an uid can just be copied. - if (ResourceLoader::get_resource_uid(old_path) == ResourceUID::INVALID_ID) { - Error err = da->copy(old_path, new_path); - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ": " + error_names[err] + "\n"); - } - return; - } + EditorFileSystem::get_singleton()->make_dir_recursive(p_new_path.get_base_dir()); - // Load the resource and save it again in the new location (this generates a new UID). - Error err; - Ref<Resource> res = ResourceLoader::load(old_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); - if (err == OK && res.is_valid()) { - err = ResourceSaver::save(res, new_path, ResourceSaver::FLAG_COMPRESS); - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + " " + vformat(TTR("Failed to save resource at %s: %s"), new_path, error_names[err])); - } - } else if (err != OK) { - // When loading files like text files the error is OK but the resource is still null. - // We can ignore such files. - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + " " + vformat(TTR("Failed to load resource at %s: %s"), new_path, error_names[err])); - } + Error err = EditorFileSystem::get_singleton()->copy_file(old_path, new_path); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ": " + error_names[err] + "\n"); } } else { - da->make_dir(new_path); - - // Recursively duplicate all files inside the folder. - Ref<DirAccess> old_dir = DirAccess::open(old_path); - ERR_FAIL_COND(old_dir.is_null()); - - Ref<FileAccess> file_access = FileAccess::create(FileAccess::ACCESS_RESOURCES); - old_dir->set_include_navigational(false); - old_dir->list_dir_begin(); - for (String f = old_dir->_get_next(); !f.is_empty(); f = old_dir->_get_next()) { - if (f.get_extension() == "import") { - continue; - } - if (file_access->file_exists(old_path + f)) { - _try_duplicate_item(FileOrFolder(old_path + f, true), new_path + f); - } else if (da->dir_exists(old_path + f)) { - _try_duplicate_item(FileOrFolder(old_path + f, false), new_path + f); - } + Error err = EditorFileSystem::get_singleton()->copy_directory(old_path, new_path); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating directory:") + "\n" + old_path + "\n"); } - old_dir->list_dir_end(); } } @@ -1695,21 +1648,27 @@ String FileSystemDock::_get_unique_name(const FileOrFolder &p_entry, const Strin return new_path; } -void FileSystemDock::_update_favorites_list_after_move(const HashMap<String, String> &p_files_renames, const HashMap<String, String> &p_folders_renames) const { - Vector<String> favorites_list = EditorSettings::get_singleton()->get_favorites(); - Vector<String> new_favorites; - - for (const String &old_path : favorites_list) { +void FileSystemDock::_update_favorites_after_move(const HashMap<String, String> &p_files_renames, const HashMap<String, String> &p_folders_renames) const { + Vector<String> favorite_files = EditorSettings::get_singleton()->get_favorites(); + Vector<String> new_favorite_files; + for (const String &old_path : favorite_files) { if (p_folders_renames.has(old_path)) { - new_favorites.push_back(p_folders_renames[old_path]); + new_favorite_files.push_back(p_folders_renames[old_path]); } else if (p_files_renames.has(old_path)) { - new_favorites.push_back(p_files_renames[old_path]); + new_favorite_files.push_back(p_files_renames[old_path]); } else { - new_favorites.push_back(old_path); + new_favorite_files.push_back(old_path); } } + EditorSettings::get_singleton()->set_favorites(new_favorite_files); - EditorSettings::get_singleton()->set_favorites(new_favorites); + HashMap<String, PackedStringArray> favorite_properties = EditorSettings::get_singleton()->get_favorite_properties(); + for (const KeyValue<String, String> &KV : p_files_renames) { + if (favorite_properties.has(KV.key)) { + favorite_properties.replace_key(KV.key, KV.value); + } + } + EditorSettings::get_singleton()->set_favorite_properties(favorite_properties); } void FileSystemDock::_make_scene_confirm() { @@ -1852,7 +1811,7 @@ void FileSystemDock::_rename_operation_confirm() { _update_resource_paths_after_move(file_renames, uids); _update_dependencies_after_move(file_renames, file_owners); _update_project_settings_after_move(file_renames, folder_renames); - _update_favorites_list_after_move(file_renames, folder_renames); + _update_favorites_after_move(file_renames, folder_renames); EditorSceneTabs::get_singleton()->set_current_tab(current_tab); @@ -1866,21 +1825,15 @@ void FileSystemDock::_rename_operation_confirm() { } void FileSystemDock::_duplicate_operation_confirm(const String &p_path) { - String base_dir = p_path.trim_suffix("/").get_base_dir(); - Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - if (!da->dir_exists(base_dir)) { - Error err = da->make_dir_recursive(base_dir); - + const String base_dir = p_path.trim_suffix("/").get_base_dir(); + if (!DirAccess::dir_exists_absolute(base_dir)) { + Error err = EditorFileSystem::get_singleton()->make_dir_recursive(base_dir); if (err != OK) { EditorNode::get_singleton()->show_warning(vformat(TTR("Could not create base directory: %s"), error_names[err])); return; } } _try_duplicate_item(to_duplicate, p_path); - - // Rescan everything. - print_verbose("FileSystem: calling rescan."); - _rescan(); } void FileSystemDock::_overwrite_dialog_action(bool p_overwrite) { @@ -2019,7 +1972,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_cop _update_resource_paths_after_move(file_renames, uids); _update_dependencies_after_move(file_renames, file_owners); _update_project_settings_after_move(file_renames, folder_renames); - _update_favorites_list_after_move(file_renames, folder_renames); + _update_favorites_after_move(file_renames, folder_renames); EditorSceneTabs::get_singleton()->set_current_tab(current_tab); @@ -2075,7 +2028,6 @@ Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion, bo // Build a list of selected items with the active one at the first position. Vector<String> selected_strings; - TreeItem *favorites_item = tree->get_root()->get_first_child(); TreeItem *cursor_item = tree->get_selected(); if (cursor_item && (p_include_unselected_cursor || cursor_item->is_selected(0)) && cursor_item != favorites_item) { selected_strings.push_back(cursor_item->get_metadata(0)); @@ -2480,7 +2432,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected if (to_rename.is_file) { String name = to_rename.path.get_file(); - tree->set_editor_selection(0, name.rfind(".")); + tree->set_editor_selection(0, name.rfind_char('.')); } else { String name = to_rename.path.left(-1).get_file(); // Removes the "/" suffix for folders. tree->set_editor_selection(0, name.length()); @@ -2532,9 +2484,6 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected make_dir_dialog->popup_centered(); } break; - case FILE_INFO: { - } break; - case FILE_REIMPORT: { ImportDock::get_singleton()->reimport_resources(p_selected); } break; @@ -2687,16 +2636,12 @@ void FileSystemDock::_search_changed(const String &p_text, const Control *p_from tree_search_box->set_text(searched_string); } - bool unfold_path = (p_text.is_empty() && !current_path.is_empty()); - switch (display_mode) { - case DISPLAY_MODE_TREE_ONLY: { - _update_tree(searched_tokens.is_empty() ? uncollapsed_paths_before_search : Vector<String>(), false, false, unfold_path); - } break; - case DISPLAY_MODE_HSPLIT: - case DISPLAY_MODE_VSPLIT: { - _update_file_list(false); - _update_tree(searched_tokens.is_empty() ? uncollapsed_paths_before_search : Vector<String>(), false, false, unfold_path); - } break; + _update_filtered_items(); + if (display_mode == DISPLAY_MODE_HSPLIT || display_mode == DISPLAY_MODE_VSPLIT) { + _update_file_list(false); + } + if (searched_tokens.is_empty()) { + _navigate_to_path(current_path); } } @@ -2776,7 +2721,7 @@ void FileSystemDock::focus_on_filter() { } void FileSystemDock::create_directory(const String &p_path, const String &p_base_dir) { - Error err = EditorFileSystem::get_singleton()->make_dir_recursive(p_path, p_base_dir); + Error err = EditorFileSystem::get_singleton()->make_dir_recursive(p_path.trim_prefix(p_base_dir), p_base_dir); if (err != OK) { EditorNode::get_singleton()->show_warning(vformat(TTR("Could not create folder: %s"), error_names[err])); } @@ -2836,7 +2781,6 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) // Check if the first selected is in favorite. TreeItem *selected = tree->get_next_selected(tree->get_root()); while (selected) { - TreeItem *favorites_item = tree->get_root()->get_first_child(); if (selected == favorites_item) { // The "Favorites" item is not draggable. return Variant(); @@ -2888,10 +2832,6 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da } int drop_section = tree->get_drop_section_at_position(p_point); - TreeItem *favorites_item = tree->get_root()->get_first_child(); - - TreeItem *resources_item = favorites_item->get_next(); - if (ti == favorites_item) { return (drop_section == 1); // The parent, first fav. } @@ -2972,9 +2912,6 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, int drop_position; Vector<String> drag_files = drag_data["files"]; - TreeItem *favorites_item = tree->get_root()->get_first_child(); - TreeItem *resources_item = favorites_item->get_next(); - if (ti == favorites_item) { // Drop on the favorite folder. drop_position = 0; @@ -3402,7 +3339,6 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect [[maybe_unused]] bool added_separator = false; if (favorites_list.has(fpath)) { - TreeItem *favorites_item = tree->get_root()->get_first_child(); TreeItem *cursor_item = tree->get_selected(); bool is_item_in_favorites = false; while (cursor_item != nullptr) { @@ -3431,7 +3367,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect const bool is_directory = fpath.ends_with("/"); p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_OPEN_IN_TERMINAL); - p_popup->set_item_text(p_popup->get_item_index(FILE_OPEN_IN_TERMINAL), is_directory ? TTR("Open in Terminal") : TTR("Open Containing Folder in Terminal")); + p_popup->set_item_text(p_popup->get_item_index(FILE_OPEN_IN_TERMINAL), is_directory ? TTR("Open in Terminal") : TTR("Open Folder in Terminal")); if (!is_directory) { p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("ExternalLink")), ED_GET_SHORTCUT("filesystem_dock/open_in_external_program"), FILE_OPEN_EXTERNAL); @@ -3722,10 +3658,10 @@ void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) { tree_item->select(0); } else { // Find parent folder. - fpath = fpath.substr(0, fpath.rfind("/") + 1); + fpath = fpath.substr(0, fpath.rfind_char('/') + 1); if (fpath.size() > String("res://").size()) { fpath = fpath.left(fpath.size() - 2); // Remove last '/'. - const int slash_idx = fpath.rfind("/"); + const int slash_idx = fpath.rfind_char('/'); fpath = fpath.substr(slash_idx + 1, fpath.size() - slash_idx - 1); } @@ -4060,17 +3996,17 @@ FileSystemDock::FileSystemDock() { // `KeyModifierMask::CMD_OR_CTRL | Key::C` conflicts with other editor shortcuts. ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::C); - ED_SHORTCUT("filesystem_dock/copy_absolute_path", TTR("Copy Absolute Path")); - ED_SHORTCUT("filesystem_dock/copy_uid", TTR("Copy UID")); + ED_SHORTCUT("filesystem_dock/copy_absolute_path", TTR("Copy Absolute Path"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::C); + ED_SHORTCUT("filesystem_dock/copy_uid", TTR("Copy UID"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | KeyModifierMask::SHIFT | Key::C); ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KeyModifierMask::CMD_OR_CTRL | Key::D); ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), Key::KEY_DELETE); ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), Key::F2); ED_SHORTCUT_OVERRIDE("filesystem_dock/rename", "macos", Key::ENTER); #if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) // Opening the system file manager or opening in an external program is not supported on the Android and web editors. - ED_SHORTCUT("filesystem_dock/show_in_explorer", TTR("Open in File Manager")); - ED_SHORTCUT("filesystem_dock/open_in_external_program", TTR("Open in External Program")); - ED_SHORTCUT("filesystem_dock/open_in_terminal", TTR("Open in Terminal")); + ED_SHORTCUT("filesystem_dock/show_in_explorer", TTR("Open in File Manager"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::R); + ED_SHORTCUT("filesystem_dock/open_in_external_program", TTR("Open in External Program"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::E); + ED_SHORTCUT("filesystem_dock/open_in_terminal", TTR("Open in Terminal"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::T); #endif // Properly translating color names would require a separate HashMap, so for simplicity they are provided as comments. diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 819abbd389..d2e403a8af 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -116,7 +116,6 @@ private: FILE_REMOVE, FILE_DUPLICATE, FILE_REIMPORT, - FILE_INFO, FILE_NEW, FILE_SHOW_IN_EXPLORER, FILE_OPEN_EXTERNAL, @@ -233,6 +232,8 @@ private: FileSystemTree *tree = nullptr; FileSystemList *files = nullptr; bool import_dock_needs_update = false; + TreeItem *resources_item = nullptr; + TreeItem *favorites_item = nullptr; bool holding_branch = false; Vector<TreeItem *> tree_items_selected_on_drag_begin; @@ -246,9 +247,10 @@ private: void _reselect_items_selected_on_drag_begin(bool reset = false); Ref<Texture2D> _get_tree_item_icon(bool p_is_valid, const String &p_file_type, const String &p_icon_path); - bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path = false); + void _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path = false); void _update_tree(const Vector<String> &p_uncollapsed_paths = Vector<String>(), bool p_uncollapse_root = false, bool p_select_in_favorites = false, bool p_unfold_path = false); void _navigate_to_path(const String &p_path, bool p_select_in_favorites = false); + bool _update_filtered_items(TreeItem *p_tree_item = nullptr); void _file_list_gui_input(Ref<InputEvent> p_event); void _tree_gui_input(Ref<InputEvent> p_event); @@ -276,7 +278,7 @@ private: void _before_move(HashMap<String, ResourceUID::ID> &r_uids, HashSet<String> &r_file_owners) const; void _update_dependencies_after_move(const HashMap<String, String> &p_renames, const HashSet<String> &p_file_owners) const; void _update_resource_paths_after_move(const HashMap<String, String> &p_renames, const HashMap<String, ResourceUID::ID> &p_uids) const; - void _update_favorites_list_after_move(const HashMap<String, String> &p_files_renames, const HashMap<String, String> &p_folders_renames) const; + void _update_favorites_after_move(const HashMap<String, String> &p_files_renames, const HashMap<String, String> &p_folders_renames) const; void _update_project_settings_after_move(const HashMap<String, String> &p_renames, const HashMap<String, String> &p_folders_renames); String _get_unique_name(const FileOrFolder &p_entry, const String &p_at_path); @@ -402,7 +404,7 @@ public: FileSortOption get_file_sort() const { return file_sort; } void set_file_list_display_mode(FileListDisplayMode p_mode); - FileListDisplayMode get_file_list_display_mode() const { return file_list_display_mode; }; + FileListDisplayMode get_file_list_display_mode() const { return file_list_display_mode; } Tree *get_tree_control() { return tree; } diff --git a/editor/group_settings_editor.cpp b/editor/group_settings_editor.cpp index bb899af582..93d5ee0716 100644 --- a/editor/group_settings_editor.cpp +++ b/editor/group_settings_editor.cpp @@ -45,7 +45,7 @@ void GroupSettingsEditor::_notification(int p_what) { update_groups(); } break; case NOTIFICATION_THEME_CHANGED: { - add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } break; } } diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index e0de6bbcb1..bd0805bd7e 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -373,7 +373,7 @@ void GroupsEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { filter->set_right_icon(get_editor_theme_icon("Search")); - add->set_icon(get_editor_theme_icon("Add")); + add->set_button_icon(get_editor_theme_icon("Add")); _update_tree(); } break; case NOTIFICATION_VISIBILITY_CHANGED: { diff --git a/editor/gui/editor_bottom_panel.cpp b/editor/gui/editor_bottom_panel.cpp index f6ba74fe95..3cc1e37be0 100644 --- a/editor/gui/editor_bottom_panel.cpp +++ b/editor/gui/editor_bottom_panel.cpp @@ -31,35 +31,35 @@ #include "editor_bottom_panel.h" #include "editor/debugger/editor_debugger_node.h" -#include "editor/editor_about.h" #include "editor/editor_command_palette.h" #include "editor/editor_node.h" #include "editor/editor_string_names.h" -#include "editor/engine_update_label.h" #include "editor/gui/editor_toaster.h" #include "editor/gui/editor_version_button.h" #include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" +#include "scene/gui/split_container.h" void EditorBottomPanel::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - expand_button->set_icon(get_editor_theme_icon(SNAME("ExpandBottomDock"))); + pin_button->set_button_icon(get_editor_theme_icon(SNAME("Pin"))); + expand_button->set_button_icon(get_editor_theme_icon(SNAME("ExpandBottomDock"))); } break; } } -void EditorBottomPanel::_switch_by_control(bool p_visible, Control *p_control) { +void EditorBottomPanel::_switch_by_control(bool p_visible, Control *p_control, bool p_ignore_lock) { for (int i = 0; i < items.size(); i++) { if (items[i].control == p_control) { - _switch_to_item(p_visible, i); + _switch_to_item(p_visible, i, p_ignore_lock); return; } } } -void EditorBottomPanel::_switch_to_item(bool p_visible, int p_idx) { +void EditorBottomPanel::_switch_to_item(bool p_visible, int p_idx, bool p_ignore_lock) { ERR_FAIL_INDEX(p_idx, items.size()); if (items[p_idx].control->is_visible() == p_visible) { @@ -70,6 +70,10 @@ void EditorBottomPanel::_switch_to_item(bool p_visible, int p_idx) { ERR_FAIL_NULL(center_split); if (p_visible) { + if (!p_ignore_lock && lock_panel_switching && pin_button->is_visible()) { + return; + } + for (int i = 0; i < items.size(); i++) { items[i].button->set_pressed_no_signal(i == p_idx); items[i].control->set_visible(i == p_idx); @@ -80,18 +84,23 @@ void EditorBottomPanel::_switch_to_item(bool p_visible, int p_idx) { } else { add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles))); } + center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); center_split->set_collapsed(false); + pin_button->show(); + + expand_button->show(); if (expand_button->is_pressed()) { EditorNode::get_top_split()->hide(); } - expand_button->show(); } else { add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles))); items[p_idx].button->set_pressed_no_signal(false); items[p_idx].control->set_visible(false); center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); center_split->set_collapsed(true); + pin_button->hide(); + expand_button->hide(); if (expand_button->is_pressed()) { EditorNode::get_top_split()->show(); @@ -101,13 +110,17 @@ void EditorBottomPanel::_switch_to_item(bool p_visible, int p_idx) { last_opened_control = items[p_idx].control; } +void EditorBottomPanel::_pin_button_toggled(bool p_pressed) { + lock_panel_switching = p_pressed; +} + void EditorBottomPanel::_expand_button_toggled(bool p_pressed) { EditorNode::get_top_split()->set_visible(!p_pressed); } bool EditorBottomPanel::_button_drag_hover(const Vector2 &, const Variant &, Button *p_button, Control *p_control) { if (!p_button->is_pressed()) { - _switch_by_control(true, p_control); + _switch_by_control(true, p_control, true); } return false; } @@ -149,7 +162,7 @@ void EditorBottomPanel::load_layout_from_config(Ref<ConfigFile> p_config_file, c Button *EditorBottomPanel::add_item(String p_text, Control *p_item, const Ref<Shortcut> &p_shortcut, bool p_at_front) { Button *tb = memnew(Button); tb->set_theme_type_variation("BottomPanelButton"); - tb->connect(SceneStringName(toggled), callable_mp(this, &EditorBottomPanel::_switch_by_control).bind(p_item)); + tb->connect(SceneStringName(toggled), callable_mp(this, &EditorBottomPanel::_switch_by_control).bind(p_item, true)); tb->set_drag_forwarding(Callable(), callable_mp(this, &EditorBottomPanel::_button_drag_hover).bind(tb, p_item), Callable()); tb->set_text(p_text); tb->set_shortcut(p_shortcut); @@ -231,10 +244,10 @@ void EditorBottomPanel::toggle_last_opened_bottom_panel() { // Select by control instead of index, so that the last bottom panel is opened correctly // if it's been reordered since. if (last_opened_control) { - _switch_by_control(!last_opened_control->is_visible(), last_opened_control); + _switch_by_control(!last_opened_control->is_visible(), last_opened_control, true); } else { // Open the first panel in the list if no panel was opened this session. - _switch_to_item(true, 0); + _switch_to_item(true, 0, true); } } @@ -263,10 +276,17 @@ EditorBottomPanel::EditorBottomPanel() { Control *h_spacer = memnew(Control); bottom_hbox->add_child(h_spacer); + pin_button = memnew(Button); + bottom_hbox->add_child(pin_button); + pin_button->hide(); + pin_button->set_theme_type_variation("FlatMenuButton"); + pin_button->set_toggle_mode(true); + pin_button->set_tooltip_text(TTR("Pin Bottom Panel Switching")); + pin_button->connect(SceneStringName(toggled), callable_mp(this, &EditorBottomPanel::_pin_button_toggled)); + expand_button = memnew(Button); bottom_hbox->add_child(expand_button); expand_button->hide(); - expand_button->set_flat(false); expand_button->set_theme_type_variation("FlatMenuButton"); expand_button->set_toggle_mode(true); expand_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KeyModifierMask::SHIFT | Key::F12)); diff --git a/editor/gui/editor_bottom_panel.h b/editor/gui/editor_bottom_panel.h index 3d44b3750a..950f0e2570 100644 --- a/editor/gui/editor_bottom_panel.h +++ b/editor/gui/editor_bottom_panel.h @@ -49,16 +49,19 @@ class EditorBottomPanel : public PanelContainer { }; Vector<BottomPanelItem> items; + bool lock_panel_switching = false; VBoxContainer *item_vbox = nullptr; HBoxContainer *bottom_hbox = nullptr; HBoxContainer *button_hbox = nullptr; EditorToaster *editor_toaster = nullptr; + Button *pin_button = nullptr; Button *expand_button = nullptr; Control *last_opened_control = nullptr; - void _switch_by_control(bool p_visible, Control *p_control); - void _switch_to_item(bool p_visible, int p_idx); + void _switch_by_control(bool p_visible, Control *p_control, bool p_ignore_lock = false); + void _switch_to_item(bool p_visible, int p_idx, bool p_ignore_lock = false); + void _pin_button_toggled(bool p_pressed); void _expand_button_toggled(bool p_pressed); bool _button_drag_hover(const Vector2 &, const Variant &, Button *p_button, Control *p_control); diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp index 91b7810f77..0381609804 100644 --- a/editor/gui/editor_file_dialog.cpp +++ b/editor/gui/editor_file_dialog.cpp @@ -65,7 +65,7 @@ void EditorFileDialog::_native_popup() { } else if (access == ACCESS_USERDATA) { root = OS::get_singleton()->get_user_data_dir(); } - DisplayServer::get_singleton()->file_dialog_with_options_show(get_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), filters, _get_options(), callable_mp(this, &EditorFileDialog::_native_dialog_cb)); + DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &EditorFileDialog::_native_dialog_cb)); } void EditorFileDialog::popup(const Rect2i &p_rect) { @@ -156,7 +156,7 @@ void EditorFileDialog::popup_file_dialog() { } void EditorFileDialog::_focus_file_text() { - int lp = file->get_text().rfind("."); + int lp = file->get_text().rfind_char('.'); if (lp != -1) { file->select(0, lp); file->grab_focus(); @@ -350,7 +350,7 @@ void EditorFileDialog::shortcut_input(const Ref<InputEvent> &p_event) { void EditorFileDialog::set_enable_multiple_selection(bool p_enable) { item_list->set_select_mode(p_enable ? ItemList::SELECT_MULTI : ItemList::SELECT_SINGLE); -}; +} Vector<String> EditorFileDialog::get_selected_files() const { Vector<String> list; @@ -360,7 +360,7 @@ Vector<String> EditorFileDialog::get_selected_files() const { } } return list; -}; +} void EditorFileDialog::update_dir() { if (drives->is_visible()) { @@ -1148,37 +1148,54 @@ void EditorFileDialog::_filter_selected(int) { void EditorFileDialog::update_filters() { filter->clear(); + processed_filters.clear(); if (filters.size() > 1) { String all_filters; + String all_filters_full; const int max_filters = 5; for (int i = 0; i < MIN(max_filters, filters.size()); i++) { - String flt = filters[i].get_slice(";", 0).strip_edges(); + String flt = filters[i].get_slicec(';', 0).strip_edges(); if (i > 0) { all_filters += ", "; } all_filters += flt; } + for (int i = 0; i < filters.size(); i++) { + String flt = filters[i].get_slicec(';', 0).strip_edges(); + if (i > 0) { + all_filters_full += ","; + } + all_filters_full += flt; + } if (max_filters < filters.size()) { all_filters += ", ..."; } - filter->add_item(TTR("All Recognized") + " (" + all_filters + ")"); + String f = TTR("All Recognized") + " (" + all_filters + ")"; + filter->add_item(f); + processed_filters.push_back(all_filters_full + ";" + f); } for (int i = 0; i < filters.size(); i++) { - String flt = filters[i].get_slice(";", 0).strip_edges(); + String flt = filters[i].get_slicec(';', 0).strip_edges(); String desc = filters[i].get_slice(";", 1).strip_edges(); if (desc.length()) { - filter->add_item(desc + " (" + flt + ")"); + String f = desc + " (" + flt + ")"; + filter->add_item(f); + processed_filters.push_back(flt + ";" + f); } else { - filter->add_item("(" + flt + ")"); + String f = "(" + flt + ")"; + filter->add_item(f); + processed_filters.push_back(flt + ";" + f); } } - filter->add_item(TTR("All Files (*)")); + String f = TTR("All Files (*)"); + filter->add_item(f); + processed_filters.push_back("*.*;" + f); } void EditorFileDialog::clear_filters() { @@ -1246,7 +1263,7 @@ void EditorFileDialog::set_current_path(const String &p_path) { if (!p_path.size()) { return; } - int pos = MAX(p_path.rfind("/"), p_path.rfind("\\")); + int pos = MAX(p_path.rfind_char('/'), p_path.rfind_char('\\')); if (pos == -1) { set_current_file(p_path); } else { @@ -1355,6 +1372,13 @@ EditorFileDialog::Access EditorFileDialog::get_access() const { void EditorFileDialog::_make_dir_confirm() { const String stripped_dirname = makedirname->get_text().strip_edges(); + if (stripped_dirname.is_empty()) { + error_dialog->set_text(TTR("The path specified is invalid.")); + error_dialog->popup_centered(Size2(250, 50) * EDSCALE); + makedirname->set_text(""); // Reset label. + return; + } + if (dir_access->dir_exists(stripped_dirname)) { error_dialog->set_text(TTR("Could not create folder. File with that name already exists.")); error_dialog->popup_centered(Size2(250, 50) * EDSCALE); @@ -1476,29 +1500,29 @@ void EditorFileDialog::_update_drives(bool p_select) { void EditorFileDialog::_update_icons() { // Update icons. - mode_thumbnails->set_icon(theme_cache.mode_thumbnails); - mode_list->set_icon(theme_cache.mode_list); + mode_thumbnails->set_button_icon(theme_cache.mode_thumbnails); + mode_list->set_button_icon(theme_cache.mode_list); if (is_layout_rtl()) { - dir_prev->set_icon(theme_cache.forward_folder); - dir_next->set_icon(theme_cache.back_folder); + dir_prev->set_button_icon(theme_cache.forward_folder); + dir_next->set_button_icon(theme_cache.back_folder); } else { - dir_prev->set_icon(theme_cache.back_folder); - dir_next->set_icon(theme_cache.forward_folder); + dir_prev->set_button_icon(theme_cache.back_folder); + dir_next->set_button_icon(theme_cache.forward_folder); } - dir_up->set_icon(theme_cache.parent_folder); + dir_up->set_button_icon(theme_cache.parent_folder); - refresh->set_icon(theme_cache.reload); - favorite->set_icon(theme_cache.favorite); - show_hidden->set_icon(theme_cache.toggle_hidden); - makedir->set_icon(theme_cache.create_folder); + refresh->set_button_icon(theme_cache.reload); + favorite->set_button_icon(theme_cache.favorite); + show_hidden->set_button_icon(theme_cache.toggle_hidden); + makedir->set_button_icon(theme_cache.create_folder); filter_box->set_right_icon(theme_cache.filter_box); - file_sort_button->set_icon(theme_cache.file_sort_button); + file_sort_button->set_button_icon(theme_cache.file_sort_button); filter_box->set_clear_button_enabled(true); - fav_up->set_icon(theme_cache.favorites_up); - fav_down->set_icon(theme_cache.favorites_down); + fav_up->set_button_icon(theme_cache.favorites_up); + fav_down->set_button_icon(theme_cache.favorites_down); } void EditorFileDialog::_favorite_selected(int p_idx) { diff --git a/editor/gui/editor_file_dialog.h b/editor/gui/editor_file_dialog.h index 1922155133..7a928a6188 100644 --- a/editor/gui/editor_file_dialog.h +++ b/editor/gui/editor_file_dialog.h @@ -145,6 +145,7 @@ private: void _push_history(); Vector<String> filters; + Vector<String> processed_filters; bool previews_enabled = true; bool preview_waiting = false; diff --git a/editor/gui/editor_quick_open_dialog.cpp b/editor/gui/editor_quick_open_dialog.cpp index 94a5ff94a3..44e7b3e483 100644 --- a/editor/gui/editor_quick_open_dialog.cpp +++ b/editor/gui/editor_quick_open_dialog.cpp @@ -30,6 +30,7 @@ #include "editor_quick_open_dialog.h" +#include "core/string/fuzzy_search.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" @@ -45,6 +46,55 @@ #include "scene/gui/texture_rect.h" #include "scene/gui/tree.h" +void HighlightedLabel::draw_substr_rects(const Vector2i &p_substr, Vector2 p_offset, int p_line_limit, int line_spacing) { + for (int i = get_lines_skipped(); i < p_line_limit; i++) { + RID line = get_line_rid(i); + Vector<Vector2> ranges = TS->shaped_text_get_selection(line, p_substr.x, p_substr.x + p_substr.y); + Rect2 line_rect = get_line_rect(i); + for (const Vector2 &range : ranges) { + Rect2 rect = Rect2(Point2(range.x, 0) + line_rect.position, Size2(range.y - range.x, line_rect.size.y)); + rect.position = p_offset + line_rect.position; + rect.position.x += range.x; + rect.size = Size2(range.y - range.x, line_rect.size.y); + rect.size.x = MIN(rect.size.x, line_rect.size.x - range.x); + if (rect.size.x > 0) { + draw_rect(rect, Color(1, 1, 1, 0.07), true); + draw_rect(rect, Color(0.5, 0.7, 1.0, 0.4), false, 1); + } + } + p_offset.y += line_spacing + TS->shaped_text_get_ascent(line) + TS->shaped_text_get_descent(line); + } +} + +void HighlightedLabel::add_highlight(const Vector2i &p_interval) { + if (p_interval.y > 0) { + highlights.append(p_interval); + queue_redraw(); + } +} + +void HighlightedLabel::reset_highlights() { + highlights.clear(); + queue_redraw(); +} + +void HighlightedLabel::_notification(int p_notification) { + if (p_notification == NOTIFICATION_DRAW) { + if (highlights.is_empty()) { + return; + } + + Vector2 offset; + int line_limit; + int line_spacing; + get_layout_data(offset, line_limit, line_spacing); + + for (const Vector2i &substr : highlights) { + draw_substr_rects(substr, offset, line_limit, line_spacing); + } + } +} + EditorQuickOpenDialog::EditorQuickOpenDialog() { VBoxContainer *vbc = memnew(VBoxContainer); vbc->add_theme_constant_override("separation", 0); @@ -100,7 +150,7 @@ void EditorQuickOpenDialog::popup_dialog(const Vector<StringName> &p_base_types, get_ok_button()->set_disabled(container->has_nothing_selected()); set_title(get_dialog_title(p_base_types)); - popup_centered_clamped(Size2(710, 650) * EDSCALE, 0.8f); + popup_centered_clamped(Size2(780, 650) * EDSCALE, 0.8f); search_box->grab_focus(); } @@ -119,13 +169,18 @@ void EditorQuickOpenDialog::cancel_pressed() { } void EditorQuickOpenDialog::_search_box_text_changed(const String &p_query) { - container->update_results(p_query.to_lower()); - + container->set_query_and_update(p_query); get_ok_button()->set_disabled(container->has_nothing_selected()); } //------------------------- Result Container +void style_button(Button *p_button) { + p_button->set_flat(true); + p_button->set_focus_mode(Control::FOCUS_NONE); + p_button->set_default_cursor_shape(Control::CURSOR_POINTING_HAND); +} + QuickOpenResultContainer::QuickOpenResultContainer() { set_h_size_flags(Control::SIZE_EXPAND_FILL); set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -175,91 +230,107 @@ QuickOpenResultContainer::QuickOpenResultContainer() { } { - // Bottom bar - HBoxContainer *bottom_bar = memnew(HBoxContainer); - add_child(bottom_bar); - + // Selected filepath file_details_path = memnew(Label); file_details_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); file_details_path->set_horizontal_alignment(HorizontalAlignment::HORIZONTAL_ALIGNMENT_CENTER); file_details_path->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); - bottom_bar->add_child(file_details_path); + add_child(file_details_path); + } - { - HBoxContainer *hbc = memnew(HBoxContainer); - hbc->add_theme_constant_override("separation", 3); - bottom_bar->add_child(hbc); - - include_addons_toggle = memnew(CheckButton); - include_addons_toggle->set_flat(true); - include_addons_toggle->set_focus_mode(Control::FOCUS_NONE); - include_addons_toggle->set_default_cursor_shape(CURSOR_POINTING_HAND); - include_addons_toggle->set_tooltip_text(TTR("Include files from addons")); - include_addons_toggle->connect(SceneStringName(toggled), callable_mp(this, &QuickOpenResultContainer::_toggle_include_addons)); - hbc->add_child(include_addons_toggle); - - VSeparator *vsep = memnew(VSeparator); - vsep->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - vsep->set_custom_minimum_size(Size2i(0, 14 * EDSCALE)); - hbc->add_child(vsep); - - display_mode_toggle = memnew(Button); - display_mode_toggle->set_flat(true); - display_mode_toggle->set_focus_mode(Control::FOCUS_NONE); - display_mode_toggle->set_default_cursor_shape(CURSOR_POINTING_HAND); - display_mode_toggle->connect(SceneStringName(pressed), callable_mp(this, &QuickOpenResultContainer::_toggle_display_mode)); - hbc->add_child(display_mode_toggle); - } + { + // Bottom bar + HBoxContainer *bottom_bar = memnew(HBoxContainer); + bottom_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); + bottom_bar->set_alignment(ALIGNMENT_END); + bottom_bar->add_theme_constant_override("separation", 3); + add_child(bottom_bar); + + fuzzy_search_toggle = memnew(CheckButton); + style_button(fuzzy_search_toggle); + fuzzy_search_toggle->set_text(TTR("Fuzzy Search")); + fuzzy_search_toggle->set_tooltip_text(TTR("Enable fuzzy matching")); + fuzzy_search_toggle->connect(SceneStringName(toggled), callable_mp(this, &QuickOpenResultContainer::_toggle_fuzzy_search)); + bottom_bar->add_child(fuzzy_search_toggle); + + include_addons_toggle = memnew(CheckButton); + style_button(include_addons_toggle); + include_addons_toggle->set_text(TTR("Addons")); + include_addons_toggle->set_tooltip_text(TTR("Include files from addons")); + include_addons_toggle->connect(SceneStringName(toggled), callable_mp(this, &QuickOpenResultContainer::_toggle_include_addons)); + bottom_bar->add_child(include_addons_toggle); + + VSeparator *vsep = memnew(VSeparator); + vsep->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + vsep->set_custom_minimum_size(Size2i(0, 14 * EDSCALE)); + bottom_bar->add_child(vsep); + + display_mode_toggle = memnew(Button); + style_button(display_mode_toggle); + display_mode_toggle->connect(SceneStringName(pressed), callable_mp(this, &QuickOpenResultContainer::_toggle_display_mode)); + bottom_bar->add_child(display_mode_toggle); } +} - // Creating and deleting nodes while searching is slow, so we allocate - // a bunch of result nodes and fill in the content based on result ranking. - result_items.resize(TOTAL_ALLOCATED_RESULT_ITEMS); - for (int i = 0; i < TOTAL_ALLOCATED_RESULT_ITEMS; i++) { +void QuickOpenResultContainer::_ensure_result_vector_capacity() { + int target_size = EDITOR_GET("filesystem/quick_open_dialog/max_results"); + int initial_size = result_items.size(); + for (int i = target_size; i < initial_size; i++) { + result_items[i]->queue_free(); + } + result_items.resize(target_size); + for (int i = initial_size; i < target_size; i++) { QuickOpenResultItem *item = memnew(QuickOpenResultItem); item->connect(SceneStringName(gui_input), callable_mp(this, &QuickOpenResultContainer::_item_input).bind(i)); result_items.write[i] = item; - } -} - -QuickOpenResultContainer::~QuickOpenResultContainer() { - if (never_opened) { - for (QuickOpenResultItem *E : result_items) { - memdelete(E); + if (!never_opened) { + _layout_result_item(item); } } } void QuickOpenResultContainer::init(const Vector<StringName> &p_base_types) { + _ensure_result_vector_capacity(); base_types = p_base_types; - never_opened = false; const int display_mode_behavior = EDITOR_GET("filesystem/quick_open_dialog/default_display_mode"); const bool adaptive_display_mode = (display_mode_behavior == 0); if (adaptive_display_mode) { _set_display_mode(get_adaptive_display_mode(p_base_types)); + } else if (never_opened) { + int last = EditorSettings::get_singleton()->get_project_metadata("quick_open_dialog", "last_mode", (int)QuickOpenDisplayMode::LIST); + _set_display_mode((QuickOpenDisplayMode)last); } + const bool fuzzy_matching = EDITOR_GET("filesystem/quick_open_dialog/enable_fuzzy_matching"); const bool include_addons = EDITOR_GET("filesystem/quick_open_dialog/include_addons"); + fuzzy_search_toggle->set_pressed_no_signal(fuzzy_matching); include_addons_toggle->set_pressed_no_signal(include_addons); + never_opened = false; - _create_initial_results(include_addons); + const bool enable_highlights = EDITOR_GET("filesystem/quick_open_dialog/show_search_highlight"); + for (QuickOpenResultItem *E : result_items) { + E->enable_highlights = enable_highlights; + } + + _create_initial_results(); } -void QuickOpenResultContainer::_create_initial_results(bool p_include_addons) { - file_type_icons.insert("__default_icon", get_editor_theme_icon(SNAME("Object"))); - _find_candidates_in_folder(EditorFileSystem::get_singleton()->get_filesystem(), p_include_addons); - max_total_results = MIN(candidates.size(), TOTAL_ALLOCATED_RESULT_ITEMS); +void QuickOpenResultContainer::_create_initial_results() { file_type_icons.clear(); - - update_results(query); + file_type_icons.insert("__default_icon", get_editor_theme_icon(SNAME("Object"))); + filepaths.clear(); + filetypes.clear(); + _find_filepaths_in_folder(EditorFileSystem::get_singleton()->get_filesystem(), include_addons_toggle->is_pressed()); + max_total_results = MIN(filepaths.size(), result_items.size()); + update_results(); } -void QuickOpenResultContainer::_find_candidates_in_folder(EditorFileSystemDirectory *p_directory, bool p_include_addons) { +void QuickOpenResultContainer::_find_filepaths_in_folder(EditorFileSystemDirectory *p_directory, bool p_include_addons) { for (int i = 0; i < p_directory->get_subdir_count(); i++) { if (p_include_addons || p_directory->get_name() != "addons") { - _find_candidates_in_folder(p_directory->get_subdir(i), p_include_addons); + _find_filepaths_in_folder(p_directory->get_subdir(i), p_include_addons); } } @@ -276,146 +347,91 @@ void QuickOpenResultContainer::_find_candidates_in_folder(EditorFileSystemDirect bool is_valid = ClassDB::is_parent_class(engine_type, parent_type) || (!is_engine_type && EditorNode::get_editor_data().script_class_is_parent(script_type, parent_type)); if (is_valid) { - Candidate c; - c.file_name = file_path.get_file(); - c.file_directory = file_path.get_base_dir(); - - EditorResourcePreview::PreviewItem item = EditorResourcePreview::get_singleton()->get_resource_preview_if_available(file_path); - if (item.preview.is_valid()) { - c.thumbnail = item.preview; - } else if (file_type_icons.has(actual_type)) { - c.thumbnail = *file_type_icons.lookup_ptr(actual_type); - } else if (has_theme_icon(actual_type, EditorStringName(EditorIcons))) { - c.thumbnail = get_editor_theme_icon(actual_type); - file_type_icons.insert(actual_type, c.thumbnail); - } else { - c.thumbnail = *file_type_icons.lookup_ptr("__default_icon"); - } - - candidates.push_back(c); - + filepaths.append(file_path); + filetypes.insert(file_path, actual_type); break; // Stop testing base types as soon as we get a match. } } } } -void QuickOpenResultContainer::update_results(const String &p_query) { +void QuickOpenResultContainer::set_query_and_update(const String &p_query) { query = p_query; - - int relevant_candidates = _sort_candidates(p_query); - _update_result_items(MIN(relevant_candidates, max_total_results), 0); -} - -int QuickOpenResultContainer::_sort_candidates(const String &p_query) { - if (p_query.is_empty()) { - return 0; + update_results(); +} + +void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &candidate, const String &filepath) { + StringName actual_type = *filetypes.lookup_ptr(filepath); + candidate.file_path = filepath; + candidate.result = nullptr; + + EditorResourcePreview::PreviewItem item = EditorResourcePreview::get_singleton()->get_resource_preview_if_available(filepath); + if (item.preview.is_valid()) { + candidate.thumbnail = item.preview; + } else if (file_type_icons.has(actual_type)) { + candidate.thumbnail = *file_type_icons.lookup_ptr(actual_type); + } else if (has_theme_icon(actual_type, EditorStringName(EditorIcons))) { + candidate.thumbnail = get_editor_theme_icon(actual_type); + file_type_icons.insert(actual_type, candidate.thumbnail); + } else { + candidate.thumbnail = *file_type_icons.lookup_ptr("__default_icon"); } +} - const PackedStringArray search_tokens = p_query.to_lower().replace("/", " ").split(" ", false); +void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_candidate, const FuzzySearchResult &p_result) { + _setup_candidate(p_candidate, p_result.target); + p_candidate.result = &p_result; +} - if (search_tokens.is_empty()) { - return 0; +void QuickOpenResultContainer::update_results() { + showing_history = false; + candidates.clear(); + if (query.is_empty()) { + _use_default_candidates(); + } else { + _score_and_sort_candidates(); } + _update_result_items(MIN(candidates.size(), max_total_results), 0); +} - // First, we assign a score to each candidate. - int num_relevant_candidates = 0; - for (Candidate &c : candidates) { - c.score = 0; - int prev_token_match_pos = -1; - - for (const String &token : search_tokens) { - const int file_pos = c.file_name.findn(token); - const int dir_pos = c.file_directory.findn(token); - - const bool file_match = file_pos > -1; - const bool dir_match = dir_pos > -1; - if (!file_match && !dir_match) { - c.score = -1.0f; - break; - } - - float token_score = file_match ? 0.6f : 0.1999f; - - // Add bias for shorter filenames/paths: they resemble the query more. - const String &matched_string = file_match ? c.file_name : c.file_directory; - int matched_string_token_pos = file_match ? file_pos : dir_pos; - token_score += 0.1f * (1.0f - ((float)matched_string_token_pos / (float)matched_string.length())); - - // Add bias if the match happened in the file name, not the extension. - if (file_match) { - int ext_pos = matched_string.rfind("."); - if (ext_pos == -1 || ext_pos > matched_string_token_pos) { - token_score += 0.1f; - } - } - - // Add bias if token is in order. - { - int candidate_string_token_pos = file_match ? (c.file_directory.length() + file_pos) : dir_pos; - - if (prev_token_match_pos != -1 && candidate_string_token_pos > prev_token_match_pos) { - token_score += 0.2f; - } - - prev_token_match_pos = candidate_string_token_pos; - } - - c.score += token_score; +void QuickOpenResultContainer::_use_default_candidates() { + if (filepaths.size() <= SHOW_ALL_FILES_THRESHOLD) { + candidates.resize(filepaths.size()); + QuickOpenResultCandidate *candidates_write = candidates.ptrw(); + for (const String &filepath : filepaths) { + _setup_candidate(*candidates_write++, filepath); } - - if (c.score > 0.0f) { - num_relevant_candidates++; + } else if (base_types.size() == 1) { + Vector<QuickOpenResultCandidate> *history = selected_history.lookup_ptr(base_types[0]); + if (history) { + showing_history = true; + candidates.append_array(*history); } } - - // Now we will sort the candidates based on score, resolving ties by favoring: - // 1. Shorter file length. - // 2. Shorter directory length. - // 3. Lower alphabetic order. - struct CandidateComparator { - _FORCE_INLINE_ bool operator()(const Candidate &p_a, const Candidate &p_b) const { - if (!Math::is_equal_approx(p_a.score, p_b.score)) { - return p_a.score > p_b.score; - } - - if (p_a.file_name.length() != p_b.file_name.length()) { - return p_a.file_name.length() < p_b.file_name.length(); - } - - if (p_a.file_directory.length() != p_b.file_directory.length()) { - return p_a.file_directory.length() < p_b.file_directory.length(); - } - - return p_a.file_name < p_b.file_name; - } - }; - candidates.sort_custom<CandidateComparator>(); - - return num_relevant_candidates; } -void QuickOpenResultContainer::_update_result_items(int p_new_visible_results_count, int p_new_selection_index) { - List<Candidate> *type_history = nullptr; - - showing_history = false; - - if (query.is_empty()) { - if (candidates.size() <= SHOW_ALL_FILES_THRESHOLD) { - p_new_visible_results_count = candidates.size(); - } else { - p_new_visible_results_count = 0; +void QuickOpenResultContainer::_update_fuzzy_search_results() { + FuzzySearch fuzzy_search; + fuzzy_search.start_offset = 6; // Don't match against "res://" at the start of each filepath. + fuzzy_search.set_query(query); + fuzzy_search.max_results = max_total_results; + bool fuzzy_matching = EDITOR_GET("filesystem/quick_open_dialog/enable_fuzzy_matching"); + int max_misses = EDITOR_GET("filesystem/quick_open_dialog/max_fuzzy_misses"); + fuzzy_search.allow_subsequences = fuzzy_matching; + fuzzy_search.max_misses = fuzzy_matching ? max_misses : 0; + fuzzy_search.search_all(filepaths, search_results); +} - if (base_types.size() == 1) { - type_history = selected_history.lookup_ptr(base_types[0]); - if (type_history) { - p_new_visible_results_count = type_history->size(); - showing_history = true; - } - } - } +void QuickOpenResultContainer::_score_and_sort_candidates() { + _update_fuzzy_search_results(); + candidates.resize(search_results.size()); + QuickOpenResultCandidate *candidates_write = candidates.ptrw(); + for (const FuzzySearchResult &result : search_results) { + _setup_candidate(*candidates_write++, result); } +} +void QuickOpenResultContainer::_update_result_items(int p_new_visible_results_count, int p_new_selection_index) { // Only need to update items that were not hidden in previous update. int num_items_needing_updates = MAX(num_visible_results, p_new_visible_results_count); num_visible_results = p_new_visible_results_count; @@ -424,13 +440,7 @@ void QuickOpenResultContainer::_update_result_items(int p_new_visible_results_co QuickOpenResultItem *item = result_items[i]; if (i < num_visible_results) { - if (type_history) { - const Candidate &c = type_history->get(i); - item->set_content(c.thumbnail, c.file_name, c.file_directory); - } else { - const Candidate &c = candidates[i]; - item->set_content(c.thumbnail, c.file_name, c.file_directory); - } + item->set_content(candidates[i]); } else { item->reset(); } @@ -443,7 +453,7 @@ void QuickOpenResultContainer::_update_result_items(int p_new_visible_results_co no_results_container->set_visible(!any_results); if (!any_results) { - if (candidates.is_empty()) { + if (filepaths.is_empty()) { no_results_label->set_text(TTR("No files found for this type")); } else if (query.is_empty()) { no_results_label->set_text(TTR("Start searching to find files...")); @@ -471,10 +481,12 @@ void QuickOpenResultContainer::handle_search_box_input(const Ref<InputEvent> &p_ } break; case Key::LEFT: case Key::RIGHT: { - // Both grid and the search box use left/right keys. By default, grid will take it. - // It would be nice if we could check for ALT to give the event to the searchbox cursor. - // However, if you press ALT, the searchbox also denies the input. - move_selection = (content_display_mode == QuickOpenDisplayMode::GRID); + if (content_display_mode == QuickOpenDisplayMode::GRID) { + // Maybe strip off the shift modifier to allow non-selecting navigation by character? + if (key_event->get_modifiers_mask() == 0) { + move_selection = true; + } + } } break; default: break; // Let the event through so it will reach the search box. @@ -489,6 +501,10 @@ void QuickOpenResultContainer::handle_search_box_input(const Ref<InputEvent> &p_ } void QuickOpenResultContainer::_move_selection_index(Key p_key) { + // Don't move selection if there are no results. + if (num_visible_results <= 0) { + return; + } const int max_index = num_visible_results - 1; int idx = selection_index; @@ -562,11 +578,15 @@ void QuickOpenResultContainer::_item_input(const Ref<InputEvent> &p_ev, int p_in } } +void QuickOpenResultContainer::_toggle_fuzzy_search(bool p_pressed) { + EditorSettings::get_singleton()->set("filesystem/quick_open_dialog/enable_fuzzy_matching", p_pressed); + update_results(); +} + void QuickOpenResultContainer::_toggle_include_addons(bool p_pressed) { EditorSettings::get_singleton()->set("filesystem/quick_open_dialog/include_addons", p_pressed); - cleanup(); - _create_initial_results(p_pressed); + _create_initial_results(); } void QuickOpenResultContainer::_toggle_display_mode() { @@ -574,49 +594,49 @@ void QuickOpenResultContainer::_toggle_display_mode() { _set_display_mode(new_display_mode); } -void QuickOpenResultContainer::_set_display_mode(QuickOpenDisplayMode p_display_mode) { - content_display_mode = p_display_mode; +CanvasItem *QuickOpenResultContainer::_get_result_root() { + if (content_display_mode == QuickOpenDisplayMode::LIST) { + return list; + } else { + return grid; + } +} - const bool show_list = (content_display_mode == QuickOpenDisplayMode::LIST); - if ((show_list && list->is_visible()) || (!show_list && grid->is_visible())) { - return; +void QuickOpenResultContainer::_layout_result_item(QuickOpenResultItem *item) { + item->set_display_mode(content_display_mode); + Node *parent = item->get_parent(); + if (parent) { + parent->remove_child(item); } + _get_result_root()->add_child(item); +} - hide(); +void QuickOpenResultContainer::_set_display_mode(QuickOpenDisplayMode p_display_mode) { + CanvasItem *prev_root = _get_result_root(); - // Move result item nodes from one container to the other. - CanvasItem *prev_root; - CanvasItem *next_root; - if (content_display_mode == QuickOpenDisplayMode::LIST) { - prev_root = Object::cast_to<CanvasItem>(grid); - next_root = Object::cast_to<CanvasItem>(list); - } else { - prev_root = Object::cast_to<CanvasItem>(list); - next_root = Object::cast_to<CanvasItem>(grid); + if (prev_root->is_visible() && content_display_mode == p_display_mode) { + return; } - const bool first_time = !list->is_visible() && !grid->is_visible(); + content_display_mode = p_display_mode; + CanvasItem *next_root = _get_result_root(); - prev_root->hide(); - for (QuickOpenResultItem *item : result_items) { - item->set_display_mode(content_display_mode); + EditorSettings::get_singleton()->set_project_metadata("quick_open_dialog", "last_mode", (int)content_display_mode); - if (!first_time) { - prev_root->remove_child(item); - } + prev_root->hide(); + next_root->show(); - next_root->add_child(item); + for (QuickOpenResultItem *item : result_items) { + _layout_result_item(item); } - next_root->show(); - show(); _update_result_items(num_visible_results, selection_index); if (content_display_mode == QuickOpenDisplayMode::LIST) { - display_mode_toggle->set_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); + display_mode_toggle->set_button_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); display_mode_toggle->set_tooltip_text(TTR("Grid view")); } else { - display_mode_toggle->set_icon(get_editor_theme_icon(SNAME("FileList"))); + display_mode_toggle->set_button_icon(get_editor_theme_icon(SNAME("FileList"))); display_mode_toggle->set_tooltip_text(TTR("List view")); } } @@ -627,16 +647,7 @@ bool QuickOpenResultContainer::has_nothing_selected() const { String QuickOpenResultContainer::get_selected() const { ERR_FAIL_COND_V_MSG(has_nothing_selected(), String(), "Tried to get selected file, but nothing was selected."); - - if (showing_history) { - const List<Candidate> *type_history = selected_history.lookup_ptr(base_types[0]); - - const Candidate &c = type_history->get(selection_index); - return c.file_directory.path_join(c.file_name); - } else { - const Candidate &c = candidates[selection_index]; - return c.file_directory.path_join(c.file_name); - } + return candidates[selection_index].file_path; } QuickOpenDisplayMode QuickOpenResultContainer::get_adaptive_display_mode(const Vector<StringName> &p_base_types) { @@ -649,8 +660,9 @@ QuickOpenDisplayMode QuickOpenResultContainer::get_adaptive_display_mode(const V for (const StringName &type : grid_preferred_types) { for (const StringName &base_type : p_base_types) { - if (base_type == type || ClassDB::is_parent_class(base_type, type)) + if (base_type == type || ClassDB::is_parent_class(base_type, type)) { return QuickOpenDisplayMode::GRID; + } } } @@ -664,32 +676,27 @@ void QuickOpenResultContainer::save_selected_item() { return; } - if (showing_history) { - // Selecting from history, so already added. - return; - } - const StringName &base_type = base_types[0]; + const QuickOpenResultCandidate &selected = candidates[selection_index]; + Vector<QuickOpenResultCandidate> *type_history = selected_history.lookup_ptr(base_type); - List<Candidate> *type_history = selected_history.lookup_ptr(base_type); if (!type_history) { - selected_history.insert(base_type, List<Candidate>()); + selected_history.insert(base_type, Vector<QuickOpenResultCandidate>()); type_history = selected_history.lookup_ptr(base_type); } else { - const Candidate &selected = candidates[selection_index]; - - for (const Candidate &candidate : *type_history) { - if (candidate.file_directory == selected.file_directory && candidate.file_name == selected.file_name) { - return; + for (int i = 0; i < type_history->size(); i++) { + if (selected.file_path == type_history->get(i).file_path) { + type_history->remove_at(i); + break; } } - - if (type_history->size() > 8) { - type_history->pop_back(); - } } - type_history->push_front(candidates[selection_index]); + type_history->insert(0, selected); + type_history->ptrw()->result = nullptr; + if (type_history->size() > MAX_HISTORY_SIZE) { + type_history->resize(MAX_HISTORY_SIZE); + } } void QuickOpenResultContainer::cleanup() { @@ -712,9 +719,9 @@ void QuickOpenResultContainer::_notification(int p_what) { panel_container->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); if (content_display_mode == QuickOpenDisplayMode::LIST) { - display_mode_toggle->set_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); + display_mode_toggle->set_button_icon(get_editor_theme_icon(SNAME("FileThumbnail"))); } else { - display_mode_toggle->set_icon(get_editor_theme_icon(SNAME("FileList"))); + display_mode_toggle->set_button_icon(get_editor_theme_icon(SNAME("FileList"))); } } break; } @@ -743,36 +750,35 @@ QuickOpenResultItem::QuickOpenResultItem() { void QuickOpenResultItem::set_display_mode(QuickOpenDisplayMode p_display_mode) { if (p_display_mode == QuickOpenDisplayMode::LIST) { grid_item->hide(); + grid_item->reset(); list_item->show(); } else { list_item->hide(); + list_item->reset(); grid_item->show(); } queue_redraw(); } -void QuickOpenResultItem::set_content(const Ref<Texture2D> &p_thumbnail, const String &p_file, const String &p_file_directory) { +void QuickOpenResultItem::set_content(const QuickOpenResultCandidate &p_candidate) { _set_enabled(true); if (list_item->is_visible()) { - list_item->set_content(p_thumbnail, p_file, p_file_directory); + list_item->set_content(p_candidate, enable_highlights); } else { - grid_item->set_content(p_thumbnail, p_file); + grid_item->set_content(p_candidate, enable_highlights); } + + queue_redraw(); } void QuickOpenResultItem::reset() { _set_enabled(false); - is_hovering = false; is_selected = false; - - if (list_item->is_visible()) { - list_item->reset(); - } else { - grid_item->reset(); - } + list_item->reset(); + grid_item->reset(); } void QuickOpenResultItem::highlight_item(bool p_enabled) { @@ -825,6 +831,22 @@ void QuickOpenResultItem::_notification(int p_what) { //----------------- List item +static Vector2i _get_path_interval(const Vector2i &p_interval, int p_dir_index) { + if (p_interval.x >= p_dir_index || p_interval.y < 1) { + return { -1, -1 }; + } + return { p_interval.x, MIN(p_interval.x + p_interval.y, p_dir_index) - p_interval.x }; +} + +static Vector2i _get_name_interval(const Vector2i &p_interval, int p_dir_index) { + if (p_interval.x + p_interval.y <= p_dir_index || p_interval.y < 1) { + return { -1, -1 }; + } + int first_name_idx = p_dir_index + 1; + int start = MAX(p_interval.x, first_name_idx); + return { start - first_name_idx, p_interval.y - start + p_interval.x }; +} + QuickOpenResultListItem::QuickOpenResultListItem() { set_h_size_flags(Control::SIZE_EXPAND_FILL); add_theme_constant_override("separation", 4 * EDSCALE); @@ -852,13 +874,13 @@ QuickOpenResultListItem::QuickOpenResultListItem() { text_container->set_v_size_flags(Control::SIZE_FILL); add_child(text_container); - name = memnew(Label); + name = memnew(HighlightedLabel); name->set_h_size_flags(Control::SIZE_EXPAND_FILL); name->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); name->set_horizontal_alignment(HorizontalAlignment::HORIZONTAL_ALIGNMENT_LEFT); text_container->add_child(name); - path = memnew(Label); + path = memnew(HighlightedLabel); path->set_h_size_flags(Control::SIZE_EXPAND_FILL); path->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); path->add_theme_font_size_override(SceneStringName(font_size), 12 * EDSCALE); @@ -866,18 +888,29 @@ QuickOpenResultListItem::QuickOpenResultListItem() { } } -void QuickOpenResultListItem::set_content(const Ref<Texture2D> &p_thumbnail, const String &p_file, const String &p_file_directory) { - thumbnail->set_texture(p_thumbnail); - name->set_text(p_file); - path->set_text(p_file_directory); +void QuickOpenResultListItem::set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight) { + thumbnail->set_texture(p_candidate.thumbnail); + name->set_text(p_candidate.file_path.get_file()); + path->set_text(p_candidate.file_path.get_base_dir()); + name->reset_highlights(); + path->reset_highlights(); + + if (p_highlight && p_candidate.result != nullptr) { + for (const FuzzyTokenMatch &match : p_candidate.result->token_matches) { + for (const Vector2i &interval : match.substrings) { + path->add_highlight(_get_path_interval(interval, p_candidate.result->dir_index)); + name->add_highlight(_get_name_interval(interval, p_candidate.result->dir_index)); + } + } + } const int max_size = 32 * EDSCALE; - bool uses_icon = p_thumbnail->get_width() < max_size; + bool uses_icon = p_candidate.thumbnail->get_width() < max_size; if (uses_icon) { - thumbnail->set_custom_minimum_size(p_thumbnail->get_size()); + thumbnail->set_custom_minimum_size(p_candidate.thumbnail->get_size()); - int margin_needed = (max_size - p_thumbnail->get_width()) / 2; + int margin_needed = (max_size - p_candidate.thumbnail->get_width()) / 2; image_container->add_theme_constant_override("margin_left", CONTAINER_MARGIN + margin_needed); image_container->add_theme_constant_override("margin_right", margin_needed); } else { @@ -888,9 +921,11 @@ void QuickOpenResultListItem::set_content(const Ref<Texture2D> &p_thumbnail, con } void QuickOpenResultListItem::reset() { - name->set_text(""); thumbnail->set_texture(nullptr); + name->set_text(""); path->set_text(""); + name->reset_highlights(); + path->reset_highlights(); } void QuickOpenResultListItem::highlight_item(const Color &p_color) { @@ -919,10 +954,10 @@ QuickOpenResultGridItem::QuickOpenResultGridItem() { thumbnail = memnew(TextureRect); thumbnail->set_h_size_flags(Control::SIZE_SHRINK_CENTER); thumbnail->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - thumbnail->set_custom_minimum_size(Size2i(80 * EDSCALE, 64 * EDSCALE)); + thumbnail->set_custom_minimum_size(Size2i(120 * EDSCALE, 64 * EDSCALE)); add_child(thumbnail); - name = memnew(Label); + name = memnew(HighlightedLabel); name->set_h_size_flags(Control::SIZE_EXPAND_FILL); name->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); name->set_horizontal_alignment(HorizontalAlignment::HORIZONTAL_ALIGNMENT_CENTER); @@ -930,16 +965,23 @@ QuickOpenResultGridItem::QuickOpenResultGridItem() { add_child(name); } -void QuickOpenResultGridItem::set_content(const Ref<Texture2D> &p_thumbnail, const String &p_file) { - thumbnail->set_texture(p_thumbnail); +void QuickOpenResultGridItem::set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight) { + thumbnail->set_texture(p_candidate.thumbnail); + name->set_text(p_candidate.file_path.get_file()); + name->set_tooltip_text(p_candidate.file_path); + name->reset_highlights(); - const String &file_name = p_file.get_basename(); - name->set_text(file_name); - name->set_tooltip_text(file_name); + if (p_highlight && p_candidate.result != nullptr) { + for (const FuzzyTokenMatch &match : p_candidate.result->token_matches) { + for (const Vector2i &interval : match.substrings) { + name->add_highlight(_get_name_interval(interval, p_candidate.result->dir_index)); + } + } + } - bool uses_icon = p_thumbnail->get_width() < (32 * EDSCALE); + bool uses_icon = p_candidate.thumbnail->get_width() < (32 * EDSCALE); - if (uses_icon || p_thumbnail->get_height() <= thumbnail->get_custom_minimum_size().y) { + if (uses_icon || p_candidate.thumbnail->get_height() <= thumbnail->get_custom_minimum_size().y) { thumbnail->set_expand_mode(TextureRect::EXPAND_KEEP_SIZE); thumbnail->set_stretch_mode(TextureRect::StretchMode::STRETCH_KEEP_CENTERED); } else { @@ -949,8 +991,9 @@ void QuickOpenResultGridItem::set_content(const Ref<Texture2D> &p_thumbnail, con } void QuickOpenResultGridItem::reset() { - name->set_text(""); thumbnail->set_texture(nullptr); + name->set_text(""); + name->reset_highlights(); } void QuickOpenResultGridItem::highlight_item(const Color &p_color) { diff --git a/editor/gui/editor_quick_open_dialog.h b/editor/gui/editor_quick_open_dialog.h index 49257aed6b..3b3f927527 100644 --- a/editor/gui/editor_quick_open_dialog.h +++ b/editor/gui/editor_quick_open_dialog.h @@ -48,6 +48,8 @@ class Texture2D; class TextureRect; class VBoxContainer; +class FuzzySearchResult; + class QuickOpenResultItem; enum class QuickOpenDisplayMode { @@ -55,13 +57,35 @@ enum class QuickOpenDisplayMode { LIST, }; +struct QuickOpenResultCandidate { + String file_path; + Ref<Texture2D> thumbnail; + const FuzzySearchResult *result = nullptr; +}; + +class HighlightedLabel : public Label { + GDCLASS(HighlightedLabel, Label) + + Vector<Vector2i> highlights; + + void draw_substr_rects(const Vector2i &p_substr, Vector2 p_offset, int p_line_limit, int line_spacing); + +public: + void add_highlight(const Vector2i &p_interval); + void reset_highlights(); + +protected: + void _notification(int p_notification); +}; + class QuickOpenResultContainer : public VBoxContainer { GDCLASS(QuickOpenResultContainer, VBoxContainer) public: void init(const Vector<StringName> &p_base_types); void handle_search_box_input(const Ref<InputEvent> &p_ie); - void update_results(const String &p_query); + void set_query_and_update(const String &p_query); + void update_results(); bool has_nothing_selected() const; String get_selected() const; @@ -70,27 +94,21 @@ public: void cleanup(); QuickOpenResultContainer(); - ~QuickOpenResultContainer(); protected: void _notification(int p_what); private: - static const int TOTAL_ALLOCATED_RESULT_ITEMS = 100; - static const int SHOW_ALL_FILES_THRESHOLD = 30; - - struct Candidate { - String file_name; - String file_directory; - - Ref<Texture2D> thumbnail; - float score = 0; - }; + static constexpr int SHOW_ALL_FILES_THRESHOLD = 30; + static constexpr int MAX_HISTORY_SIZE = 20; + Vector<FuzzySearchResult> search_results; Vector<StringName> base_types; - Vector<Candidate> candidates; + Vector<String> filepaths; + OAHashMap<String, StringName> filetypes; + Vector<QuickOpenResultCandidate> candidates; - OAHashMap<StringName, List<Candidate>> selected_history; + OAHashMap<StringName, Vector<QuickOpenResultCandidate>> selected_history; String query; int selection_index = -1; @@ -114,15 +132,21 @@ private: Label *file_details_path = nullptr; Button *display_mode_toggle = nullptr; CheckButton *include_addons_toggle = nullptr; + CheckButton *fuzzy_search_toggle = nullptr; OAHashMap<StringName, Ref<Texture2D>> file_type_icons; static QuickOpenDisplayMode get_adaptive_display_mode(const Vector<StringName> &p_base_types); - void _create_initial_results(bool p_include_addons); - void _find_candidates_in_folder(EditorFileSystemDirectory *p_directory, bool p_include_addons); + void _ensure_result_vector_capacity(); + void _create_initial_results(); + void _find_filepaths_in_folder(EditorFileSystemDirectory *p_directory, bool p_include_addons); - int _sort_candidates(const String &p_query); + void _setup_candidate(QuickOpenResultCandidate &p_candidate, const String &p_filepath); + void _setup_candidate(QuickOpenResultCandidate &p_candidate, const FuzzySearchResult &p_result); + void _update_fuzzy_search_results(); + void _use_default_candidates(); + void _score_and_sort_candidates(); void _update_result_items(int p_new_visible_results_count, int p_new_selection_index); void _move_selection_index(Key p_key); @@ -130,9 +154,12 @@ private: void _item_input(const Ref<InputEvent> &p_ev, int p_index); + CanvasItem *_get_result_root(); + void _layout_result_item(QuickOpenResultItem *p_item); void _set_display_mode(QuickOpenDisplayMode p_display_mode); void _toggle_display_mode(); void _toggle_include_addons(bool p_pressed); + void _toggle_fuzzy_search(bool p_pressed); static void _bind_methods(); }; @@ -143,14 +170,14 @@ class QuickOpenResultGridItem : public VBoxContainer { public: QuickOpenResultGridItem(); - void set_content(const Ref<Texture2D> &p_thumbnail, const String &p_file_name); void reset(); + void set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight); void highlight_item(const Color &p_color); void remove_highlight(); private: TextureRect *thumbnail = nullptr; - Label *name = nullptr; + HighlightedLabel *name = nullptr; }; class QuickOpenResultListItem : public HBoxContainer { @@ -159,8 +186,8 @@ class QuickOpenResultListItem : public HBoxContainer { public: QuickOpenResultListItem(); - void set_content(const Ref<Texture2D> &p_thumbnail, const String &p_file_name, const String &p_file_directory); void reset(); + void set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight); void highlight_item(const Color &p_color); void remove_highlight(); @@ -174,8 +201,8 @@ private: VBoxContainer *text_container = nullptr; TextureRect *thumbnail = nullptr; - Label *name = nullptr; - Label *path = nullptr; + HighlightedLabel *name = nullptr; + HighlightedLabel *path = nullptr; }; class QuickOpenResultItem : public HBoxContainer { @@ -184,10 +211,11 @@ class QuickOpenResultItem : public HBoxContainer { public: QuickOpenResultItem(); - void set_content(const Ref<Texture2D> &p_thumbnail, const String &p_file_name, const String &p_file_directory); - void set_display_mode(QuickOpenDisplayMode p_display_mode); - void reset(); + bool enable_highlights = true; + void reset(); + void set_content(const QuickOpenResultCandidate &p_candidate); + void set_display_mode(QuickOpenDisplayMode p_display_mode); void highlight_item(bool p_enabled); protected: diff --git a/editor/gui/editor_run_bar.cpp b/editor/gui/editor_run_bar.cpp index 908b1e6719..64135c8d50 100644 --- a/editor/gui/editor_run_bar.cpp +++ b/editor/gui/editor_run_bar.cpp @@ -52,8 +52,8 @@ void EditorRunBar::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { _update_play_buttons(); - pause_button->set_icon(get_editor_theme_icon(SNAME("Pause"))); - stop_button->set_icon(get_editor_theme_icon(SNAME("Stop"))); + pause_button->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); + stop_button->set_button_icon(get_editor_theme_icon(SNAME("Stop"))); if (is_movie_maker_enabled()) { main_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("LaunchPadMovieMode"), EditorStringName(EditorStyles))); @@ -63,7 +63,7 @@ void EditorRunBar::_notification(int p_what) { write_movie_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("MovieWriterButtonNormal"), EditorStringName(EditorStyles))); } - write_movie_button->set_icon(get_editor_theme_icon(SNAME("MainMovieWrite"))); + write_movie_button->set_button_icon(get_editor_theme_icon(SNAME("MainMovieWrite"))); // This button behaves differently, so color it as such. write_movie_button->begin_bulk_theme_override(); write_movie_button->add_theme_color_override("icon_normal_color", get_theme_color(SNAME("movie_writer_icon_normal"), EditorStringName(EditorStyles))); @@ -77,15 +77,15 @@ void EditorRunBar::_notification(int p_what) { void EditorRunBar::_reset_play_buttons() { play_button->set_pressed(false); - play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); play_button->set_tooltip_text(TTR("Play the project.")); play_scene_button->set_pressed(false); - play_scene_button->set_icon(get_editor_theme_icon(SNAME("PlayScene"))); + play_scene_button->set_button_icon(get_editor_theme_icon(SNAME("PlayScene"))); play_scene_button->set_tooltip_text(TTR("Play the edited scene.")); play_custom_scene_button->set_pressed(false); - play_custom_scene_button->set_icon(get_editor_theme_icon(SNAME("PlayCustom"))); + play_custom_scene_button->set_button_icon(get_editor_theme_icon(SNAME("PlayCustom"))); play_custom_scene_button->set_tooltip_text(TTR("Play a custom scene.")); } @@ -106,7 +106,7 @@ void EditorRunBar::_update_play_buttons() { if (active_button) { active_button->set_pressed(true); - active_button->set_icon(get_editor_theme_icon(SNAME("Reload"))); + active_button->set_button_icon(get_editor_theme_icon(SNAME("Reload"))); active_button->set_tooltip_text(TTR("Reload the played scene.")); } } diff --git a/editor/gui/editor_scene_tabs.cpp b/editor/gui/editor_scene_tabs.cpp index 4862b3436e..5b42afdbe8 100644 --- a/editor/gui/editor_scene_tabs.cpp +++ b/editor/gui/editor_scene_tabs.cpp @@ -53,7 +53,7 @@ void EditorSceneTabs::_notification(int p_what) { tabbar_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("tabbar_background"), SNAME("TabContainer"))); scene_tabs->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor))); - scene_tab_add->set_icon(get_editor_theme_icon(SNAME("Add"))); + scene_tab_add->set_button_icon(get_editor_theme_icon(SNAME("Add"))); scene_tab_add->add_theme_color_override("icon_normal_color", Color(0.6f, 0.6f, 0.6f, 0.8f)); scene_tab_add_ph->set_custom_minimum_size(scene_tab_add->get_minimum_size()); diff --git a/editor/gui/editor_spin_slider.cpp b/editor/gui/editor_spin_slider.cpp index a073a2338b..aa9e9f841d 100644 --- a/editor/gui/editor_spin_slider.cpp +++ b/editor/gui/editor_spin_slider.cpp @@ -37,10 +37,6 @@ #include "editor/themes/editor_scale.h" #include "scene/theme/theme_db.h" -bool EditorSpinSlider::is_text_field() const { - return true; -} - String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const { if (!read_only && grabber->is_visible()) { Key key = (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) ? Key::META : Key::CTRL; @@ -71,6 +67,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { } else { set_value(get_value() - get_step()); } + emit_signal("updown_pressed"); return; } _grab_start(); @@ -441,7 +438,7 @@ void EditorSpinSlider::_draw_spin_slider() { Vector2 scale = get_global_transform_with_canvas().get_scale(); grabber->set_scale(scale); grabber->reset_size(); - grabber->set_position(get_global_position() + (grabber_rect.get_center() - grabber->get_size() * 0.5) * scale); + grabber->set_position((grabber_rect.get_center() - grabber->get_size() * 0.5) * scale); if (mousewheel_over_grabber) { Input::get_singleton()->warp_mouse(grabber->get_position() + grabber_rect.size); @@ -700,6 +697,7 @@ void EditorSpinSlider::_bind_methods() { ADD_SIGNAL(MethodInfo("grabbed")); ADD_SIGNAL(MethodInfo("ungrabbed")); + ADD_SIGNAL(MethodInfo("updown_pressed")); ADD_SIGNAL(MethodInfo("value_focus_entered")); ADD_SIGNAL(MethodInfo("value_focus_exited")); @@ -735,7 +733,7 @@ EditorSpinSlider::EditorSpinSlider() { grabber = memnew(TextureRect); add_child(grabber); grabber->hide(); - grabber->set_as_top_level(true); + grabber->set_z_index(1); grabber->set_mouse_filter(MOUSE_FILTER_STOP); grabber->connect(SceneStringName(mouse_entered), callable_mp(this, &EditorSpinSlider::_grabber_mouse_entered)); grabber->connect(SceneStringName(mouse_exited), callable_mp(this, &EditorSpinSlider::_grabber_mouse_exited)); diff --git a/editor/gui/editor_spin_slider.h b/editor/gui/editor_spin_slider.h index 2476c2f71b..dfc50878dd 100644 --- a/editor/gui/editor_spin_slider.h +++ b/editor/gui/editor_spin_slider.h @@ -101,8 +101,6 @@ protected: void _focus_entered(); public: - virtual bool is_text_field() const override; - String get_tooltip(const Point2 &p_pos) const override; String get_text_value() const; diff --git a/editor/gui/editor_toaster.cpp b/editor/gui/editor_toaster.cpp index 24f19db578..ff425ba65e 100644 --- a/editor/gui/editor_toaster.cpp +++ b/editor/gui/editor_toaster.cpp @@ -108,14 +108,13 @@ void EditorToaster::_notification(int p_what) { } } break; - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (vbox_container->is_visible()) { - main_button->set_icon(get_editor_theme_icon(SNAME("Notification"))); + main_button->set_button_icon(get_editor_theme_icon(SNAME("Notification"))); } else { - main_button->set_icon(get_editor_theme_icon(SNAME("NotificationDisabled"))); + main_button->set_button_icon(get_editor_theme_icon(SNAME("NotificationDisabled"))); } - disable_notifications_button->set_icon(get_editor_theme_icon(SNAME("NotificationDisabled"))); + disable_notifications_button->set_button_icon(get_editor_theme_icon(SNAME("NotificationDisabled"))); // Styleboxes background. info_panel_style_background->set_bg_color(get_theme_color(SNAME("base_color"), EditorStringName(Editor))); @@ -134,9 +133,6 @@ void EditorToaster::_notification(int p_what) { error_panel_style_progress->set_bg_color(get_theme_color(SNAME("base_color"), EditorStringName(Editor)).lightened(0.03)); error_panel_style_progress->set_border_color(get_theme_color(SNAME("error_color"), EditorStringName(Editor))); - - main_button->queue_redraw(); - disable_notifications_button->queue_redraw(); } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -243,6 +239,7 @@ void EditorToaster::_auto_hide_or_free_toasts() { main_button->set_tooltip_text(TTR("No notifications.")); main_button->set_modulate(Color(0.5, 0.5, 0.5)); main_button->set_disabled(true); + set_process_internal(false); } else { main_button->set_tooltip_text(TTR("Show notifications.")); main_button->set_modulate(Color(1, 1, 1)); @@ -311,9 +308,9 @@ void EditorToaster::_draw_progress(Control *panel) { void EditorToaster::_set_notifications_enabled(bool p_enabled) { vbox_container->set_visible(p_enabled); if (p_enabled) { - main_button->set_icon(get_editor_theme_icon(SNAME("Notification"))); + main_button->set_button_icon(get_editor_theme_icon(SNAME("Notification"))); } else { - main_button->set_icon(get_editor_theme_icon(SNAME("NotificationDisabled"))); + main_button->set_button_icon(get_editor_theme_icon(SNAME("NotificationDisabled"))); } _update_disable_notifications_button(); } @@ -361,6 +358,9 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_ } panel->set_modulate(Color(1, 1, 1, 0)); panel->connect(SceneStringName(draw), callable_mp(this, &EditorToaster::_draw_progress).bind(panel)); + panel->connect(SceneStringName(theme_changed), callable_mp(this, &EditorToaster::_toast_theme_changed).bind(panel)); + + Toast &toast = toasts[panel]; // Horizontal container. HBoxContainer *hbox_container = memnew(HBoxContainer); @@ -375,20 +375,20 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_ if (p_time > 0.0) { Button *close_button = memnew(Button); close_button->set_flat(true); - close_button->set_icon(get_editor_theme_icon(SNAME("Close"))); - close_button->connect(SceneStringName(pressed), callable_mp(this, &EditorToaster::close).bind(panel)); - close_button->connect(SceneStringName(theme_changed), callable_mp(this, &EditorToaster::_close_button_theme_changed).bind(close_button)); + close_button->connect(SceneStringName(pressed), callable_mp(this, &EditorToaster::instant_close).bind(panel)); hbox_container->add_child(close_button); + + toast.close_button = close_button; } - toasts[panel].severity = p_severity; + toast.severity = p_severity; if (p_time > 0.0) { - toasts[panel].duration = p_time; - toasts[panel].remaining_time = p_time; + toast.duration = p_time; + toast.remaining_time = p_time; } else { - toasts[panel].duration = -1.0; + toast.duration = -1.0; } - toasts[panel].popped = true; + toast.popped = true; vbox_container->add_child(panel); _auto_hide_or_free_toasts(); _update_vbox_position(); @@ -406,7 +406,7 @@ void EditorToaster::popup_str(const String &p_message, Severity p_severity, cons // Since "_popup_str" adds nodes to the tree, and since the "add_child" method is not // thread-safe, it's better to defer the call to the next cycle to be thread-safe. is_processing_error = true; - MessageQueue::get_main_singleton()->push_callable(callable_mp(this, &EditorToaster::_popup_str).bind(p_message, p_severity, p_tooltip)); + callable_mp(this, &EditorToaster::_popup_str).call_deferred(p_message, p_severity, p_tooltip); is_processing_error = false; } @@ -433,19 +433,22 @@ void EditorToaster::_popup_str(const String &p_message, Severity p_severity, con hb->add_child(count_label); control = popup(hb, p_severity, default_message_duration, p_tooltip); - toasts[control].message = p_message; - toasts[control].tooltip = p_tooltip; - toasts[control].count = 1; - toasts[control].message_label = label; - toasts[control].message_count_label = count_label; + + Toast &toast = toasts[control]; + toast.message = p_message; + toast.tooltip = p_tooltip; + toast.count = 1; + toast.message_label = label; + toast.message_count_label = count_label; } else { - if (toasts[control].popped) { - toasts[control].count += 1; + Toast &toast = toasts[control]; + if (toast.popped) { + toast.count += 1; } else { - toasts[control].count = 1; + toast.count = 1; } - toasts[control].remaining_time = toasts[control].duration; - toasts[control].popped = true; + toast.remaining_time = toast.duration; + toast.popped = true; control->show(); vbox_container->move_child(control, vbox_container->get_child_count()); _auto_hide_or_free_toasts(); @@ -480,6 +483,16 @@ void EditorToaster::_popup_str(const String &p_message, Severity p_severity, con vbox_container->reset_size(); is_processing_error = false; + set_process_internal(true); +} + +void EditorToaster::_toast_theme_changed(Control *p_control) { + ERR_FAIL_COND(!toasts.has(p_control)); + + Toast &toast = toasts[p_control]; + if (toast.close_button) { + toast.close_button->set_button_icon(get_editor_theme_icon(SNAME("Close"))); + } } void EditorToaster::close(Control *p_control) { @@ -488,11 +501,17 @@ void EditorToaster::close(Control *p_control) { toasts[p_control].popped = false; } -void EditorToaster::_close_button_theme_changed(Control *p_close_button) { - Button *close_button = Object::cast_to<Button>(p_close_button); - if (close_button) { - close_button->set_icon(get_editor_theme_icon(SNAME("Close"))); - } +void EditorToaster::instant_close(Control *p_control) { + close(p_control); + p_control->set_modulate(Color(1, 1, 1, 0)); +} + +void EditorToaster::_bind_methods() { + ClassDB::bind_method(D_METHOD("push_toast", "message", "severity", "tooltip"), &EditorToaster::_popup_str, DEFVAL(EditorToaster::SEVERITY_INFO), DEFVAL(String())); + + BIND_ENUM_CONSTANT(SEVERITY_INFO); + BIND_ENUM_CONSTANT(SEVERITY_WARNING); + BIND_ENUM_CONSTANT(SEVERITY_ERROR); } EditorToaster *EditorToaster::get_singleton() { @@ -501,7 +520,6 @@ EditorToaster *EditorToaster::get_singleton() { EditorToaster::EditorToaster() { set_notify_transform(true); - set_process_internal(true); // VBox. vbox_container = memnew(VBoxContainer); @@ -566,7 +584,7 @@ EditorToaster::EditorToaster() { eh.errfunc = _error_handler; add_error_handler(&eh); -}; +} EditorToaster::~EditorToaster() { singleton = nullptr; diff --git a/editor/gui/editor_toaster.h b/editor/gui/editor_toaster.h index 4bf32d94ba..0d0080945e 100644 --- a/editor/gui/editor_toaster.h +++ b/editor/gui/editor_toaster.h @@ -31,8 +31,6 @@ #ifndef EDITOR_TOASTER_H #define EDITOR_TOASTER_H -#include "core/string/ustring.h" -#include "core/templates/local_vector.h" #include "scene/gui/box_container.h" class Button; @@ -76,6 +74,9 @@ private: real_t remaining_time = 0.0; bool popped = false; + // Buttons + Button *close_button = nullptr; + // Messages String message; String tooltip; @@ -101,9 +102,10 @@ private: void _set_notifications_enabled(bool p_enabled); void _repop_old(); void _popup_str(const String &p_message, Severity p_severity, const String &p_tooltip); - void _close_button_theme_changed(Control *p_close_button); + void _toast_theme_changed(Control *p_control); protected: + static void _bind_methods(); static EditorToaster *singleton; void _notification(int p_what); @@ -114,6 +116,7 @@ public: Control *popup(Control *p_control, Severity p_severity = SEVERITY_INFO, double p_time = 0.0, const String &p_tooltip = String()); void popup_str(const String &p_message, Severity p_severity = SEVERITY_INFO, const String &p_tooltip = String()); void close(Control *p_control); + void instant_close(Control *p_control); EditorToaster(); ~EditorToaster(); diff --git a/editor/gui/editor_zoom_widget.cpp b/editor/gui/editor_zoom_widget.cpp index 50a4f020ab..ff232a854f 100644 --- a/editor/gui/editor_zoom_widget.cpp +++ b/editor/gui/editor_zoom_widget.cpp @@ -162,8 +162,8 @@ void EditorZoomWidget::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - zoom_minus->set_icon(get_editor_theme_icon(SNAME("ZoomLess"))); - zoom_plus->set_icon(get_editor_theme_icon(SNAME("ZoomMore"))); + zoom_minus->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess"))); + zoom_plus->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore"))); } break; } } diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp index 2e36b66025..e89912d5bc 100644 --- a/editor/gui/scene_tree_editor.cpp +++ b/editor/gui/scene_tree_editor.cpp @@ -369,16 +369,14 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { msg_temp += String::utf8("• ") + String(E.name) + "\n"; } } - } - if (num_connections >= 1 || num_groups >= 1) { - if (num_groups < 1) { - msg_temp += "\n"; - } - msg_temp += TTR("Click to show signals dock."); + } else { + msg_temp += "\n"; } Ref<Texture2D> icon_temp; SceneTreeEditorButton signal_temp = BUTTON_SIGNALS; + String msg_temp_end = TTR("Click to show signals dock."); + if (num_connections >= 1 && num_groups >= 1) { icon_temp = get_editor_theme_icon(SNAME("SignalsAndGroups")); } else if (num_connections >= 1) { @@ -386,9 +384,11 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } else if (num_groups >= 1) { icon_temp = get_editor_theme_icon(SNAME("Groups")); signal_temp = BUTTON_GROUPS; + msg_temp_end = TTR("Click to show groups dock."); } if (num_connections >= 1 || num_groups >= 1) { + msg_temp += msg_temp_end; item->add_button(0, icon_temp, signal_temp, false, msg_temp); } } @@ -1098,8 +1098,19 @@ void SceneTreeEditor::rename_node(Node *p_node, const String &p_name, TreeItem * // Trim leading/trailing whitespace to prevent node names from containing accidental whitespace, which would make it more difficult to get the node via `get_node()`. new_name = new_name.strip_edges(); + if (new_name.is_empty() && p_node->get_owner() != nullptr && !p_node->get_scene_file_path().is_empty()) { + // If name is empty and node is root of an instance, revert to the original name. + const Ref<PackedScene> node_scene = ResourceLoader::load(p_node->get_scene_file_path()); + if (node_scene.is_valid()) { + const Ref<SceneState> &state = node_scene->get_state(); + if (state->get_node_count() > 0) { + new_name = state->get_node_name(0); // Root's name. + } + } + } + if (new_name.is_empty()) { - // If name is empty, fallback to class name. + // If name is still empty, fallback to class name. if (GLOBAL_GET("editor/naming/node_name_casing").operator int() != NAME_CASING_PASCAL_CASE) { new_name = Node::adjust_name_casing(p_node->get_class()); } else { @@ -1684,24 +1695,30 @@ void SceneTreeDialog::_show_all_nodes_changed(bool p_button_pressed) { } void SceneTreeDialog::set_valid_types(const Vector<StringName> &p_valid) { - if (p_valid.is_empty()) { - return; + if (allowed_types_hbox) { + allowed_types_hbox->queue_free(); + allowed_types_hbox = nullptr; + valid_type_icons.clear(); } tree->set_valid_types(p_valid); - HBoxContainer *hbox = memnew(HBoxContainer); - content->add_child(hbox); - content->move_child(hbox, 0); + if (p_valid.is_empty()) { + return; + } + + allowed_types_hbox = memnew(HBoxContainer); + content->add_child(allowed_types_hbox); + content->move_child(allowed_types_hbox, 0); { Label *label = memnew(Label); - hbox->add_child(label); + allowed_types_hbox->add_child(label); label->set_text(TTR("Allowed:")); } HFlowContainer *hflow = memnew(HFlowContainer); - hbox->add_child(hflow); + allowed_types_hbox->add_child(hflow); hflow->set_h_size_flags(Control::SIZE_EXPAND_FILL); for (const StringName &type : p_valid) { @@ -1735,6 +1752,9 @@ void SceneTreeDialog::set_valid_types(const Vector<StringName> &p_valid) { } show_all_nodes->show(); + if (is_inside_tree()) { + _update_valid_type_icons(); + } } void SceneTreeDialog::_notification(int p_what) { @@ -1753,11 +1773,7 @@ void SceneTreeDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - filter->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - for (TextureRect *trect : valid_type_icons) { - trect->set_custom_minimum_size(Vector2(get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)), 0)); - trect->set_texture(trect->get_meta("icon")); - } + _update_valid_type_icons(); } break; case NOTIFICATION_EXIT_TREE: { @@ -1766,6 +1782,14 @@ void SceneTreeDialog::_notification(int p_what) { } } +void SceneTreeDialog::_update_valid_type_icons() { + filter->set_right_icon(get_editor_theme_icon(SNAME("Search"))); + for (TextureRect *trect : valid_type_icons) { + trect->set_custom_minimum_size(Vector2(get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)), 0)); + trect->set_texture(trect->get_meta("icon")); + } +} + void SceneTreeDialog::_cancel() { hide(); } diff --git a/editor/gui/scene_tree_editor.h b/editor/gui/scene_tree_editor.h index e623c8405d..eed6d4b954 100644 --- a/editor/gui/scene_tree_editor.h +++ b/editor/gui/scene_tree_editor.h @@ -199,6 +199,7 @@ class SceneTreeDialog : public ConfirmationDialog { LineEdit *filter = nullptr; CheckButton *show_all_nodes = nullptr; LocalVector<TextureRect *> valid_type_icons; + HBoxContainer *allowed_types_hbox = nullptr; void _select(); void _cancel(); @@ -208,6 +209,7 @@ class SceneTreeDialog : public ConfirmationDialog { void _show_all_nodes_changed(bool p_button_pressed); protected: + void _update_valid_type_icons(); void _notification(int p_what); static void _bind_methods(); diff --git a/editor/icons/2DNodes.svg b/editor/icons/2DNodes.svg new file mode 100644 index 0000000000..90b92a4bc7 --- /dev/null +++ b/editor/icons/2DNodes.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path fill="none" stroke="#8da5f3" stroke-width="2" d="M 8,13 C 5.2385763,13 3,10.761424 3,8 3,5.2385763 5.2385763,3 8,3"/><path fill="none" stroke="#8eef97" stroke-width="2" d="m 8,13 c 2.761424,0 5,-2.238576 5,-5 C 13,5.2385763 10.761424,3 8,3"/></svg>
\ No newline at end of file diff --git a/editor/icons/Camera.svg b/editor/icons/Camera.svg new file mode 100644 index 0000000000..8612d458a7 --- /dev/null +++ b/editor/icons/Camera.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path fill="#e0e0e0" d="M9 2a3 3 0 0 0-3 2.777 3 3 0 1 0-3 5.047V12a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-1l3 2V7l-3 2V7.23A3 3 0 0 0 9 2z"/></svg>
\ No newline at end of file diff --git a/editor/icons/FPS.svg b/editor/icons/FPS.svg new file mode 100644 index 0000000000..5ee818c308 --- /dev/null +++ b/editor/icons/FPS.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M7.25 4h-2v8h2v-2c1.656 0 3-1.344 3-3 0-1.657-1.344-3-3-3zm0 4v-2c.553 0 1 .448 1 1s-.447 1-1 1zM.25 7v5h2v-2h2v-2h-2v-1c0-.553.447-1 1-1h1v-2h-1c-1.656 0-3 1.344-3 3zM13.25 7c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h2v-2h-2c-1.381 0-2.5 1.119-2.5 2.5s1.119 2.5 2.5 2.5c.276 0 .5.224.5.5s-.224.5-.5.5h-2v2h2c1.381 0 2.5-1.119 2.5-2.5s-1.119-2.5-2.5-2.5z"/></svg>
\ No newline at end of file diff --git a/editor/icons/FlipWinding.svg b/editor/icons/FlipWinding.svg new file mode 100644 index 0000000000..8964ca8d5d --- /dev/null +++ b/editor/icons/FlipWinding.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><rect width="4.596" height="4.596" x="5.7" y="5.7" fill="#e0e0e0" fill-opacity=".6" rx="1" ry="1" transform="rotate(45 8 8)"/><path fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 2a6 6 0 00-2.5 11m.5-3L6 14H2M9 14a6 6 0 002.5-11M11 6 10 2h4"/></svg>
\ No newline at end of file diff --git a/editor/icons/Game.svg b/editor/icons/Game.svg new file mode 100644 index 0000000000..e75e5c5312 --- /dev/null +++ b/editor/icons/Game.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M 1,15 V 12 C 1,11.5 1.5,11 2,11 H 3 V 10 C 3,9.5 3.5,9 4,9 h 1 c 0.5,0 1,0.5 1,1 v 1 H 8 V 5 h 2 v 6 h 4 c 0.5,0 1,0.5 1,1 v 3 z"/><circle cx="9" cy="4" r="3" fill="#e0e0e0"/></svg>
\ No newline at end of file diff --git a/editor/icons/LookAtModifier3D.svg b/editor/icons/LookAtModifier3D.svg new file mode 100644 index 0000000000..9315b297ef --- /dev/null +++ b/editor/icons/LookAtModifier3D.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#fc7f7f"><path d="m5.742 11.508c.916-2.959 3.507-4.508 5.592-4.508.803 0 1.673.223 2.492.658.297-.182.563-.423.768-.731.754-1.134.446-2.665-.688-3.419-.309-.205-.66-.338-1.026-.389-.188-1.349-1.433-2.291-2.782-2.103s-2.29 1.433-2.103 2.782c.051.367.184.717.389 1.026l-3.56 3.56c-1.134-.754-2.665-.446-3.419.688s-.446 2.664.688 3.419c.308.205.659.338 1.026.389.188 1.349 1.433 2.29 2.782 2.103.342-.048.658-.164.936-.333-.467-.612-.856-1.337-1.102-2.206-.085-.3-.085-.617.007-.936z"/><path d="m11.334 8c-1.704 0-3.861 1.299-4.637 3.804-.034.119-.034.246 0 .366.745 2.638 2.97 3.83 4.637 3.83s3.891-1.192 4.641-3.816c.034-.12.034-.247 0-.367-.734-2.526-2.938-3.817-4.641-3.817zm0 6.667c-1.473 0-2.667-1.194-2.667-2.667s1.194-2.666 2.667-2.666 2.667 1.193 2.667 2.666-1.194 2.667-2.667 2.667z"/><circle cx="11.334" cy="12" r="1.333"/></g></svg>
\ No newline at end of file diff --git a/editor/icons/MaterialPreviewQuad.svg b/editor/icons/MaterialPreviewQuad.svg new file mode 100644 index 0000000000..9765a15df7 --- /dev/null +++ b/editor/icons/MaterialPreviewQuad.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="none" stroke="#000" stroke-linejoin="round" stroke-opacity=".8" stroke-width="2" d="m2 1 12 1v11l-12 1z"/><path fill="#f9f9f9" d="m2 14 12-1v-11l-12-1z"/></svg>
\ No newline at end of file diff --git a/editor/icons/NextFrame.svg b/editor/icons/NextFrame.svg new file mode 100644 index 0000000000..9609b2538b --- /dev/null +++ b/editor/icons/NextFrame.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m 12,3 c -0.552285,0 -1,0.4477153 -1,1 v 8 c 0,0.552285 0.447715,1 1,1 h 1 c 0.552285,0 1,-0.447715 1,-1 V 4 C 14,3.4477153 13.552285,3 13,3 Z M 2.975,3.002 C 2.4332786,3.0155465 2.0009144,3.45811 2,4 v 8 c -3.148e-4,0.838862 0.9701632,1.305289 1.625,0.781 l 5,-4 c 0.4989606,-0.4003069 0.4989606,-1.1596931 0,-1.56 l -5,-4 C 3.4409271,3.0736532 3.2107095,2.9960875 2.975,3.002 Z"/></svg>
\ No newline at end of file diff --git a/editor/icons/Unfavorite.svg b/editor/icons/Unfavorite.svg new file mode 100644 index 0000000000..78f1b90fd0 --- /dev/null +++ b/editor/icons/Unfavorite.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M 8 1.6992188 L 5.6269531 5.796875 L 1 6.8945312 L 4.2363281 10.302734 L 3.8769531 14.976562 L 8.0175781 12.998047 L 12.173828 14.941406 L 11.777344 10.287109 L 15 6.8945312 L 10.373047 5.796875 L 8 1.6992188 z M 8 4.2773438 L 9.4882812 6.8457031 L 12.388672 7.5332031 L 10.369141 9.6601562 L 10.617188 12.576172 L 8.0097656 11.359375 L 5.4160156 12.599609 L 5.640625 9.6699219 L 3.6113281 7.5332031 L 6.5117188 6.8457031 L 8 4.2773438 z"/></svg>
\ No newline at end of file diff --git a/editor/import/3d/collada.h b/editor/import/3d/collada.h index 416b917a46..f9c26e090c 100644 --- a/editor/import/3d/collada.h +++ b/editor/import/3d/collada.h @@ -359,7 +359,7 @@ public: for (int i = 0; i < children.size(); i++) { memdelete(children[i]); } - }; + } }; struct NodeSkeleton : public Node { diff --git a/editor/import/3d/editor_import_collada.cpp b/editor/import/3d/editor_import_collada.cpp index 04a3f23154..c04278fc55 100644 --- a/editor/import/3d/editor_import_collada.cpp +++ b/editor/import/3d/editor_import_collada.cpp @@ -1263,7 +1263,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres //bleh, must ignore invalid ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA); - mesh = Ref<ImporterMesh>(memnew(ImporterMesh)); + mesh.instantiate(); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; String name = meshdata.name; if (name.is_empty()) { diff --git a/editor/import/3d/resource_importer_obj.cpp b/editor/import/3d/resource_importer_obj.cpp index a579224ecd..59d39152e9 100644 --- a/editor/import/3d/resource_importer_obj.cpp +++ b/editor/import/3d/resource_importer_obj.cpp @@ -202,12 +202,12 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S return OK; } -static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, Vector3 p_scale_mesh, Vector3 p_offset_mesh, bool p_disable_compression, List<String> *r_missing_deps) { +static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_generate_lods, bool p_generate_shadow_mesh, bool p_generate_lightmap_uv2, float p_generate_lightmap_uv2_texel_size, const PackedByteArray &p_src_lightmap_cache, Vector3 p_scale_mesh, Vector3 p_offset_mesh, bool p_disable_compression, Vector<Vector<uint8_t>> &r_lightmap_caches, List<String> *r_missing_deps) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path)); - // Avoid trying to load/interpret potential build artifacts from Visual Studio (e.g. when compiling native plugins inside the project tree) - // This should only match, if it's indeed a COFF file header + // Avoid trying to load/interpret potential build artifacts from Visual Studio (e.g. when compiling native plugins inside the project tree). + // This should only match if it's indeed a COFF file header. // https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types const int first_bytes = f->get_16(); static const Vector<int> coff_header_machines{ @@ -445,6 +445,7 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes, } mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, array, TypedArray<Array>(), Dictionary(), material, name, mesh_flags); + print_verbose("OBJ: Added surface :" + mesh->get_surface_name(mesh->get_surface_count() - 1)); if (!current_material.is_empty()) { @@ -508,6 +509,43 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes, } } + if (p_generate_lightmap_uv2) { + Vector<uint8_t> lightmap_cache; + mesh->lightmap_unwrap_cached(Transform3D(), p_generate_lightmap_uv2_texel_size, p_src_lightmap_cache, lightmap_cache); + + if (!lightmap_cache.is_empty()) { + if (r_lightmap_caches.is_empty()) { + r_lightmap_caches.push_back(lightmap_cache); + } else { + // MD5 is stored at the beginning of the cache data. + const String new_md5 = String::md5(lightmap_cache.ptr()); + + for (int i = 0; i < r_lightmap_caches.size(); i++) { + const String md5 = String::md5(r_lightmap_caches[i].ptr()); + if (new_md5 < md5) { + r_lightmap_caches.insert(i, lightmap_cache); + break; + } + + if (new_md5 == md5) { + break; + } + } + } + } + } + + if (p_generate_lods) { + // Use normal merge/split angles that match the defaults used for 3D scene importing. + mesh->generate_lods(60.0f, {}); + } + + if (p_generate_shadow_mesh) { + mesh->create_shadow_mesh(); + } + + mesh->optimize_indices(); + if (p_single_mesh && mesh->get_surface_count() > 0) { r_meshes.push_back(mesh); } @@ -518,7 +556,10 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes, Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) { List<Ref<ImporterMesh>> meshes; - Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, Vector3(1, 1, 1), Vector3(0, 0, 0), p_flags & IMPORT_FORCE_DISABLE_MESH_COMPRESSION, r_missing_deps); + // LOD, shadow mesh and lightmap UV2 generation are handled by ResourceImporterScene in this case, + // so disable it within the OBJ mesh import. + Vector<Vector<uint8_t>> mesh_lightmap_caches; + Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, false, false, 0.2, PackedByteArray(), Vector3(1, 1, 1), Vector3(0, 0, 0), p_flags & IMPORT_FORCE_DISABLE_MESH_COMPRESSION, mesh_lightmap_caches, r_missing_deps); if (err != OK) { if (r_err) { @@ -587,19 +628,51 @@ String ResourceImporterOBJ::get_preset_name(int p_idx) const { void ResourceImporterOBJ::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_lods"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_shadow_mesh"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_lightmap_uv2", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "generate_lightmap_uv2_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.2)); r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "scale_mesh"), Vector3(1, 1, 1))); r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "offset_mesh"), Vector3(0, 0, 0))); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_disable_mesh_compression"), false)); } bool ResourceImporterOBJ::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { + if (p_option == "generate_lightmap_uv2_texel_size" && !p_options["generate_lightmap_uv2"]) { + // Only display the lightmap texel size import option when lightmap UV2 generation is enabled. + return false; + } + return true; } -Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterOBJ::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { List<Ref<ImporterMesh>> meshes; - Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["scale_mesh"], p_options["offset_mesh"], p_options["force_disable_mesh_compression"], nullptr); + Vector<uint8_t> src_lightmap_cache; + Vector<Vector<uint8_t>> mesh_lightmap_caches; + + Error err; + { + src_lightmap_cache = FileAccess::get_file_as_bytes(p_source_file + ".unwrap_cache", &err); + if (err != OK) { + src_lightmap_cache.clear(); + } + } + + err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["generate_lods"], p_options["generate_shadow_mesh"], p_options["generate_lightmap_uv2"], p_options["generate_lightmap_uv2_texel_size"], src_lightmap_cache, p_options["scale_mesh"], p_options["offset_mesh"], p_options["force_disable_mesh_compression"], mesh_lightmap_caches, nullptr); + + if (mesh_lightmap_caches.size()) { + Ref<FileAccess> f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE); + if (f.is_valid()) { + f->store_32(mesh_lightmap_caches.size()); + for (int i = 0; i < mesh_lightmap_caches.size(); i++) { + String md5 = String::md5(mesh_lightmap_caches[i].ptr()); + f->store_buffer(mesh_lightmap_caches[i].ptr(), mesh_lightmap_caches[i].size()); + } + } + } + err = OK; ERR_FAIL_COND_V(err != OK, err); ERR_FAIL_COND_V(meshes.size() != 1, ERR_BUG); diff --git a/editor/import/3d/resource_importer_obj.h b/editor/import/3d/resource_importer_obj.h index faf0f336c0..c4a99428ef 100644 --- a/editor/import/3d/resource_importer_obj.h +++ b/editor/import/3d/resource_importer_obj.h @@ -61,10 +61,7 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - - // Threaded import can currently cause deadlocks, see GH-48265. - virtual bool can_import_threaded() const override { return false; } + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterOBJ(); }; diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp index cb348f713c..86af9caf26 100644 --- a/editor/import/3d/resource_importer_scene.cpp +++ b/editor/import/3d/resource_importer_scene.cpp @@ -2043,9 +2043,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/shadow_meshes", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lightmap_uv", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lods", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "lods/normal_split_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), 25.0f)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "lods/normal_merge_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), 60.0f)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "lods/raycast_normals", PROPERTY_HINT_NONE, ""), false)); } break; case INTERNAL_IMPORT_CATEGORY_MATERIAL: { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "use_external/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); @@ -2474,9 +2472,7 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_ //do mesh processing bool generate_lods = p_generate_lods; - float split_angle = 25.0f; float merge_angle = 60.0f; - bool raycast_normals = false; bool create_shadow_meshes = p_create_shadow_meshes; bool bake_lightmaps = p_light_bake_mode == LIGHT_BAKE_STATIC_LIGHTMAPS; String save_to_file; @@ -2523,18 +2519,10 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_ } } - if (mesh_settings.has("lods/normal_split_angle")) { - split_angle = mesh_settings["lods/normal_split_angle"]; - } - if (mesh_settings.has("lods/normal_merge_angle")) { merge_angle = mesh_settings["lods/normal_merge_angle"]; } - if (mesh_settings.has("lods/raycast_normals")) { - raycast_normals = mesh_settings["lods/raycast_normals"]; - } - if (bool(mesh_settings.get("save_to_file/enabled", false))) { save_to_file = mesh_settings.get("save_to_file/path", String()); if (!save_to_file.is_resource_file()) { @@ -2579,17 +2567,17 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_ } } - src_mesh_node->get_mesh()->optimize_indices_for_cache(); - if (generate_lods) { Array skin_pose_transform_array = _get_skinned_pose_transforms(src_mesh_node); - src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle, skin_pose_transform_array, raycast_normals); + src_mesh_node->get_mesh()->generate_lods(merge_angle, skin_pose_transform_array); } if (create_shadow_meshes) { src_mesh_node->get_mesh()->create_shadow_mesh(); } + src_mesh_node->get_mesh()->optimize_indices(); + if (!save_to_file.is_empty()) { Ref<Mesh> existing = ResourceCache::get_ref(save_to_file); if (existing.is_valid()) { @@ -2634,6 +2622,7 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_ mesh_node->set_layer_mask(src_mesh_node->get_layer_mask()); mesh_node->set_cast_shadows_setting(src_mesh_node->get_cast_shadows_setting()); + mesh_node->set_visible(src_mesh_node->is_visible()); mesh_node->set_visibility_range_begin(src_mesh_node->get_visibility_range_begin()); mesh_node->set_visibility_range_begin_margin(src_mesh_node->get_visibility_range_begin_margin()); mesh_node->set_visibility_range_end(src_mesh_node->get_visibility_range_end()); @@ -2883,7 +2872,7 @@ Error ResourceImporterScene::_check_resource_save_paths(const Dictionary &p_data return OK; } -Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterScene::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { const String &src_path = p_source_file; Ref<EditorSceneFormatImporter> importer; @@ -3103,7 +3092,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p if (!scr.is_valid()) { EditorNode::add_io_error(TTR("Couldn't load post-import script:") + " " + post_import_script_path); } else { - post_import_script = Ref<EditorScenePostImport>(memnew(EditorScenePostImport)); + post_import_script.instantiate(); post_import_script->set_script(scr); if (!post_import_script->get_script_instance()) { EditorNode::add_io_error(TTR("Invalid/broken script for post-import (check console):") + " " + post_import_script_path); diff --git a/editor/import/3d/resource_importer_scene.h b/editor/import/3d/resource_importer_scene.h index fe757dc2a3..b2f5fab0eb 100644 --- a/editor/import/3d/resource_importer_scene.h +++ b/editor/import/3d/resource_importer_scene.h @@ -299,13 +299,11 @@ public: void _compress_animations(AnimationPlayer *anim, int p_page_size_kb); Node *pre_import(const String &p_source_file, const HashMap<StringName, Variant> &p_options); - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; virtual bool has_advanced_options() const override; virtual void show_advanced_options(const String &p_path) override; - virtual bool can_import_threaded() const override { return false; } - ResourceImporterScene(const String &p_scene_import_type = "PackedScene", bool p_singleton = false); ~ResourceImporterScene(); diff --git a/editor/import/3d/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp index 011d0135b4..945c1811d7 100644 --- a/editor/import/3d/scene_import_settings.cpp +++ b/editor/import/3d/scene_import_settings.cpp @@ -368,6 +368,7 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite mesh_node->set_transform(src_mesh_node->get_transform()); mesh_node->set_skin(src_mesh_node->get_skin()); mesh_node->set_skeleton_path(src_mesh_node->get_skeleton_path()); + mesh_node->set_visible(src_mesh_node->is_visible()); if (src_mesh_node->get_mesh().is_valid()) { Ref<ImporterMesh> editor_mesh = src_mesh_node->get_mesh(); mesh_node->set_mesh(editor_mesh->get_mesh()); @@ -1019,11 +1020,11 @@ void SceneImportSettingsDialog::_play_animation() { if (animation_player->has_animation(id)) { if (animation_player->is_playing()) { animation_player->pause(); - animation_play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); set_process(false); } else { animation_player->play(id); - animation_play_button->set_icon(get_editor_theme_icon(SNAME("Pause"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); set_process(true); } } @@ -1032,7 +1033,7 @@ void SceneImportSettingsDialog::_play_animation() { void SceneImportSettingsDialog::_stop_current_animation() { animation_pingpong = false; animation_player->stop(); - animation_play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); animation_slider->set_value_no_signal(0.0); set_process(false); } @@ -1044,7 +1045,7 @@ void SceneImportSettingsDialog::_reset_animation(const String &p_animation_name) if (animation_player != nullptr && animation_player->is_playing()) { animation_player->stop(); } - animation_play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); _reset_bone_transforms(); set_process(false); @@ -1066,7 +1067,7 @@ void SceneImportSettingsDialog::_reset_animation(const String &p_animation_name) animation_player->play(p_animation_name); } else { animation_player->stop(true); - animation_play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); animation_player->set_assigned_animation(p_animation_name); animation_player->seek(0.0, true); animation_slider->set_value_no_signal(0.0); @@ -1081,7 +1082,7 @@ void SceneImportSettingsDialog::_animation_slider_value_changed(double p_value) } if (animation_player->is_playing()) { animation_player->stop(); - animation_play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); set_process(false); } animation_player->seek(p_value * animation_map[selected_id].animation->get_length(), true); @@ -1097,7 +1098,7 @@ void SceneImportSettingsDialog::_animation_finished(const StringName &p_name) { switch (loop_mode) { case Animation::LOOP_NONE: { - animation_play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); animation_slider->set_value_no_signal(1.0); set_process(false); } break; @@ -1318,17 +1319,17 @@ void SceneImportSettingsDialog::_notification(int p_what) { action_menu->end_bulk_theme_override(); if (animation_player != nullptr && animation_player->is_playing()) { - animation_play_button->set_icon(get_editor_theme_icon(SNAME("Pause"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); } else { - animation_play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + animation_play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); } - animation_stop_button->set_icon(get_editor_theme_icon(SNAME("Stop"))); + animation_stop_button->set_button_icon(get_editor_theme_icon(SNAME("Stop"))); - light_1_switch->set_icon(theme_cache.light_1_icon); - light_2_switch->set_icon(theme_cache.light_2_icon); - light_rotate_switch->set_icon(theme_cache.rotate_icon); + light_1_switch->set_button_icon(theme_cache.light_1_icon); + light_2_switch->set_button_icon(theme_cache.light_2_icon); + light_rotate_switch->set_button_icon(theme_cache.rotate_icon); - animation_toggle_skeleton_visibility->set_icon(get_editor_theme_icon(SNAME("Skeleton3D"))); + animation_toggle_skeleton_visibility->set_button_icon(get_editor_theme_icon(SNAME("Skeleton3D"))); } break; case NOTIFICATION_PROCESS: { diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp index 9a0c62193c..dd45806385 100644 --- a/editor/import/audio_stream_import_settings.cpp +++ b/editor/import/audio_stream_import_settings.cpp @@ -45,8 +45,8 @@ void AudioStreamImportSettingsDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); - _stop_button->set_icon(get_editor_theme_icon(SNAME("Stop"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _stop_button->set_button_icon(get_editor_theme_icon(SNAME("Stop"))); _preview->set_color(get_theme_color(SNAME("dark_color_2"), EditorStringName(Editor))); color_rect->set_color(get_theme_color(SNAME("dark_color_1"), EditorStringName(Editor))); @@ -61,9 +61,9 @@ void AudioStreamImportSettingsDialog::_notification(int p_what) { _duration_label->add_theme_font_size_override(SceneStringName(font_size), get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts))); _duration_label->end_bulk_theme_override(); - zoom_in->set_icon(get_editor_theme_icon(SNAME("ZoomMore"))); - zoom_out->set_icon(get_editor_theme_icon(SNAME("ZoomLess"))); - zoom_reset->set_icon(get_editor_theme_icon(SNAME("ZoomReset"))); + zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore"))); + zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess"))); + zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset"))); _indicator->queue_redraw(); _preview->queue_redraw(); @@ -233,25 +233,25 @@ void AudioStreamImportSettingsDialog::_play() { // '_pausing' variable indicates that we want to pause the audio player, not stop it. See '_on_finished()'. _pausing = true; _player->stop(); - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); set_process(false); } else { _player->play(_current); - _play_button->set_icon(get_editor_theme_icon(SNAME("Pause"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); set_process(true); } } void AudioStreamImportSettingsDialog::_stop() { _player->stop(); - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); _current = 0; _indicator->queue_redraw(); set_process(false); } void AudioStreamImportSettingsDialog::_on_finished() { - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); if (!_pausing) { _current = 0; _indicator->queue_redraw(); @@ -580,12 +580,10 @@ AudioStreamImportSettingsDialog::AudioStreamImportSettingsDialog() { bar_beats_edit->set_max(32); bar_beats_edit->connect(SceneStringName(value_changed), callable_mp(this, &AudioStreamImportSettingsDialog::_settings_changed).unbind(1)); interactive_hb->add_child(bar_beats_edit); - interactive_hb->add_spacer(); main_vbox->add_margin_child(TTR("Music Playback:"), interactive_hb); color_rect = memnew(ColorRect); - main_vbox->add_margin_child(TTR("Preview:"), color_rect); - + main_vbox->add_margin_child(TTR("Preview:"), color_rect, true); color_rect->set_custom_minimum_size(Size2(600, 200) * EDSCALE); color_rect->set_v_size_flags(Control::SIZE_EXPAND_FILL); diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index e124697b20..8bbad91b68 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -940,7 +940,7 @@ void DynamicFontImportSettingsDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - add_var->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_var->set_button_icon(get_editor_theme_icon(SNAME("Add"))); label_warn->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } break; } diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index 3243dcf256..650c0e27ca 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -163,7 +163,7 @@ bool EditorImportPlugin::get_option_visibility(const String &p_path, const Strin ERR_FAIL_V_MSG(false, "Unimplemented _get_option_visibility in add-on."); } -Error EditorImportPlugin::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error EditorImportPlugin::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { Dictionary options; TypedArray<String> platform_variants, gen_files; diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index ea5cfc2682..df472b416b 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -69,7 +69,7 @@ public: virtual int get_import_order() const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; virtual bool can_import_threaded() const override; Error append_import_external_resource(const String &p_file, const HashMap<StringName, Variant> &p_custom_options = HashMap<StringName, Variant>(), const String &p_custom_importer = String(), Variant p_generator_parameters = Variant()); }; diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp index e7b7850b02..8441a49666 100644 --- a/editor/import/resource_importer_bitmask.cpp +++ b/editor/import/resource_importer_bitmask.cpp @@ -72,7 +72,7 @@ void ResourceImporterBitMap::get_import_options(const String &p_path, List<Impor r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.5)); } -Error ResourceImporterBitMap::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterBitMap::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { int create_from = p_options["create_from"]; float threshold = p_options["threshold"]; Ref<Image> image; diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h index 8963c8d918..fcb152b47d 100644 --- a/editor/import/resource_importer_bitmask.h +++ b/editor/import/resource_importer_bitmask.h @@ -48,7 +48,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterBitMap(); ~ResourceImporterBitMap(); diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp index 085ca1362d..b7efdbb6d6 100644 --- a/editor/import/resource_importer_bmfont.cpp +++ b/editor/import/resource_importer_bmfont.cpp @@ -67,7 +67,7 @@ void ResourceImporterBMFont::get_import_options(const String &p_path, List<Impor r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "scaling_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled (Integer),Enabled (Fractional)"), TextServer::FIXED_SIZE_SCALE_ENABLED)); } -Error ResourceImporterBMFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterBMFont::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing BMFont font from: " + p_source_file); Array fallbacks = p_options["fallbacks"]; diff --git a/editor/import/resource_importer_bmfont.h b/editor/import/resource_importer_bmfont.h index d31cd03736..74fef9ff16 100644 --- a/editor/import/resource_importer_bmfont.h +++ b/editor/import/resource_importer_bmfont.h @@ -48,7 +48,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterBMFont(); }; diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index c181011402..17f6070d35 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -72,7 +72,7 @@ void ResourceImporterCSVTranslation::get_import_options(const String &p_path, Li r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "delimiter", PROPERTY_HINT_ENUM, "Comma,Semicolon,Tab"), 0)); } -Error ResourceImporterCSVTranslation::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterCSVTranslation::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { bool compress = p_options["compress"]; String delimiter; @@ -147,6 +147,9 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const if (r_gen_files) { r_gen_files->push_back(save_path); } + + ResourceUID::ID save_id = hash64_murmur3_64(translations[i]->get_locale().hash64(), p_source_id); + ResourceSaver::set_uid(save_path, save_id); } return OK; diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h index c6b05eb043..63676c61a6 100644 --- a/editor/import/resource_importer_csv_translation.h +++ b/editor/import/resource_importer_csv_translation.h @@ -49,7 +49,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterCSVTranslation(); }; diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index fa222b2790..a4a5e445e3 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -141,7 +141,7 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) { DynamicFontImportSettingsDialog::get_singleton()->open_settings(p_path); } -Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterDynamicFont::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing dynamic font from: " + p_source_file); int antialiasing = p_options["antialiasing"]; diff --git a/editor/import/resource_importer_dynamic_font.h b/editor/import/resource_importer_dynamic_font.h index de89e6b76f..73ef96d583 100644 --- a/editor/import/resource_importer_dynamic_font.h +++ b/editor/import/resource_importer_dynamic_font.h @@ -58,7 +58,9 @@ public: bool has_advanced_options() const override; void show_advanced_options(const String &p_path) override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterDynamicFont(); }; diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp index 4f6dd4e4ef..5a4f64d245 100644 --- a/editor/import/resource_importer_image.cpp +++ b/editor/import/resource_importer_image.cpp @@ -70,7 +70,7 @@ String ResourceImporterImage::get_preset_name(int p_idx) const { void ResourceImporterImage::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { } -Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterImage::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'."); diff --git a/editor/import/resource_importer_image.h b/editor/import/resource_importer_image.h index 1490ab30d5..da1925bc5c 100644 --- a/editor/import/resource_importer_image.h +++ b/editor/import/resource_importer_image.h @@ -50,7 +50,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterImage(); }; diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index f01381904d..950058e88e 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -75,7 +75,7 @@ void ResourceImporterImageFont::get_import_options(const String &p_path, List<Im r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "scaling_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled (Integer),Enabled (Fractional)"), TextServer::FIXED_SIZE_SCALE_ENABLED)); } -Error ResourceImporterImageFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterImageFont::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing image font from: " + p_source_file); int columns = p_options["columns"]; @@ -199,7 +199,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin case STEP_OFF_Y_BEGIN: { // Read advance and offset. if (range[c] == ' ') { - int next = range.find(" ", c + 1); + int next = range.find_char(' ', c + 1); if (next < c) { next = range.length(); } diff --git a/editor/import/resource_importer_imagefont.h b/editor/import/resource_importer_imagefont.h index 065351c361..79e9455d6d 100644 --- a/editor/import/resource_importer_imagefont.h +++ b/editor/import/resource_importer_imagefont.h @@ -48,7 +48,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterImageFont(); }; diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index 312195fcd7..0d0c89425d 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -289,7 +289,7 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons } } -Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterLayeredTexture::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { int compress_mode = p_options["compress/mode"]; float lossy = p_options["compress/lossy_quality"]; bool high_quality = p_options["compress/high_quality"]; diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 26495eed8d..271f1f4543 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -112,11 +112,13 @@ public: void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2); - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const override; virtual String get_import_settings_string() const override; + virtual bool can_import_threaded() const override { return true; } + void set_mode(Mode p_mode) { mode = p_mode; } ResourceImporterLayeredTexture(bool p_singleton = false); diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index b7508e7644..639ce48f75 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -89,7 +89,7 @@ static String _include_function(const String &p_path, void *userpointer) { return file_inc->get_as_utf8_string(); } -Error ResourceImporterShaderFile::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterShaderFile::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { /* STEP 1, Read shader code */ ERR_FAIL_COND_V_EDMSG((OS::get_singleton()->get_current_rendering_method() == "gl_compatibility"), ERR_UNAVAILABLE, "Cannot import custom .glsl shaders when using the gl_compatibility rendering_method. Please switch to the forward_plus or mobile rendering methods to use custom shaders."); ERR_FAIL_COND_V_EDMSG((DisplayServer::get_singleton()->get_name() == "headless"), ERR_UNAVAILABLE, "Cannot import custom .glsl shaders when running in headless mode."); diff --git a/editor/import/resource_importer_shader_file.h b/editor/import/resource_importer_shader_file.h index aefc967989..440a3d86b4 100644 --- a/editor/import/resource_importer_shader_file.h +++ b/editor/import/resource_importer_shader_file.h @@ -49,7 +49,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterShaderFile(); }; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 24a14c60ad..d72c15bc2a 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -241,7 +241,10 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_as_srgb"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_clamp_exposure"), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); + + // Maximum bound is the highest allowed value for lossy compression (the lowest common denominator). + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,16383,1"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "detect_3d/compress_to", PROPERTY_HINT_ENUM, "Disabled,VRAM Compressed,Basis Universal"), (p_preset == PRESET_DETECT) ? 1 : 0)); // Do path based customization only if a path was passed. @@ -428,7 +431,7 @@ Dictionary ResourceImporterTexture::_load_editor_meta(const String &p_path) cons return f->get_var(); } -Error ResourceImporterTexture::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { // Parse import options. int32_t loader_flags = ImageFormatLoader::FLAG_NONE; @@ -454,7 +457,28 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String const bool normal_map_invert_y = p_options["process/normal_map_invert_y"]; // Support for texture streaming is not implemented yet. const bool stream = false; - const int size_limit = p_options["process/size_limit"]; + + int size_limit = p_options["process/size_limit"]; + bool using_fallback_size_limit = false; + if (size_limit == 0) { + using_fallback_size_limit = true; + // If no size limit is defined, use a fallback size limit to prevent textures from looking incorrect or failing to import. + switch (compress_mode) { + case COMPRESS_LOSSY: + // Maximum WebP size on either axis. + size_limit = 16383; + break; + case COMPRESS_BASIS_UNIVERSAL: + // Maximum Basis Universal size on either axis. + size_limit = 16384; + break; + default: + // As of June 2024, no GPU can correctly display a texture larger than 32768 pixels on either axis. + size_limit = 32768; + break; + } + } + const bool hdr_as_srgb = p_options["process/hdr_as_srgb"]; if (hdr_as_srgb) { loader_flags |= ImageFormatLoader::FLAG_FORCE_LINEAR; @@ -523,11 +547,19 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String int new_width = size_limit; int new_height = target_image->get_height() * new_width / target_image->get_width(); + if (using_fallback_size_limit) { + // Only warn if downsizing occurred when the user did not explicitly request it. + WARN_PRINT(vformat("%s: Texture was downsized on import as its width (%d pixels) exceeded the importable size limit (%d pixels).", p_source_file, target_image->get_width(), size_limit)); + } target_image->resize(new_width, new_height, Image::INTERPOLATE_CUBIC); } else { int new_height = size_limit; int new_width = target_image->get_width() * new_height / target_image->get_height(); + if (using_fallback_size_limit) { + // Only warn if downsizing occurred when the user did not explicitly request it. + WARN_PRINT(vformat("%s: Texture was downsized on import as its height (%d pixels) exceeded the importable size limit (%d pixels).", p_source_file, target_image->get_height(), size_limit)); + } target_image->resize(new_width, new_height, Image::INTERPOLATE_CUBIC); } @@ -558,7 +590,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { const Color color = target_image->get_pixel(i, j); - target_image->set_pixel(i, j, Color(color.r, 1 - color.g, color.b)); + target_image->set_pixel(i, j, Color(color.r, 1 - color.g, color.b, color.a)); } } } diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index 6d74c4e2f9..8aa044f3c8 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -100,7 +100,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } void update_imports(); diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index d6ce39f6a6..7e645cc0d0 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -91,7 +91,7 @@ String ResourceImporterTextureAtlas::get_option_group_file() const { return "atlas_file"; } -Error ResourceImporterTextureAtlas::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterTextureAtlas::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { /* If this happens, it's because the atlas_file field was not filled, so just import a broken texture */ //use an xpm because it's size independent, the editor images are vector and size dependent diff --git a/editor/import/resource_importer_texture_atlas.h b/editor/import/resource_importer_texture_atlas.h index 0f2b10424c..943f221679 100644 --- a/editor/import/resource_importer_texture_atlas.h +++ b/editor/import/resource_importer_texture_atlas.h @@ -64,9 +64,11 @@ public: virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; virtual String get_option_group_file() const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; virtual Error import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) override; + virtual bool can_import_threaded() const override { return true; } + ResourceImporterTextureAtlas(); }; diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 7a6f39906c..f500ec4a07 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -94,7 +94,7 @@ void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOp r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "PCM (Uncompressed),IMA ADPCM,Quite OK Audio"), 2)); } -Error ResourceImporterWAV::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterWAV::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { /* STEP 1, READ WAVE FILE */ Error err; @@ -112,7 +112,15 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } /* GET FILESIZE */ - file->get_32(); // filesize + + // The file size in header is 8 bytes less than the actual size. + // See https://docs.fileformat.com/audio/wav/ + const int FILE_SIZE_HEADER_OFFSET = 8; + uint32_t file_size_header = file->get_32() + FILE_SIZE_HEADER_OFFSET; + uint64_t file_size = file->get_length(); + if (file_size != file_size_header) { + WARN_PRINT(vformat("File size %d is %s than the expected size %d. (%s)", file_size, file_size > file_size_header ? "larger" : "smaller", file_size_header, p_source_file)); + } /* CHECK WAVE */ @@ -198,11 +206,14 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s break; } + uint64_t remaining_bytes = file_size - file_pos; frames = chunksize; - - if (format_channels == 0) { - ERR_FAIL_COND_V(format_channels == 0, ERR_INVALID_DATA); + if (remaining_bytes < chunksize) { + WARN_PRINT(vformat("Data chunk size is smaller than expected. Proceeding with actual data size. (%s)", p_source_file)); + frames = remaining_bytes; } + + ERR_FAIL_COND_V(format_channels == 0, ERR_INVALID_DATA); frames /= format_channels; frames /= (format_bits >> 3); diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h index 47af37ba41..361541c6c1 100644 --- a/editor/import/resource_importer_wav.h +++ b/editor/import/resource_importer_wav.h @@ -140,7 +140,9 @@ public: } } - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterWAV(); }; diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 14065abf73..6c22a965ae 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -790,23 +790,14 @@ ImportDock::ImportDock() { import->set_text(TTR("Reimport")); import->set_disabled(true); import->connect(SceneStringName(pressed), callable_mp(this, &ImportDock::_reimport_pressed)); - if (!DisplayServer::get_singleton()->get_swap_cancel_ok()) { - advanced_spacer = hb->add_spacer(); - advanced = memnew(Button); - advanced->set_text(TTR("Advanced...")); - hb->add_child(advanced); - } + advanced_spacer = hb->add_spacer(); + advanced = memnew(Button); + advanced->set_text(TTR("Advanced...")); + hb->add_child(advanced); hb->add_spacer(); hb->add_child(import); hb->add_spacer(); - if (DisplayServer::get_singleton()->get_swap_cancel_ok()) { - advanced = memnew(Button); - advanced->set_text(TTR("Advanced...")); - hb->add_child(advanced); - advanced_spacer = hb->add_spacer(); - } - advanced->hide(); advanced_spacer->hide(); advanced->connect(SceneStringName(pressed), callable_mp(this, &ImportDock::_advanced_options)); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index d13a022d52..46876644fb 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -427,35 +427,36 @@ void InspectorDock::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { - resource_new_button->set_icon(get_editor_theme_icon(SNAME("New"))); - resource_load_button->set_icon(get_editor_theme_icon(SNAME("Load"))); - resource_save_button->set_icon(get_editor_theme_icon(SNAME("Save"))); - resource_extra_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); - open_docs_button->set_icon(get_editor_theme_icon(SNAME("HelpSearch"))); + resource_new_button->set_button_icon(get_editor_theme_icon(SNAME("New"))); + resource_load_button->set_button_icon(get_editor_theme_icon(SNAME("Load"))); + resource_save_button->set_button_icon(get_editor_theme_icon(SNAME("Save"))); + resource_extra_button->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + open_docs_button->set_button_icon(get_editor_theme_icon(SNAME("HelpSearch"))); PopupMenu *resource_extra_popup = resource_extra_button->get_popup(); resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_EDIT_CLIPBOARD), get_editor_theme_icon(SNAME("ActionPaste"))); resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_COPY), get_editor_theme_icon(SNAME("ActionCopy"))); + resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_SHOW_IN_FILESYSTEM), get_editor_theme_icon(SNAME("ShowInFileSystem"))); if (is_layout_rtl()) { - backward_button->set_icon(get_editor_theme_icon(SNAME("Forward"))); - forward_button->set_icon(get_editor_theme_icon(SNAME("Back"))); + backward_button->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); + forward_button->set_button_icon(get_editor_theme_icon(SNAME("Back"))); } else { - backward_button->set_icon(get_editor_theme_icon(SNAME("Back"))); - forward_button->set_icon(get_editor_theme_icon(SNAME("Forward"))); + backward_button->set_button_icon(get_editor_theme_icon(SNAME("Back"))); + forward_button->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); } const int icon_width = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)); history_menu->get_popup()->add_theme_constant_override("icon_max_width", icon_width); - history_menu->set_icon(get_editor_theme_icon(SNAME("History"))); - object_menu->set_icon(get_editor_theme_icon(SNAME("Tools"))); + history_menu->set_button_icon(get_editor_theme_icon(SNAME("History"))); + object_menu->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); search->set_right_icon(get_editor_theme_icon(SNAME("Search"))); if (info_is_warning) { - info->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); + info->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning"))); info->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } else { - info->set_icon(get_editor_theme_icon(SNAME("NodeInfo"))); + info->set_button_icon(get_editor_theme_icon(SNAME("NodeInfo"))); info->add_theme_color_override(SceneStringName(font_color), get_theme_color(SceneStringName(font_color), EditorStringName(Editor))); } } break; @@ -482,10 +483,10 @@ void InspectorDock::set_info(const String &p_button_text, const String &p_messag info_is_warning = p_is_warning; if (info_is_warning) { - info->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); + info->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning"))); info->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } else { - info->set_icon(get_editor_theme_icon(SNAME("NodeInfo"))); + info->set_button_icon(get_editor_theme_icon(SNAME("NodeInfo"))); info->add_theme_color_override(SceneStringName(font_color), get_theme_color(SceneStringName(font_color), EditorStringName(Editor))); } diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 60ce8100aa..924f7abdd2 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -113,7 +113,7 @@ class InspectorDock : public VBoxContainer { void _new_resource(); void _load_resource(const String &p_type = ""); - void _open_resource_selector() { _load_resource(); }; // just used to call from arg-less signal + void _open_resource_selector() { _load_resource(); } // just used to call from arg-less signal void _resource_file_selected(const String &p_file); void _save_resource(bool save_as); void _unref_resource(); diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index 921467ccbc..7b2e6e81ee 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -441,7 +441,7 @@ void LocalizationEditor::_filesystem_files_moved(const String &p_old_file, const bool remapped_files_updated = false; for (int j = 0; j < remapped_files.size(); j++) { - int splitter_pos = remapped_files[j].rfind(":"); + int splitter_pos = remapped_files[j].rfind_char(':'); String res_path = remapped_files[j].substr(0, splitter_pos); if (res_path == p_old_file) { @@ -482,7 +482,7 @@ void LocalizationEditor::_filesystem_file_removed(const String &p_file) { for (int i = 0; i < remap_keys.size() && !remaps_changed; i++) { PackedStringArray remapped_files = remaps[remap_keys[i]]; for (int j = 0; j < remapped_files.size() && !remaps_changed; j++) { - int splitter_pos = remapped_files[j].rfind(":"); + int splitter_pos = remapped_files[j].rfind_char(':'); String res_path = remapped_files[j].substr(0, splitter_pos); remaps_changed = p_file == res_path; if (remaps_changed) { @@ -567,7 +567,7 @@ void LocalizationEditor::update_translations() { PackedStringArray selected = remaps[keys[i]]; for (int j = 0; j < selected.size(); j++) { const String &s2 = selected[j]; - int qp = s2.rfind(":"); + int qp = s2.rfind_char(':'); String path = s2.substr(0, qp); String locale = s2.substr(qp + 1, s2.length()); diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index 0da8d8291f..985a319c84 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -52,8 +52,8 @@ void NodeDock::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - connections_button->set_icon(get_editor_theme_icon(SNAME("Signals"))); - groups_button->set_icon(get_editor_theme_icon(SNAME("Groups"))); + connections_button->set_button_icon(get_editor_theme_icon(SNAME("Signals"))); + groups_button->set_button_icon(get_editor_theme_icon(SNAME("Groups"))); } break; } } diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 804f9c607e..990b8df49d 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -158,9 +158,9 @@ void AbstractPolygon2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - button_create->set_icon(get_editor_theme_icon(SNAME("CurveCreate"))); - button_edit->set_icon(get_editor_theme_icon(SNAME("CurveEdit"))); - button_delete->set_icon(get_editor_theme_icon(SNAME("CurveDelete"))); + button_create->set_button_icon(get_editor_theme_icon(SNAME("CurveCreate"))); + button_edit->set_button_icon(get_editor_theme_icon(SNAME("CurveEdit"))); + button_delete->set_button_icon(get_editor_theme_icon(SNAME("CurveDelete"))); } break; case NOTIFICATION_READY: { diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index cbf8b27b32..3f534eebc5 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -576,12 +576,12 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) { error_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); error_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); - tool_blend->set_icon(get_editor_theme_icon(SNAME("EditPivot"))); - tool_select->set_icon(get_editor_theme_icon(SNAME("ToolSelect"))); - tool_create->set_icon(get_editor_theme_icon(SNAME("EditKey"))); - tool_erase->set_icon(get_editor_theme_icon(SNAME("Remove"))); - snap->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); - open_editor->set_icon(get_editor_theme_icon(SNAME("Edit"))); + tool_blend->set_button_icon(get_editor_theme_icon(SNAME("EditPivot"))); + tool_select->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + tool_create->set_button_icon(get_editor_theme_icon(SNAME("EditKey"))); + tool_erase->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); + snap->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); + open_editor->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); interpolation->clear(); interpolation->add_icon_item(get_editor_theme_icon(SNAME("TrackContinuous")), TTR("Continuous"), 0); interpolation->add_icon_item(get_editor_theme_icon(SNAME("TrackDiscrete")), TTR("Discrete"), 1); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 934f26415a..ba2dad5880 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -798,14 +798,14 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) { error_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); error_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); - tool_blend->set_icon(get_editor_theme_icon(SNAME("EditPivot"))); - tool_select->set_icon(get_editor_theme_icon(SNAME("ToolSelect"))); - tool_create->set_icon(get_editor_theme_icon(SNAME("EditKey"))); - tool_triangle->set_icon(get_editor_theme_icon(SNAME("ToolTriangle"))); - tool_erase->set_icon(get_editor_theme_icon(SNAME("Remove"))); - snap->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); - open_editor->set_icon(get_editor_theme_icon(SNAME("Edit"))); - auto_triangles->set_icon(get_editor_theme_icon(SNAME("AutoTriangle"))); + tool_blend->set_button_icon(get_editor_theme_icon(SNAME("EditPivot"))); + tool_select->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + tool_create->set_button_icon(get_editor_theme_icon(SNAME("EditKey"))); + tool_triangle->set_button_icon(get_editor_theme_icon(SNAME("ToolTriangle"))); + tool_erase->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); + snap->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); + open_editor->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + auto_triangles->set_button_icon(get_editor_theme_icon(SNAME("AutoTriangle"))); interpolation->clear(); interpolation->add_icon_item(get_editor_theme_icon(SNAME("TrackContinuous")), TTR("Continuous"), 0); interpolation->add_icon_item(get_editor_theme_icon(SNAME("TrackDiscrete")), TTR("Discrete"), 1); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 9e282cb3fa..096e92e235 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -45,6 +45,7 @@ #include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/gui/check_box.h" +#include "scene/gui/grid_container.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" #include "scene/gui/panel.h" @@ -178,7 +179,7 @@ void AnimationNodeBlendTreeEditor::update_graph() { Button *delete_button = memnew(Button); delete_button->set_flat(true); delete_button->set_focus_mode(FOCUS_NONE); - delete_button->set_icon(get_editor_theme_icon(SNAME("Close"))); + delete_button->set_button_icon(get_editor_theme_icon(SNAME("Close"))); delete_button->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_node_request).bind(E), CONNECT_DEFERRED); node->get_titlebar_hbox()->add_child(delete_button); } @@ -216,7 +217,7 @@ void AnimationNodeBlendTreeEditor::update_graph() { node->add_child(memnew(HSeparator)); Button *open_in_editor = memnew(Button); open_in_editor->set_text(TTR("Open Editor")); - open_in_editor->set_icon(get_editor_theme_icon(SNAME("Edit"))); + open_in_editor->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); node->add_child(open_in_editor); open_in_editor->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor).bind(E), CONNECT_DEFERRED); open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER); @@ -230,7 +231,7 @@ void AnimationNodeBlendTreeEditor::update_graph() { } else { inspect_filters->set_text(TTR("Edit Filters")); } - inspect_filters->set_icon(get_editor_theme_icon(SNAME("AnimationFilter"))); + inspect_filters->set_button_icon(get_editor_theme_icon(SNAME("AnimationFilter"))); node->add_child(inspect_filters); inspect_filters->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendTreeEditor::_inspect_filters).bind(E), CONNECT_DEFERRED); inspect_filters->set_h_size_flags(SIZE_SHRINK_CENTER); @@ -240,7 +241,7 @@ void AnimationNodeBlendTreeEditor::update_graph() { if (anim.is_valid()) { MenuButton *mb = memnew(MenuButton); mb->set_text(anim->get_animation()); - mb->set_icon(get_editor_theme_icon(SNAME("Animation"))); + mb->set_button_icon(get_editor_theme_icon(SNAME("Animation"))); mb->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); mb->set_disabled(read_only); Array options; @@ -1265,7 +1266,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); open_file->connect("file_selected", callable_mp(this, &AnimationNodeBlendTreeEditor::_file_opened)); - animation_node_inspector_plugin = Ref<EditorInspectorPluginAnimationNodeAnimation>(memnew(EditorInspectorPluginAnimationNodeAnimation)); + animation_node_inspector_plugin.instantiate(); EditorInspector::add_inspector_plugin(animation_node_inspector_plugin); } @@ -1375,7 +1376,7 @@ void AnimationNodeAnimationEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { button->set_theme_type_variation(SNAME("InspectorActionButton")); - button->set_icon(get_editor_theme_icon(SNAME("Edit"))); + button->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); } break; } } @@ -1397,32 +1398,30 @@ bool EditorInspectorPluginAnimationNodeAnimation::parse_property(Object *p_objec } AnimationNodeAnimationEditorDialog::AnimationNodeAnimationEditorDialog() { - set_title(TTR("Select Markers...")); - VBoxContainer *vbox = memnew(VBoxContainer); - add_child(vbox); - vbox->set_offsets_preset(Control::PRESET_FULL_RECT); - - HBoxContainer *container_start = memnew(HBoxContainer); - vbox->add_child(container_start); - Label *label_start = memnew(Label); - container_start->add_child(label_start); + set_title(TTR("Select Markers")); + + GridContainer *grid = memnew(GridContainer); + grid->set_columns(2); + grid->set_offsets_preset(Control::PRESET_FULL_RECT); + add_child(grid); + + Label *label_start = memnew(Label(TTR("Start Marker"))); + grid->add_child(label_start); label_start->set_h_size_flags(Control::SIZE_EXPAND_FILL); label_start->set_stretch_ratio(1); - label_start->set_text(TTR("Start Marker")); select_start = memnew(OptionButton); - container_start->add_child(select_start); + select_start->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + grid->add_child(select_start); select_start->set_h_size_flags(Control::SIZE_EXPAND_FILL); select_start->set_stretch_ratio(2); - HBoxContainer *container_end = memnew(HBoxContainer); - vbox->add_child(container_end); - Label *label_end = memnew(Label); - container_end->add_child(label_end); + Label *label_end = memnew(Label(TTR("End Marker"))); + grid->add_child(label_end); label_end->set_h_size_flags(Control::SIZE_EXPAND_FILL); label_end->set_stretch_ratio(1); - label_end->set_text(TTR("End Marker")); select_end = memnew(OptionButton); - container_end->add_child(select_end); + select_end->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + grid->add_child(select_end); select_end->set_h_size_flags(Control::SIZE_EXPAND_FILL); select_end->set_stretch_ratio(2); } diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp index 147b92c094..46410b581e 100644 --- a/editor/plugins/animation_library_editor.cpp +++ b/editor/plugins/animation_library_editor.cpp @@ -30,7 +30,12 @@ #include "animation_library_editor.h" +#include "core/string/print_string.h" +#include "core/string/ustring.h" +#include "core/templates/vector.h" +#include "core/variant/variant.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" @@ -518,6 +523,8 @@ void AnimationLibraryEditor::_item_renamed() { if (restore_text) { ti->set_text(0, old_text); } + + _save_mixer_lib_folding(ti); } void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int p_id, MouseButton p_button) { @@ -670,6 +677,8 @@ void AnimationLibraryEditor::update_tree() { TreeItem *root = tree->create_item(); List<StringName> libs; + Vector<uint64_t> collapsed_lib_ids = _load_mixer_libs_folding(); + mixer->get_animation_library_list(&libs); for (const StringName &K : libs) { @@ -759,12 +768,203 @@ void AnimationLibraryEditor::update_tree() { anitem->set_text(1, anim_path.get_file()); } } + anitem->add_button(1, get_editor_theme_icon("Save"), ANIM_BUTTON_FILE, animation_library_is_foreign, TTR("Save animation to resource on disk.")); anitem->add_button(1, get_editor_theme_icon("Remove"), ANIM_BUTTON_DELETE, animation_library_is_foreign, TTR("Remove animation from Library.")); + + for (const uint64_t &lib_id : collapsed_lib_ids) { + Object *lib_obj = ObjectDB::get_instance(ObjectID(lib_id)); + AnimationLibrary *cur_lib = Object::cast_to<AnimationLibrary>(lib_obj); + StringName M = mixer->get_animation_library_name(cur_lib); + + if (M == K) { + libitem->set_collapsed_recursive(true); + } + } } } } +void AnimationLibraryEditor::_save_mixer_lib_folding(TreeItem *p_item) { + //Check if ti is a library or animation + if (p_item->get_parent()->get_parent() != nullptr) { + return; + } + + Ref<ConfigFile> config; + config.instantiate(); + + String path = EditorPaths::get_singleton()->get_project_settings_dir().path_join("lib_folding.cfg"); + Error err = config->load(path); + if (err != OK && err != ERR_FILE_NOT_FOUND) { + ERR_PRINT("Error loading lib_folding.cfg: " + itos(err)); + } + + // Get unique identifier for this scene+mixer combination + String md = (mixer->get_tree()->get_edited_scene_root()->get_scene_file_path() + mixer->get_path()).md5_text(); + + PackedStringArray collapsed_lib_names; + PackedStringArray collapsed_lib_ids; + + if (config->has_section(md)) { + collapsed_lib_names = String(config->get_value(md, "folding")).split("\n"); + collapsed_lib_ids = String(config->get_value(md, "id")).split("\n"); + } + + String lib_name = p_item->get_text(0); + + // Get library reference and check validity + Ref<AnimationLibrary> al; + uint64_t lib_id = 0; + + if (mixer->has_animation_library(lib_name)) { + al = mixer->get_animation_library(lib_name); + ERR_FAIL_COND(al.is_null()); + lib_id = uint64_t(al->get_instance_id()); + } else { + ERR_PRINT("Library not found: " + lib_name); + } + + int at = collapsed_lib_names.find(lib_name); + if (p_item->is_collapsed()) { + if (at != -1) { + //Entry exists and needs updating + collapsed_lib_ids.set(at, String::num_int64(lib_id + INT64_MIN)); + } else { + //Check if it's a rename + int id_at = collapsed_lib_ids.find(String::num_int64(lib_id + INT64_MIN)); + if (id_at != -1) { + //It's actually a rename + collapsed_lib_names.set(id_at, lib_name); + } else { + //It's a new entry + collapsed_lib_names.append(lib_name); + collapsed_lib_ids.append(String::num_int64(lib_id + INT64_MIN)); + } + } + } else { + if (at != -1) { + collapsed_lib_names.remove_at(at); + collapsed_lib_ids.remove_at(at); + } + } + + //Runtime IDs + config->set_value(md, "root", uint64_t(mixer->get_tree()->get_edited_scene_root()->get_instance_id())); + config->set_value(md, "mixer", uint64_t(mixer->get_instance_id())); + + //Plan B recovery mechanism + config->set_value(md, "mixer_signature", _get_mixer_signature()); + + //Save folding state as text and runtime ID + config->set_value(md, "folding", String("\n").join(collapsed_lib_names)); + config->set_value(md, "id", String("\n").join(collapsed_lib_ids)); + + err = config->save(path); + if (err != OK) { + ERR_PRINT("Error saving lib_folding.cfg: " + itos(err)); + } +} + +Vector<uint64_t> AnimationLibraryEditor::_load_mixer_libs_folding() { + Ref<ConfigFile> config; + config.instantiate(); + + String path = EditorPaths::get_singleton()->get_project_settings_dir().path_join("lib_folding.cfg"); + Error err = config->load(path); + if (err != OK && err != ERR_FILE_NOT_FOUND) { + ERR_PRINT("Error loading lib_folding.cfg: " + itos(err)); + return Vector<uint64_t>(); + } + + // Get unique identifier for this scene+mixer combination + String md = (mixer->get_tree()->get_edited_scene_root()->get_scene_file_path() + mixer->get_path()).md5_text(); + + Vector<uint64_t> collapsed_lib_ids; + + if (config->has_section(md)) { + _load_config_libs_folding(collapsed_lib_ids, config.ptr(), md); + + } else { + //The scene/mixer combination is no longer valid and we'll try to recover + uint64_t current_mixer_id = uint64_t(mixer->get_instance_id()); + String current_mixer_signature = _get_mixer_signature(); + List<String> sections; + config->get_sections(§ions); + + for (const String §ion : sections) { + Variant mixer_id = config->get_value(section, "mixer"); + if ((mixer_id.get_type() == Variant::INT && uint64_t(mixer_id) == current_mixer_id) || config->get_value(section, "mixer_signature") == current_mixer_signature) { // Ensure value exists and is correct type + // Found the mixer in a different section! + _load_config_libs_folding(collapsed_lib_ids, config.ptr(), section); + + //Cleanup old entry and copy fold data into new one! + String collapsed_lib_names_str = String(config->get_value(section, "folding")); + String collapsed_lib_ids_str = String(config->get_value(section, "id")); + config->erase_section(section); + + config->set_value(md, "root", uint64_t(mixer->get_tree()->get_edited_scene_root()->get_instance_id())); + config->set_value(md, "mixer", uint64_t(mixer->get_instance_id())); + config->set_value(md, "mixer_signature", _get_mixer_signature()); + config->set_value(md, "folding", collapsed_lib_names_str); + config->set_value(md, "id", collapsed_lib_ids_str); + + err = config->save(path); + if (err != OK) { + ERR_PRINT("Error saving lib_folding.cfg: " + itos(err)); + } + break; + } + } + } + + return collapsed_lib_ids; +} + +void AnimationLibraryEditor::_load_config_libs_folding(Vector<uint64_t> &p_lib_ids, ConfigFile *p_config, String p_section) { + if (uint64_t(p_config->get_value(p_section, "root", 0)) != uint64_t(mixer->get_tree()->get_edited_scene_root()->get_instance_id())) { + // Root changed - tries to match by library names + PackedStringArray collapsed_lib_names = String(p_config->get_value(p_section, "folding", "")).split("\n"); + for (const String &lib_name : collapsed_lib_names) { + if (mixer->has_animation_library(lib_name)) { + p_lib_ids.append(mixer->get_animation_library(lib_name)->get_instance_id()); + } else { + print_line("Can't find ", lib_name, " in mixer"); + } + } + } else { + // Root same - uses saved instance IDs + for (const String &saved_id : String(p_config->get_value(p_section, "id")).split("\n")) { + p_lib_ids.append(uint64_t(saved_id.to_int() - INT64_MIN)); + } + } +} + +String AnimationLibraryEditor::_get_mixer_signature() const { + String signature = String(); + + // Get all libraries sorted for consistency + List<StringName> libs; + mixer->get_animation_library_list(&libs); + libs.sort_custom<StringName::AlphCompare>(); + + // Add libraries and their animations to signature + for (const StringName &lib_name : libs) { + signature += "::" + String(lib_name); + Ref<AnimationLibrary> lib = mixer->get_animation_library(lib_name); + if (lib.is_valid()) { + List<StringName> anims; + lib->get_animation_list(&anims); + anims.sort_custom<StringName::AlphCompare>(); + for (const StringName &anim_name : anims) { + signature += "," + String(anim_name); + } + } + } + + return signature.md5_text(); +} + void AnimationLibraryEditor::show_dialog() { update_tree(); popup_centered_ratio(0.5); @@ -773,8 +973,8 @@ void AnimationLibraryEditor::show_dialog() { void AnimationLibraryEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - new_library_button->set_icon(get_editor_theme_icon(SNAME("Add"))); - load_library_button->set_icon(get_editor_theme_icon(SNAME("Load"))); + new_library_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + load_library_button->set_button_icon(get_editor_theme_icon(SNAME("Load"))); } } } @@ -855,11 +1055,12 @@ AnimationLibraryEditor::AnimationLibraryEditor() { tree->set_column_custom_minimum_width(1, EDSCALE * 250); tree->set_column_expand(1, false); tree->set_hide_root(true); - tree->set_hide_folding(true); + tree->set_hide_folding(false); tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->connect("item_edited", callable_mp(this, &AnimationLibraryEditor::_item_renamed)); tree->connect("button_clicked", callable_mp(this, &AnimationLibraryEditor::_button_pressed)); + tree->connect("item_collapsed", callable_mp(this, &AnimationLibraryEditor::_save_mixer_lib_folding)); file_popup = memnew(PopupMenu); add_child(file_popup); diff --git a/editor/plugins/animation_library_editor.h b/editor/plugins/animation_library_editor.h index beb34c6343..c4ad1684a6 100644 --- a/editor/plugins/animation_library_editor.h +++ b/editor/plugins/animation_library_editor.h @@ -31,6 +31,8 @@ #ifndef ANIMATION_LIBRARY_EDITOR_H #define ANIMATION_LIBRARY_EDITOR_H +#include "core/io/config_file.h" +#include "core/templates/vector.h" #include "editor/animation_track_editor.h" #include "editor/plugins/editor_plugin.h" #include "scene/animation/animation_mixer.h" @@ -103,6 +105,11 @@ class AnimationLibraryEditor : public AcceptDialog { void _load_file(const String &p_path); void _load_files(const PackedStringArray &p_paths); + void _save_mixer_lib_folding(TreeItem *p_item); + Vector<uint64_t> _load_mixer_libs_folding(); + void _load_config_libs_folding(Vector<uint64_t> &p_lib_ids, ConfigFile *p_config, String p_section); + String _get_mixer_signature() const; + void _item_renamed(); void _button_pressed(TreeItem *p_item, int p_column, int p_id, MouseButton p_button); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 1581e7cc66..4edd021b4d 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -113,7 +113,7 @@ void AnimationPlayerEditor::_notification(int p_what) { // Need the last frame after it stopped. frame->set_value(player->get_current_animation_position()); track_editor->set_anim_pos(player->get_current_animation_position()); - stop->set_icon(stop_icon); + stop->set_button_icon(stop_icon); } last_active = player->is_playing(); @@ -145,16 +145,16 @@ void AnimationPlayerEditor::_notification(int p_what) { stop_icon = get_editor_theme_icon(SNAME("Stop")); pause_icon = get_editor_theme_icon(SNAME("Pause")); if (player && player->is_playing()) { - stop->set_icon(pause_icon); + stop->set_button_icon(pause_icon); } else { - stop->set_icon(stop_icon); + stop->set_button_icon(stop_icon); } - autoplay->set_icon(get_editor_theme_icon(SNAME("AutoPlay"))); - play->set_icon(get_editor_theme_icon(SNAME("PlayStart"))); - play_from->set_icon(get_editor_theme_icon(SNAME("Play"))); - play_bw->set_icon(get_editor_theme_icon(SNAME("PlayStartBackwards"))); - play_bw_from->set_icon(get_editor_theme_icon(SNAME("PlayBackwards"))); + autoplay->set_button_icon(get_editor_theme_icon(SNAME("AutoPlay"))); + play->set_button_icon(get_editor_theme_icon(SNAME("PlayStart"))); + play_from->set_button_icon(get_editor_theme_icon(SNAME("Play"))); + play_bw->set_button_icon(get_editor_theme_icon(SNAME("PlayStartBackwards"))); + play_bw_from->set_button_icon(get_editor_theme_icon(SNAME("PlayBackwards"))); autoplay_icon = get_editor_theme_icon(SNAME("AutoPlay")); reset_icon = get_editor_theme_icon(SNAME("Reload")); @@ -168,10 +168,10 @@ void AnimationPlayerEditor::_notification(int p_what) { autoplay_reset_icon = ImageTexture::create_from_image(autoplay_reset_img); } - onion_toggle->set_icon(get_editor_theme_icon(SNAME("Onion"))); - onion_skinning->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + onion_toggle->set_button_icon(get_editor_theme_icon(SNAME("Onion"))); + onion_skinning->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); - pin->set_icon(get_editor_theme_icon(SNAME("Pin"))); + pin->set_button_icon(get_editor_theme_icon(SNAME("Pin"))); tool_anim->add_theme_style_override(CoreStringName(normal), get_theme_stylebox(CoreStringName(normal), SNAME("Button"))); track_editor->get_edit_menu()->add_theme_style_override(CoreStringName(normal), get_theme_stylebox(CoreStringName(normal), SNAME("Button"))); @@ -307,7 +307,7 @@ void AnimationPlayerEditor::_play_pressed() { } //unstop - stop->set_icon(pause_icon); + stop->set_button_icon(pause_icon); } void AnimationPlayerEditor::_play_from_pressed() { @@ -331,7 +331,7 @@ void AnimationPlayerEditor::_play_from_pressed() { } //unstop - stop->set_icon(pause_icon); + stop->set_button_icon(pause_icon); } String AnimationPlayerEditor::_get_current() const { @@ -359,7 +359,7 @@ void AnimationPlayerEditor::_play_bw_pressed() { } //unstop - stop->set_icon(pause_icon); + stop->set_button_icon(pause_icon); } void AnimationPlayerEditor::_play_bw_from_pressed() { @@ -383,7 +383,7 @@ void AnimationPlayerEditor::_play_bw_from_pressed() { } //unstop - stop->set_icon(pause_icon); + stop->set_button_icon(pause_icon); } void AnimationPlayerEditor::_stop_pressed() { @@ -400,7 +400,7 @@ void AnimationPlayerEditor::_stop_pressed() { frame->set_value(0); track_editor->set_anim_pos(0); } - stop->set_icon(stop_icon); + stop->set_button_icon(stop_icon); } void AnimationPlayerEditor::_animation_selected(int p_which) { @@ -580,8 +580,10 @@ float AnimationPlayerEditor::_get_editor_step() const { const Ref<Animation> anim = player->get_animation(current); ERR_FAIL_COND_V(anim.is_null(), 0.0); + float step = track_editor->get_snap_unit(); + // Use more precise snapping when holding Shift - return Input::get_singleton()->is_key_pressed(Key::SHIFT) ? anim->get_step() * 0.25 : anim->get_step(); + return Input::get_singleton()->is_key_pressed(Key::SHIFT) ? step * 0.25 : step; } void AnimationPlayerEditor::_animation_name_edited() { @@ -959,9 +961,9 @@ void AnimationPlayerEditor::_update_animation() { updating = true; if (player->is_playing()) { - stop->set_icon(pause_icon); + stop->set_button_icon(pause_icon); } else { - stop->set_icon(stop_icon); + stop->set_button_icon(stop_icon); } scale->set_text(String::num(player->get_speed_scale(), 2)); @@ -1397,7 +1399,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_timeline_o } track_editor->set_anim_pos(pos); -}; +} void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) { _update_player(); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index e9dd54f73b..8526150e0c 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -917,7 +917,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { } if (state_machine_draw->has_focus()) { - state_machine_draw->draw_rect(Rect2(Point2(), state_machine_draw->get_size()), theme_cache.highlight_color, false); + state_machine_draw->draw_rect(Rect2(Point2(), state_machine_draw->get_size()), theme_cache.focus_color, false); } int sep = 3 * EDSCALE; @@ -1271,18 +1271,18 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) { error_panel->add_theme_style_override(SceneStringName(panel), theme_cache.error_panel_style); error_label->add_theme_color_override(SceneStringName(font_color), theme_cache.error_color); - tool_select->set_icon(theme_cache.tool_icon_select); - tool_create->set_icon(theme_cache.tool_icon_create); - tool_connect->set_icon(theme_cache.tool_icon_connect); + tool_select->set_button_icon(theme_cache.tool_icon_select); + tool_create->set_button_icon(theme_cache.tool_icon_create); + tool_connect->set_button_icon(theme_cache.tool_icon_connect); switch_mode->clear(); switch_mode->add_icon_item(theme_cache.transition_icon_immediate, TTR("Immediate")); switch_mode->add_icon_item(theme_cache.transition_icon_sync, TTR("Sync")); switch_mode->add_icon_item(theme_cache.transition_icon_end, TTR("At End")); - auto_advance->set_icon(theme_cache.play_icon_auto); + auto_advance->set_button_icon(theme_cache.play_icon_auto); - tool_erase->set_icon(theme_cache.tool_icon_erase); + tool_erase->set_button_icon(theme_cache.tool_icon_erase); play_mode->clear(); play_mode->add_icon_item(theme_cache.play_icon_travel, TTR("Travel")); @@ -1642,6 +1642,7 @@ void AnimationNodeStateMachineEditor::_bind_methods() { BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, AnimationNodeStateMachineEditor, transition_icon_disabled_color, "transition_icon_disabled_color", "GraphStateMachine"); BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, AnimationNodeStateMachineEditor, highlight_color, "highlight_color", "GraphStateMachine"); BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, AnimationNodeStateMachineEditor, highlight_disabled_color, "highlight_disabled_color", "GraphStateMachine"); + BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, AnimationNodeStateMachineEditor, focus_color, "focus_color", "GraphStateMachine"); BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, AnimationNodeStateMachineEditor, guideline_color, "guideline_color", "GraphStateMachine"); BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_ICON, AnimationNodeStateMachineEditor, transition_icons[0], "TransitionImmediateBig", "EditorIcons"); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index eb623a147d..0b6320f0ce 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -117,6 +117,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { Color transition_icon_disabled_color; Color highlight_color; Color highlight_disabled_color; + Color focus_color; Color guideline_color; Ref<Texture2D> transition_icons[6]{}; diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index fec8d4b897..7c9c003ea1 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -212,12 +212,12 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const // Overlay and thumbnail need the same format for `blend_rect` to work. thumbnail->convert(Image::FORMAT_RGBA8); thumbnail->blend_rect(overlay, overlay->get_used_rect(), overlay_pos); - preview_images[i].button->set_icon(ImageTexture::create_from_image(thumbnail)); + preview_images[i].button->set_button_icon(ImageTexture::create_from_image(thumbnail)); // Make it clearer that clicking it will open an external link preview_images[i].button->set_default_cursor_shape(Control::CURSOR_POINTING_HAND); } else { - preview_images[i].button->set_icon(p_image); + preview_images[i].button->set_button_icon(p_image); } break; } @@ -302,7 +302,7 @@ void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video, cons new_preview.video_link = p_url; new_preview.is_video = p_video; new_preview.button = memnew(Button); - new_preview.button->set_icon(previews->get_editor_theme_icon(SNAME("ThumbnailWait"))); + new_preview.button->set_button_icon(previews->get_editor_theme_icon(SNAME("ThumbnailWait"))); new_preview.button->set_toggle_mode(true); new_preview.button->connect(SceneStringName(pressed), callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click).bind(p_id)); preview_hb->add_child(new_preview.button); @@ -907,7 +907,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons for (int i = 0; i < headers.size(); i++) { if (headers[i].findn("ETag:") == 0) { // Save etag String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().path_join("assetimage_" + image_queue[p_queue_id].image_url.md5_text()); - String new_etag = headers[i].substr(headers[i].find(":") + 1, headers[i].length()).strip_edges(); + String new_etag = headers[i].substr(headers[i].find_char(':') + 1, headers[i].length()).strip_edges(); Ref<FileAccess> file = FileAccess::open(cache_filename_base + ".etag", FileAccess::WRITE); if (file.is_valid()) { file->store_line(new_etag); diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index f691bad3c3..23eeedea93 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -50,8 +50,8 @@ void AudioStreamEditor::_notification(int p_what) { _current_label->add_theme_font_override(SceneStringName(font), font); _duration_label->add_theme_font_override(SceneStringName(font), font); - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); - _stop_button->set_icon(get_editor_theme_icon(SNAME("Stop"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _stop_button->set_button_icon(get_editor_theme_icon(SNAME("Stop"))); _preview->set_color(get_theme_color(SNAME("dark_color_2"), EditorStringName(Editor))); set_color(get_theme_color(SNAME("dark_color_1"), EditorStringName(Editor))); @@ -121,26 +121,26 @@ void AudioStreamEditor::_play() { if (_player->is_playing()) { _pausing = true; _player->stop(); - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); set_process(false); } else { _pausing = false; _player->play(_current); - _play_button->set_icon(get_editor_theme_icon(SNAME("Pause"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); set_process(true); } } void AudioStreamEditor::_stop() { _player->stop(); - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); _current = 0; _indicator->queue_redraw(); set_process(false); } void AudioStreamEditor::_on_finished() { - _play_button->set_icon(get_editor_theme_icon(SNAME("MainPlay"))); + _play_button->set_button_icon(get_editor_theme_icon(SNAME("MainPlay"))); if (!_pausing) { _current = 0; _indicator->queue_redraw(); diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp index d81ec21705..8b105955e7 100644 --- a/editor/plugins/bone_map_editor_plugin.cpp +++ b/editor/plugins/bone_map_editor_plugin.cpp @@ -119,7 +119,7 @@ void BoneMapperItem::create_editor() { hbox->add_child(skeleton_bone_selector); picker_button = memnew(Button); - picker_button->set_icon(get_editor_theme_icon(SNAME("ClassList"))); + picker_button->set_button_icon(get_editor_theme_icon(SNAME("ClassList"))); picker_button->connect(SceneStringName(pressed), callable_mp(this, &BoneMapperItem::_open_picker)); hbox->add_child(picker_button); @@ -296,7 +296,7 @@ void BoneMapper::create_editor() { group_hbox->add_child(profile_group_selector); clear_mapping_button = memnew(Button); - clear_mapping_button->set_icon(get_editor_theme_icon(SNAME("Clear"))); + clear_mapping_button->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); clear_mapping_button->set_tooltip_text(TTR("Clear mappings in current group.")); clear_mapping_button->connect(SceneStringName(pressed), callable_mp(this, &BoneMapper::_clear_mapping_current_group)); group_hbox->add_child(clear_mapping_button); @@ -859,7 +859,7 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) { // 4-1. Guess Finger int tips_index = -1; - bool thumb_tips_size = 0; + bool thumb_tips_size = false; bool named_finger_is_found = false; LocalVector<String> fingers; fingers.push_back("thumb|pollex"); @@ -994,7 +994,7 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) { } tips_index = -1; - thumb_tips_size = 0; + thumb_tips_size = false; named_finger_is_found = false; if (right_hand_or_palm != -1) { LocalVector<LocalVector<String>> right_fingers_map; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index e9a796dae7..d3bae447cc 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1464,10 +1464,12 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { List<CanvasItem *> selection = _get_edited_canvas_items(false, true, &has_locked_items); // Remove not movable nodes - for (CanvasItem *E : selection) { - if (!_is_node_movable(E, true)) { + for (List<CanvasItem *>::Element *E = selection.front(); E;) { + List<CanvasItem *>::Element *N = E->next(); + if (!_is_node_movable(E->get(), true)) { selection.erase(E); } + E = N; } drag_selection = selection; @@ -1928,37 +1930,50 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { // Drag resize handles if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && ((b->is_alt_pressed() && b->is_command_or_control_pressed()) || tool == TOOL_SCALE)) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && + ((tool == TOOL_SELECT && b->is_alt_pressed() && b->is_command_or_control_pressed()) || tool == TOOL_SCALE)) { bool has_locked_items = false; List<CanvasItem *> selection = _get_edited_canvas_items(false, true, &has_locked_items); - if (selection.size() == 1) { + + // Remove non-movable nodes. + for (CanvasItem *ci : selection) { + if (!_is_node_movable(ci, true)) { + selection.erase(ci); + } + } + + if (!selection.is_empty()) { CanvasItem *ci = selection.front()->get(); - if (_is_node_movable(ci)) { - Transform2D xform = transform * ci->get_global_transform_with_canvas(); - Transform2D unscaled_transform = (xform * ci->get_transform().affine_inverse() * ci->_edit_get_transform()).orthonormalized(); - Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + Transform2D edit_transform; + if (!Math::is_inf(temp_pivot.x) || !Math::is_inf(temp_pivot.y)) { + edit_transform = Transform2D(ci->_edit_get_rotation(), temp_pivot); + } else { + edit_transform = ci->_edit_get_transform(); + } - drag_type = DRAG_SCALE_BOTH; + Transform2D xform = transform * ci->get_global_transform_with_canvas(); + Transform2D unscaled_transform = (xform * ci->get_transform().affine_inverse() * edit_transform).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; - if (show_transformation_gizmos) { - Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); - Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { - drag_type = DRAG_SCALE_X; - } - Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { - drag_type = DRAG_SCALE_Y; - } - } + drag_type = DRAG_SCALE_BOTH; - drag_from = transform.affine_inverse().xform(b->get_position()); - drag_selection = List<CanvasItem *>(); - drag_selection.push_back(ci); - _save_canvas_item_state(drag_selection); - return true; + if (show_transformation_gizmos) { + Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); + Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_SCALE_X; + } + Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_SCALE_Y; + } } + + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = selection; + _save_canvas_item_state(drag_selection); + return true; } else { if (has_locked_items) { EditorToaster::get_singleton()->popup_str(TTR(locked_transform_warning), EditorToaster::SEVERITY_WARNING); @@ -1966,66 +1981,87 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { return has_locked_items; } } - } - - if (drag_type == DRAG_SCALE_BOTH || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { + } else if (drag_type == DRAG_SCALE_BOTH || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { // Resize the node if (m.is_valid()) { _restore_canvas_item_state(drag_selection); - CanvasItem *ci = drag_selection.front()->get(); drag_to = transform.affine_inverse().xform(m->get_position()); - Transform2D parent_xform = ci->get_global_transform_with_canvas() * ci->get_transform().affine_inverse(); - Transform2D unscaled_transform = (transform * parent_xform * ci->_edit_get_transform()).orthonormalized(); - Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform; - - bool uniform = m->is_shift_pressed(); - bool is_ctrl = m->is_command_or_control_pressed(); - - Point2 drag_from_local = simple_xform.xform(drag_from); - Point2 drag_to_local = simple_xform.xform(drag_to); - Point2 offset = drag_to_local - drag_from_local; + Size2 scale_max; + if (drag_type != DRAG_SCALE_BOTH) { + for (CanvasItem *ci : drag_selection) { + scale_max = scale_max.max(ci->_edit_get_scale()); + } + } - Size2 scale = ci->_edit_get_scale(); - Size2 original_scale = scale; - real_t ratio = scale.y / scale.x; - if (drag_type == DRAG_SCALE_BOTH) { - Size2 scale_factor = drag_to_local / drag_from_local; - if (uniform) { - scale *= (scale_factor.x + scale_factor.y) / 2.0; + for (CanvasItem *ci : drag_selection) { + Transform2D edit_transform; + bool using_temp_pivot = !Math::is_inf(temp_pivot.x) || !Math::is_inf(temp_pivot.y); + if (using_temp_pivot) { + edit_transform = Transform2D(ci->_edit_get_rotation(), temp_pivot); } else { - scale *= scale_factor; + edit_transform = ci->_edit_get_transform(); } - } else { - Size2 scale_factor = Vector2(offset.x, -offset.y) / SCALE_HANDLE_DISTANCE; - Size2 parent_scale = parent_xform.get_scale(); - scale_factor *= Vector2(1.0 / parent_scale.x, 1.0 / parent_scale.y); - if (drag_type == DRAG_SCALE_X) { - scale.x += scale_factor.x; + Transform2D parent_xform = ci->get_global_transform_with_canvas() * ci->get_transform().affine_inverse(); + Transform2D unscaled_transform = (transform * parent_xform * edit_transform).orthonormalized(); + Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform; + + bool uniform = m->is_shift_pressed(); + bool is_ctrl = m->is_command_or_control_pressed(); + + Point2 drag_from_local = simple_xform.xform(drag_from); + Point2 drag_to_local = simple_xform.xform(drag_to); + Point2 offset = drag_to_local - drag_from_local; + + Size2 scale = ci->_edit_get_scale(); + Size2 original_scale = scale; + real_t ratio = scale.y / scale.x; + if (drag_type == DRAG_SCALE_BOTH) { + Size2 scale_factor = drag_to_local / drag_from_local; if (uniform) { - scale.y = scale.x * ratio; + scale *= (scale_factor.x + scale_factor.y) / 2.0; + } else { + scale *= scale_factor; } - } else if (drag_type == DRAG_SCALE_Y) { - scale.y -= scale_factor.y; - if (uniform) { - scale.x = scale.y / ratio; + } else { + Size2 scale_factor = Vector2(offset.x, -offset.y) / SCALE_HANDLE_DISTANCE; + Size2 parent_scale = parent_xform.get_scale(); + // Take into account the biggest scale, so all nodes are scaled uniformly. + scale_factor *= Vector2(1.0 / parent_scale.x, 1.0 / parent_scale.y) / (scale_max / original_scale); + + if (drag_type == DRAG_SCALE_X) { + scale.x += scale_factor.x; + if (uniform) { + scale.y = scale.x * ratio; + } + } else if (drag_type == DRAG_SCALE_Y) { + scale.y -= scale_factor.y; + if (uniform) { + scale.x = scale.y / ratio; + } } } - } - if (snap_scale && !is_ctrl) { - if (snap_relative) { - scale.x = original_scale.x * (roundf((scale.x / original_scale.x) / snap_scale_step) * snap_scale_step); - scale.y = original_scale.y * (roundf((scale.y / original_scale.y) / snap_scale_step) * snap_scale_step); - } else { - scale.x = roundf(scale.x / snap_scale_step) * snap_scale_step; - scale.y = roundf(scale.y / snap_scale_step) * snap_scale_step; + if (snap_scale && !is_ctrl) { + if (snap_relative) { + scale.x = original_scale.x * (Math::round((scale.x / original_scale.x) / snap_scale_step) * snap_scale_step); + scale.y = original_scale.y * (Math::round((scale.y / original_scale.y) / snap_scale_step) * snap_scale_step); + } else { + scale.x = Math::round(scale.x / snap_scale_step) * snap_scale_step; + scale.y = Math::round(scale.y / snap_scale_step) * snap_scale_step; + } + } + + ci->_edit_set_scale(scale); + + if (using_temp_pivot) { + Point2 ci_origin = ci->_edit_get_transform().get_origin(); + ci->_edit_set_position(ci_origin + (ci_origin - temp_pivot) * ((scale - original_scale) / original_scale)); } } - ci->_edit_set_scale(scale); return true; } @@ -2073,7 +2109,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { //Start moving the nodes if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { - if ((b->is_alt_pressed() && !b->is_command_or_control_pressed()) || tool == TOOL_MOVE) { + if ((tool == TOOL_SELECT && b->is_alt_pressed() && !b->is_command_or_control_pressed()) || tool == TOOL_MOVE) { bool has_locked_items = false; List<CanvasItem *> selection = _get_edited_canvas_items(false, true, &has_locked_items); @@ -2133,7 +2169,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } Point2 drag_delta = drag_to - drag_from; - if (drag_selection.size() == 1 && (drag_type == DRAG_MOVE_X || drag_type == DRAG_MOVE_Y)) { + if (drag_type == DRAG_MOVE_X || drag_type == DRAG_MOVE_Y) { const CanvasItem *selected = drag_selection.front()->get(); Transform2D parent_xform = selected->get_global_transform_with_canvas() * selected->get_transform().affine_inverse(); Transform2D unscaled_transform = (transform * parent_xform * selected->_edit_get_transform()).orthonormalized(); @@ -3466,16 +3502,14 @@ void CanvasItemEditor::_draw_selection() { Ref<Texture2D> previous_position_icon = get_editor_theme_icon(SNAME("EditorPositionPrevious")); RID vp_ci = viewport->get_canvas_item(); - List<CanvasItem *> selection = _get_edited_canvas_items(true, false); - bool single = selection.size() == 1; + bool transform_tool = tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT; + for (CanvasItem *E : selection) { CanvasItem *ci = Object::cast_to<CanvasItem>(E); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(ci); - bool item_locked = ci->has_meta("_edit_lock_"); - // Draw the previous position if we are dragging the node if (show_helpers && (drag_type == DRAG_MOVE || drag_type == DRAG_ROTATE || @@ -3500,6 +3534,7 @@ void CanvasItemEditor::_draw_selection() { } } + bool item_locked = ci->has_meta("_edit_lock_"); Transform2D xform = transform * ci->get_global_transform_with_canvas(); // Draw the selected items position / surrounding boxes @@ -3529,7 +3564,7 @@ void CanvasItemEditor::_draw_selection() { viewport->draw_set_transform_matrix(viewport->get_transform()); } - if (single && !item_locked && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks + if (single && !item_locked && transform_tool) { // Draw the pivot if (ci->_edit_use_pivot()) { // Draw the node's pivot @@ -3572,73 +3607,88 @@ void CanvasItemEditor::_draw_selection() { select_handle->draw(vp_ci, (ofs - (select_handle->get_size() / 2)).floor()); } } + } + } - // Draw the move handles - bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL); - bool is_alt = Input::get_singleton()->is_key_pressed(Key::ALT); - if (tool == TOOL_MOVE && show_transformation_gizmos) { - if (_is_node_movable(ci)) { - Transform2D unscaled_transform = (xform * ci->get_transform().affine_inverse() * ci->_edit_get_transform()).orthonormalized(); - Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + // Remove non-movable nodes. + for (CanvasItem *ci : selection) { + if (!_is_node_movable(ci)) { + selection.erase(ci); + } + } - Size2 move_factor = Size2(MOVE_HANDLE_DISTANCE, MOVE_HANDLE_DISTANCE); - viewport->draw_set_transform_matrix(simple_xform); + if (!selection.is_empty() && transform_tool && show_transformation_gizmos) { + CanvasItem *ci = selection.front()->get(); - Vector<Point2> points = { - Vector2(move_factor.x * EDSCALE, 5 * EDSCALE), - Vector2(move_factor.x * EDSCALE, -5 * EDSCALE), - Vector2((move_factor.x + 10) * EDSCALE, 0) - }; + Transform2D xform = transform * ci->get_global_transform_with_canvas(); + bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL); + bool is_alt = Input::get_singleton()->is_key_pressed(Key::ALT); - viewport->draw_colored_polygon(points, get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor))); - viewport->draw_line(Point2(), Point2(move_factor.x * EDSCALE, 0), get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor)), Math::round(EDSCALE)); + // Draw the move handles. + if ((tool == TOOL_SELECT && is_alt && !is_ctrl) || tool == TOOL_MOVE) { + Transform2D unscaled_transform = (xform * ci->get_transform().affine_inverse() * ci->_edit_get_transform()).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; - points.clear(); - points.push_back(Vector2(5 * EDSCALE, move_factor.y * EDSCALE)); - points.push_back(Vector2(-5 * EDSCALE, move_factor.y * EDSCALE)); - points.push_back(Vector2(0, (move_factor.y + 10) * EDSCALE)); + Size2 move_factor = Size2(MOVE_HANDLE_DISTANCE, MOVE_HANDLE_DISTANCE); + viewport->draw_set_transform_matrix(simple_xform); - viewport->draw_colored_polygon(points, get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor))); - viewport->draw_line(Point2(), Point2(0, move_factor.y * EDSCALE), get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)), Math::round(EDSCALE)); + Vector<Point2> points = { + Vector2(move_factor.x * EDSCALE, 5 * EDSCALE), + Vector2(move_factor.x * EDSCALE, -5 * EDSCALE), + Vector2((move_factor.x + 10) * EDSCALE, 0) + }; - viewport->draw_set_transform_matrix(viewport->get_transform()); - } - } + viewport->draw_colored_polygon(points, get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor))); + viewport->draw_line(Point2(), Point2(move_factor.x * EDSCALE, 0), get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor)), Math::round(EDSCALE)); - // Draw the rescale handles - if (show_transformation_gizmos && ((is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y)) { - if (_is_node_movable(ci)) { - Transform2D unscaled_transform = (xform * ci->get_transform().affine_inverse() * ci->_edit_get_transform()).orthonormalized(); - Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + points.clear(); + points.push_back(Vector2(5 * EDSCALE, move_factor.y * EDSCALE)); + points.push_back(Vector2(-5 * EDSCALE, move_factor.y * EDSCALE)); + points.push_back(Vector2(0, (move_factor.y + 10) * EDSCALE)); - Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); - bool uniform = Input::get_singleton()->is_key_pressed(Key::SHIFT); - Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom; + viewport->draw_colored_polygon(points, get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor))); + viewport->draw_line(Point2(), Point2(0, move_factor.y * EDSCALE), get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)), Math::round(EDSCALE)); - if (drag_type == DRAG_SCALE_X) { - scale_factor.x += offset.x; - if (uniform) { - scale_factor.y += offset.x; - } - } else if (drag_type == DRAG_SCALE_Y) { - scale_factor.y += offset.y; - if (uniform) { - scale_factor.x += offset.y; - } - } + viewport->draw_set_transform_matrix(viewport->get_transform()); + } - viewport->draw_set_transform_matrix(simple_xform); - Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - viewport->draw_rect(x_handle_rect, get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor))); - viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor)), Math::round(EDSCALE)); + // Draw the rescale handles. + if ((tool == TOOL_SELECT && is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { + Transform2D edit_transform; + if (!Math::is_inf(temp_pivot.x) || !Math::is_inf(temp_pivot.y)) { + edit_transform = Transform2D(ci->_edit_get_rotation(), temp_pivot); + } else { + edit_transform = ci->_edit_get_transform(); + } + Transform2D unscaled_transform = (xform * ci->get_transform().affine_inverse() * edit_transform).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; - Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - viewport->draw_rect(y_handle_rect, get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor))); - viewport->draw_line(Point2(), Point2(0, scale_factor.y * EDSCALE), get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)), Math::round(EDSCALE)); + Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); + bool uniform = Input::get_singleton()->is_key_pressed(Key::SHIFT); + Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom; - viewport->draw_set_transform_matrix(viewport->get_transform()); + if (drag_type == DRAG_SCALE_X) { + scale_factor.x += offset.x; + if (uniform) { + scale_factor.y += offset.x; + } + } else if (drag_type == DRAG_SCALE_Y) { + scale_factor.y += offset.y; + if (uniform) { + scale_factor.x += offset.y; } } + + viewport->draw_set_transform_matrix(simple_xform); + Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + viewport->draw_rect(x_handle_rect, get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor))); + viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor)), Math::round(EDSCALE)); + + Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + viewport->draw_rect(y_handle_rect, get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor))); + viewport->draw_line(Point2(), Point2(0, scale_factor.y * EDSCALE), get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)), Math::round(EDSCALE)); + + viewport->draw_set_transform_matrix(viewport->get_transform()); } } @@ -3863,7 +3913,7 @@ void CanvasItemEditor::_draw_message() { Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label")); int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label")); - Point2 msgpos = Point2(RULER_WIDTH + 5 * EDSCALE, viewport->get_size().y - 20 * EDSCALE); + Point2 msgpos = Point2(RULER_WIDTH + 10 * EDSCALE, viewport->get_size().y - 14 * EDSCALE); viewport->draw_string(font, msgpos + Point2(1, 1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); viewport->draw_string(font, msgpos + Point2(-1, -1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); viewport->draw_string(font, msgpos, message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 1)); @@ -3964,39 +4014,38 @@ void CanvasItemEditor::set_current_tool(Tool p_tool) { } void CanvasItemEditor::_update_editor_settings() { - button_center_view->set_icon(get_editor_theme_icon(SNAME("CenterView"))); - select_button->set_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + button_center_view->set_button_icon(get_editor_theme_icon(SNAME("CenterView"))); + select_button->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); select_sb->set_texture(get_editor_theme_icon(SNAME("EditorRect2D"))); - list_select_button->set_icon(get_editor_theme_icon(SNAME("ListSelect"))); - move_button->set_icon(get_editor_theme_icon(SNAME("ToolMove"))); - scale_button->set_icon(get_editor_theme_icon(SNAME("ToolScale"))); - rotate_button->set_icon(get_editor_theme_icon(SNAME("ToolRotate"))); - smart_snap_button->set_icon(get_editor_theme_icon(SNAME("Snap"))); - grid_snap_button->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); - snap_config_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); - skeleton_menu->set_icon(get_editor_theme_icon(SNAME("Bone"))); - override_camera_button->set_icon(get_editor_theme_icon(SNAME("Camera2D"))); - pan_button->set_icon(get_editor_theme_icon(SNAME("ToolPan"))); - ruler_button->set_icon(get_editor_theme_icon(SNAME("Ruler"))); - pivot_button->set_icon(get_editor_theme_icon(SNAME("EditPivot"))); + list_select_button->set_button_icon(get_editor_theme_icon(SNAME("ListSelect"))); + move_button->set_button_icon(get_editor_theme_icon(SNAME("ToolMove"))); + scale_button->set_button_icon(get_editor_theme_icon(SNAME("ToolScale"))); + rotate_button->set_button_icon(get_editor_theme_icon(SNAME("ToolRotate"))); + smart_snap_button->set_button_icon(get_editor_theme_icon(SNAME("Snap"))); + grid_snap_button->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); + snap_config_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + skeleton_menu->set_button_icon(get_editor_theme_icon(SNAME("Bone"))); + pan_button->set_button_icon(get_editor_theme_icon(SNAME("ToolPan"))); + ruler_button->set_button_icon(get_editor_theme_icon(SNAME("Ruler"))); + pivot_button->set_button_icon(get_editor_theme_icon(SNAME("EditPivot"))); select_handle = get_editor_theme_icon(SNAME("EditorHandle")); anchor_handle = get_editor_theme_icon(SNAME("EditorControlAnchor")); - lock_button->set_icon(get_editor_theme_icon(SNAME("Lock"))); - unlock_button->set_icon(get_editor_theme_icon(SNAME("Unlock"))); - group_button->set_icon(get_editor_theme_icon(SNAME("Group"))); - ungroup_button->set_icon(get_editor_theme_icon(SNAME("Ungroup"))); - key_loc_button->set_icon(get_editor_theme_icon(SNAME("KeyPosition"))); - key_rot_button->set_icon(get_editor_theme_icon(SNAME("KeyRotation"))); - key_scale_button->set_icon(get_editor_theme_icon(SNAME("KeyScale"))); - key_insert_button->set_icon(get_editor_theme_icon(SNAME("Key"))); - key_auto_insert_button->set_icon(get_editor_theme_icon(SNAME("AutoKey"))); + lock_button->set_button_icon(get_editor_theme_icon(SNAME("Lock"))); + unlock_button->set_button_icon(get_editor_theme_icon(SNAME("Unlock"))); + group_button->set_button_icon(get_editor_theme_icon(SNAME("Group"))); + ungroup_button->set_button_icon(get_editor_theme_icon(SNAME("Ungroup"))); + key_loc_button->set_button_icon(get_editor_theme_icon(SNAME("KeyPosition"))); + key_rot_button->set_button_icon(get_editor_theme_icon(SNAME("KeyRotation"))); + key_scale_button->set_button_icon(get_editor_theme_icon(SNAME("KeyScale"))); + key_insert_button->set_button_icon(get_editor_theme_icon(SNAME("Key"))); + key_auto_insert_button->set_button_icon(get_editor_theme_icon(SNAME("AutoKey"))); // Use a different color for the active autokey icon to make them easier // to distinguish from the other key icons at the top. On a light theme, // the icon will be dark, so we need to lighten it before blending it // with the red color. const Color key_auto_color = EditorThemeManager::is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25); key_auto_insert_button->add_theme_color_override("icon_pressed_color", key_auto_color.lerp(Color(1, 0, 0), 0.55)); - animation_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + animation_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); context_toolbar_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("ContextualToolbar"), EditorStringName(EditorStyles))); @@ -4014,8 +4063,6 @@ void CanvasItemEditor::_notification(int p_what) { case NOTIFICATION_READY: { _update_lock_and_group_button(); - EditorRunBar::get_singleton()->connect("play_pressed", callable_mp(this, &CanvasItemEditor::_update_override_camera_button).bind(true)); - EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &CanvasItemEditor::_update_override_camera_button).bind(false)); ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &CanvasItemEditor::_project_settings_changed)); } break; @@ -4114,15 +4161,6 @@ void CanvasItemEditor::_notification(int p_what) { _update_editor_settings(); } break; - case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible() && override_camera_button->is_pressed()) { - EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton(); - - debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE); - override_camera_button->set_pressed(false); - } - } break; - case NOTIFICATION_APPLICATION_FOCUS_OUT: case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { if (drag_type != DRAG_NONE) { @@ -4280,16 +4318,6 @@ void CanvasItemEditor::_button_toggle_grid_snap(bool p_status) { viewport->queue_redraw(); } -void CanvasItemEditor::_button_override_camera(bool p_pressed) { - EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton(); - - if (p_pressed) { - debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_2D); - } else { - debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE); - } -} - void CanvasItemEditor::_button_tool_select(int p_index) { Button *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button }; for (int i = 0; i < TOOL_MAX; i++) { @@ -4396,17 +4424,6 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, te->commit_insert_queue(); } -void CanvasItemEditor::_update_override_camera_button(bool p_game_running) { - if (p_game_running) { - override_camera_button->set_disabled(false); - override_camera_button->set_tooltip_text(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera.")); - } else { - override_camera_button->set_disabled(true); - override_camera_button->set_pressed(false); - override_camera_button->set_tooltip_text(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature.")); - } -} - void CanvasItemEditor::_popup_callback(int p_op) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); last_option = MenuOption(p_op); @@ -5387,7 +5404,7 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(pivot_button); pivot_button->set_toggle_mode(true); pivot_button->connect(SceneStringName(pressed), callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_EDIT_PIVOT)); - pivot_button->set_tooltip_text(TTR("Click to change object's rotation pivot.") + "\n" + TTR("Shift: Set temporary rotation pivot.") + "\n" + TTR("Click this button while holding Shift to put the temporary rotation pivot in the center of the selected nodes.")); + pivot_button->set_tooltip_text(TTR("Click to change object's pivot.") + "\n" + TTR("Shift: Set temporary pivot.") + "\n" + TTR("Click this button while holding Shift to put the temporary pivot in the center of the selected nodes.")); pan_button = memnew(Button); pan_button->set_theme_type_variation("FlatButton"); @@ -5512,16 +5529,6 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(memnew(VSeparator)); - override_camera_button = memnew(Button); - override_camera_button->set_theme_type_variation("FlatButton"); - main_menu_hbox->add_child(override_camera_button); - override_camera_button->connect(SceneStringName(toggled), callable_mp(this, &CanvasItemEditor::_button_override_camera)); - override_camera_button->set_toggle_mode(true); - override_camera_button->set_disabled(true); - _update_override_camera_button(false); - - main_menu_hbox->add_child(memnew(VSeparator)); - view_menu = memnew(MenuButton); view_menu->set_flat(false); view_menu->set_theme_type_variation("FlatMenuButton"); @@ -5661,7 +5668,7 @@ CanvasItemEditor::CanvasItemEditor() { snap_dialog->connect(SceneStringName(confirmed), callable_mp(this, &CanvasItemEditor::_snap_changed)); add_child(snap_dialog); - select_sb = Ref<StyleBoxTexture>(memnew(StyleBoxTexture)); + select_sb.instantiate(); selection_menu = memnew(PopupMenu); add_child(selection_menu); @@ -6264,7 +6271,7 @@ void CanvasItemEditorViewport::_update_theme() { for (BaseButton *btn : btn_list) { CheckBox *check = Object::cast_to<CheckBox>(btn); - check->set_icon(get_editor_theme_icon(check->get_text())); + check->set_button_icon(get_editor_theme_icon(check->get_text())); } label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index bae9efebc9..c5335bf9c1 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -335,7 +335,6 @@ private: Button *group_button = nullptr; Button *ungroup_button = nullptr; - Button *override_camera_button = nullptr; MenuButton *view_menu = nullptr; PopupMenu *grid_menu = nullptr; PopupMenu *theme_menu = nullptr; @@ -518,11 +517,8 @@ private: void _zoom_on_position(real_t p_zoom, Point2 p_position = Point2()); void _button_toggle_smart_snap(bool p_status); void _button_toggle_grid_snap(bool p_status); - void _button_override_camera(bool p_pressed); void _button_tool_select(int p_index); - void _update_override_camera_button(bool p_game_running); - HSplitContainer *left_panel_split = nullptr; HSplitContainer *right_panel_split = nullptr; VSplitContainer *bottom_split = nullptr; diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index cd13deb3e9..a52d949819 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -157,7 +157,7 @@ ControlPositioningWarning::ControlPositioningWarning() { void EditorPropertyAnchorsPreset::_set_read_only(bool p_read_only) { options->set_disabled(p_read_only); -}; +} void EditorPropertyAnchorsPreset::_option_selected(int p_which) { int64_t val = options->get_item_metadata(p_which); @@ -221,7 +221,7 @@ void EditorPropertySizeFlags::_set_read_only(bool p_read_only) { check->set_disabled(p_read_only); } flag_presets->set_disabled(p_read_only); -}; +} void EditorPropertySizeFlags::_preset_selected(int p_which) { int preset = flag_presets->get_item_id(p_which); @@ -536,7 +536,6 @@ ControlEditorPopupButton::ControlEditorPopupButton() { set_focus_mode(FOCUS_NONE); popup_panel = memnew(PopupPanel); - popup_panel->set_theme_type_variation("ControlEditorPopupPanel"); add_child(popup_panel); popup_panel->connect("about_to_popup", callable_mp(this, &ControlEditorPopupButton::_popup_visibility_changed).bind(true)); popup_panel->connect("popup_hide", callable_mp(this, &ControlEditorPopupButton::_popup_visibility_changed).bind(false)); @@ -573,27 +572,27 @@ void AnchorPresetPicker::_notification(int p_notification) { switch (p_notification) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - preset_buttons[PRESET_TOP_LEFT]->set_icon(get_editor_theme_icon(SNAME("ControlAlignTopLeft"))); - preset_buttons[PRESET_CENTER_TOP]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterTop"))); - preset_buttons[PRESET_TOP_RIGHT]->set_icon(get_editor_theme_icon(SNAME("ControlAlignTopRight"))); + preset_buttons[PRESET_TOP_LEFT]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignTopLeft"))); + preset_buttons[PRESET_CENTER_TOP]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterTop"))); + preset_buttons[PRESET_TOP_RIGHT]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignTopRight"))); - preset_buttons[PRESET_CENTER_LEFT]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterLeft"))); - preset_buttons[PRESET_CENTER]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenter"))); - preset_buttons[PRESET_CENTER_RIGHT]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterRight"))); + preset_buttons[PRESET_CENTER_LEFT]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterLeft"))); + preset_buttons[PRESET_CENTER]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenter"))); + preset_buttons[PRESET_CENTER_RIGHT]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterRight"))); - preset_buttons[PRESET_BOTTOM_LEFT]->set_icon(get_editor_theme_icon(SNAME("ControlAlignBottomLeft"))); - preset_buttons[PRESET_CENTER_BOTTOM]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterBottom"))); - preset_buttons[PRESET_BOTTOM_RIGHT]->set_icon(get_editor_theme_icon(SNAME("ControlAlignBottomRight"))); + preset_buttons[PRESET_BOTTOM_LEFT]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignBottomLeft"))); + preset_buttons[PRESET_CENTER_BOTTOM]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterBottom"))); + preset_buttons[PRESET_BOTTOM_RIGHT]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignBottomRight"))); - preset_buttons[PRESET_TOP_WIDE]->set_icon(get_editor_theme_icon(SNAME("ControlAlignTopWide"))); - preset_buttons[PRESET_HCENTER_WIDE]->set_icon(get_editor_theme_icon(SNAME("ControlAlignHCenterWide"))); - preset_buttons[PRESET_BOTTOM_WIDE]->set_icon(get_editor_theme_icon(SNAME("ControlAlignBottomWide"))); + preset_buttons[PRESET_TOP_WIDE]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignTopWide"))); + preset_buttons[PRESET_HCENTER_WIDE]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignHCenterWide"))); + preset_buttons[PRESET_BOTTOM_WIDE]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignBottomWide"))); - preset_buttons[PRESET_LEFT_WIDE]->set_icon(get_editor_theme_icon(SNAME("ControlAlignLeftWide"))); - preset_buttons[PRESET_VCENTER_WIDE]->set_icon(get_editor_theme_icon(SNAME("ControlAlignVCenterWide"))); - preset_buttons[PRESET_RIGHT_WIDE]->set_icon(get_editor_theme_icon(SNAME("ControlAlignRightWide"))); + preset_buttons[PRESET_LEFT_WIDE]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignLeftWide"))); + preset_buttons[PRESET_VCENTER_WIDE]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignVCenterWide"))); + preset_buttons[PRESET_RIGHT_WIDE]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignRightWide"))); - preset_buttons[PRESET_FULL_RECT]->set_icon(get_editor_theme_icon(SNAME("ControlAlignFullRect"))); + preset_buttons[PRESET_FULL_RECT]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignFullRect"))); } break; } } @@ -691,17 +690,17 @@ void SizeFlagPresetPicker::_notification(int p_notification) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (vertical) { - preset_buttons[SIZE_SHRINK_BEGIN]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterTop"))); - preset_buttons[SIZE_SHRINK_CENTER]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenter"))); - preset_buttons[SIZE_SHRINK_END]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterBottom"))); + preset_buttons[SIZE_SHRINK_BEGIN]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterTop"))); + preset_buttons[SIZE_SHRINK_CENTER]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenter"))); + preset_buttons[SIZE_SHRINK_END]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterBottom"))); - preset_buttons[SIZE_FILL]->set_icon(get_editor_theme_icon(SNAME("ControlAlignVCenterWide"))); + preset_buttons[SIZE_FILL]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignVCenterWide"))); } else { - preset_buttons[SIZE_SHRINK_BEGIN]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterLeft"))); - preset_buttons[SIZE_SHRINK_CENTER]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenter"))); - preset_buttons[SIZE_SHRINK_END]->set_icon(get_editor_theme_icon(SNAME("ControlAlignCenterRight"))); + preset_buttons[SIZE_SHRINK_BEGIN]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterLeft"))); + preset_buttons[SIZE_SHRINK_CENTER]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenter"))); + preset_buttons[SIZE_SHRINK_END]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignCenterRight"))); - preset_buttons[SIZE_FILL]->set_icon(get_editor_theme_icon(SNAME("ControlAlignHCenterWide"))); + preset_buttons[SIZE_FILL]->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignHCenterWide"))); } } break; } @@ -1051,9 +1050,9 @@ void ControlEditorToolbar::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - anchors_button->set_icon(get_editor_theme_icon(SNAME("ControlLayout"))); - anchor_mode_button->set_icon(get_editor_theme_icon(SNAME("Anchor"))); - containers_button->set_icon(get_editor_theme_icon(SNAME("ContainerLayout"))); + anchors_button->set_button_icon(get_editor_theme_icon(SNAME("ControlLayout"))); + anchor_mode_button->set_button_icon(get_editor_theme_icon(SNAME("Anchor"))); + containers_button->set_button_icon(get_editor_theme_icon(SNAME("ContainerLayout"))); } break; } } diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h index 2672e8ef97..56e9f6ced4 100644 --- a/editor/plugins/control_editor_plugin.h +++ b/editor/plugins/control_editor_plugin.h @@ -241,7 +241,7 @@ protected: static ControlEditorToolbar *singleton; public: - bool is_anchors_mode_enabled() { return anchors_mode; }; + bool is_anchors_mode_enabled() { return anchors_mode; } static ControlEditorToolbar *get_singleton() { return singleton; } diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index e518cf7815..67006af44b 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -972,7 +972,7 @@ void CurveEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { spacing = Math::round(BASE_SPACING * get_theme_default_base_scale()); - snap_button->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); + snap_button->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); PopupMenu *p = presets_button->get_popup(); p->clear(); p->add_icon_item(get_editor_theme_icon(SNAME("CurveConstant")), TTR("Constant"), CurveEdit::PRESET_CONSTANT); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 9a53f07a3f..3618c0e6d3 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/io/file_access_memory.h" +#include "core/io/image.h" #include "core/io/resource_loader.h" #include "core/object/script_language.h" #include "core/os/os.h" diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp index 6366d20539..7cf0b2d2ac 100644 --- a/editor/plugins/font_config_plugin.cpp +++ b/editor/plugins/font_config_plugin.cpp @@ -149,7 +149,7 @@ void EditorPropertyFontMetaOverride::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (button_add) { - button_add->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } } break; } @@ -295,7 +295,7 @@ void EditorPropertyFontMetaOverride::update_property() { hbox->add_child(prop); prop->set_h_size_flags(SIZE_EXPAND_FILL); Button *remove = memnew(Button); - remove->set_icon(get_editor_theme_icon(SNAME("Remove"))); + remove->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); hbox->add_child(remove); remove->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyFontMetaOverride::_remove).bind(remove, name)); @@ -470,7 +470,7 @@ void EditorPropertyOTVariation::update_property() { Vector3i range = supported.get_value_at_index(i); EditorPropertyInteger *prop = memnew(EditorPropertyInteger); - prop->setup(range.x, range.y, false, 1, false, false); + prop->setup(range.x, range.y, false, true, false, false); prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag)); String name = TS->tag_to_name(name_tag); @@ -552,7 +552,7 @@ void EditorPropertyOTFeatures::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (button_add) { - button_add->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } } break; } @@ -789,7 +789,7 @@ void EditorPropertyOTFeatures::update_property() { hbox->add_child(prop); prop->set_h_size_flags(SIZE_EXPAND_FILL); Button *remove = memnew(Button); - remove->set_icon(get_editor_theme_icon(SNAME("Remove"))); + remove->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); hbox->add_child(remove); remove->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyOTFeatures::_remove).bind(remove, name_tag)); @@ -798,7 +798,7 @@ void EditorPropertyOTFeatures::update_property() { } button_add = EditorInspector::create_inspector_action_button(TTR("Add Feature")); - button_add->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_add->set_button_icon(get_editor_theme_icon(SNAME("Add"))); button_add->connect(SceneStringName(pressed), callable_mp(this, &EditorPropertyOTFeatures::_add_menu)); property_vbox->add_child(button_add); diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp new file mode 100644 index 0000000000..5c1f81ee94 --- /dev/null +++ b/editor/plugins/game_view_plugin.cpp @@ -0,0 +1,487 @@ +/**************************************************************************/ +/* game_view_plugin.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "game_view_plugin.h" + +#include "core/debugger/debugger_marshalls.h" +#include "editor/editor_main_screen.h" +#include "editor/editor_node.h" +#include "editor/editor_settings.h" +#include "editor/themes/editor_scale.h" +#include "scene/gui/button.h" +#include "scene/gui/menu_button.h" +#include "scene/gui/panel.h" +#include "scene/gui/separator.h" + +void GameViewDebugger::_session_started(Ref<EditorDebuggerSession> p_session) { + Array setup_data; + Dictionary settings; + settings["editors/panning/2d_editor_panning_scheme"] = EDITOR_GET("editors/panning/2d_editor_panning_scheme"); + settings["editors/panning/simple_panning"] = EDITOR_GET("editors/panning/simple_panning"); + settings["editors/panning/warped_mouse_panning"] = EDITOR_GET("editors/panning/warped_mouse_panning"); + settings["editors/panning/2d_editor_pan_speed"] = EDITOR_GET("editors/panning/2d_editor_pan_speed"); + settings["canvas_item_editor/pan_view"] = DebuggerMarshalls::serialize_key_shortcut(ED_GET_SHORTCUT("canvas_item_editor/pan_view")); + setup_data.append(settings); + p_session->send_message("scene:runtime_node_select_setup", setup_data); + + Array type; + type.append(node_type); + p_session->send_message("scene:runtime_node_select_set_type", type); + Array visible; + visible.append(selection_visible); + p_session->send_message("scene:runtime_node_select_set_visible", visible); + Array mode; + mode.append(select_mode); + p_session->send_message("scene:runtime_node_select_set_mode", mode); + + emit_signal(SNAME("session_started")); +} + +void GameViewDebugger::_session_stopped() { + emit_signal(SNAME("session_stopped")); +} + +void GameViewDebugger::set_suspend(bool p_enabled) { + Array message; + message.append(p_enabled); + + for (Ref<EditorDebuggerSession> &I : sessions) { + if (I->is_active()) { + I->send_message("scene:suspend_changed", message); + } + } +} + +void GameViewDebugger::next_frame() { + for (Ref<EditorDebuggerSession> &I : sessions) { + if (I->is_active()) { + I->send_message("scene:next_frame", Array()); + } + } +} + +void GameViewDebugger::set_node_type(int p_type) { + node_type = p_type; + + Array message; + message.append(p_type); + + for (Ref<EditorDebuggerSession> &I : sessions) { + if (I->is_active()) { + I->send_message("scene:runtime_node_select_set_type", message); + } + } +} + +void GameViewDebugger::set_selection_visible(bool p_visible) { + selection_visible = p_visible; + + Array message; + message.append(p_visible); + + for (Ref<EditorDebuggerSession> &I : sessions) { + if (I->is_active()) { + I->send_message("scene:runtime_node_select_set_visible", message); + } + } +} + +void GameViewDebugger::set_select_mode(int p_mode) { + select_mode = p_mode; + + Array message; + message.append(p_mode); + + for (Ref<EditorDebuggerSession> &I : sessions) { + if (I->is_active()) { + I->send_message("scene:runtime_node_select_set_mode", message); + } + } +} + +void GameViewDebugger::set_camera_override(bool p_enabled) { + EditorDebuggerNode::get_singleton()->set_camera_override(p_enabled ? camera_override_mode : EditorDebuggerNode::OVERRIDE_NONE); +} + +void GameViewDebugger::set_camera_manipulate_mode(EditorDebuggerNode::CameraOverride p_mode) { + camera_override_mode = p_mode; + + if (EditorDebuggerNode::get_singleton()->get_camera_override() != EditorDebuggerNode::OVERRIDE_NONE) { + set_camera_override(true); + } +} + +void GameViewDebugger::reset_camera_2d_position() { + for (Ref<EditorDebuggerSession> &I : sessions) { + if (I->is_active()) { + I->send_message("scene:runtime_node_select_reset_camera_2d", Array()); + } + } +} + +void GameViewDebugger::reset_camera_3d_position() { + for (Ref<EditorDebuggerSession> &I : sessions) { + if (I->is_active()) { + I->send_message("scene:runtime_node_select_reset_camera_3d", Array()); + } + } +} + +void GameViewDebugger::setup_session(int p_session_id) { + Ref<EditorDebuggerSession> session = get_session(p_session_id); + ERR_FAIL_COND(session.is_null()); + + sessions.append(session); + + session->connect("started", callable_mp(this, &GameViewDebugger::_session_started).bind(session)); + session->connect("stopped", callable_mp(this, &GameViewDebugger::_session_stopped)); +} + +void GameViewDebugger::_bind_methods() { + ADD_SIGNAL(MethodInfo("session_started")); + ADD_SIGNAL(MethodInfo("session_stopped")); +} + +/////// + +void GameView::_sessions_changed() { + // The debugger session's `session_started/stopped` signal can be unreliable, so count it manually. + active_sessions = 0; + Array sessions = debugger->get_sessions(); + for (int i = 0; i < sessions.size(); i++) { + if (Object::cast_to<EditorDebuggerSession>(sessions[i])->is_active()) { + active_sessions++; + } + } + + _update_debugger_buttons(); +} + +void GameView::_update_debugger_buttons() { + bool empty = active_sessions == 0; + + suspend_button->set_disabled(empty); + camera_override_button->set_disabled(empty); + + PopupMenu *menu = camera_override_menu->get_popup(); + + bool disable_camera_reset = empty || !camera_override_button->is_pressed() || !menu->is_item_checked(menu->get_item_index(CAMERA_MODE_INGAME)); + menu->set_item_disabled(CAMERA_RESET_2D, disable_camera_reset); + menu->set_item_disabled(CAMERA_RESET_3D, disable_camera_reset); + + if (empty) { + suspend_button->set_pressed(false); + camera_override_button->set_pressed(false); + } + next_frame_button->set_disabled(!suspend_button->is_pressed()); +} + +void GameView::_suspend_button_toggled(bool p_pressed) { + _update_debugger_buttons(); + + debugger->set_suspend(p_pressed); +} + +void GameView::_node_type_pressed(int p_option) { + RuntimeNodeSelect::NodeType type = (RuntimeNodeSelect::NodeType)p_option; + for (int i = 0; i < RuntimeNodeSelect::NODE_TYPE_MAX; i++) { + node_type_button[i]->set_pressed_no_signal(i == type); + } + + _update_debugger_buttons(); + + debugger->set_node_type(type); +} + +void GameView::_select_mode_pressed(int p_option) { + RuntimeNodeSelect::SelectMode mode = (RuntimeNodeSelect::SelectMode)p_option; + for (int i = 0; i < RuntimeNodeSelect::SELECT_MODE_MAX; i++) { + select_mode_button[i]->set_pressed_no_signal(i == mode); + } + + debugger->set_select_mode(mode); +} + +void GameView::_hide_selection_toggled(bool p_pressed) { + hide_selection->set_button_icon(get_editor_theme_icon(p_pressed ? SNAME("GuiVisibilityHidden") : SNAME("GuiVisibilityVisible"))); + + debugger->set_selection_visible(!p_pressed); +} + +void GameView::_camera_override_button_toggled(bool p_pressed) { + _update_debugger_buttons(); + + debugger->set_camera_override(p_pressed); +} + +void GameView::_camera_override_menu_id_pressed(int p_id) { + PopupMenu *menu = camera_override_menu->get_popup(); + if (p_id != CAMERA_RESET_2D && p_id != CAMERA_RESET_3D) { + for (int i = 0; i < menu->get_item_count(); i++) { + menu->set_item_checked(i, false); + } + } + + switch (p_id) { + case CAMERA_RESET_2D: { + debugger->reset_camera_2d_position(); + } break; + case CAMERA_RESET_3D: { + debugger->reset_camera_3d_position(); + } break; + case CAMERA_MODE_INGAME: { + debugger->set_camera_manipulate_mode(EditorDebuggerNode::OVERRIDE_INGAME); + menu->set_item_checked(menu->get_item_index(p_id), true); + + _update_debugger_buttons(); + } break; + case CAMERA_MODE_EDITORS: { + debugger->set_camera_manipulate_mode(EditorDebuggerNode::OVERRIDE_EDITORS); + menu->set_item_checked(menu->get_item_index(p_id), true); + + _update_debugger_buttons(); + } break; + } +} + +void GameView::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + suspend_button->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); + next_frame_button->set_button_icon(get_editor_theme_icon(SNAME("NextFrame"))); + + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_button_icon(get_editor_theme_icon(SNAME("InputEventJoypadMotion"))); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_button_icon(get_editor_theme_icon(SNAME("2DNodes"))); +#ifndef _3D_DISABLED + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_button_icon(get_editor_theme_icon(SNAME("Node3D"))); +#endif // _3D_DISABLED + + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_button_icon(get_editor_theme_icon(SNAME("ListSelect"))); + + hide_selection->set_button_icon(get_editor_theme_icon(hide_selection->is_pressed() ? SNAME("GuiVisibilityHidden") : SNAME("GuiVisibilityVisible"))); + + camera_override_button->set_button_icon(get_editor_theme_icon(SNAME("Camera"))); + camera_override_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + } break; + } +} + +void GameView::set_state(const Dictionary &p_state) { + if (p_state.has("hide_selection")) { + hide_selection->set_pressed(p_state["hide_selection"]); + _hide_selection_toggled(hide_selection->is_pressed()); + } + if (p_state.has("select_mode")) { + _select_mode_pressed(p_state["select_mode"]); + } + if (p_state.has("camera_override_mode")) { + _camera_override_menu_id_pressed(p_state["camera_override_mode"]); + } +} + +Dictionary GameView::get_state() const { + Dictionary d; + d["hide_selection"] = hide_selection->is_pressed(); + + for (int i = 0; i < RuntimeNodeSelect::SELECT_MODE_MAX; i++) { + if (select_mode_button[i]->is_pressed()) { + d["select_mode"] = i; + break; + } + } + + PopupMenu *menu = camera_override_menu->get_popup(); + for (int i = CAMERA_MODE_INGAME; i < CAMERA_MODE_EDITORS + 1; i++) { + if (menu->is_item_checked(menu->get_item_index(i))) { + d["camera_override_mode"] = i; + break; + } + } + + return d; +} + +GameView::GameView(Ref<GameViewDebugger> p_debugger) { + debugger = p_debugger; + + // Add some margin to the sides for better aesthetics. + // This prevents the first button's hover/pressed effect from "touching" the panel's border, + // which looks ugly. + MarginContainer *toolbar_margin = memnew(MarginContainer); + toolbar_margin->add_theme_constant_override("margin_left", 4 * EDSCALE); + toolbar_margin->add_theme_constant_override("margin_right", 4 * EDSCALE); + add_child(toolbar_margin); + + HBoxContainer *main_menu_hbox = memnew(HBoxContainer); + toolbar_margin->add_child(main_menu_hbox); + + suspend_button = memnew(Button); + main_menu_hbox->add_child(suspend_button); + suspend_button->set_toggle_mode(true); + suspend_button->set_theme_type_variation("FlatButton"); + suspend_button->connect(SceneStringName(toggled), callable_mp(this, &GameView::_suspend_button_toggled)); + suspend_button->set_tooltip_text(TTR("Suspend")); + + next_frame_button = memnew(Button); + main_menu_hbox->add_child(next_frame_button); + next_frame_button->set_theme_type_variation("FlatButton"); + next_frame_button->connect(SceneStringName(pressed), callable_mp(*debugger, &GameViewDebugger::next_frame)); + next_frame_button->set_tooltip_text(TTR("Next Frame")); + + main_menu_hbox->add_child(memnew(VSeparator)); + + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE] = memnew(Button); + main_menu_hbox->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_text(TTR("Input")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_toggle_mode(true); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_pressed(true); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_theme_type_variation("FlatButton"); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_NONE)); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_tooltip_text(TTR("Allow game input.")); + + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D] = memnew(Button); + main_menu_hbox->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_text(TTR("2D")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_toggle_mode(true); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_theme_type_variation("FlatButton"); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_2D)); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_tooltip_text(TTR("Disable game input and allow to select Node2Ds, Controls, and manipulate the 2D camera.")); + +#ifndef _3D_DISABLED + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D] = memnew(Button); + main_menu_hbox->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]); + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_text(TTR("3D")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_toggle_mode(true); + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_theme_type_variation("FlatButton"); + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_3D)); + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_tooltip_text(TTR("Disable game input and allow to select Node3Ds and manipulate the 3D camera.")); +#endif // _3D_DISABLED + + main_menu_hbox->add_child(memnew(VSeparator)); + + hide_selection = memnew(Button); + main_menu_hbox->add_child(hide_selection); + hide_selection->set_toggle_mode(true); + hide_selection->set_theme_type_variation("FlatButton"); + hide_selection->connect(SceneStringName(toggled), callable_mp(this, &GameView::_hide_selection_toggled)); + hide_selection->set_tooltip_text(TTR("Toggle Selection Visibility")); + + main_menu_hbox->add_child(memnew(VSeparator)); + + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE] = memnew(Button); + main_menu_hbox->add_child(select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_toggle_mode(true); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_pressed(true); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_theme_type_variation("FlatButton"); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_select_mode_pressed).bind(RuntimeNodeSelect::SELECT_MODE_SINGLE)); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q)); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_shortcut_context(this); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Alt+RMB: Show list of all nodes at position clicked.")); + + select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST] = memnew(Button); + main_menu_hbox->add_child(select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_toggle_mode(true); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_theme_type_variation("FlatButton"); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_select_mode_pressed).bind(RuntimeNodeSelect::SELECT_MODE_LIST)); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_tooltip_text(TTR("Show list of selectable nodes at position clicked.")); + + main_menu_hbox->add_child(memnew(VSeparator)); + + camera_override_button = memnew(Button); + main_menu_hbox->add_child(camera_override_button); + camera_override_button->set_toggle_mode(true); + camera_override_button->set_theme_type_variation("FlatButton"); + camera_override_button->connect(SceneStringName(toggled), callable_mp(this, &GameView::_camera_override_button_toggled)); + camera_override_button->set_tooltip_text(TTR("Override the in-game camera.")); + + camera_override_menu = memnew(MenuButton); + main_menu_hbox->add_child(camera_override_menu); + camera_override_menu->set_flat(false); + camera_override_menu->set_theme_type_variation("FlatMenuButton"); + camera_override_menu->set_h_size_flags(SIZE_SHRINK_END); + camera_override_menu->set_tooltip_text(TTR("Camera Override Options")); + + PopupMenu *menu = camera_override_menu->get_popup(); + menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_camera_override_menu_id_pressed)); + menu->add_item(TTR("Reset 2D Camera"), CAMERA_RESET_2D); + menu->add_item(TTR("Reset 3D Camera"), CAMERA_RESET_3D); + menu->add_separator(); + menu->add_radio_check_item(TTR("Manipulate In-Game"), CAMERA_MODE_INGAME); + menu->set_item_checked(menu->get_item_index(CAMERA_MODE_INGAME), true); + menu->add_radio_check_item(TTR("Manipulate From Editors"), CAMERA_MODE_EDITORS); + + _update_debugger_buttons(); + + panel = memnew(Panel); + add_child(panel); + panel->set_theme_type_variation("GamePanel"); + panel->set_v_size_flags(SIZE_EXPAND_FILL); + + p_debugger->connect("session_started", callable_mp(this, &GameView::_sessions_changed)); + p_debugger->connect("session_stopped", callable_mp(this, &GameView::_sessions_changed)); +} + +/////// + +void GameViewPlugin::make_visible(bool p_visible) { + game_view->set_visible(p_visible); +} + +void GameViewPlugin::set_state(const Dictionary &p_state) { + game_view->set_state(p_state); +} + +Dictionary GameViewPlugin::get_state() const { + return game_view->get_state(); +} + +void GameViewPlugin::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + add_debugger_plugin(debugger); + } break; + case NOTIFICATION_EXIT_TREE: { + remove_debugger_plugin(debugger); + } break; + } +} + +GameViewPlugin::GameViewPlugin() { + debugger.instantiate(); + + game_view = memnew(GameView(debugger)); + game_view->set_v_size_flags(Control::SIZE_EXPAND_FILL); + EditorNode::get_singleton()->get_editor_main_screen()->get_control()->add_child(game_view); + game_view->hide(); +} + +GameViewPlugin::~GameViewPlugin() { +} diff --git a/editor/plugins/game_view_plugin.h b/editor/plugins/game_view_plugin.h new file mode 100644 index 0000000000..f8701c3e76 --- /dev/null +++ b/editor/plugins/game_view_plugin.h @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* game_view_plugin.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GAME_VIEW_PLUGIN_H +#define GAME_VIEW_PLUGIN_H + +#include "editor/debugger/editor_debugger_node.h" +#include "editor/plugins/editor_debugger_plugin.h" +#include "editor/plugins/editor_plugin.h" +#include "scene/debugger/scene_debugger.h" +#include "scene/gui/box_container.h" + +class GameViewDebugger : public EditorDebuggerPlugin { + GDCLASS(GameViewDebugger, EditorDebuggerPlugin); + +private: + Vector<Ref<EditorDebuggerSession>> sessions; + + int node_type = RuntimeNodeSelect::NODE_TYPE_NONE; + bool selection_visible = true; + int select_mode = RuntimeNodeSelect::SELECT_MODE_SINGLE; + EditorDebuggerNode::CameraOverride camera_override_mode = EditorDebuggerNode::OVERRIDE_INGAME; + + void _session_started(Ref<EditorDebuggerSession> p_session); + void _session_stopped(); + +protected: + static void _bind_methods(); + +public: + void set_suspend(bool p_enabled); + void next_frame(); + + void set_node_type(int p_type); + void set_select_mode(int p_mode); + + void set_selection_visible(bool p_visible); + + void set_camera_override(bool p_enabled); + void set_camera_manipulate_mode(EditorDebuggerNode::CameraOverride p_mode); + + void reset_camera_2d_position(); + void reset_camera_3d_position(); + + virtual void setup_session(int p_session_id) override; + + GameViewDebugger() {} +}; + +class GameView : public VBoxContainer { + GDCLASS(GameView, VBoxContainer); + + enum { + CAMERA_RESET_2D, + CAMERA_RESET_3D, + CAMERA_MODE_INGAME, + CAMERA_MODE_EDITORS, + }; + + Ref<GameViewDebugger> debugger; + + int active_sessions = 0; + + Button *suspend_button = nullptr; + Button *next_frame_button = nullptr; + + Button *node_type_button[RuntimeNodeSelect::NODE_TYPE_MAX]; + Button *select_mode_button[RuntimeNodeSelect::SELECT_MODE_MAX]; + + Button *hide_selection = nullptr; + + Button *camera_override_button = nullptr; + MenuButton *camera_override_menu = nullptr; + + Panel *panel = nullptr; + + void _sessions_changed(); + + void _update_debugger_buttons(); + + void _suspend_button_toggled(bool p_pressed); + + void _node_type_pressed(int p_option); + void _select_mode_pressed(int p_option); + + void _hide_selection_toggled(bool p_pressed); + + void _camera_override_button_toggled(bool p_pressed); + void _camera_override_menu_id_pressed(int p_id); + +protected: + void _notification(int p_what); + +public: + void set_state(const Dictionary &p_state); + Dictionary get_state() const; + + GameView(Ref<GameViewDebugger> p_debugger); +}; + +class GameViewPlugin : public EditorPlugin { + GDCLASS(GameViewPlugin, EditorPlugin); + + GameView *game_view = nullptr; + + Ref<GameViewDebugger> debugger; + +protected: + void _notification(int p_what); + +public: + virtual String get_name() const override { return "Game"; } + bool has_main_screen() const override { return true; } + virtual void edit(Object *p_object) override {} + virtual bool handles(Object *p_object) const override { return false; } + virtual void make_visible(bool p_visible) override; + + virtual void set_state(const Dictionary &p_state) override; + virtual Dictionary get_state() const override; + + GameViewPlugin(); + ~GameViewPlugin(); +}; + +#endif // GAME_VIEW_PLUGIN_H diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h index ad6b534235..c8ed05c6b7 100644 --- a/editor/plugins/gdextension_export_plugin.h +++ b/editor/plugins/gdextension_export_plugin.h @@ -77,12 +77,14 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p HashSet<String> archs; HashSet<String> features_wo_arch; + Vector<String> features_vector; for (const String &tag : p_features) { if (all_archs.has(tag)) { archs.insert(tag); } else { features_wo_arch.insert(tag); } + features_vector.append(tag); } if (archs.is_empty()) { @@ -90,11 +92,22 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p } HashSet<String> libs_added; + struct FoundLibInfo { + int count = 0; + Vector<String> libs; + }; + HashMap<String, FoundLibInfo> libs_found; + for (const String &arch_tag : archs) { + if (arch_tag != "universal") { + libs_found[arch_tag] = FoundLibInfo(); + } + } for (const String &arch_tag : archs) { PackedStringArray tags; String library_path = GDExtensionLibraryLoader::find_extension_library( p_path, config, [features_wo_arch, arch_tag](const String &p_feature) { return features_wo_arch.has(p_feature) || (p_feature == arch_tag); }, &tags); + if (libs_added.has(library_path)) { continue; // Universal library, already added for another arch, do not duplicate. } @@ -122,15 +135,19 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p String linker_flags = "-Wl,-U,_" + entry_symbol; add_ios_linker_flags(linker_flags); } - } else { - Vector<String> features_vector; - for (const String &E : p_features) { - features_vector.append(E); - } - if (get_export_platform().is_valid()) { - get_export_platform()->add_message(EditorExportPlatform::EXPORT_MESSAGE_WARNING, TTR("GDExtension"), vformat(TTR("No suitable library found for GDExtension: \"%s\". Possible feature flags for your platform: %s"), p_path, String(", ").join(features_vector))); + + // Update found library info. + if (arch_tag == "universal") { + for (const String &sub_arch_tag : archs) { + if (sub_arch_tag != "universal") { + libs_found[sub_arch_tag].count++; + libs_found[sub_arch_tag].libs.push_back(library_path); + } + } + } else { + libs_found[arch_tag].count++; + libs_found[arch_tag].libs.push_back(library_path); } - return; } Vector<SharedObject> dependencies_shared_objects = GDExtensionLibraryLoader::find_extension_dependencies(p_path, config, [p_features](String p_feature) { return p_features.has(p_feature); }); @@ -138,6 +155,18 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p _add_shared_object(shared_object); } } + + for (const KeyValue<String, FoundLibInfo> &E : libs_found) { + if (E.value.count == 0) { + if (get_export_platform().is_valid()) { + get_export_platform()->add_message(EditorExportPlatform::EXPORT_MESSAGE_WARNING, TTR("GDExtension"), vformat(TTR("No \"%s\" library found for GDExtension: \"%s\". Possible feature flags for your platform: %s"), E.key, p_path, String(", ").join(features_vector))); + } + } else if (E.value.count > 1) { + if (get_export_platform().is_valid()) { + get_export_platform()->add_message(EditorExportPlatform::EXPORT_MESSAGE_WARNING, TTR("GDExtension"), vformat(TTR("Multiple \"%s\" libraries found for GDExtension: \"%s\": \"%s\"."), E.key, p_path, String(", ").join(E.value.libs))); + } + } + } } #endif // GDEXTENSION_EXPORT_PLUGIN_H diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp index 01492c1dd0..573c686d57 100644 --- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp @@ -93,7 +93,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g } if (Object::cast_to<CylinderShape3D>(*s)) { - return p_id == 0 ? "Radius" : "Height"; + return helper->cylinder_get_handle_name(p_id); } if (Object::cast_to<SeparationRayShape3D>(*s)) { @@ -219,25 +219,15 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i } if (Object::cast_to<CylinderShape3D>(*s)) { - Vector3 axis; - axis[p_id == 0 ? 0 : 1] = 1.0; Ref<CylinderShape3D> cs2 = s; - Vector3 ra, rb; - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = axis.dot(ra); - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - if (p_id == 0) { - cs2->set_radius(d); - } else if (p_id == 1) { - cs2->set_height(d * 2.0); - } + real_t height = cs2->get_height(); + real_t radius = cs2->get_radius(); + Vector3 position; + helper->cylinder_set_handle(sg, p_id, height, radius, position); + cs2->set_height(height); + cs2->set_radius(radius); + cs->set_global_position(position); } } @@ -293,31 +283,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo if (Object::cast_to<CylinderShape3D>(*s)) { Ref<CylinderShape3D> ss = s; - if (p_cancel) { - if (p_id == 0) { - ss->set_radius(p_restore); - } else { - ss->set_height(p_restore); - } - return; - } - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - if (p_id == 0) { - ur->create_action(TTR("Change Cylinder Shape Radius")); - ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); - ur->add_undo_method(ss.ptr(), "set_radius", p_restore); - } else { - ur->create_action( - /// - - //////// - TTR("Change Cylinder Shape Height")); - ur->add_do_method(ss.ptr(), "set_height", ss->get_height()); - ur->add_undo_method(ss.ptr(), "set_height", p_restore); - } - - ur->commit_action(); + helper->cylinder_commit_handle(p_id, TTR("Change Cylinder Shape Radius"), TTR("Change Cylinder Shape Height"), p_cancel, cs, *ss, *ss); } if (Object::cast_to<SeparationRayShape3D>(*s)) { @@ -534,10 +500,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_collision_segments(collision_segments); - Vector<Vector3> handles = { - Vector3(cs2->get_radius(), 0, 0), - Vector3(0, cs2->get_height() * 0.5, 0) - }; + Vector<Vector3> handles = helper->cylinder_get_handles(cs2->get_height(), cs2->get_radius()); p_gizmo->add_handles(handles, handles_material); } @@ -575,20 +538,19 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (Object::cast_to<ConvexPolygonShape3D>(*s)) { Vector<Vector3> points = Object::cast_to<ConvexPolygonShape3D>(*s)->get_points(); - if (points.size() > 3) { + if (points.size() > 1) { // Need at least 2 points for a line. Vector<Vector3> varr = Variant(points); Geometry3D::MeshData md; Error err = ConvexHullComputer::convex_hull(varr, md); if (err == OK) { - Vector<Vector3> points2; - points2.resize(md.edges.size() * 2); + Vector<Vector3> lines; + lines.resize(md.edges.size() * 2); for (uint32_t i = 0; i < md.edges.size(); i++) { - points2.write[i * 2 + 0] = md.vertices[md.edges[i].vertex_a]; - points2.write[i * 2 + 1] = md.vertices[md.edges[i].vertex_b]; + lines.write[i * 2 + 0] = md.vertices[md.edges[i].vertex_a]; + lines.write[i * 2 + 1] = md.vertices[md.edges[i].vertex_b]; } - - p_gizmo->add_lines(points2, material); - p_gizmo->add_collision_segments(points2); + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); } } } diff --git a/editor/plugins/gizmos/gizmo_3d_helper.cpp b/editor/plugins/gizmos/gizmo_3d_helper.cpp index 1226be90cb..ff1b67aa4a 100644 --- a/editor/plugins/gizmos/gizmo_3d_helper.cpp +++ b/editor/plugins/gizmos/gizmo_3d_helper.cpp @@ -139,3 +139,98 @@ void Gizmo3DHelper::box_commit_handle(const String &p_action_name, bool p_cancel ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin()); ur->commit_action(); } + +Vector<Vector3> Gizmo3DHelper::cylinder_get_handles(real_t p_height, real_t p_radius) { + Vector<Vector3> handles; + handles.push_back(Vector3(p_radius, 0, 0)); + handles.push_back(Vector3(0, p_height * 0.5, 0)); + handles.push_back(Vector3(0, p_height * -0.5, 0)); + return handles; +} + +String Gizmo3DHelper::cylinder_get_handle_name(int p_id) const { + if (p_id == 0) { + return "Radius"; + } else { + return "Height"; + } +} + +void Gizmo3DHelper::cylinder_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_cylinder_position) { + int sign = p_id == 2 ? -1 : 1; + int axis = p_id == 0 ? 0 : 1; + + Vector3 axis_vector; + axis_vector[axis] = sign; + Vector3 ra, rb; + Geometry3D::get_closest_points_between_segments(axis_vector * -4096, axis_vector * 4096, p_segment[0], p_segment[1], ra, rb); + float d = axis_vector.dot(ra); + + // Snap to grid. + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); + } + + if (p_id == 0) { + // Adjust radius. + if (d < 0.001) { + d = 0.001; + } + r_radius = d; + r_cylinder_position = initial_transform.get_origin(); + } else if (p_id == 1 || p_id == 2) { + real_t initial_height = initial_value; + + // Adjust height. + if (Input::get_singleton()->is_key_pressed(Key::ALT)) { + r_height = d * 2.0; + } else { + r_height = (initial_height * 0.5) + d; + } + + if (r_height < 0.001) { + r_height = 0.001; + } + + // Adjust position. + if (Input::get_singleton()->is_key_pressed(Key::ALT)) { + r_cylinder_position = initial_transform.get_origin(); + } else { + Vector3 offset; + offset[axis] = (r_height - initial_height) * 0.5 * sign; + r_cylinder_position = initial_transform.xform(offset); + } + } +} + +void Gizmo3DHelper::cylinder_commit_handle(int p_id, const String &p_radius_action_name, const String &p_height_action_name, bool p_cancel, Object *p_position_object, Object *p_height_object, Object *p_radius_object, const StringName &p_position_property, const StringName &p_height_property, const StringName &p_radius_property) { + if (!p_height_object) { + p_height_object = p_position_object; + } + if (!p_radius_object) { + p_radius_object = p_position_object; + } + + if (p_cancel) { + if (p_id == 0) { + p_radius_object->set(p_radius_property, initial_value); + } else { + p_height_object->set(p_height_property, initial_value); + } + p_position_object->set(p_position_property, initial_transform.get_origin()); + return; + } + + EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); + ur->create_action(p_id == 0 ? p_radius_action_name : p_height_action_name); + if (p_id == 0) { + ur->add_do_property(p_radius_object, p_radius_property, p_radius_object->get(p_radius_property)); + ur->add_undo_property(p_radius_object, p_radius_property, initial_value); + } else { + ur->add_do_property(p_height_object, p_height_property, p_height_object->get(p_height_property)); + ur->add_do_property(p_position_object, p_position_property, p_position_object->get(p_position_property)); + ur->add_undo_property(p_height_object, p_height_property, initial_value); + ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin()); + } + ur->commit_action(); +} diff --git a/editor/plugins/gizmos/gizmo_3d_helper.h b/editor/plugins/gizmos/gizmo_3d_helper.h index 387ea020b8..6d27e54770 100644 --- a/editor/plugins/gizmos/gizmo_3d_helper.h +++ b/editor/plugins/gizmos/gizmo_3d_helper.h @@ -50,6 +50,11 @@ public: String box_get_handle_name(int p_id) const; void box_set_handle(const Vector3 p_segment[2], int p_id, Vector3 &r_box_size, Vector3 &r_box_position); void box_commit_handle(const String &p_action_name, bool p_cancel, Object *p_position_object, Object *p_size_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_size_property = "size"); + + Vector<Vector3> cylinder_get_handles(real_t p_height, real_t p_radius); + String cylinder_get_handle_name(int p_id) const; + void cylinder_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_cylinder_position); + void cylinder_commit_handle(int p_id, const String &p_radius_action_name, const String &p_height_action_name, bool p_cancel, Object *p_position_object, Object *p_height_object = nullptr, Object *p_radius_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_height_property = "height", const StringName &p_radius_property = "radius"); }; #endif // GIZMO_3D_HELPER_H diff --git a/editor/plugins/gizmos/marker_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/marker_3d_gizmo_plugin.cpp index 39ae020d53..5a6527f876 100644 --- a/editor/plugins/gizmos/marker_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/marker_3d_gizmo_plugin.cpp @@ -36,7 +36,7 @@ #include "scene/3d/marker_3d.h" Marker3DGizmoPlugin::Marker3DGizmoPlugin() { - pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + pos3d_mesh.instantiate(); Vector<Vector3> cursor_points; Vector<Color> cursor_colors; diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp index c21a1b5dd6..4c2a3b60f8 100644 --- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp @@ -181,7 +181,7 @@ GPUParticlesCollisionSDF3DEditorPlugin::GPUParticlesCollisionSDF3DEditorPlugin() bake_hb->hide(); bake = memnew(Button); bake->set_theme_type_variation("FlatButton"); - bake->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); + bake->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); bake->set_text(TTR("Bake SDF")); bake->connect(SceneStringName(pressed), callable_mp(this, &GPUParticlesCollisionSDF3DEditorPlugin::_bake)); bake_hb->add_child(bake); diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index 1300394ca3..291ffc24d2 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -604,8 +604,8 @@ void GradientEditor::set_gradient(const Ref<Gradient> &p_gradient) { void GradientEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - reverse_button->set_icon(get_editor_theme_icon(SNAME("ReverseGradient"))); - snap_button->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); + reverse_button->set_button_icon(get_editor_theme_icon(SNAME("ReverseGradient"))); + snap_button->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); } break; case NOTIFICATION_READY: { Ref<Gradient> gradient = gradient_editor_rect->get_gradient(); diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp index 5bf1422780..46c9f4501b 100644 --- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp +++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp @@ -262,8 +262,8 @@ void GradientTexture2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - reverse_button->set_icon(get_editor_theme_icon(SNAME("ReverseGradient"))); - snap_button->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); + reverse_button->set_button_icon(get_editor_theme_icon(SNAME("ReverseGradient"))); + snap_button->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); } break; case NOTIFICATION_READY: { if (texture.is_valid()) { diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp index 30debfc14f..0c3ceff977 100644 --- a/editor/plugins/input_event_editor_plugin.cpp +++ b/editor/plugins/input_event_editor_plugin.cpp @@ -37,7 +37,7 @@ void InputEventConfigContainer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - open_config_button->set_icon(get_editor_theme_icon(SNAME("Edit"))); + open_config_button->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); } break; } } diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index 429add4540..e3b59f9bfb 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -35,8 +35,8 @@ Ref<OccluderPolygon2D> LightOccluder2DEditor::_ensure_occluder() const { Ref<OccluderPolygon2D> occluder = node->get_occluder_polygon(); - if (!occluder.is_valid()) { - occluder = Ref<OccluderPolygon2D>(memnew(OccluderPolygon2D)); + if (occluder.is_null()) { + occluder.instantiate(); node->set_occluder_polygon(occluder); } return occluder; diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp index 854ab7de8f..3f21d5d11c 100644 --- a/editor/plugins/lightmap_gi_editor_plugin.cpp +++ b/editor/plugins/lightmap_gi_editor_plugin.cpp @@ -93,10 +93,14 @@ void LightmapGIEditorPlugin::_bake_select_file(const String &p_file) { file_dialog->popup_file_dialog(); } break; case LightmapGI::BAKE_ERROR_NO_MESHES: { - EditorNode::get_singleton()->show_warning(TTR("No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake Light' flag is on.")); + EditorNode::get_singleton()->show_warning( + TTR("No meshes with lightmapping support to bake. Make sure they contain UV2 data and their Global Illumination property is set to Static.") + + String::utf8("\n\n• ") + TTR("To import a scene with lightmapping support, set Meshes > Light Baking to Static Lightmaps in the Import dock.") + + String::utf8("\n• ") + TTR("To enable lightmapping support on a primitive mesh, edit the PrimitiveMesh resource in the inspector and check Add UV2.") + + String::utf8("\n• ") + TTR("To enable lightmapping support on a CSG mesh, select the root CSG node and choose CSG > Bake Mesh Instance at the top of the 3D editor viewport.\nSelect the generated MeshInstance3D node and choose Mesh > Unwrap UV2 for Lightmap/AO at the top of the 3D editor viewport.")); } break; case LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE: { - EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable.")); + EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images. Make sure the lightmap destination path is writable.")); } break; case LightmapGI::BAKE_ERROR_NO_SCENE_ROOT: { EditorNode::get_singleton()->show_warning(TTR("No editor scene root found.")); @@ -108,7 +112,7 @@ void LightmapGIEditorPlugin::_bake_select_file(const String &p_file) { EditorNode::get_singleton()->show_warning(TTR("Maximum texture size is too small for the lightmap images.\nWhile this can be fixed by increasing the maximum texture size, it is recommended you split the scene into more objects instead.")); } break; case LightmapGI::BAKE_ERROR_LIGHTMAP_TOO_SMALL: { - EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images. Make sure all meshes selected to bake have `lightmap_size_hint` value set high enough, and `texel_scale` value of LightmapGI is not too low.")); + EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images. Make sure all meshes to bake have the Lightmap Size Hint property set high enough, and the LightmapGI's Texel Scale value is not too low.")); } break; case LightmapGI::BAKE_ERROR_ATLAS_TOO_SMALL: { EditorNode::get_singleton()->show_warning(TTR("Failed fitting a lightmap image into an atlas. This should never happen and should be reported.")); @@ -148,7 +152,7 @@ EditorProgress *LightmapGIEditorPlugin::tmp_progress = nullptr; bool LightmapGIEditorPlugin::bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh) { if (!tmp_progress) { - tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, false)); + tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, true)); ERR_FAIL_NULL_V(tmp_progress, false); } return tmp_progress->step(p_description, p_progress * 1000, p_refresh); @@ -177,7 +181,7 @@ LightmapGIEditorPlugin::LightmapGIEditorPlugin() { bake->set_theme_type_variation("FlatButton"); // TODO: Rework this as a dedicated toolbar control so we can hook into theme changes and update it // when the editor theme updates. - bake->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); + bake->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); bake->set_text(TTR("Bake Lightmaps")); #ifdef MODULE_LIGHTMAPPER_RD_ENABLED diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 2702b6c909..8bdc763ebe 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -56,9 +56,15 @@ void MaterialEditor::gui_input(const Ref<InputEvent> &p_event) { if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) { rot.x -= mm->get_relative().y * 0.01; rot.y -= mm->get_relative().x * 0.01; - - rot.x = CLAMP(rot.x, -Math_PI / 2, Math_PI / 2); + if (quad_instance->is_visible()) { + // Clamp rotation so the quad is always visible. + const real_t limit = Math::deg_to_rad(80.0); + rot = rot.clampf(-limit, limit); + } else { + rot.x = CLAMP(rot.x, -Math_PI / 2, Math_PI / 2); + } _update_rotation(); + _store_rotation_metadata(); } } @@ -70,6 +76,7 @@ void MaterialEditor::_update_theme_item_cache() { theme_cache.sphere_icon = get_editor_theme_icon(SNAME("MaterialPreviewSphere")); theme_cache.box_icon = get_editor_theme_icon(SNAME("MaterialPreviewCube")); + theme_cache.quad_icon = get_editor_theme_icon(SNAME("MaterialPreviewQuad")); theme_cache.checkerboard = get_editor_theme_icon(SNAME("Checkerboard")); } @@ -77,11 +84,12 @@ void MaterialEditor::_update_theme_item_cache() { void MaterialEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - light_1_switch->set_icon(theme_cache.light_1_icon); - light_2_switch->set_icon(theme_cache.light_2_icon); + light_1_switch->set_button_icon(theme_cache.light_1_icon); + light_2_switch->set_button_icon(theme_cache.light_2_icon); - sphere_switch->set_icon(theme_cache.sphere_icon); - box_switch->set_icon(theme_cache.box_icon); + sphere_switch->set_button_icon(theme_cache.sphere_icon); + box_switch->set_button_icon(theme_cache.box_icon); + quad_switch->set_button_icon(theme_cache.quad_icon); error_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor))); } break; @@ -95,6 +103,18 @@ void MaterialEditor::_notification(int p_what) { } } +void MaterialEditor::_set_rotation(real_t p_x_degrees, real_t p_y_degrees) { + rot.x = Math::deg_to_rad(p_x_degrees); + rot.y = Math::deg_to_rad(p_y_degrees); + _update_rotation(); +} + +// Store the rotation so it can persist when switching between materials. +void MaterialEditor::_store_rotation_metadata() { + Vector2 rotation_degrees = Vector2(Math::rad_to_deg(rot.x), Math::rad_to_deg(rot.y)); + EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_rotation", rotation_degrees); +} + void MaterialEditor::_update_rotation() { Transform3D t; t.basis.rotate(Vector3(0, 1, 0), -rot.y); @@ -124,6 +144,7 @@ void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_en vc->show(); sphere_instance->set_material_override(material); box_instance->set_material_override(material); + quad_instance->set_material_override(material); break; default: layout_error->show(); @@ -136,10 +157,6 @@ void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_en } else { hide(); } - - rot.x = Math::deg_to_rad(-15.0); - rot.y = Math::deg_to_rad(30.0); - _update_rotation(); } void MaterialEditor::_on_light_1_switch_pressed() { @@ -151,19 +168,36 @@ void MaterialEditor::_on_light_2_switch_pressed() { } void MaterialEditor::_on_sphere_switch_pressed() { - box_instance->hide(); sphere_instance->show(); + box_instance->hide(); + quad_instance->hide(); box_switch->set_pressed(false); - sphere_switch->set_pressed(true); - EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_on_sphere", true); + quad_switch->set_pressed(false); + _set_rotation(-15.0, 30.0); + _store_rotation_metadata(); + EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "sphere"); } void MaterialEditor::_on_box_switch_pressed() { + sphere_instance->hide(); box_instance->show(); + quad_instance->hide(); + sphere_switch->set_pressed(false); + quad_switch->set_pressed(false); + _set_rotation(-15.0, 30.0); + _store_rotation_metadata(); + EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "box"); +} + +void MaterialEditor::_on_quad_switch_pressed() { sphere_instance->hide(); - box_switch->set_pressed(true); + box_instance->hide(); + quad_instance->show(); sphere_switch->set_pressed(false); - EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_on_sphere", false); + box_switch->set_pressed(false); + _set_rotation(0.0, 0.0); + _store_rotation_metadata(); + EditorSettings::get_singleton()->set_project_metadata("inspector_options", "material_preview_mesh", "quad"); } MaterialEditor::MaterialEditor() { @@ -213,7 +247,7 @@ MaterialEditor::MaterialEditor() { viewport = memnew(SubViewport); Ref<World3D> world_3d; world_3d.instantiate(); - viewport->set_world_3d(world_3d); //use own world + viewport->set_world_3d(world_3d); // Use own world. vc->add_child(viewport); viewport->set_disable_input(true); viewport->set_transparent_background(true); @@ -221,7 +255,7 @@ MaterialEditor::MaterialEditor() { camera = memnew(Camera3D); camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 1.1))); - // Use low field of view so the sphere/box is fully encompassed within the preview, + // Use low field of view so the sphere/box/quad is fully encompassed within the preview, // without much distortion. camera->set_perspective(20, 0.1, 10); camera->make_current(); @@ -249,13 +283,19 @@ MaterialEditor::MaterialEditor() { box_instance = memnew(MeshInstance3D); rotation->add_child(box_instance); - box_instance->set_transform(Transform3D() * 0.25); + quad_instance = memnew(MeshInstance3D); + rotation->add_child(quad_instance); + sphere_instance->set_transform(Transform3D() * 0.375); + box_instance->set_transform(Transform3D() * 0.25); + quad_instance->set_transform(Transform3D() * 0.375); sphere_mesh.instantiate(); sphere_instance->set_mesh(sphere_mesh); box_mesh.instantiate(); box_instance->set_mesh(box_mesh); + quad_mesh.instantiate(); + quad_instance->set_mesh(quad_mesh); set_custom_minimum_size(Size2(1, 150) * EDSCALE); @@ -269,17 +309,21 @@ MaterialEditor::MaterialEditor() { sphere_switch = memnew(Button); sphere_switch->set_theme_type_variation("PreviewLightButton"); sphere_switch->set_toggle_mode(true); - sphere_switch->set_pressed(true); vb_shape->add_child(sphere_switch); sphere_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_sphere_switch_pressed)); box_switch = memnew(Button); box_switch->set_theme_type_variation("PreviewLightButton"); box_switch->set_toggle_mode(true); - box_switch->set_pressed(false); vb_shape->add_child(box_switch); box_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_box_switch_pressed)); + quad_switch = memnew(Button); + quad_switch->set_theme_type_variation("PreviewLightButton"); + quad_switch->set_toggle_mode(true); + vb_shape->add_child(quad_switch); + quad_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_quad_switch_pressed)); + layout_3d->add_spacer(); VBoxContainer *vb_light = memnew(VBoxContainer); @@ -299,14 +343,23 @@ MaterialEditor::MaterialEditor() { vb_light->add_child(light_2_switch); light_2_switch->connect(SceneStringName(pressed), callable_mp(this, &MaterialEditor::_on_light_2_switch_pressed)); - if (EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_on_sphere", true)) { + String shape = EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_mesh", "sphere"); + if (shape == "sphere") { box_instance->hide(); + quad_instance->hide(); + sphere_switch->set_pressed_no_signal(true); + } else if (shape == "box") { + sphere_instance->hide(); + quad_instance->hide(); + box_switch->set_pressed_no_signal(true); } else { - box_instance->show(); sphere_instance->hide(); - box_switch->set_pressed(true); - sphere_switch->set_pressed(false); + box_instance->hide(); + quad_switch->set_pressed_no_signal(true); } + + Vector2 stored_rot = EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_rotation", Vector2()); + _set_rotation(stored_rot.x, stored_rot.y); } /////////////////////// diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 28c59d27db..c1b37a5831 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -62,6 +62,7 @@ class MaterialEditor : public Control { Node3D *rotation = nullptr; MeshInstance3D *sphere_instance = nullptr; MeshInstance3D *box_instance = nullptr; + MeshInstance3D *quad_instance = nullptr; DirectionalLight3D *light1 = nullptr; DirectionalLight3D *light2 = nullptr; Camera3D *camera = nullptr; @@ -69,6 +70,7 @@ class MaterialEditor : public Control { Ref<SphereMesh> sphere_mesh; Ref<BoxMesh> box_mesh; + Ref<QuadMesh> quad_mesh; VBoxContainer *layout_error = nullptr; Label *error_label = nullptr; @@ -80,6 +82,7 @@ class MaterialEditor : public Control { Button *sphere_switch = nullptr; Button *box_switch = nullptr; + Button *quad_switch = nullptr; Button *light_1_switch = nullptr; Button *light_2_switch = nullptr; @@ -88,6 +91,7 @@ class MaterialEditor : public Control { Ref<Texture2D> light_2_icon; Ref<Texture2D> sphere_icon; Ref<Texture2D> box_icon; + Ref<Texture2D> quad_icon; Ref<Texture2D> checkerboard; } theme_cache; @@ -95,11 +99,14 @@ class MaterialEditor : public Control { void _on_light_2_switch_pressed(); void _on_sphere_switch_pressed(); void _on_box_switch_pressed(); + void _on_quad_switch_pressed(); protected: virtual void _update_theme_item_cache() override; void _notification(int p_what); void gui_input(const Ref<InputEvent> &p_event) override; + void _set_rotation(real_t p_x_degrees, real_t p_y_degrees); + void _store_rotation_metadata(); void _update_rotation(); public: diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index c8eda600b8..645dd1784e 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -58,8 +58,8 @@ void MeshEditor::_update_theme_item_cache() { void MeshEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - light_1_switch->set_icon(theme_cache.light_1_icon); - light_2_switch->set_icon(theme_cache.light_2_icon); + light_1_switch->set_button_icon(theme_cache.light_1_icon); + light_2_switch->set_button_icon(theme_cache.light_2_icon); } break; } } diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index eda6cdffb1..fdc222e64f 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -40,6 +40,7 @@ #include "scene/3d/physics/collision_shape_3d.h" #include "scene/3d/physics/physics_body_3d.h" #include "scene/3d/physics/static_body_3d.h" +#include "scene/gui/aspect_ratio_container.h" #include "scene/gui/box_container.h" #include "scene/gui/dialogs.h" #include "scene/gui/menu_button.h" @@ -445,10 +446,43 @@ void MeshInstance3DEditor::_debug_uv_draw() { } debug_uv->set_clip_contents(true); - debug_uv->draw_rect(Rect2(Vector2(), debug_uv->get_size()), get_theme_color(SNAME("dark_color_3"), EditorStringName(Editor))); + debug_uv->draw_rect( + Rect2(Vector2(), debug_uv->get_size()), + get_theme_color(SNAME("dark_color_3"), EditorStringName(Editor))); + + // Draw an outline to represent the UV2's beginning and end area (useful on Black OLED theme). + // Top-left coordinate needs to be `(1, 1)` to prevent `clip_contents` from clipping the top and left lines. + debug_uv->draw_rect( + Rect2(Vector2(1, 1), debug_uv->get_size() - Vector2(1, 1)), + get_theme_color(SNAME("mono_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.125), + false, + Math::round(EDSCALE)); + + for (int x = 1; x <= 7; x++) { + debug_uv->draw_line( + Vector2(debug_uv->get_size().x * 0.125 * x, 0), + Vector2(debug_uv->get_size().x * 0.125 * x, debug_uv->get_size().y), + get_theme_color(SNAME("mono_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.125), + Math::round(EDSCALE)); + } + + for (int y = 1; y <= 7; y++) { + debug_uv->draw_line( + Vector2(0, debug_uv->get_size().y * 0.125 * y), + Vector2(debug_uv->get_size().x, debug_uv->get_size().y * 0.125 * y), + get_theme_color(SNAME("mono_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.125), + Math::round(EDSCALE)); + } + debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size()); + // Use a translucent color to allow overlapping triangles to be visible. - debug_uv->draw_multiline(uv_lines, get_theme_color(SNAME("mono_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.5)); + // Divide line width by the drawing scale set above, so that line width is consistent regardless of dialog size. + // Aspect ratio is preserved by the parent AspectRatioContainer, so we only need to check the X size which is always equal to Y. + debug_uv->draw_multiline( + uv_lines, + get_theme_color(SNAME("mono_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.5), + Math::round(EDSCALE) / debug_uv->get_size().x); } void MeshInstance3DEditor::_create_navigation_mesh() { @@ -527,7 +561,7 @@ void MeshInstance3DEditor::_create_outline_mesh() { void MeshInstance3DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - options->set_icon(get_editor_theme_icon(SNAME("MeshInstance3D"))); + options->set_button_icon(get_editor_theme_icon(SNAME("MeshInstance3D"))); } break; } } @@ -613,10 +647,14 @@ MeshInstance3DEditor::MeshInstance3DEditor() { debug_uv_dialog = memnew(AcceptDialog); debug_uv_dialog->set_title(TTR("UV Channel Debug")); add_child(debug_uv_dialog); + + debug_uv_arc = memnew(AspectRatioContainer); + debug_uv_dialog->add_child(debug_uv_arc); + debug_uv = memnew(Control); debug_uv->set_custom_minimum_size(Size2(600, 600) * EDSCALE); debug_uv->connect(SceneStringName(draw), callable_mp(this, &MeshInstance3DEditor::_debug_uv_draw)); - debug_uv_dialog->add_child(debug_uv); + debug_uv_arc->add_child(debug_uv); navigation_mesh_dialog = memnew(ConfirmationDialog); navigation_mesh_dialog->set_title(TTR("Create NavigationMesh")); diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h index c982df9c5f..569ecd4fff 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.h +++ b/editor/plugins/mesh_instance_3d_editor_plugin.h @@ -36,6 +36,7 @@ #include "scene/gui/option_button.h" class AcceptDialog; +class AspectRatioContainer; class ConfirmationDialog; class MenuButton; class SpinBox; @@ -79,6 +80,7 @@ class MeshInstance3DEditor : public Control { AcceptDialog *err_dialog = nullptr; AcceptDialog *debug_uv_dialog = nullptr; + AspectRatioContainer *debug_uv_arc = nullptr; Control *debug_uv = nullptr; Vector<Vector2> uv_lines; diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index d6650bd08f..6f79ab0529 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -260,7 +260,7 @@ MeshLibraryEditor::MeshLibraryEditor() { Node3DEditor::get_singleton()->add_control_to_menu_panel(menu); menu->set_position(Point2(1, 1)); menu->set_text(TTR("MeshLibrary")); - menu->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MeshLibrary"), EditorStringName(EditorIcons))); + menu->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MeshLibrary"), EditorStringName(EditorIcons))); menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); menu->get_popup()->add_item(TTR("Remove Selected Item"), MENU_OPTION_REMOVE_ITEM); menu->get_popup()->add_separator(); diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp index 729ceccd25..9e686dd689 100644 --- a/editor/plugins/multimesh_editor_plugin.cpp +++ b/editor/plugins/multimesh_editor_plugin.cpp @@ -272,7 +272,7 @@ MultiMeshEditor::MultiMeshEditor() { Node3DEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text("MultiMesh"); - options->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MultiMeshInstance3D"), EditorStringName(EditorIcons))); + options->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MultiMeshInstance3D"), EditorStringName(EditorIcons))); options->get_popup()->add_item(TTR("Populate Surface")); options->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &MultiMeshEditor::_menu_option)); diff --git a/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp b/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp index 9629a673e9..efa98d8e4d 100644 --- a/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp +++ b/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp @@ -30,144 +30,506 @@ #include "navigation_obstacle_3d_editor_plugin.h" -#include "canvas_item_editor_plugin.h" -#include "core/input/input.h" -#include "core/io/file_access.h" +#include "core/config/project_settings.h" #include "core/math/geometry_2d.h" -#include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" -#include "node_3d_editor_plugin.h" -#include "scene/3d/camera_3d.h" -#include "scene/gui/separator.h" +#include "editor/plugins/node_3d_editor_plugin.h" +#include "scene/3d/navigation_obstacle_3d.h" +#include "scene/gui/button.h" +#include "scene/gui/dialogs.h" +#include "servers/navigation_server_3d.h" + +bool NavigationObstacle3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<NavigationObstacle3D>(p_spatial) != nullptr; +} + +String NavigationObstacle3DGizmoPlugin::get_gizmo_name() const { + return "NavigationObstacle3D"; +} + +void NavigationObstacle3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + p_gizmo->clear(); + + if (!p_gizmo->is_selected() && get_state() == HIDDEN) { + return; + } + + NavigationObstacle3D *obstacle = Object::cast_to<NavigationObstacle3D>(p_gizmo->get_node_3d()); + + if (!obstacle) { + return; + } + + const Vector<Vector3> &vertices = obstacle->get_vertices(); + if (vertices.is_empty()) { + return; + } + + float height = obstacle->get_height(); + + const Basis safe_basis = Basis(Vector3(0.0, 1.0, 0.0), obstacle->get_global_rotation().y, obstacle->get_global_basis().get_scale().abs().maxf(0.001)); + const Basis gbi = obstacle->get_global_basis().inverse(); + const Basis safe_global_basis = gbi * safe_basis; + const int vertex_count = vertices.size(); + + Vector<Vector3> lines_mesh_vertices; + lines_mesh_vertices.resize(vertex_count * 8); + Vector3 *lines_mesh_vertices_ptrw = lines_mesh_vertices.ptrw(); + + int vertex_index = 0; + + for (int i = 0; i < vertex_count; i++) { + Vector3 point = vertices[i]; + Vector3 next_point = vertices[(i + 1) % vertex_count]; + + Vector3 direction = safe_basis.xform(next_point.direction_to(point)); + Vector3 arrow_dir = direction.cross(Vector3(0.0, 1.0, 0.0)); + Vector3 edge_middle = point + ((next_point - point) * 0.5); + + // Ensure vector stays perpendicular even when scaled non-uniformly. + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(edge_middle); + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(edge_middle) + gbi.xform(arrow_dir) * 0.5; + + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(point); + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(next_point); + + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(Vector3(point.x, height, point.z)); + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(Vector3(next_point.x, height, next_point.z)); + + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(point); + lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(Vector3(point.x, height, point.z)); + } + + Vector<Vector2> polygon_2d_vertices; + polygon_2d_vertices.resize(vertex_count); + for (int i = 0; i < vertex_count; i++) { + const Vector3 &vert = vertices[i]; + polygon_2d_vertices.write[i] = Vector2(vert.x, vert.z); + } + Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(polygon_2d_vertices); + + NavigationServer3D *ns3d = NavigationServer3D::get_singleton(); + + if (triangulated_polygon_2d_indices.is_empty()) { + p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material()); + } else { + p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushout_edge_material()); + } + p_gizmo->add_collision_segments(lines_mesh_vertices); + + if (p_gizmo->is_selected()) { + NavigationObstacle3DEditorPlugin::singleton->redraw(); + } +} + +bool NavigationObstacle3DGizmoPlugin::can_be_hidden() const { + return true; +} + +int NavigationObstacle3DGizmoPlugin::get_priority() const { + return -1; +} + +int NavigationObstacle3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const { + if (NavigationObstacle3DEditorPlugin::singleton->get_mode() != 1) { // MODE_EDIT + return -1; + } + + NavigationObstacle3D *obstacle_node = Object::cast_to<NavigationObstacle3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL_V(obstacle_node, -1); + + const Vector3 safe_scale = obstacle_node->get_global_basis().get_scale().abs().maxf(0.001); + const Transform3D gt = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y), obstacle_node->get_global_position()); + const Vector<Vector3> &vertices = obstacle_node->get_vertices(); + + for (int idx = 0; idx < vertices.size(); ++idx) { + Vector3 pos = gt.xform(vertices[idx]); + if (p_camera->unproject_position(pos).distance_to(p_point) < 20) { + return idx; + } + } + + return -1; +} + +Vector<int> NavigationObstacle3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const { + Vector<int> contained_points; + if (NavigationObstacle3DEditorPlugin::singleton->get_mode() != 1) { // MODE_EDIT + return contained_points; + } + + NavigationObstacle3D *obstacle_node = Object::cast_to<NavigationObstacle3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL_V(obstacle_node, contained_points); + + const Vector3 safe_scale = obstacle_node->get_global_basis().get_scale().abs().maxf(0.001); + const Transform3D gt = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y), obstacle_node->get_global_position()); + const Vector<Vector3> &vertices = obstacle_node->get_vertices(); + + for (int idx = 0; idx < vertices.size(); ++idx) { + Vector3 pos = gt.xform(vertices[idx]); + bool is_contained_in_frustum = true; + for (int i = 0; i < p_frustum.size(); ++i) { + if (p_frustum[i].distance_to(pos) > 0) { + is_contained_in_frustum = false; + break; + } + } + + if (is_contained_in_frustum) { + contained_points.push_back(idx); + } + } + + return contained_points; +} + +Transform3D NavigationObstacle3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const { + NavigationObstacle3D *obstacle_node = Object::cast_to<NavigationObstacle3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL_V(obstacle_node, Transform3D()); + + const Vector<Vector3> &vertices = obstacle_node->get_vertices(); + ERR_FAIL_INDEX_V(p_id, vertices.size(), Transform3D()); + + const Basis safe_basis_inverse = Basis(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y, obstacle_node->get_global_basis().get_scale().abs().maxf(0.001)).inverse(); + Transform3D subgizmo_transform = Transform3D(Basis(), safe_basis_inverse.xform(vertices[p_id])); + return subgizmo_transform; +} + +void NavigationObstacle3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) { + NavigationObstacle3D *obstacle_node = Object::cast_to<NavigationObstacle3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL(obstacle_node); + + const Basis safe_basis = Basis(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y, obstacle_node->get_global_basis().get_scale().abs().maxf(0.001)); + Vector3 new_vertex_pos = p_transform.origin; + + Vector<Vector3> vertices = obstacle_node->get_vertices(); + ERR_FAIL_INDEX(p_id, vertices.size()); + + Vector3 vertex = safe_basis.xform(new_vertex_pos); + vertex.y = 0.0; + vertices.write[p_id] = vertex; -void NavigationObstacle3DEditor::_notification(int p_what) { + obstacle_node->set_vertices(vertices); +} + +void NavigationObstacle3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) { + NavigationObstacle3D *obstacle_node = Object::cast_to<NavigationObstacle3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL(obstacle_node); + + const Basis safe_basis = Basis(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y, obstacle_node->get_global_basis().get_scale().abs().maxf(0.001)); + + Vector<Vector3> vertices = obstacle_node->get_vertices(); + Vector<Vector3> restore_vertices = vertices; + + for (int i = 0; i < p_ids.size(); ++i) { + const int idx = p_ids[i]; + Vector3 vertex = safe_basis.xform(p_restore[i].origin); + vertex.y = 0.0; + restore_vertices.write[idx] = vertex; + } + + if (p_cancel) { + obstacle_node->set_vertices(restore_vertices); + return; + } + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Set Obstacle Vertices")); + undo_redo->add_do_method(obstacle_node, "set_vertices", vertices); + undo_redo->add_undo_method(obstacle_node, "set_vertices", restore_vertices); + undo_redo->commit_action(); +} + +NavigationObstacle3DGizmoPlugin::NavigationObstacle3DGizmoPlugin() { + current_state = VISIBLE; +} + +void NavigationObstacle3DEditorPlugin::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + _update_theme(); + } break; + case NOTIFICATION_READY: { - button_create->set_icon(get_editor_theme_icon(SNAME("Edit"))); - button_edit->set_icon(get_editor_theme_icon(SNAME("MovePoint"))); + _update_theme(); button_edit->set_pressed(true); - get_tree()->connect("node_removed", callable_mp(this, &NavigationObstacle3DEditor::_node_removed)); + get_tree()->connect("node_removed", callable_mp(this, &NavigationObstacle3DEditorPlugin::_node_removed)); + EditorNode::get_singleton()->get_gui_base()->connect(SceneStringName(theme_changed), callable_mp(this, &NavigationObstacle3DEditorPlugin::_update_theme)); + } break; + case NOTIFICATION_EXIT_TREE: { + get_tree()->disconnect("node_removed", callable_mp(this, &NavigationObstacle3DEditorPlugin::_node_removed)); + EditorNode::get_singleton()->get_gui_base()->disconnect(SceneStringName(theme_changed), callable_mp(this, &NavigationObstacle3DEditorPlugin::_update_theme)); } break; } } -void NavigationObstacle3DEditor::_node_removed(Node *p_node) { - if (p_node == obstacle_node) { - obstacle_node = nullptr; - if (point_lines_meshinstance->get_parent() == p_node) { - p_node->remove_child(point_lines_meshinstance); +void NavigationObstacle3DEditorPlugin::edit(Object *p_object) { + obstacle_node = Object::cast_to<NavigationObstacle3D>(p_object); + + RenderingServer *rs = RenderingServer::get_singleton(); + + if (obstacle_node) { + if (obstacle_node->get_vertices().is_empty()) { + set_mode(MODE_CREATE); + } else { + set_mode(MODE_EDIT); } - hide(); + wip_vertices.clear(); + wip_active = false; + edited_point = -1; + + rs->instance_set_scenario(point_lines_instance_rid, obstacle_node->get_world_3d()->get_scenario()); + rs->instance_set_scenario(point_handles_instance_rid, obstacle_node->get_world_3d()->get_scenario()); + + redraw(); + + } else { + obstacle_node = nullptr; + + rs->mesh_clear(point_lines_mesh_rid); + rs->mesh_clear(point_handle_mesh_rid); + rs->instance_set_scenario(point_lines_instance_rid, RID()); + rs->instance_set_scenario(point_handles_instance_rid, RID()); } } -void NavigationObstacle3DEditor::_menu_option(int p_option) { - switch (p_option) { - case MODE_CREATE: { - mode = MODE_CREATE; - button_create->set_pressed(true); - button_edit->set_pressed(false); - } break; - case MODE_EDIT: { - mode = MODE_EDIT; - button_create->set_pressed(false); - button_edit->set_pressed(true); - } break; +bool NavigationObstacle3DEditorPlugin::handles(Object *p_object) const { + return Object::cast_to<NavigationObstacle3D>(p_object); +} + +void NavigationObstacle3DEditorPlugin::make_visible(bool p_visible) { + if (p_visible) { + obstacle_editor->show(); + } else { + obstacle_editor->hide(); + edit(nullptr); } } -void NavigationObstacle3DEditor::_wip_close() { - ERR_FAIL_NULL_MSG(obstacle_node, "Edited NavigationObstacle3D is not valid."); +void NavigationObstacle3DEditorPlugin::action_flip_vertices() { + if (!obstacle_node) { + return; + } + + Vector<Vector3> flipped_vertices = obstacle_node->get_vertices(); + flipped_vertices.reverse(); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Set NavigationObstacle3D Vertices")); + undo_redo->create_action(TTR("Edit Obstacle (Flip Winding)")); + undo_redo->add_do_method(obstacle_node, "set_vertices", flipped_vertices); undo_redo->add_undo_method(obstacle_node, "set_vertices", obstacle_node->get_vertices()); + undo_redo->commit_action(); - PackedVector3Array polygon_3d_vertices; - Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(wip); + obstacle_node->update_gizmos(); +} - if (!triangulated_polygon_2d_indices.is_empty()) { - polygon_3d_vertices.resize(wip.size()); - Vector3 *polygon_3d_vertices_ptr = polygon_3d_vertices.ptrw(); - for (int i = 0; i < wip.size(); i++) { - const Vector2 &vert = wip[i]; - polygon_3d_vertices_ptr[i] = Vector3(vert.x, 0.0, vert.y); - } +void NavigationObstacle3DEditorPlugin::action_clear_vertices() { + if (!obstacle_node) { + return; } - undo_redo->add_do_method(obstacle_node, "set_vertices", polygon_3d_vertices); - undo_redo->add_do_method(this, "_polygon_draw"); - undo_redo->add_undo_method(this, "_polygon_draw"); - wip.clear(); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Edit Obstacle (Clear Vertices)")); + undo_redo->add_do_method(obstacle_node, "set_vertices", Vector<Vector3>()); + undo_redo->add_undo_method(obstacle_node, "set_vertices", obstacle_node->get_vertices()); + undo_redo->commit_action(); + + obstacle_node->update_gizmos(); + edit(obstacle_node); +} + +void NavigationObstacle3DEditorPlugin::_update_theme() { + button_create->set_tooltip_text(TTR("Add Vertex")); + button_edit->set_tooltip_text(TTR("Edit Vertex")); + button_delete->set_tooltip_text(TTR("Delete Vertex")); + button_flip->set_tooltip_text(TTR("Flip Winding")); + button_clear->set_tooltip_text(TTR("Clear Vertices")); + button_create->set_button_icon(button_create->get_editor_theme_icon(SNAME("CurveCreate"))); + button_edit->set_button_icon(button_edit->get_editor_theme_icon(SNAME("CurveEdit"))); + button_delete->set_button_icon(button_delete->get_editor_theme_icon(SNAME("CurveDelete"))); + button_flip->set_button_icon(button_flip->get_editor_theme_icon(SNAME("FlipWinding"))); + button_clear->set_button_icon(button_clear->get_editor_theme_icon(SNAME("Clear"))); +} + +void NavigationObstacle3DEditorPlugin::_node_removed(Node *p_node) { + if (obstacle_node == p_node) { + obstacle_node = nullptr; + + RenderingServer *rs = RenderingServer::get_singleton(); + rs->mesh_clear(point_lines_mesh_rid); + rs->mesh_clear(point_handle_mesh_rid); + + obstacle_editor->hide(); + } +} + +void NavigationObstacle3DEditorPlugin::set_mode(int p_option) { + if (p_option == NavigationObstacle3DEditorPlugin::ACTION_FLIP) { + button_flip->set_pressed(false); + action_flip_vertices(); + return; + } + + if (p_option == NavigationObstacle3DEditorPlugin::ACTION_CLEAR) { + button_clear->set_pressed(false); + button_clear_dialog->reset_size(); + button_clear_dialog->popup_centered(); + return; + } + + mode = p_option; + + button_create->set_pressed(p_option == NavigationObstacle3DEditorPlugin::MODE_CREATE); + button_edit->set_pressed(p_option == NavigationObstacle3DEditorPlugin::MODE_EDIT); + button_delete->set_pressed(p_option == NavigationObstacle3DEditorPlugin::MODE_DELETE); + button_flip->set_pressed(false); + button_clear->set_pressed(false); +} + +void NavigationObstacle3DEditorPlugin::_wip_cancel() { + wip_vertices.clear(); wip_active = false; - mode = MODE_EDIT; - button_edit->set_pressed(true); - button_create->set_pressed(false); + edited_point = -1; - undo_redo->commit_action(); + + redraw(); } -EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) { +void NavigationObstacle3DEditorPlugin::_wip_close() { + ERR_FAIL_NULL_MSG(obstacle_node, "Edited NavigationObstacle3D is not valid."); + + Vector<Vector2> wip_2d_vertices; + wip_2d_vertices.resize(wip_vertices.size()); + for (int i = 0; i < wip_vertices.size(); i++) { + const Vector3 &vert = wip_vertices[i]; + wip_2d_vertices.write[i] = Vector2(vert.x, vert.z); + } + Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(wip_2d_vertices); + + if (!triangulated_polygon_2d_indices.is_empty()) { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Set Obstacle Vertices")); + undo_redo->add_do_method(obstacle_node, "set_vertices", wip_vertices); + undo_redo->add_undo_method(obstacle_node, "set_vertices", obstacle_node->get_vertices()); + undo_redo->commit_action(); + + wip_vertices.clear(); + wip_active = false; + //mode = MODE_EDIT; + NavigationObstacle3DEditorPlugin::singleton->set_mode(NavigationObstacle3DEditorPlugin::MODE_EDIT); + button_edit->set_pressed(true); + button_create->set_pressed(false); + edited_point = -1; + } +} + +EditorPlugin::AfterGUIInput NavigationObstacle3DEditorPlugin::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) { if (!obstacle_node) { return EditorPlugin::AFTER_GUI_INPUT_PASS; } - Transform3D gt = obstacle_node->get_global_transform(); - Transform3D gi = gt.affine_inverse(); - Plane p(Vector3(0.0, 1.0, 0.0), gt.origin); + if (!obstacle_node->is_visible_in_tree()) { + return EditorPlugin::AFTER_GUI_INPUT_PASS; + } + + Ref<InputEventMouse> mouse_event = p_event; + + if (mouse_event.is_null()) { + return EditorPlugin::AFTER_GUI_INPUT_PASS; + } Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - Vector2 gpoint = mb->get_position(); - Vector3 ray_from = p_camera->project_ray_origin(gpoint); - Vector3 ray_dir = p_camera->project_ray_normal(gpoint); + Vector2 mouse_position = mb->get_position(); + Vector3 ray_from = p_camera->project_ray_origin(mouse_position); + Vector3 ray_dir = p_camera->project_ray_normal(mouse_position); + + const Vector3 safe_scale = obstacle_node->get_global_basis().get_scale().abs().maxf(0.001); + const Transform3D gt = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y), obstacle_node->get_global_position()); + Transform3D gi = gt.affine_inverse(); + Plane projection_plane(Vector3(0.0, 1.0, 0.0), gt.origin); Vector3 spoint; - if (!p.intersects_ray(ray_from, ray_dir, &spoint)) { + if (!projection_plane.intersects_ray(ray_from, ray_dir, &spoint)) { return EditorPlugin::AFTER_GUI_INPUT_PASS; } spoint = gi.xform(spoint); - Vector2 cpoint(spoint.x, spoint.z); - - //DO NOT snap here, it's confusing in 3D for adding points. - //Let the snap happen when the point is being moved, instead. - //cpoint = CanvasItemEditor::get_singleton()->snap_point(cpoint); - - PackedVector2Array poly = _get_polygon(); + Vector3 cpoint = Vector3(spoint.x, 0.0, spoint.z); + Vector<Vector3> obstacle_vertices = obstacle_node->get_vertices(); - //first check if a point is to be added (segment split) real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); switch (mode) { case MODE_CREATE: { if (mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { + if (obstacle_vertices.size() >= 3) { + int closest_idx = -1; + Vector2 closest_edge_point; + real_t closest_dist = 1e10; + for (int i = 0; i < obstacle_vertices.size(); i++) { + Vector2 points[2] = { + p_camera->unproject_position(gt.xform(obstacle_vertices[i])), + p_camera->unproject_position(gt.xform(obstacle_vertices[(i + 1) % obstacle_vertices.size()])) + }; + + Vector2 cp = Geometry2D::get_closest_point_to_segment(mouse_position, points); + if (cp.distance_squared_to(points[0]) < grab_threshold || cp.distance_squared_to(points[1]) < grab_threshold) { + continue; // Skip edge as clicked point is too close to existing vertex. + } + + real_t d = cp.distance_to(mouse_position); + if (d < closest_dist && d < grab_threshold) { + closest_dist = d; + closest_edge_point = cp; + closest_idx = i; + } + } + if (closest_idx >= 0) { + edited_point = -1; + Vector3 _ray_from = p_camera->project_ray_origin(closest_edge_point); + Vector3 _ray_dir = p_camera->project_ray_normal(closest_edge_point); + Vector3 edge_intersection_point; + if (projection_plane.intersects_ray(_ray_from, _ray_dir, &edge_intersection_point)) { + edge_intersection_point = gi.xform(edge_intersection_point); + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Edit Obstacle (Add Vertex)")); + undo_redo->add_undo_method(obstacle_node, "set_vertices", obstacle_vertices); + obstacle_vertices.insert(closest_idx + 1, edge_intersection_point); + undo_redo->add_do_method(obstacle_node, "set_vertices", obstacle_vertices); + undo_redo->commit_action(); + redraw(); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } + } + } if (!wip_active) { - wip.clear(); - wip.push_back(cpoint); + wip_vertices.clear(); + wip_vertices.push_back(cpoint); wip_active = true; edited_point_pos = cpoint; snap_ignore = false; - _polygon_draw(); + redraw(); edited_point = 1; return EditorPlugin::AFTER_GUI_INPUT_STOP; } else { - if (wip.size() > 1 && p_camera->unproject_position(gt.xform(Vector3(wip[0].x, 0.0, wip[0].y))).distance_to(gpoint) < grab_threshold) { - //wip closed + if (wip_vertices.size() > 1 && p_camera->unproject_position(gt.xform(wip_vertices[0])).distance_to(mouse_position) < grab_threshold) { _wip_close(); return EditorPlugin::AFTER_GUI_INPUT_STOP; } else { - wip.push_back(cpoint); - edited_point = wip.size(); + wip_vertices.push_back(cpoint); + edited_point = wip_vertices.size(); snap_ignore = false; - _polygon_draw(); + redraw(); return EditorPlugin::AFTER_GUI_INPUT_STOP; } } @@ -181,13 +543,11 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (mb->is_ctrl_pressed()) { - if (poly.size() < 3) { + if (obstacle_vertices.size() < 3) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Edit Vertices")); + undo_redo->create_action(TTR("Edit Obstacle (Add Vertex)")); undo_redo->add_undo_method(obstacle_node, "set_vertices", obstacle_node->get_vertices()); - poly.push_back(cpoint); - undo_redo->add_do_method(this, "_polygon_draw"); - undo_redo->add_undo_method(this, "_polygon_draw"); + obstacle_vertices.push_back(cpoint); undo_redo->commit_action(); return EditorPlugin::AFTER_GUI_INPUT_STOP; } @@ -196,18 +556,18 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam int closest_idx = -1; Vector2 closest_pos; real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { + for (int i = 0; i < obstacle_vertices.size(); i++) { Vector2 points[2] = { - p_camera->unproject_position(gt.xform(Vector3(poly[i].x, 0.0, poly[i].y))), - p_camera->unproject_position(gt.xform(Vector3(poly[(i + 1) % poly.size()].x, 0.0, poly[(i + 1) % poly.size()].y))) + p_camera->unproject_position(gt.xform(obstacle_vertices[i])), + p_camera->unproject_position(gt.xform(obstacle_vertices[(i + 1) % obstacle_vertices.size()])) }; - Vector2 cp = Geometry2D::get_closest_point_to_segment(gpoint, points); + Vector2 cp = Geometry2D::get_closest_point_to_segment(mouse_position, points); if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) { continue; //not valid to reuse point } - real_t d = cp.distance_to(gpoint); + real_t d = cp.distance_to(mouse_position); if (d < closest_dist && d < grab_threshold) { closest_dist = d; closest_pos = cp; @@ -216,26 +576,24 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam } if (closest_idx >= 0) { - pre_move_edit = poly; - poly.insert(closest_idx + 1, cpoint); + pre_move_edit = obstacle_vertices; + obstacle_vertices.insert(closest_idx + 1, cpoint); edited_point = closest_idx + 1; edited_point_pos = cpoint; - _set_polygon(poly); - _polygon_draw(); + obstacle_node->set_vertices(obstacle_vertices); + redraw(); snap_ignore = true; return EditorPlugin::AFTER_GUI_INPUT_STOP; } } else { - //look for points to move - int closest_idx = -1; Vector2 closest_pos; real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x, 0.0, poly[i].y))); + for (int i = 0; i < obstacle_vertices.size(); i++) { + Vector2 cp = p_camera->unproject_position(gt.xform(obstacle_vertices[i])); - real_t d = cp.distance_to(gpoint); + real_t d = cp.distance_to(mouse_position); if (d < closest_dist && d < grab_threshold) { closest_dist = d; closest_pos = cp; @@ -244,10 +602,10 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam } if (closest_idx >= 0) { - pre_move_edit = poly; + pre_move_edit = obstacle_vertices; edited_point = closest_idx; - edited_point_pos = poly[closest_idx]; - _polygon_draw(); + edited_point_pos = obstacle_vertices[closest_idx]; + redraw(); snap_ignore = false; return EditorPlugin::AFTER_GUI_INPUT_STOP; } @@ -256,16 +614,13 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam snap_ignore = false; if (edited_point != -1) { - //apply + ERR_FAIL_INDEX_V(edited_point, obstacle_vertices.size(), EditorPlugin::AFTER_GUI_INPUT_PASS); + obstacle_vertices.write[edited_point] = edited_point_pos; - ERR_FAIL_INDEX_V(edited_point, poly.size(), EditorPlugin::AFTER_GUI_INPUT_PASS); - poly.write[edited_point] = edited_point_pos; EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Edit Poly")); - //undo_redo->add_do_method(obj, "set_polygon", poly); - //undo_redo->add_undo_method(obj, "set_polygon", pre_move_edit); - undo_redo->add_do_method(this, "_polygon_draw"); - undo_redo->add_undo_method(this, "_polygon_draw"); + undo_redo->create_action(TTR("Edit Obstacle (Move Vertex)")); + undo_redo->add_undo_method(obstacle_node, "set_vertices", obstacle_node->get_vertices()); + undo_redo->add_do_method(obstacle_node, "set_vertices", obstacle_vertices); undo_redo->commit_action(); edited_point = -1; @@ -273,30 +628,31 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam } } } - if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed() && edited_point == -1) { + + } break; + + case MODE_DELETE: { + if (mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { int closest_idx = -1; - Vector2 closest_pos; real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x, 0.0, poly[i].y))); - - real_t d = cp.distance_to(gpoint); + for (int i = 0; i < obstacle_vertices.size(); i++) { + Vector2 point = p_camera->unproject_position(gt.xform(obstacle_vertices[i])); + real_t d = point.distance_to(mouse_position); if (d < closest_dist && d < grab_threshold) { closest_dist = d; - closest_pos = cp; closest_idx = i; } } if (closest_idx >= 0) { + edited_point = -1; EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Edit Poly (Remove Point)")); - //undo_redo->add_undo_method(obj, "set_polygon", poly); - poly.remove_at(closest_idx); - //undo_redo->add_do_method(obj, "set_polygon", poly); - undo_redo->add_do_method(this, "_polygon_draw"); - undo_redo->add_undo_method(this, "_polygon_draw"); + undo_redo->create_action(TTR("Edit Obstacle (Remove Vertex)")); + undo_redo->add_undo_method(obstacle_node, "set_vertices", obstacle_vertices); + obstacle_vertices.remove_at(closest_idx); + undo_redo->add_do_method(obstacle_node, "set_vertices", obstacle_vertices); undo_redo->commit_action(); + redraw(); return EditorPlugin::AFTER_GUI_INPUT_STOP; } } @@ -309,20 +665,25 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam if (mm.is_valid()) { if (edited_point != -1 && (wip_active || mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) { - Vector2 gpoint = mm->get_position(); + Vector2 mouse_position = mm->get_position(); - Vector3 ray_from = p_camera->project_ray_origin(gpoint); - Vector3 ray_dir = p_camera->project_ray_normal(gpoint); + Vector3 ray_from = p_camera->project_ray_origin(mouse_position); + Vector3 ray_dir = p_camera->project_ray_normal(mouse_position); - Vector3 spoint; + const Vector3 safe_scale = obstacle_node->get_global_basis().get_scale().abs().maxf(0.001); + const Transform3D gt = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y), obstacle_node->get_global_position()); + Transform3D gi = gt.affine_inverse(); + Plane projection_plane(Vector3(0.0, 1.0, 0.0), gt.origin); - if (!p.intersects_ray(ray_from, ray_dir, &spoint)) { + Vector3 intersection_point; + + if (!projection_plane.intersects_ray(ray_from, ray_dir, &intersection_point)) { return EditorPlugin::AFTER_GUI_INPUT_PASS; } - spoint = gi.xform(spoint); + intersection_point = gi.xform(intersection_point); - Vector2 cpoint(spoint.x, spoint.z); + Vector2 cpoint(intersection_point.x, intersection_point.z); if (snap_ignore && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { snap_ignore = false; @@ -331,272 +692,219 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam if (!snap_ignore && Node3DEditor::get_singleton()->is_snap_enabled()) { cpoint = cpoint.snappedf(Node3DEditor::get_singleton()->get_translate_snap()); } - edited_point_pos = cpoint; + edited_point_pos = Vector3(cpoint.x, 0.0, cpoint.y); - _polygon_draw(); + redraw(); } } - return EditorPlugin::AFTER_GUI_INPUT_PASS; -} + Ref<InputEventKey> k = p_event; -PackedVector2Array NavigationObstacle3DEditor::_get_polygon() { - ERR_FAIL_NULL_V_MSG(obstacle_node, PackedVector2Array(), "Edited object is not valid."); - return PackedVector2Array(obstacle_node->call("get_polygon")); -} + if (k.is_valid() && k->is_pressed()) { + if (wip_active && k->get_keycode() == Key::ENTER) { + _wip_close(); + } else if (wip_active && k->get_keycode() == Key::ESCAPE) { + _wip_cancel(); + } + } -void NavigationObstacle3DEditor::_set_polygon(const PackedVector2Array &p_poly) { - ERR_FAIL_NULL_MSG(obstacle_node, "Edited object is not valid."); - obstacle_node->call("set_polygon", p_poly); + return EditorPlugin::AFTER_GUI_INPUT_PASS; } -void NavigationObstacle3DEditor::_polygon_draw() { +void NavigationObstacle3DEditorPlugin::redraw() { if (!obstacle_node) { return; } + RenderingServer *rs = RenderingServer::get_singleton(); + + rs->mesh_clear(point_lines_mesh_rid); + rs->mesh_clear(point_handle_mesh_rid); + + if (!obstacle_node->is_visible_in_tree()) { + return; + } - PackedVector2Array poly; - PackedVector3Array polygon_3d_vertices; + Vector<Vector3> edited_vertices; if (wip_active) { - poly = wip; + edited_vertices = wip_vertices; } else { - poly = _get_polygon(); + edited_vertices = obstacle_node->get_vertices(); } - polygon_3d_vertices.resize(poly.size()); - Vector3 *polygon_3d_vertices_ptr = polygon_3d_vertices.ptrw(); - for (int i = 0; i < poly.size(); i++) { - const Vector2 &vert = poly[i]; - polygon_3d_vertices_ptr[i] = Vector3(vert.x, 0.0, vert.y); + if (edited_vertices.is_empty()) { + return; } - point_handle_mesh->clear_surfaces(); - point_lines_mesh->clear_surfaces(); - point_lines_meshinstance->set_material_override(line_material); - point_lines_mesh->surface_begin(Mesh::PRIMITIVE_LINES); + Array point_lines_mesh_array; + point_lines_mesh_array.resize(Mesh::ARRAY_MAX); - Rect2 rect; + Vector<Vector3> point_lines_mesh_vertices; + point_lines_mesh_vertices.resize(edited_vertices.size() * 2); + Vector3 *point_lines_mesh_vertices_ptr = point_lines_mesh_vertices.ptrw(); - for (int i = 0; i < poly.size(); i++) { - Vector2 p, p2; - if (i == edited_point) { - p = edited_point_pos; - } else { - p = poly[i]; - } + int vertex_index = 0; - if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point)) { - p2 = edited_point_pos; + for (int i = 0; i < edited_vertices.size(); i++) { + Vector3 point, next_point; + if (i == edited_point) { + point = edited_point_pos; } else { - p2 = poly[(i + 1) % poly.size()]; + point = edited_vertices[i]; } - if (i == 0) { - rect.position = p; + if ((wip_active && i == edited_vertices.size() - 1) || (((i + 1) % edited_vertices.size()) == edited_point)) { + next_point = edited_point_pos; } else { - rect.expand_to(p); + next_point = edited_vertices[(i + 1) % edited_vertices.size()]; } - Vector3 point = Vector3(p.x, 0.0, p.y); - Vector3 next_point = Vector3(p2.x, 0.0, p2.y); - - point_lines_mesh->surface_set_color(Color(1, 0.3, 0.1, 0.8)); - point_lines_mesh->surface_add_vertex(point); - point_lines_mesh->surface_set_color(Color(1, 0.3, 0.1, 0.8)); - point_lines_mesh->surface_add_vertex(next_point); - - //Color col=Color(1,0.3,0.1,0.8); - //vpc->draw_line(point,next_point,col,2); - //vpc->draw_texture(handle,point-handle->get_size()*0.5); - } - - rect = rect.grow(1); - - AABB r; - r.position.x = rect.position.x; - r.position.y = 0.0; - r.position.z = rect.position.y; - r.size.x = rect.size.x; - r.size.y = 0; - r.size.z = rect.size.y; - - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(0.3, 0, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(0.0, 0.3, 0)); - - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0)); - - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0)); - - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + r.size); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + r.size - Vector3(0.3, 0, 0)); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + r.size); - point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); - point_lines_mesh->surface_add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0)); - - point_lines_mesh->surface_end(); - - if (poly.size() == 0) { - return; + point_lines_mesh_vertices_ptr[vertex_index++] = point; + point_lines_mesh_vertices_ptr[vertex_index++] = next_point; } + point_lines_mesh_array[Mesh::ARRAY_VERTEX] = point_lines_mesh_vertices; + + rs->mesh_add_surface_from_arrays(point_lines_mesh_rid, RS::PRIMITIVE_LINES, point_lines_mesh_array); + rs->instance_set_surface_override_material(point_lines_instance_rid, 0, line_material->get_rid()); + const Vector3 safe_scale = obstacle_node->get_global_basis().get_scale().abs().maxf(0.001); + const Transform3D gt = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y), obstacle_node->get_global_position()); + rs->instance_set_transform(point_lines_instance_rid, gt); + Array point_handle_mesh_array; point_handle_mesh_array.resize(Mesh::ARRAY_MAX); Vector<Vector3> point_handle_mesh_vertices; - point_handle_mesh_vertices.resize(poly.size()); + point_handle_mesh_vertices.resize(edited_vertices.size()); Vector3 *point_handle_mesh_vertices_ptr = point_handle_mesh_vertices.ptrw(); - for (int i = 0; i < poly.size(); i++) { - Vector2 point_2d; - Vector2 p2; + for (int i = 0; i < edited_vertices.size(); i++) { + Vector3 point_handle_3d; if (i == edited_point) { - point_2d = edited_point_pos; + point_handle_3d = edited_point_pos; } else { - point_2d = poly[i]; + point_handle_3d = edited_vertices[i]; } - Vector3 point_handle_3d = Vector3(point_2d.x, 0.0, point_2d.y); point_handle_mesh_vertices_ptr[i] = point_handle_3d; } point_handle_mesh_array[Mesh::ARRAY_VERTEX] = point_handle_mesh_vertices; - point_handle_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS, point_handle_mesh_array); - point_handle_mesh->surface_set_material(0, handle_material); -} - -void NavigationObstacle3DEditor::edit(Node *p_node) { - obstacle_node = Object::cast_to<NavigationObstacle3D>(p_node); - if (obstacle_node) { - //Enable the pencil tool if the polygon is empty - if (_get_polygon().is_empty()) { - _menu_option(MODE_CREATE); - } - wip.clear(); - wip_active = false; - edited_point = -1; - if (point_lines_meshinstance->get_parent()) { - point_lines_meshinstance->reparent(p_node, false); - } else { - p_node->add_child(point_lines_meshinstance); - } - _polygon_draw(); - - } else { - obstacle_node = nullptr; - - if (point_lines_meshinstance->get_parent()) { - point_lines_meshinstance->get_parent()->remove_child(point_lines_meshinstance); - } - } + rs->mesh_add_surface_from_arrays(point_handle_mesh_rid, RS::PRIMITIVE_POINTS, point_handle_mesh_array); + rs->instance_set_surface_override_material(point_handles_instance_rid, 0, handle_material->get_rid()); + rs->instance_set_transform(point_handles_instance_rid, gt); } -void NavigationObstacle3DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_polygon_draw"), &NavigationObstacle3DEditor::_polygon_draw); -} - -NavigationObstacle3DEditor::NavigationObstacle3DEditor() { - obstacle_node = nullptr; - - button_create = memnew(Button); - button_create->set_theme_type_variation("FlatButton"); - add_child(button_create); - button_create->connect(SceneStringName(pressed), callable_mp(this, &NavigationObstacle3DEditor::_menu_option).bind(MODE_CREATE)); - button_create->set_toggle_mode(true); - - button_edit = memnew(Button); - button_edit->set_theme_type_variation("FlatButton"); - add_child(button_edit); - button_edit->connect(SceneStringName(pressed), callable_mp(this, &NavigationObstacle3DEditor::_menu_option).bind(MODE_EDIT)); - button_edit->set_toggle_mode(true); +NavigationObstacle3DEditorPlugin *NavigationObstacle3DEditorPlugin::singleton = nullptr; - mode = MODE_EDIT; - wip_active = false; - point_lines_meshinstance = memnew(MeshInstance3D); - point_lines_mesh.instantiate(); - point_lines_meshinstance->set_mesh(point_lines_mesh); - point_lines_meshinstance->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001))); +NavigationObstacle3DEditorPlugin::NavigationObstacle3DEditorPlugin() { + singleton = this; line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); line_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); line_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); - line_material->set_albedo(Color(1, 1, 1)); + line_material->set_albedo(Color(1, 0.3, 0.1, 0.8)); + line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); handle_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true); handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true); handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); handle_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); Ref<Texture2D> handle = EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Editor3DHandle"), EditorStringName(EditorIcons)); handle_material->set_point_size(handle->get_width()); handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle); + handle_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); - point_handles_meshinstance = memnew(MeshInstance3D); - point_lines_meshinstance->add_child(point_handles_meshinstance); - point_handle_mesh.instantiate(); - point_handles_meshinstance->set_mesh(point_handle_mesh); - point_handles_meshinstance->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001))); + RenderingServer *rs = RenderingServer::get_singleton(); - snap_ignore = false; -} + point_lines_mesh_rid = rs->mesh_create(); + point_handle_mesh_rid = rs->mesh_create(); -NavigationObstacle3DEditor::~NavigationObstacle3DEditor() { - memdelete(point_lines_meshinstance); -} + point_lines_instance_rid = rs->instance_create(); + point_handles_instance_rid = rs->instance_create(); -void NavigationObstacle3DEditorPlugin::edit(Object *p_object) { - obstacle_editor->edit(Object::cast_to<Node>(p_object)); -} + rs->instance_set_base(point_lines_instance_rid, point_lines_mesh_rid); + rs->instance_set_base(point_handles_instance_rid, point_handle_mesh_rid); -bool NavigationObstacle3DEditorPlugin::handles(Object *p_object) const { - return Object::cast_to<NavigationObstacle3D>(p_object); -} + obstacle_editor = memnew(HBoxContainer); + obstacle_editor->hide(); -void NavigationObstacle3DEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - obstacle_editor->show(); - } else { - obstacle_editor->hide(); - obstacle_editor->edit(nullptr); - } -} + Ref<ButtonGroup> bg; + bg.instantiate(); + + button_create = memnew(Button); + button_create->set_theme_type_variation("FlatButton"); + obstacle_editor->add_child(button_create); + button_create->set_tooltip_text(TTR("Add Vertex")); + button_create->connect(SceneStringName(pressed), callable_mp(this, &NavigationObstacle3DEditorPlugin::set_mode).bind(NavigationObstacle3DEditorPlugin::MODE_CREATE)); + button_create->set_toggle_mode(true); + button_create->set_button_group(bg); + + button_edit = memnew(Button); + button_edit->set_theme_type_variation("FlatButton"); + obstacle_editor->add_child(button_edit); + button_edit->connect(SceneStringName(pressed), callable_mp(this, &NavigationObstacle3DEditorPlugin::set_mode).bind(NavigationObstacle3DEditorPlugin::MODE_EDIT)); + button_edit->set_toggle_mode(true); + button_edit->set_button_group(bg); + + button_delete = memnew(Button); + button_delete->set_theme_type_variation("FlatButton"); + obstacle_editor->add_child(button_delete); + button_delete->connect(SceneStringName(pressed), callable_mp(this, &NavigationObstacle3DEditorPlugin::set_mode).bind(NavigationObstacle3DEditorPlugin::MODE_DELETE)); + button_delete->set_toggle_mode(true); + button_delete->set_button_group(bg); + + button_flip = memnew(Button); + button_flip->set_theme_type_variation("FlatButton"); + obstacle_editor->add_child(button_flip); + button_flip->connect(SceneStringName(pressed), callable_mp(this, &NavigationObstacle3DEditorPlugin::set_mode).bind(NavigationObstacle3DEditorPlugin::ACTION_FLIP)); + button_flip->set_toggle_mode(true); + + button_clear = memnew(Button); + button_clear->set_theme_type_variation("FlatButton"); + obstacle_editor->add_child(button_clear); + button_clear->connect(SceneStringName(pressed), callable_mp(this, &NavigationObstacle3DEditorPlugin::set_mode).bind(NavigationObstacle3DEditorPlugin::ACTION_CLEAR)); + button_clear->set_toggle_mode(true); + + button_clear_dialog = memnew(ConfirmationDialog); + button_clear_dialog->set_title(TTR("Please Confirm...")); + button_clear_dialog->set_text(TTR("Remove all vertices?")); + button_clear_dialog->connect(SceneStringName(confirmed), callable_mp(NavigationObstacle3DEditorPlugin::singleton, &NavigationObstacle3DEditorPlugin::action_clear_vertices)); + obstacle_editor->add_child(button_clear_dialog); -NavigationObstacle3DEditorPlugin::NavigationObstacle3DEditorPlugin() { - obstacle_editor = memnew(NavigationObstacle3DEditor); Node3DEditor::get_singleton()->add_control_to_menu_panel(obstacle_editor); - obstacle_editor->hide(); + Ref<NavigationObstacle3DGizmoPlugin> gizmo_plugin = memnew(NavigationObstacle3DGizmoPlugin()); + obstacle_3d_gizmo_plugin = gizmo_plugin; + Node3DEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin); } NavigationObstacle3DEditorPlugin::~NavigationObstacle3DEditorPlugin() { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + + if (point_lines_instance_rid.is_valid()) { + rs->free(point_lines_instance_rid); + point_lines_instance_rid = RID(); + } + if (point_lines_mesh_rid.is_valid()) { + rs->free(point_lines_mesh_rid); + point_lines_mesh_rid = RID(); + } + + if (point_handles_instance_rid.is_valid()) { + rs->free(point_handles_instance_rid); + point_handles_instance_rid = RID(); + } + if (point_handle_mesh_rid.is_valid()) { + rs->free(point_handle_mesh_rid); + point_handle_mesh_rid = RID(); + } } diff --git a/editor/plugins/navigation_obstacle_3d_editor_plugin.h b/editor/plugins/navigation_obstacle_3d_editor_plugin.h index c62a5a281b..b6f3a11cf6 100644 --- a/editor/plugins/navigation_obstacle_3d_editor_plugin.h +++ b/editor/plugins/navigation_obstacle_3d_editor_plugin.h @@ -32,79 +32,99 @@ #define NAVIGATION_OBSTACLE_3D_EDITOR_PLUGIN_H #include "editor/plugins/editor_plugin.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/3d/physics/collision_polygon_3d.h" +#include "editor/plugins/node_3d_editor_gizmos.h" #include "scene/gui/box_container.h" -#include "scene/resources/immediate_mesh.h" -#include "scene/3d/navigation_obstacle_3d.h" +class Button; +class ConfirmationDialog; +class NavigationObstacle3D; -class CanvasItemEditor; -class MenuButton; +class NavigationObstacle3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(NavigationObstacle3DGizmoPlugin, EditorNode3DGizmoPlugin); -class NavigationObstacle3DEditor : public HBoxContainer { - GDCLASS(NavigationObstacle3DEditor, HBoxContainer); +public: + virtual bool has_gizmo(Node3D *p_spatial) override; + virtual String get_gizmo_name() const override; - enum Mode { - MODE_CREATE, - MODE_EDIT, + virtual void redraw(EditorNode3DGizmo *p_gizmo) override; - }; + bool can_be_hidden() const override; + int get_priority() const override; - Mode mode; + virtual int subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const override; + virtual Vector<int> subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const override; + virtual Transform3D get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const override; + virtual void set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) override; + virtual void commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel = false) override; - Button *button_create = nullptr; - Button *button_edit = nullptr; + NavigationObstacle3DGizmoPlugin(); +}; + +class NavigationObstacle3DEditorPlugin : public EditorPlugin { + GDCLASS(NavigationObstacle3DEditorPlugin, EditorPlugin); + + Ref<NavigationObstacle3DGizmoPlugin> obstacle_3d_gizmo_plugin; + + NavigationObstacle3D *obstacle_node = nullptr; Ref<StandardMaterial3D> line_material; Ref<StandardMaterial3D> handle_material; - Panel *panel = nullptr; - NavigationObstacle3D *obstacle_node = nullptr; - Ref<ImmediateMesh> point_lines_mesh; - MeshInstance3D *point_lines_meshinstance = nullptr; - MeshInstance3D *point_handles_meshinstance = nullptr; - Ref<ArrayMesh> point_handle_mesh; + RID point_lines_mesh_rid; + RID point_lines_instance_rid; + RID point_handle_mesh_rid; + RID point_handles_instance_rid; - MenuButton *options = nullptr; +public: + enum Mode { + MODE_CREATE = 0, + MODE_EDIT, + MODE_DELETE, + ACTION_FLIP, + ACTION_CLEAR, + }; - int edited_point = 0; - Vector2 edited_point_pos; - PackedVector2Array pre_move_edit; - PackedVector2Array wip; - bool wip_active; - bool snap_ignore; +private: + int mode = MODE_EDIT; - float prev_depth = 0.0f; + int edited_point = 0; + Vector3 edited_point_pos; + Vector<Vector3> pre_move_edit; + Vector<Vector3> wip_vertices; + bool wip_active = false; + bool snap_ignore = false; void _wip_close(); - void _polygon_draw(); - void _menu_option(int p_option); + void _wip_cancel(); + void _update_theme(); + + Button *button_create = nullptr; + Button *button_edit = nullptr; + Button *button_delete = nullptr; + Button *button_flip = nullptr; + Button *button_clear = nullptr; - PackedVector2Array _get_polygon(); - void _set_polygon(const PackedVector2Array &p_poly); + ConfirmationDialog *button_clear_dialog = nullptr; protected: void _notification(int p_what); void _node_removed(Node *p_node); - static void _bind_methods(); public: - virtual EditorPlugin::AfterGUIInput forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event); - void edit(Node *p_node); - NavigationObstacle3DEditor(); - ~NavigationObstacle3DEditor(); -}; + HBoxContainer *obstacle_editor = nullptr; + static NavigationObstacle3DEditorPlugin *singleton; -class NavigationObstacle3DEditorPlugin : public EditorPlugin { - GDCLASS(NavigationObstacle3DEditorPlugin, EditorPlugin); + void redraw(); - NavigationObstacle3DEditor *obstacle_editor = nullptr; + void set_mode(int p_mode); + int get_mode() { return mode; } -public: - virtual EditorPlugin::AfterGUIInput forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) override { return obstacle_editor->forward_3d_gui_input(p_camera, p_event); } + void action_flip_vertices(); + void action_clear_vertices(); + + virtual EditorPlugin::AfterGUIInput forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) override; - virtual String get_name() const override { return "NavigationObstacle3DEditor"; } + virtual String get_name() const override { return "NavigationObstacle3D"; } bool has_main_screen() const override { return false; } virtual void edit(Object *p_object) override; virtual bool handles(Object *p_object) const override; diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp index ec59bbb543..c11a7cf20e 100644 --- a/editor/plugins/navigation_polygon_editor_plugin.cpp +++ b/editor/plugins/navigation_polygon_editor_plugin.cpp @@ -38,8 +38,8 @@ Ref<NavigationPolygon> NavigationPolygonEditor::_ensure_navpoly() const { Ref<NavigationPolygon> navpoly = node->get_navigation_polygon(); - if (!navpoly.is_valid()) { - navpoly = Ref<NavigationPolygon>(memnew(NavigationPolygon)); + if (navpoly.is_null()) { + navpoly.instantiate(); node->set_navigation_polygon(navpoly); } return navpoly; @@ -177,8 +177,8 @@ NavigationPolygonEditor::NavigationPolygonEditor() { void NavigationPolygonEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - button_bake->set_icon(get_editor_theme_icon(SNAME("Bake"))); - button_reset->set_icon(get_editor_theme_icon(SNAME("Reload"))); + button_bake->set_button_icon(get_editor_theme_icon(SNAME("Bake"))); + button_reset->set_button_icon(get_editor_theme_icon(SNAME("Reload"))); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { if (rebake_timer) { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 0df0274495..daede895b5 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1692,7 +1692,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { - emit_signal(SNAME("clicked"), this); + emit_signal(SNAME("clicked")); ViewportNavMouseButton orbit_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/orbit_mouse_button").operator int(); ViewportNavMouseButton pan_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/pan_mouse_button").operator int(); @@ -3139,8 +3139,8 @@ void Node3DEditorViewport::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - view_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); - preview_camera->set_icon(get_editor_theme_icon(SNAME("Camera3D"))); + view_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + preview_camera->set_button_icon(get_editor_theme_icon(SNAME("Camera3D"))); Control *gui_base = EditorNode::get_singleton()->get_gui_base(); const Ref<StyleBox> &information_3d_stylebox = gui_base->get_theme_stylebox(SNAME("Information3dViewport"), EditorStringName(EditorStyles)); @@ -3265,7 +3265,7 @@ void Node3DEditorViewport::_draw() { if (message_time > 0) { Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label")); int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label")); - Point2 msgpos = Point2(5, get_size().y - 20); + Point2 msgpos = Point2(10 * EDSCALE, get_size().y - 14 * EDSCALE); font->draw_string(ci, msgpos + Point2(1, 1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); font->draw_string(ci, msgpos + Point2(-1, -1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); font->draw_string(ci, msgpos, message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 1)); @@ -4210,7 +4210,7 @@ Dictionary Node3DEditorViewport::get_state() const { void Node3DEditorViewport::_bind_methods() { ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport"))); - ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport"))); + ADD_SIGNAL(MethodInfo("clicked")); } void Node3DEditorViewport::reset() { @@ -6572,18 +6572,6 @@ void Node3DEditor::_menu_item_toggled(bool pressed, int p_option) { tool_option_button[TOOL_OPT_USE_SNAP]->set_pressed(pressed); snap_enabled = pressed; } break; - - case MENU_TOOL_OVERRIDE_CAMERA: { - EditorDebuggerNode *const debugger = EditorDebuggerNode::get_singleton(); - - using Override = EditorDebuggerNode::CameraOverride; - if (pressed) { - debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id)); - } else { - debugger->set_camera_override(Override::OVERRIDE_NONE); - } - - } break; } } @@ -6610,36 +6598,6 @@ void Node3DEditor::_menu_gizmo_toggled(int p_option) { update_all_gizmos(); } -void Node3DEditor::_update_camera_override_button(bool p_game_running) { - Button *const button = tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]; - - if (p_game_running) { - button->set_disabled(false); - button->set_tooltip_text(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera.")); - } else { - button->set_disabled(true); - button->set_pressed(false); - button->set_tooltip_text(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature.")); - } -} - -void Node3DEditor::_update_camera_override_viewport(Object *p_viewport) { - Node3DEditorViewport *current_viewport = Object::cast_to<Node3DEditorViewport>(p_viewport); - - if (!current_viewport) { - return; - } - - EditorDebuggerNode *const debugger = EditorDebuggerNode::get_singleton(); - - camera_override_viewport_id = current_viewport->index; - if (debugger->get_camera_override() >= EditorDebuggerNode::OVERRIDE_3D_1) { - using Override = EditorDebuggerNode::CameraOverride; - - debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id)); - } -} - void Node3DEditor::_menu_item_pressed(int p_option) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); switch (p_option) { @@ -6670,6 +6628,9 @@ void Node3DEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_1_VIEWPORT: { viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_1_VIEWPORT); + if (last_used_viewport > 0) { + last_used_viewport = 0; + } view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), true); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -6681,6 +6642,9 @@ void Node3DEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_2_VIEWPORTS: { viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_2_VIEWPORTS); + if (last_used_viewport > 1) { + last_used_viewport = 0; + } view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), true); @@ -6692,6 +6656,9 @@ void Node3DEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_2_VIEWPORTS_ALT: { viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_2_VIEWPORTS_ALT); + if (last_used_viewport > 1) { + last_used_viewport = 0; + } view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -6703,6 +6670,9 @@ void Node3DEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_3_VIEWPORTS: { viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_3_VIEWPORTS); + if (last_used_viewport > 2) { + last_used_viewport = 0; + } view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -6714,6 +6684,9 @@ void Node3DEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_3_VIEWPORTS_ALT: { viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_3_VIEWPORTS_ALT); + if (last_used_viewport > 2) { + last_used_viewport = 0; + } view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -7077,12 +7050,12 @@ void fragment() { col.a = EDITOR_GET("editors/3d/manipulator_gizmo_opacity"); - move_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); - move_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); - rotate_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); - scale_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); - scale_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); - axis_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); + move_gizmo[i].instantiate(); + move_plane_gizmo[i].instantiate(); + rotate_gizmo[i].instantiate(); + scale_gizmo[i].instantiate(); + scale_plane_gizmo[i].instantiate(); + axis_gizmo[i].instantiate(); Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D); mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); @@ -7313,7 +7286,7 @@ void fragment() { border_mat->set_shader(border_shader); border_mat->set_shader_parameter("albedo", Color(0.75, 0.75, 0.75, col.a / 3.0)); - rotate_gizmo[3] = Ref<ArrayMesh>(memnew(ArrayMesh)); + rotate_gizmo[3].instantiate(); rotate_gizmo[3]->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays); rotate_gizmo[3]->surface_set_material(0, border_mat); } @@ -8021,19 +7994,18 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { } void Node3DEditor::_update_theme() { - tool_button[TOOL_MODE_SELECT]->set_icon(get_editor_theme_icon(SNAME("ToolSelect"))); - tool_button[TOOL_MODE_MOVE]->set_icon(get_editor_theme_icon(SNAME("ToolMove"))); - tool_button[TOOL_MODE_ROTATE]->set_icon(get_editor_theme_icon(SNAME("ToolRotate"))); - tool_button[TOOL_MODE_SCALE]->set_icon(get_editor_theme_icon(SNAME("ToolScale"))); - tool_button[TOOL_MODE_LIST_SELECT]->set_icon(get_editor_theme_icon(SNAME("ListSelect"))); - tool_button[TOOL_LOCK_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Lock"))); - tool_button[TOOL_UNLOCK_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Unlock"))); - tool_button[TOOL_GROUP_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Group"))); - tool_button[TOOL_UNGROUP_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Ungroup"))); - - tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_icon(get_editor_theme_icon(SNAME("Object"))); - tool_option_button[TOOL_OPT_USE_SNAP]->set_icon(get_editor_theme_icon(SNAME("Snap"))); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_editor_theme_icon(SNAME("Camera3D"))); + tool_button[TOOL_MODE_SELECT]->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + tool_button[TOOL_MODE_MOVE]->set_button_icon(get_editor_theme_icon(SNAME("ToolMove"))); + tool_button[TOOL_MODE_ROTATE]->set_button_icon(get_editor_theme_icon(SNAME("ToolRotate"))); + tool_button[TOOL_MODE_SCALE]->set_button_icon(get_editor_theme_icon(SNAME("ToolScale"))); + tool_button[TOOL_MODE_LIST_SELECT]->set_button_icon(get_editor_theme_icon(SNAME("ListSelect"))); + tool_button[TOOL_LOCK_SELECTED]->set_button_icon(get_editor_theme_icon(SNAME("Lock"))); + tool_button[TOOL_UNLOCK_SELECTED]->set_button_icon(get_editor_theme_icon(SNAME("Unlock"))); + tool_button[TOOL_GROUP_SELECTED]->set_button_icon(get_editor_theme_icon(SNAME("Group"))); + tool_button[TOOL_UNGROUP_SELECTED]->set_button_icon(get_editor_theme_icon(SNAME("Ungroup"))); + + tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_button_icon(get_editor_theme_icon(SNAME("Object"))); + tool_option_button[TOOL_OPT_USE_SNAP]->set_button_icon(get_editor_theme_icon(SNAME("Snap"))); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_editor_theme_icon(SNAME("Panels1"))); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_editor_theme_icon(SNAME("Panels2"))); @@ -8042,9 +8014,9 @@ void Node3DEditor::_update_theme() { view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_editor_theme_icon(SNAME("Panels3Alt"))); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_editor_theme_icon(SNAME("Panels4"))); - sun_button->set_icon(get_editor_theme_icon(SNAME("PreviewSun"))); - environ_button->set_icon(get_editor_theme_icon(SNAME("PreviewEnvironment"))); - sun_environ_settings->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + sun_button->set_button_icon(get_editor_theme_icon(SNAME("PreviewSun"))); + environ_button->set_button_icon(get_editor_theme_icon(SNAME("PreviewEnvironment"))); + sun_environ_settings->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); sun_title->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("title_font"), SNAME("Window"))); environ_title->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("title_font"), SNAME("Window"))); @@ -8068,9 +8040,6 @@ void Node3DEditor::_notification(int p_what) { SceneTreeDock::get_singleton()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons)); editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_selection_changed)); - EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button).bind(false)); - EditorRunBar::get_singleton()->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button).bind(true)); - _update_preview_environment(); sun_state->set_custom_minimum_size(sun_vb->get_combined_minimum_size()); @@ -8106,15 +8075,6 @@ void Node3DEditor::_notification(int p_what) { } } break; - case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible() && tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->is_pressed()) { - EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton(); - - debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_pressed(false); - } - } break; - case NOTIFICATION_PHYSICS_PROCESS: { if (do_snap_selected_nodes_to_floor) { _snap_selected_nodes_to_floor(); @@ -8216,6 +8176,10 @@ VSplitContainer *Node3DEditor::get_shader_split() { return shader_split; } +Node3DEditorViewport *Node3DEditor::get_last_used_viewport() { + return viewports[last_used_viewport]; +} + void Node3DEditor::add_control_to_left_panel(Control *p_control) { left_panel_split->add_child(p_control); left_panel_split->move_child(p_control, 0); @@ -8393,6 +8357,10 @@ void Node3DEditor::_toggle_maximize_view(Object *p_viewport) { } } +void Node3DEditor::_viewport_clicked(int p_viewport_idx) { + last_used_viewport = p_viewport_idx; +} + void Node3DEditor::_node_added(Node *p_node) { if (EditorNode::get_singleton()->get_scene_root()->is_ancestor_of(p_node)) { if (Object::cast_to<WorldEnvironment>(p_node)) { @@ -8512,7 +8480,7 @@ void Node3DEditor::clear() { } for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { - viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(Node3DEditorViewport::VIEW_AUDIO_LISTENER), i == 0); + viewports[i]->view_menu->get_popup()->set_item_checked(viewports[i]->view_menu->get_popup()->get_item_index(Node3DEditorViewport::VIEW_AUDIO_LISTENER), i == 0); viewports[i]->viewport->set_as_audio_listener_3d(i == 0); } @@ -8671,7 +8639,7 @@ Node3DEditor::Node3DEditor() { gizmo.visible = true; gizmo.scale = 1.0; - viewport_environment = Ref<Environment>(memnew(Environment)); + viewport_environment.instantiate(); VBoxContainer *vbc = this; custom_camera = nullptr; @@ -8684,8 +8652,6 @@ Node3DEditor::Node3DEditor() { snap_key_enabled = false; tool_mode = TOOL_MODE_SELECT; - camera_override_viewport_id = 0; - // Add some margin to the sides for better aesthetics. // This prevents the first button's hover/pressed effect from "touching" the panel's border, // which looks ugly. @@ -8803,16 +8769,6 @@ Node3DEditor::Node3DEditor() { tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut_context(this); main_menu_hbox->add_child(memnew(VSeparator)); - - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(Button); - main_menu_hbox->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_theme_type_variation("FlatButton"); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_disabled(true); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect(SceneStringName(toggled), callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_OVERRIDE_CAMERA)); - _update_camera_override_button(false); - - main_menu_hbox->add_child(memnew(VSeparator)); sun_button = memnew(Button); sun_button->set_tooltip_text(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled.")); sun_button->set_toggle_mode(true); @@ -8955,7 +8911,7 @@ Node3DEditor::Node3DEditor() { for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { viewports[i] = memnew(Node3DEditorViewport(this, i)); viewports[i]->connect("toggle_maximize_view", callable_mp(this, &Node3DEditor::_toggle_maximize_view)); - viewports[i]->connect("clicked", callable_mp(this, &Node3DEditor::_update_camera_override_viewport)); + viewports[i]->connect("clicked", callable_mp(this, &Node3DEditor::_viewport_clicked).bind(i)); viewports[i]->assign_pending_data_pointers(preview_node, &preview_bounds, accept); viewport_base->add_child(viewports[i]); } diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 1b03362606..d35fcb7653 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -622,7 +622,6 @@ public: enum ToolOptions { TOOL_OPT_LOCAL_COORDS, TOOL_OPT_USE_SNAP, - TOOL_OPT_OVERRIDE_CAMERA, TOOL_OPT_MAX }; @@ -632,6 +631,8 @@ private: Node3DEditorViewportContainer *viewport_base = nullptr; Node3DEditorViewport *viewports[VIEWPORTS_COUNT]; + int last_used_viewport = 0; + VSplitContainer *shader_split = nullptr; HSplitContainer *left_panel_split = nullptr; HSplitContainer *right_panel_split = nullptr; @@ -704,7 +705,6 @@ private: MENU_TOOL_LIST_SELECT, MENU_TOOL_LOCAL_COORDS, MENU_TOOL_USE_SNAP, - MENU_TOOL_OVERRIDE_CAMERA, MENU_TRANSFORM_CONFIGURE_SNAP, MENU_TRANSFORM_DIALOG, MENU_VIEW_USE_1_VIEWPORT, @@ -759,8 +759,6 @@ private: void _menu_item_pressed(int p_option); void _menu_item_toggled(bool pressed, int p_option); void _menu_gizmo_toggled(int p_option); - void _update_camera_override_button(bool p_game_running); - void _update_camera_override_viewport(Object *p_viewport); // Used for secondary menu items which are displayed depending on the currently selected node // (such as MeshInstance's "Mesh" menu). PanelContainer *context_toolbar_panel = nullptr; @@ -771,8 +769,6 @@ private: void _generate_selection_boxes(); - int camera_override_viewport_id; - void _init_indicators(); void _update_gizmos_menu(); void _update_gizmos_menu_theme(); @@ -781,6 +777,7 @@ private: void _finish_grid(); void _toggle_maximize_view(Object *p_viewport); + void _viewport_clicked(int p_viewport_idx); Node *custom_camera = nullptr; @@ -967,6 +964,7 @@ public: ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), nullptr); return viewports[p_idx]; } + Node3DEditorViewport *get_last_used_viewport(); void add_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin); void remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin); diff --git a/editor/plugins/occluder_instance_3d_editor_plugin.cpp b/editor/plugins/occluder_instance_3d_editor_plugin.cpp index c14d9e02aa..b9c884178f 100644 --- a/editor/plugins/occluder_instance_3d_editor_plugin.cpp +++ b/editor/plugins/occluder_instance_3d_editor_plugin.cpp @@ -105,7 +105,7 @@ void OccluderInstance3DEditorPlugin::_bind_methods() { OccluderInstance3DEditorPlugin::OccluderInstance3DEditorPlugin() { bake = memnew(Button); bake->set_theme_type_variation("FlatButton"); - bake->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); + bake->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); bake->set_text(TTR("Bake Occluders")); bake->hide(); bake->connect(SceneStringName(pressed), Callable(this, "_bake")); diff --git a/editor/plugins/packed_scene_editor_plugin.cpp b/editor/plugins/packed_scene_editor_plugin.cpp index c2d9851c17..4684c5a456 100644 --- a/editor/plugins/packed_scene_editor_plugin.cpp +++ b/editor/plugins/packed_scene_editor_plugin.cpp @@ -43,7 +43,7 @@ void PackedSceneEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - open_scene_button->set_icon(get_editor_theme_icon(SNAME("PackedScene"))); + open_scene_button->set_button_icon(get_editor_theme_icon(SNAME("PackedScene"))); } break; } } diff --git a/editor/plugins/parallax_background_editor_plugin.cpp b/editor/plugins/parallax_background_editor_plugin.cpp index 6c55fd2753..e802f42596 100644 --- a/editor/plugins/parallax_background_editor_plugin.cpp +++ b/editor/plugins/parallax_background_editor_plugin.cpp @@ -119,7 +119,7 @@ void ParallaxBackgroundEditorPlugin::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &ParallaxBackgroundEditorPlugin::_menu_callback)); - menu->set_icon(menu->get_editor_theme_icon(SNAME("ParallaxBackground"))); + menu->set_button_icon(menu->get_editor_theme_icon(SNAME("ParallaxBackground"))); } break; } } diff --git a/editor/plugins/particle_process_material_editor_plugin.cpp b/editor/plugins/particle_process_material_editor_plugin.cpp index 67c9403aaf..7b46653ac7 100644 --- a/editor/plugins/particle_process_material_editor_plugin.cpp +++ b/editor/plugins/particle_process_material_editor_plugin.cpp @@ -346,7 +346,7 @@ float ParticleProcessMaterialMinMaxPropertyEditor::_get_max_spread() const { void ParticleProcessMaterialMinMaxPropertyEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - toggle_mode_button->set_icon(get_editor_theme_icon(SNAME("Anchor"))); + toggle_mode_button->set_button_icon(get_editor_theme_icon(SNAME("Anchor"))); range_slider_left_icon = get_editor_theme_icon(SNAME("RangeSliderLeft")); range_slider_right_icon = get_editor_theme_icon(SNAME("RangeSliderRight")); diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 34f5dcf963..36a2d7acad 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -60,7 +60,7 @@ void ParticlesEditorPlugin::_notification(int p_what) { DEV_ASSERT(false); } - menu->set_icon(menu->get_editor_theme_icon(handled_type)); + menu->set_button_icon(menu->get_editor_theme_icon(handled_type)); menu->set_text(handled_type); PopupMenu *popup = menu->get_popup(); diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index c96f23869e..96e022e230 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -43,14 +43,14 @@ void Path2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - curve_edit->set_icon(get_editor_theme_icon(SNAME("CurveEdit"))); - curve_edit_curve->set_icon(get_editor_theme_icon(SNAME("CurveCurve"))); - curve_create->set_icon(get_editor_theme_icon(SNAME("CurveCreate"))); - curve_del->set_icon(get_editor_theme_icon(SNAME("CurveDelete"))); - curve_close->set_icon(get_editor_theme_icon(SNAME("CurveClose"))); - curve_clear_points->set_icon(get_editor_theme_icon(SNAME("Clear"))); - - create_curve_button->set_icon(get_editor_theme_icon(SNAME("Curve2D"))); + curve_edit->set_button_icon(get_editor_theme_icon(SNAME("CurveEdit"))); + curve_edit_curve->set_button_icon(get_editor_theme_icon(SNAME("CurveCurve"))); + curve_create->set_button_icon(get_editor_theme_icon(SNAME("CurveCreate"))); + curve_del->set_button_icon(get_editor_theme_icon(SNAME("CurveDelete"))); + curve_close->set_button_icon(get_editor_theme_icon(SNAME("CurveClose"))); + curve_clear_points->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); + + create_curve_button->set_button_icon(get_editor_theme_icon(SNAME("Curve2D"))); } break; } } diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 4fdcb79696..de4ab828bc 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -277,8 +277,15 @@ void Path3DGizmo::redraw() { Ref<StandardMaterial3D> path_tilt_material = gizmo_plugin->get_material("path_tilt_material", this); Ref<StandardMaterial3D> path_tilt_muted_material = gizmo_plugin->get_material("path_tilt_muted_material", this); Ref<StandardMaterial3D> handles_material = gizmo_plugin->get_material("handles"); + Ref<StandardMaterial3D> first_pt_handle_material = gizmo_plugin->get_material("first_pt_handle"); + Ref<StandardMaterial3D> last_pt_handle_material = gizmo_plugin->get_material("last_pt_handle"); + Ref<StandardMaterial3D> closed_pt_handle_material = gizmo_plugin->get_material("closed_pt_handle"); Ref<StandardMaterial3D> sec_handles_material = gizmo_plugin->get_material("sec_handles"); + first_pt_handle_material->set_albedo(Color(0.2, 1.0, 0.0)); + last_pt_handle_material->set_albedo(Color(1.0, 0.2, 0.0)); + closed_pt_handle_material->set_albedo(Color(1.0, 0.8, 0.0)); + Ref<Curve3D> c = path->get_curve(); if (c.is_null()) { return; @@ -369,7 +376,7 @@ void Path3DGizmo::redraw() { info.point_idx = idx; // Collect in-handles except for the first point. - if (idx > 0 && Path3DEditorPlugin::singleton->curve_edit_curve->is_pressed()) { + if (idx > (c->is_closed() ? -1 : 0) && Path3DEditorPlugin::singleton->curve_edit_curve->is_pressed()) { const Vector3 in = c->get_point_in(idx); info.type = HandleType::HANDLE_TYPE_IN; @@ -383,7 +390,7 @@ void Path3DGizmo::redraw() { } // Collect out-handles except for the last point. - if (idx < c->get_point_count() - 1 && Path3DEditorPlugin::singleton->curve_edit_curve->is_pressed()) { + if (idx < (c->is_closed() ? c->get_point_count() : c->get_point_count() - 1) && Path3DEditorPlugin::singleton->curve_edit_curve->is_pressed()) { const Vector3 out = c->get_point_out(idx); info.type = HandleType::HANDLE_TYPE_OUT; @@ -441,7 +448,42 @@ void Path3DGizmo::redraw() { } if (!Path3DEditorPlugin::singleton->curve_edit->is_pressed() && primary_handle_points.size()) { - add_handles(primary_handle_points, handles_material); + // Need to define indices separately. + // Point count. + const int pc = primary_handle_points.size(); + Vector<int> idx; + idx.resize(pc); + int *idx_ptr = idx.ptrw(); + for (int j = 0; j < pc; j++) { + idx_ptr[j] = j; + } + + // Initialize arrays for first point. + PackedVector3Array first_pt_handle_point; + Vector<int> first_pt_id; + first_pt_handle_point.append(primary_handle_points[0]); + first_pt_id.append(idx[0]); + + // Initialize arrays and add handle for last point if needed. + if (pc > 1) { + PackedVector3Array last_pt_handle_point; + Vector<int> last_pt_id; + last_pt_handle_point.append(primary_handle_points[pc - 1]); + last_pt_id.append(idx[pc - 1]); + primary_handle_points.remove_at(pc - 1); + idx.remove_at(pc - 1); + add_handles(last_pt_handle_point, c->is_closed() ? handles_material : last_pt_handle_material, last_pt_id); + } + + // Add handle for first point. + primary_handle_points.remove_at(0); + idx.remove_at(0); + add_handles(first_pt_handle_point, c->is_closed() ? closed_pt_handle_material : first_pt_handle_material, first_pt_id); + + // Add handles for remaining intermediate points. + if (!primary_handle_points.is_empty()) { + add_handles(primary_handle_points, handles_material, idx); + } } if (secondary_handle_points.size()) { add_handles(secondary_handle_points, sec_handles_material, collected_secondary_handle_ids, false, true); @@ -469,7 +511,7 @@ Path3DGizmo::Path3DGizmo(Path3D *p_path, float p_disk_size) { Path3DEditorPlugin::singleton->curve_edit_curve->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw)); Path3DEditorPlugin::singleton->curve_create->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw)); Path3DEditorPlugin::singleton->curve_del->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw)); - Path3DEditorPlugin::singleton->curve_close->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw)); + Path3DEditorPlugin::singleton->curve_closed->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw)); } EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) { @@ -696,7 +738,7 @@ void Path3DEditorPlugin::_mode_changed(int p_mode) { Node3DEditor::get_singleton()->clear_subgizmo_selection(); } -void Path3DEditorPlugin::_close_curve() { +void Path3DEditorPlugin::_toggle_closed_curve() { Ref<Curve3D> c = path->get_curve(); if (c.is_null()) { return; @@ -704,13 +746,10 @@ void Path3DEditorPlugin::_close_curve() { if (c->get_point_count() < 2) { return; } - if (c->get_point_position(0) == c->get_point_position(c->get_point_count() - 1)) { - return; - } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Close Curve")); - ur->add_do_method(c.ptr(), "add_point", c->get_point_position(0), c->get_point_in(0), c->get_point_out(0), -1); - ur->add_undo_method(c.ptr(), "remove_point", c->get_point_count()); + ur->create_action(TTR("Toggle Open/Closed Curve")); + ur->add_do_method(c.ptr(), "set_closed", !c.ptr()->is_closed()); + ur->add_undo_method(c.ptr(), "set_closed", c.ptr()->is_closed()); ur->commit_action(); } @@ -771,6 +810,7 @@ void Path3DEditorPlugin::_clear_curve_points() { return; } Ref<Curve3D> curve = path->get_curve(); + curve->set_closed(false); curve->clear_points(); } @@ -790,14 +830,14 @@ void Path3DEditorPlugin::_restore_curve_points(const PackedVector3Array &p_point } void Path3DEditorPlugin::_update_theme() { - curve_edit->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveEdit"))); - curve_edit_curve->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveCurve"))); - curve_edit_tilt->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveTilt"))); - curve_create->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveCreate"))); - curve_del->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveDelete"))); - curve_close->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveClose"))); - curve_clear_points->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("Clear"))); - create_curve_button->set_icon(topmenu_bar->get_editor_theme_icon(SNAME("Curve3D"))); + curve_edit->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveEdit"))); + curve_edit_curve->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveCurve"))); + curve_edit_tilt->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveTilt"))); + curve_create->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveCreate"))); + curve_del->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveDelete"))); + curve_closed->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("CurveClose"))); + curve_clear_points->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("Clear"))); + create_curve_button->set_button_icon(topmenu_bar->get_editor_theme_icon(SNAME("Curve3D"))); } void Path3DEditorPlugin::_update_toolbar() { @@ -872,12 +912,12 @@ Path3DEditorPlugin::Path3DEditorPlugin() { toolbar->add_child(curve_del); curve_del->connect(SceneStringName(pressed), callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(MODE_DELETE)); - curve_close = memnew(Button); - curve_close->set_theme_type_variation("FlatButton"); - curve_close->set_focus_mode(Control::FOCUS_NONE); - curve_close->set_tooltip_text(TTR("Close Curve")); - toolbar->add_child(curve_close); - curve_close->connect(SceneStringName(pressed), callable_mp(this, &Path3DEditorPlugin::_close_curve)); + curve_closed = memnew(Button); + curve_closed->set_theme_type_variation("FlatButton"); + curve_closed->set_focus_mode(Control::FOCUS_NONE); + curve_closed->set_tooltip_text(TTR("Close Curve")); + toolbar->add_child(curve_closed); + curve_closed->connect(SceneStringName(pressed), callable_mp(this, &Path3DEditorPlugin::_toggle_closed_curve)); curve_clear_points = memnew(Button); curve_clear_points->set_theme_type_variation("FlatButton"); @@ -922,7 +962,7 @@ Ref<EditorNode3DGizmo> Path3DGizmoPlugin::create_gizmo(Node3D *p_spatial) { Path3D *path = Object::cast_to<Path3D>(p_spatial); if (path) { - ref = Ref<Path3DGizmo>(memnew(Path3DGizmo(path, disk_size))); + ref.instantiate(path, disk_size); } return ref; @@ -943,6 +983,14 @@ void Path3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Ref<Curve3D> curve = path->get_curve(); Ref<StandardMaterial3D> handle_material = get_material("handles", p_gizmo); + Ref<StandardMaterial3D> first_pt_handle_material = get_material("first_pt_handle", p_gizmo); + Ref<StandardMaterial3D> last_pt_handle_material = get_material("last_pt_handle", p_gizmo); + Ref<StandardMaterial3D> closed_pt_handle_material = get_material("closed_pt_handle", p_gizmo); + + first_pt_handle_material->set_albedo(Color(0.2, 1.0, 0.0)); + last_pt_handle_material->set_albedo(Color(1.0, 0.2, 0.0)); + closed_pt_handle_material->set_albedo(Color(1.0, 0.8, 0.0)); + PackedVector3Array handles; if (Path3DEditorPlugin::singleton->curve_edit->is_pressed()) { @@ -955,7 +1003,37 @@ void Path3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } if (handles.size()) { - p_gizmo->add_vertices(handles, handle_material, Mesh::PRIMITIVE_POINTS); + // Point count. + const int pc = handles.size(); + + // Initialize arrays for first point. + PackedVector3Array first_pt; + first_pt.append(handles[0]); + + // Initialize arrays and add handle for last point if needed. + if (pc > 1) { + PackedVector3Array last_pt; + last_pt.append(handles[handles.size() - 1]); + handles.remove_at(handles.size() - 1); + if (curve->is_closed()) { + p_gizmo->add_vertices(last_pt, handle_material, Mesh::PRIMITIVE_POINTS); + } else { + p_gizmo->add_vertices(last_pt, last_pt_handle_material, Mesh::PRIMITIVE_POINTS); + } + } + + // Add handle for first point. + handles.remove_at(0); + if (curve->is_closed()) { + p_gizmo->add_vertices(first_pt, closed_pt_handle_material, Mesh::PRIMITIVE_POINTS); + } else { + p_gizmo->add_vertices(first_pt, first_pt_handle_material, Mesh::PRIMITIVE_POINTS); + } + + // Add handles for remaining intermediate points. + if (!handles.is_empty()) { + p_gizmo->add_vertices(handles, handle_material, Mesh::PRIMITIVE_POINTS); + } } } @@ -1072,5 +1150,8 @@ Path3DGizmoPlugin::Path3DGizmoPlugin(float p_disk_size) { create_material("path_tilt_material", path_tilt_color); create_material("path_tilt_muted_material", path_tilt_color * 0.7); create_handle_material("handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons))); + create_handle_material("first_pt_handle", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons))); + create_handle_material("last_pt_handle", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons))); + create_handle_material("closed_pt_handle", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons))); create_handle_material("sec_handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorCurveHandle"), EditorStringName(EditorIcons))); } diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h index 60cb7f940f..3e45c2718f 100644 --- a/editor/plugins/path_3d_editor_plugin.h +++ b/editor/plugins/path_3d_editor_plugin.h @@ -120,7 +120,7 @@ class Path3DEditorPlugin : public EditorPlugin { Button *curve_edit_curve = nullptr; Button *curve_edit_tilt = nullptr; Button *curve_del = nullptr; - Button *curve_close = nullptr; + Button *curve_closed = nullptr; Button *curve_clear_points = nullptr; MenuButton *handle_menu = nullptr; @@ -144,7 +144,7 @@ class Path3DEditorPlugin : public EditorPlugin { void _update_toolbar(); void _mode_changed(int p_mode); - void _close_curve(); + void _toggle_closed_curve(); void _handle_option_pressed(int p_option); bool handle_clicked = false; bool mirror_handle_angle = true; diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp index c858fa8606..15a957d5c4 100644 --- a/editor/plugins/physical_bone_3d_editor_plugin.cpp +++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp @@ -60,7 +60,7 @@ PhysicalBone3DEditor::PhysicalBone3DEditor() { button_transform_joint->set_text(TTR("Move Joint")); // TODO: Rework this as a dedicated toolbar control so we can hook into theme changes and update it // when the editor theme updates. - button_transform_joint->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("PhysicalBone3D"), EditorStringName(EditorIcons))); + button_transform_joint->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("PhysicalBone3D"), EditorStringName(EditorIcons))); button_transform_joint->set_toggle_mode(true); button_transform_joint->connect(SceneStringName(toggled), callable_mp(this, &PhysicalBone3DEditor::_on_toggle_button_transform_joint)); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 842142db79..8ab08ff28f 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -111,22 +111,22 @@ void Polygon2DEditor::_notification(int p_what) { } break; case NOTIFICATION_READY: { - button_uv->set_icon(get_editor_theme_icon(SNAME("Uv"))); - - uv_button[UV_MODE_CREATE]->set_icon(get_editor_theme_icon(SNAME("Edit"))); - uv_button[UV_MODE_CREATE_INTERNAL]->set_icon(get_editor_theme_icon(SNAME("EditInternal"))); - uv_button[UV_MODE_REMOVE_INTERNAL]->set_icon(get_editor_theme_icon(SNAME("RemoveInternal"))); - uv_button[UV_MODE_EDIT_POINT]->set_icon(get_editor_theme_icon(SNAME("ToolSelect"))); - uv_button[UV_MODE_MOVE]->set_icon(get_editor_theme_icon(SNAME("ToolMove"))); - uv_button[UV_MODE_ROTATE]->set_icon(get_editor_theme_icon(SNAME("ToolRotate"))); - uv_button[UV_MODE_SCALE]->set_icon(get_editor_theme_icon(SNAME("ToolScale"))); - uv_button[UV_MODE_ADD_POLYGON]->set_icon(get_editor_theme_icon(SNAME("Edit"))); - uv_button[UV_MODE_REMOVE_POLYGON]->set_icon(get_editor_theme_icon(SNAME("Close"))); - uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_editor_theme_icon(SNAME("Bucket"))); - uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_editor_theme_icon(SNAME("Clear"))); - - b_snap_grid->set_icon(get_editor_theme_icon(SNAME("Grid"))); - b_snap_enable->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); + button_uv->set_button_icon(get_editor_theme_icon(SNAME("Uv"))); + + uv_button[UV_MODE_CREATE]->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + uv_button[UV_MODE_CREATE_INTERNAL]->set_button_icon(get_editor_theme_icon(SNAME("EditInternal"))); + uv_button[UV_MODE_REMOVE_INTERNAL]->set_button_icon(get_editor_theme_icon(SNAME("RemoveInternal"))); + uv_button[UV_MODE_EDIT_POINT]->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + uv_button[UV_MODE_MOVE]->set_button_icon(get_editor_theme_icon(SNAME("ToolMove"))); + uv_button[UV_MODE_ROTATE]->set_button_icon(get_editor_theme_icon(SNAME("ToolRotate"))); + uv_button[UV_MODE_SCALE]->set_button_icon(get_editor_theme_icon(SNAME("ToolScale"))); + uv_button[UV_MODE_ADD_POLYGON]->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + uv_button[UV_MODE_REMOVE_POLYGON]->set_button_icon(get_editor_theme_icon(SNAME("Close"))); + uv_button[UV_MODE_PAINT_WEIGHT]->set_button_icon(get_editor_theme_icon(SNAME("Bucket"))); + uv_button[UV_MODE_CLEAR_WEIGHT]->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); + + b_snap_grid->set_button_icon(get_editor_theme_icon(SNAME("Grid"))); + b_snap_enable->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE); uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); @@ -275,7 +275,11 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { uv_button[UV_MODE_REMOVE_POLYGON]->hide(); uv_button[UV_MODE_PAINT_WEIGHT]->hide(); uv_button[UV_MODE_CLEAR_WEIGHT]->hide(); - _uv_mode(UV_MODE_EDIT_POINT); + if (node->get_polygon().is_empty()) { + _uv_mode(UV_MODE_CREATE); + } else { + _uv_mode(UV_MODE_EDIT_POINT); + } bone_scroll_main_vb->hide(); bone_paint_strength->hide(); @@ -317,9 +321,16 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { uv_edit_draw->queue_redraw(); } +void Polygon2DEditor::_uv_edit_popup_show() { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->connect("version_changed", callable_mp(this, &Polygon2DEditor::_update_available_modes)); +} + void Polygon2DEditor::_uv_edit_popup_hide() { EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "uv_editor", Rect2(uv_edit->get_position(), uv_edit->get_size())); _cancel_editing(); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->disconnect("version_changed", callable_mp(this, &Polygon2DEditor::_update_available_modes)); } void Polygon2DEditor::_menu_option(int p_option) { @@ -346,6 +357,7 @@ void Polygon2DEditor::_menu_option(int p_option) { uv_edit->popup_centered_ratio(0.85); } _update_bone_list(); + _update_available_modes(); get_tree()->connect("process_frame", callable_mp(this, &Polygon2DEditor::_center_view), CONNECT_ONE_SHOT); } break; case UVEDIT_POLYGON_TO_UV: { @@ -408,6 +420,7 @@ void Polygon2DEditor::_cancel_editing() { node->set_polygons(polygons_prev); _update_polygon_editing_state(); + _update_available_modes(); } else if (uv_drag) { uv_drag = false; if (uv_edit_mode[0]->is_pressed()) { // Edit UV. @@ -566,6 +579,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag = false; uv_create = false; + _update_available_modes(); _uv_mode(UV_MODE_EDIT_POINT); _menu_option(MODE_EDIT); } else { @@ -973,6 +987,23 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } } +void Polygon2DEditor::_update_available_modes() { + // Force point editing mode if there's no polygon yet. + if (node->get_polygon().is_empty()) { + if (!uv_edit_mode[1]->is_pressed()) { + uv_edit_mode[1]->set_pressed(true); + _uv_edit_mode_select(1); + } + uv_edit_mode[0]->set_disabled(true); + uv_edit_mode[2]->set_disabled(true); + uv_edit_mode[3]->set_disabled(true); + } else { + uv_edit_mode[0]->set_disabled(false); + uv_edit_mode[2]->set_disabled(false); + uv_edit_mode[3]->set_disabled(false); + } +} + void Polygon2DEditor::_center_view() { Size2 texture_size; if (node->get_texture().is_valid()) { @@ -1324,6 +1355,7 @@ Polygon2DEditor::Polygon2DEditor() { add_child(uv_edit); uv_edit->connect(SceneStringName(confirmed), callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); uv_edit->connect("canceled", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); + uv_edit->connect("about_to_popup", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_show)); VBoxContainer *uv_main_vb = memnew(VBoxContainer); uv_edit->add_child(uv_main_vb); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index 164aa3eccc..4e1cd7172e 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -142,6 +142,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _cancel_editing(); void _update_polygon_editing_state(); + void _update_available_modes(); void _center_view(); void _update_zoom_and_pan(bool p_zoom_at_center); @@ -157,6 +158,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _set_snap_step_y(real_t p_val); void _uv_edit_mode_select(int p_mode); + void _uv_edit_popup_show(); void _uv_edit_popup_hide(); void _bone_paint_selected(int p_index); @@ -168,7 +170,7 @@ protected: virtual Vector2 _get_offset(int p_idx) const override; - virtual bool _has_uv() const override { return true; }; + virtual bool _has_uv() const override { return true; } virtual void _commit_action() override; void _notification(int p_what); diff --git a/editor/plugins/polygon_3d_editor_plugin.cpp b/editor/plugins/polygon_3d_editor_plugin.cpp index 56baa4a839..017504f0d6 100644 --- a/editor/plugins/polygon_3d_editor_plugin.cpp +++ b/editor/plugins/polygon_3d_editor_plugin.cpp @@ -46,8 +46,8 @@ void Polygon3DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - button_create->set_icon(get_editor_theme_icon(SNAME("Edit"))); - button_edit->set_icon(get_editor_theme_icon(SNAME("MovePoint"))); + button_create->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + button_edit->set_button_icon(get_editor_theme_icon(SNAME("MovePoint"))); button_edit->set_pressed(true); get_tree()->connect("node_removed", callable_mp(this, &Polygon3DEditor::_node_removed)); @@ -554,7 +554,7 @@ Polygon3DEditor::Polygon3DEditor() { imgeom->set_mesh(imesh); imgeom->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001))); - line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + line_material.instantiate(); line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); line_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); @@ -562,7 +562,7 @@ Polygon3DEditor::Polygon3DEditor() { line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); line_material->set_albedo(Color(1, 1, 1)); - handle_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + handle_material.instantiate(); handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true); handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index ba6699fcc4..bb0607a3c6 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -45,7 +45,7 @@ void ResourcePreloaderEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - load->set_icon(get_editor_theme_icon(SNAME("Folder"))); + load->set_button_icon(get_editor_theme_icon(SNAME("Folder"))); } break; } } diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index cd422fc291..0a4e3d78c8 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -169,13 +169,13 @@ void EditorPropertyRootMotion::update_property() { NodePath p = get_edited_property_value(); assign->set_tooltip_text(p); if (p == NodePath()) { - assign->set_icon(Ref<Texture2D>()); + assign->set_button_icon(Ref<Texture2D>()); assign->set_text(TTR("Assign...")); assign->set_flat(false); return; } - assign->set_icon(Ref<Texture2D>()); + assign->set_button_icon(Ref<Texture2D>()); assign->set_text(p); } @@ -188,7 +188,7 @@ void EditorPropertyRootMotion::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { Ref<Texture2D> t = get_editor_theme_icon(SNAME("Clear")); - clear->set_icon(t); + clear->set_button_icon(t); } break; } } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 7e0331d15c..49ecbac751 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -261,6 +261,52 @@ Ref<EditorSyntaxHighlighter> EditorJSONSyntaxHighlighter::_create() const { return syntax_highlighter; } +//// + +void EditorMarkdownSyntaxHighlighter::_update_cache() { + highlighter->set_text_edit(text_edit); + highlighter->clear_keyword_colors(); + highlighter->clear_member_keyword_colors(); + highlighter->clear_color_regions(); + + // Disable automatic symbolic highlights, as these don't make sense for prose. + highlighter->set_symbol_color(EDITOR_GET("text_editor/theme/highlighting/text_color")); + highlighter->set_number_color(EDITOR_GET("text_editor/theme/highlighting/text_color")); + highlighter->set_member_variable_color(EDITOR_GET("text_editor/theme/highlighting/text_color")); + highlighter->set_function_color(EDITOR_GET("text_editor/theme/highlighting/text_color")); + + // Headings (any level). + const Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color"); + highlighter->add_color_region("#", "", function_color); + + // Bold. + highlighter->add_color_region("**", "**", function_color); + // `__bold__` syntax is not supported as color regions must begin with a symbol, + // not a character that is valid in an identifier. + + // Code (both inline code and triple-backticks code blocks). + const Color code_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color"); + highlighter->add_color_region("`", "`", code_color); + + // Link (both references and inline links with URLs). The URL is not highlighted. + const Color link_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color"); + highlighter->add_color_region("[", "]", link_color); + + // Quote. + const Color quote_color = EDITOR_GET("text_editor/theme/highlighting/string_color"); + highlighter->add_color_region(">", "", quote_color, true); + + // HTML comment, which is also supported in Markdown. + const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color"); + highlighter->add_color_region("<!--", "-->", comment_color); +} + +Ref<EditorSyntaxHighlighter> EditorMarkdownSyntaxHighlighter::_create() const { + Ref<EditorMarkdownSyntaxHighlighter> syntax_highlighter; + syntax_highlighter.instantiate(); + return syntax_highlighter; +} + //////////////////////////////////////////////////////////////////////////////// /*** SCRIPT EDITOR ****/ @@ -1734,18 +1780,18 @@ void ScriptEditor::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { tab_container->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("ScriptEditor"), EditorStringName(EditorStyles))); - help_search->set_icon(get_editor_theme_icon(SNAME("HelpSearch"))); - site_search->set_icon(get_editor_theme_icon(SNAME("ExternalLink"))); + help_search->set_button_icon(get_editor_theme_icon(SNAME("HelpSearch"))); + site_search->set_button_icon(get_editor_theme_icon(SNAME("ExternalLink"))); if (is_layout_rtl()) { - script_forward->set_icon(get_editor_theme_icon(SNAME("Back"))); - script_back->set_icon(get_editor_theme_icon(SNAME("Forward"))); + script_forward->set_button_icon(get_editor_theme_icon(SNAME("Back"))); + script_back->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); } else { - script_forward->set_icon(get_editor_theme_icon(SNAME("Forward"))); - script_back->set_icon(get_editor_theme_icon(SNAME("Back"))); + script_forward->set_button_icon(get_editor_theme_icon(SNAME("Forward"))); + script_back->set_button_icon(get_editor_theme_icon(SNAME("Back"))); } - members_overview_alphabeta_sort_button->set_icon(get_editor_theme_icon(SNAME("Sort"))); + members_overview_alphabeta_sort_button->set_button_icon(get_editor_theme_icon(SNAME("Sort"))); filter_scripts->set_right_icon(get_editor_theme_icon(SNAME("Search"))); filter_methods->set_right_icon(get_editor_theme_icon(SNAME("Search"))); @@ -2139,8 +2185,6 @@ void ScriptEditor::_update_script_colors() { continue; } - script_list->set_item_custom_bg_color(i, Color(0, 0, 0, 0)); - if (script_temperature_enabled) { int pass = n->get_meta("__editor_pass", -1); if (pass < 0) { @@ -2166,7 +2210,7 @@ void ScriptEditor::_update_script_names() { HashSet<Ref<Script>> used; Node *edited = EditorNode::get_singleton()->get_edited_scene(); - if (edited) { + if (edited && EDITOR_GET("text_editor/script_list/highlight_scene_scripts")) { _find_scripts(edited, edited, used); } @@ -2336,7 +2380,7 @@ void ScriptEditor::_update_script_names() { script_list->set_item_tooltip(index, sedata_filtered[i].tooltip); script_list->set_item_metadata(index, sedata_filtered[i].index); /* Saving as metadata the script's index in the tab container and not the filtered one */ if (sedata_filtered[i].used) { - script_list->set_item_custom_bg_color(index, Color(88 / 255.0, 88 / 255.0, 60 / 255.0)); + script_list->set_item_custom_bg_color(index, Color(.5, .5, .5, .125)); } if (tab_container->get_current_tab() == sedata_filtered[i].index) { script_list->select(index); @@ -4347,28 +4391,28 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { disk_changed = memnew(ConfirmationDialog); { - disk_changed->set_title(TTR("Files have been modified on disk")); + disk_changed->set_title(TTR("Files have been modified outside Godot")); VBoxContainer *vbc = memnew(VBoxContainer); disk_changed->add_child(vbc); Label *files_are_newer_label = memnew(Label); - files_are_newer_label->set_text(TTR("The following files are newer on disk.")); + files_are_newer_label->set_text(TTR("The following files are newer on disk:")); vbc->add_child(files_are_newer_label); - Label *what_action_label = memnew(Label); - what_action_label->set_text(TTR("What action should be taken?:")); - vbc->add_child(what_action_label); - disk_changed_list = memnew(Tree); vbc->add_child(disk_changed_list); disk_changed_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); disk_changed_list->set_v_size_flags(SIZE_EXPAND_FILL); + Label *what_action_label = memnew(Label); + what_action_label->set_text(TTR("What action should be taken?")); + vbc->add_child(what_action_label); + disk_changed->connect(SceneStringName(confirmed), callable_mp(this, &ScriptEditor::reload_scripts).bind(false)); - disk_changed->set_ok_button_text(TTR("Discard local changes and reload")); + disk_changed->set_ok_button_text(TTR("Reload from disk")); - disk_changed->add_button(TTR("Keep local changes and overwrite"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave"); + disk_changed->add_button(TTR("Ignore external changes"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave"); disk_changed->connect("custom_action", callable_mp(this, &ScriptEditor::_resave_scripts)); } @@ -4414,6 +4458,10 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { json_syntax_highlighter.instantiate(); register_syntax_highlighter(json_syntax_highlighter); + Ref<EditorMarkdownSyntaxHighlighter> markdown_syntax_highlighter; + markdown_syntax_highlighter.instantiate(); + register_syntax_highlighter(markdown_syntax_highlighter); + _update_online_doc(); } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 8e82d60605..5de0aaa1e9 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -120,6 +120,24 @@ public: EditorJSONSyntaxHighlighter() { highlighter.instantiate(); } }; +class EditorMarkdownSyntaxHighlighter : public EditorSyntaxHighlighter { + GDCLASS(EditorMarkdownSyntaxHighlighter, EditorSyntaxHighlighter) + +private: + Ref<CodeHighlighter> highlighter; + +public: + virtual void _update_cache() override; + virtual Dictionary _get_line_syntax_highlighting_impl(int p_line) override { return highlighter->get_line_syntax_highlighting(p_line); } + + virtual PackedStringArray _get_supported_languages() const override { return PackedStringArray{ "md", "markdown" }; } + virtual String _get_name() const override { return TTR("Markdown"); } + + virtual Ref<EditorSyntaxHighlighter> _create() const override; + + EditorMarkdownSyntaxHighlighter() { highlighter.instantiate(); } +}; + /////////////////////////////////////////////////////////////////////////////// class ScriptEditorQuickOpen : public ConfirmationDialog { diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index b45b30b52e..cf586c792e 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -282,7 +282,7 @@ void ScriptTextEditor::_warning_clicked(const Variant &p_line) { CodeEdit *text_editor = code_editor->get_text_editor(); String prev_line = line > 0 ? text_editor->get_line(line - 1) : ""; if (prev_line.contains("@warning_ignore")) { - const int closing_bracket_idx = prev_line.find(")"); + const int closing_bracket_idx = prev_line.find_char(')'); const String text_to_insert = ", " + code.quote(quote_style); text_editor->insert_text(text_to_insert, line - 1, closing_bracket_idx); } else { @@ -951,7 +951,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c } else if (p_symbol.is_resource_file() || p_symbol.begins_with("uid://")) { String symbol = p_symbol; if (symbol.begins_with("uid://")) { - symbol = ResourceUID::get_singleton()->get_id_path(ResourceUID::get_singleton()->text_to_id(symbol)); + symbol = ResourceUID::uid_to_path(symbol); } List<String> scene_extensions; @@ -1205,7 +1205,7 @@ void ScriptTextEditor::_update_connected_methods() { // Account for inner classes by stripping the class names from the method, // starting from the right since our inner class might be inside of another inner class. - int pos = raw_name.rfind("."); + int pos = raw_name.rfind_char('.'); if (pos != -1) { name = raw_name.substr(pos + 1); } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 6b00a2c9c5..5166619f90 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -396,6 +396,7 @@ void ShaderEditorPlugin::_setup_popup_menu(PopupMenuType p_type, PopupMenu *p_me if (p_type == FILE) { p_menu->add_separator(); p_menu->add_item(TTR("Open File in Inspector"), FILE_INSPECT); + p_menu->add_item(TTR("Inspect Native Shader Code..."), FILE_INSPECT_NATIVE_SHADER_CODE); p_menu->add_separator(); p_menu->add_shortcut(ED_SHORTCUT("shader_editor/close_file", TTR("Close File"), KeyModifierMask::CMD_OR_CTRL | Key::W), FILE_CLOSE); } else { @@ -554,6 +555,12 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) { EditorNode::get_singleton()->push_item(edited_shaders[index].shader_inc.ptr()); } } break; + case FILE_INSPECT_NATIVE_SHADER_CODE: { + int index = shader_tabs->get_current_tab(); + if (edited_shaders[index].shader.is_valid()) { + edited_shaders[index].shader->inspect_native_shader_code(); + } + } break; case FILE_CLOSE: { _close_shader(shader_tabs->get_current_tab()); } break; @@ -754,6 +761,7 @@ void ShaderEditorPlugin::_set_file_specific_items_disabled(bool p_disabled) { file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE), p_disabled); file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE_AS), p_disabled); file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_INSPECT), p_disabled); + file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_INSPECT_NATIVE_SHADER_CODE), p_disabled); file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_CLOSE), p_disabled); } diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 43e6af79fa..19e43921c3 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -69,6 +69,7 @@ class ShaderEditorPlugin : public EditorPlugin { FILE_SAVE, FILE_SAVE_AS, FILE_INSPECT, + FILE_INSPECT_NATIVE_SHADER_CODE, FILE_CLOSE, CLOSE_ALL, CLOSE_OTHER_TABS, diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp index d732d51f69..d2fd9b1cc0 100644 --- a/editor/plugins/shader_file_editor_plugin.cpp +++ b/editor/plugins/shader_file_editor_plugin.cpp @@ -63,7 +63,7 @@ void ShaderFileEditor::_version_selected(int p_option) { for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) { if (bytecode->get_stage_bytecode(RD::ShaderStage(i)).is_empty() && bytecode->get_stage_compile_error(RD::ShaderStage(i)) == String()) { - stages[i]->set_icon(Ref<Texture2D>()); + stages[i]->set_button_icon(Ref<Texture2D>()); continue; } @@ -73,7 +73,7 @@ void ShaderFileEditor::_version_selected(int p_option) { } else { icon = get_editor_theme_icon(SNAME("ImportCheck")); } - stages[i]->set_icon(icon); + stages[i]->set_button_icon(icon); if (first_found == -1) { first_found = i; diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp index 8f54641dcb..97ad0ff640 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.cpp +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -96,7 +96,7 @@ Skeleton2DEditor::Skeleton2DEditor() { CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text(TTR("Skeleton2D")); - options->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Skeleton2D"), EditorStringName(EditorIcons))); + options->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Skeleton2D"), EditorStringName(EditorIcons))); options->get_popup()->add_item(TTR("Reset to Rest Pose"), MENU_OPTION_SET_REST); options->get_popup()->add_separator(); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 81beaf6f91..369a1fc864 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -123,7 +123,7 @@ void BonePropertiesEditor::_notification(int p_what) { const Color section_color = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)); section->set_bg_color(section_color); rest_section->set_bg_color(section_color); - add_metadata_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_metadata_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } break; } } @@ -351,12 +351,12 @@ void Skeleton3DEditor::set_keyable(const bool p_keyable) { } else { animation_hb->hide(); } -}; +} void Skeleton3DEditor::set_bone_options_enabled(const bool p_bone_options_enabled) { skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_RESET_SELECTED_POSES, !p_bone_options_enabled); skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_SELECTED_POSES_TO_RESTS, !p_bone_options_enabled); -}; +} void Skeleton3DEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("update_all"), &Skeleton3DEditor::update_all); @@ -1136,13 +1136,13 @@ void Skeleton3DEditor::_notification(int p_what) { add_theme_constant_override("separation", 0); } break; case NOTIFICATION_THEME_CHANGED: { - skeleton_options->set_icon(get_editor_theme_icon(SNAME("Skeleton3D"))); - edit_mode_button->set_icon(get_editor_theme_icon(SNAME("ToolBoneSelect"))); - key_loc_button->set_icon(get_editor_theme_icon(SNAME("KeyPosition"))); - key_rot_button->set_icon(get_editor_theme_icon(SNAME("KeyRotation"))); - key_scale_button->set_icon(get_editor_theme_icon(SNAME("KeyScale"))); - key_insert_button->set_icon(get_editor_theme_icon(SNAME("Key"))); - key_insert_all_button->set_icon(get_editor_theme_icon(SNAME("NewKey"))); + skeleton_options->set_button_icon(get_editor_theme_icon(SNAME("Skeleton3D"))); + edit_mode_button->set_button_icon(get_editor_theme_icon(SNAME("ToolBoneSelect"))); + key_loc_button->set_button_icon(get_editor_theme_icon(SNAME("KeyPosition"))); + key_rot_button->set_button_icon(get_editor_theme_icon(SNAME("KeyRotation"))); + key_scale_button->set_button_icon(get_editor_theme_icon(SNAME("KeyScale"))); + key_insert_button->set_button_icon(get_editor_theme_icon(SNAME("Key"))); + key_insert_all_button->set_button_icon(get_editor_theme_icon(SNAME("NewKey"))); bones_section->set_bg_color(get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor))); update_joint_tree(); @@ -1186,8 +1186,8 @@ Skeleton3DEditor::Skeleton3DEditor(EditorInspectorPluginSkeleton *e_plugin, Skel singleton = this; // Handle. - handle_material = Ref<ShaderMaterial>(memnew(ShaderMaterial)); - handle_shader = Ref<Shader>(memnew(Shader)); + handle_material.instantiate(); + handle_shader.instantiate(); handle_shader->set_code(R"( // Skeleton 3D gizmo handle shader. diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index 0265183dfa..c6f8c5d357 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/editor/plugins/skeleton_3d_editor_plugin.h @@ -228,14 +228,14 @@ public: void move_skeleton_bone(NodePath p_skeleton_path, int32_t p_selected_boneidx, int32_t p_target_boneidx); - Skeleton3D *get_skeleton() const { return skeleton; }; + Skeleton3D *get_skeleton() const { return skeleton; } bool is_edit_mode() const { return edit_mode; } void update_bone_original(); - Vector3 get_bone_original_position() const { return bone_original_position; }; - Quaternion get_bone_original_rotation() const { return bone_original_rotation; }; - Vector3 get_bone_original_scale() const { return bone_original_scale; }; + Vector3 get_bone_original_position() const { return bone_original_position; } + Quaternion get_bone_original_rotation() const { return bone_original_rotation; } + Vector3 get_bone_original_scale() const { return bone_original_scale; } Skeleton3DEditor(EditorInspectorPluginSkeleton *e_plugin, Skeleton3D *skeleton); ~Skeleton3DEditor(); diff --git a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp index 9b98b6ffa2..d0c8744dc2 100644 --- a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp @@ -75,7 +75,7 @@ void SkeletonIK3DEditorPlugin::make_visible(bool p_visible) { SkeletonIK3DEditorPlugin::SkeletonIK3DEditorPlugin() { play_btn = memnew(Button); - play_btn->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Play"), EditorStringName(EditorIcons))); + play_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Play"), EditorStringName(EditorIcons))); play_btn->set_text(TTR("Play IK")); play_btn->set_toggle_mode(true); play_btn->hide(); diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index c7db243662..c365ad6133 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -560,7 +560,7 @@ void Sprite2DEditor::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - options->set_icon(get_editor_theme_icon(SNAME("Sprite2D"))); + options->set_button_icon(get_editor_theme_icon(SNAME("Sprite2D"))); options->get_popup()->set_item_icon(MENU_OPTION_CONVERT_TO_MESH_2D, get_editor_theme_icon(SNAME("MeshInstance2D"))); options->get_popup()->set_item_icon(MENU_OPTION_CONVERT_TO_POLYGON_2D, get_editor_theme_icon(SNAME("Polygon2D"))); @@ -593,12 +593,12 @@ Sprite2DEditor::Sprite2DEditor() { add_child(err_dialog); debug_uv_dialog = memnew(ConfirmationDialog); + debug_uv_dialog->set_size(Size2(960, 540) * EDSCALE); VBoxContainer *vb = memnew(VBoxContainer); debug_uv_dialog->add_child(vb); debug_uv = memnew(Panel); debug_uv->connect(SceneStringName(gui_input), callable_mp(this, &Sprite2DEditor::_debug_uv_input)); debug_uv->connect(SceneStringName(draw), callable_mp(this, &Sprite2DEditor::_debug_uv_draw)); - debug_uv->set_custom_minimum_size(Size2(800, 500) * EDSCALE); debug_uv->set_clip_contents(true); vb->add_margin_child(TTR("Preview:"), debug_uv, true); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 168a3b3ac2..f29ace1d15 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -498,9 +498,9 @@ void SpriteFramesEditor::_toggle_show_settings() { void SpriteFramesEditor::_update_show_settings() { if (is_layout_rtl()) { - toggle_settings_button->set_icon(get_editor_theme_icon(split_sheet_settings_vb->is_visible() ? SNAME("Back") : SNAME("Forward"))); + toggle_settings_button->set_button_icon(get_editor_theme_icon(split_sheet_settings_vb->is_visible() ? SNAME("Back") : SNAME("Forward"))); } else { - toggle_settings_button->set_icon(get_editor_theme_icon(split_sheet_settings_vb->is_visible() ? SNAME("Forward") : SNAME("Back"))); + toggle_settings_button->set_button_icon(get_editor_theme_icon(split_sheet_settings_vb->is_visible() ? SNAME("Forward") : SNAME("Back"))); } } @@ -639,32 +639,32 @@ void SpriteFramesEditor::_notification(int p_what) { pause_icon = get_editor_theme_icon(SNAME("Pause")); _update_stop_icon(); - autoplay->set_icon(get_editor_theme_icon(SNAME("AutoPlay"))); - anim_loop->set_icon(get_editor_theme_icon(SNAME("Loop"))); - play->set_icon(get_editor_theme_icon(SNAME("PlayStart"))); - play_from->set_icon(get_editor_theme_icon(SNAME("Play"))); - play_bw->set_icon(get_editor_theme_icon(SNAME("PlayStartBackwards"))); - play_bw_from->set_icon(get_editor_theme_icon(SNAME("PlayBackwards"))); - - load->set_icon(get_editor_theme_icon(SNAME("Load"))); - load_sheet->set_icon(get_editor_theme_icon(SNAME("SpriteSheet"))); - copy->set_icon(get_editor_theme_icon(SNAME("ActionCopy"))); - paste->set_icon(get_editor_theme_icon(SNAME("ActionPaste"))); - empty_before->set_icon(get_editor_theme_icon(SNAME("InsertBefore"))); - empty_after->set_icon(get_editor_theme_icon(SNAME("InsertAfter"))); - move_up->set_icon(get_editor_theme_icon(SNAME("MoveLeft"))); - move_down->set_icon(get_editor_theme_icon(SNAME("MoveRight"))); - delete_frame->set_icon(get_editor_theme_icon(SNAME("Remove"))); - zoom_out->set_icon(get_editor_theme_icon(SNAME("ZoomLess"))); - zoom_reset->set_icon(get_editor_theme_icon(SNAME("ZoomReset"))); - zoom_in->set_icon(get_editor_theme_icon(SNAME("ZoomMore"))); - add_anim->set_icon(get_editor_theme_icon(SNAME("New"))); - duplicate_anim->set_icon(get_editor_theme_icon(SNAME("Duplicate"))); - delete_anim->set_icon(get_editor_theme_icon(SNAME("Remove"))); + autoplay->set_button_icon(get_editor_theme_icon(SNAME("AutoPlay"))); + anim_loop->set_button_icon(get_editor_theme_icon(SNAME("Loop"))); + play->set_button_icon(get_editor_theme_icon(SNAME("PlayStart"))); + play_from->set_button_icon(get_editor_theme_icon(SNAME("Play"))); + play_bw->set_button_icon(get_editor_theme_icon(SNAME("PlayStartBackwards"))); + play_bw_from->set_button_icon(get_editor_theme_icon(SNAME("PlayBackwards"))); + + load->set_button_icon(get_editor_theme_icon(SNAME("Load"))); + load_sheet->set_button_icon(get_editor_theme_icon(SNAME("SpriteSheet"))); + copy->set_button_icon(get_editor_theme_icon(SNAME("ActionCopy"))); + paste->set_button_icon(get_editor_theme_icon(SNAME("ActionPaste"))); + empty_before->set_button_icon(get_editor_theme_icon(SNAME("InsertBefore"))); + empty_after->set_button_icon(get_editor_theme_icon(SNAME("InsertAfter"))); + move_up->set_button_icon(get_editor_theme_icon(SNAME("MoveLeft"))); + move_down->set_button_icon(get_editor_theme_icon(SNAME("MoveRight"))); + delete_frame->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); + zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess"))); + zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset"))); + zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore"))); + add_anim->set_button_icon(get_editor_theme_icon(SNAME("New"))); + duplicate_anim->set_button_icon(get_editor_theme_icon(SNAME("Duplicate"))); + delete_anim->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); anim_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - split_sheet_zoom_out->set_icon(get_editor_theme_icon(SNAME("ZoomLess"))); - split_sheet_zoom_reset->set_icon(get_editor_theme_icon(SNAME("ZoomReset"))); - split_sheet_zoom_in->set_icon(get_editor_theme_icon(SNAME("ZoomMore"))); + split_sheet_zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess"))); + split_sheet_zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset"))); + split_sheet_zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore"))); split_sheet_scroll->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); _update_show_settings(); @@ -1740,9 +1740,9 @@ void SpriteFramesEditor::_update_stop_icon() { is_playing = animated_sprite->call("is_playing"); } if (is_playing) { - stop->set_icon(pause_icon); + stop->set_button_icon(pause_icon); } else { - stop->set_icon(stop_icon); + stop->set_button_icon(stop_icon); } } diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp index 0b53c10fab..2d71c617de 100644 --- a/editor/plugins/style_box_editor_plugin.cpp +++ b/editor/plugins/style_box_editor_plugin.cpp @@ -58,7 +58,7 @@ void StyleBoxPreview::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { set_texture(get_editor_theme_icon(SNAME("Checkerboard"))); - grid_preview->set_icon(get_editor_theme_icon(SNAME("StyleBoxGrid"))); + grid_preview->set_button_icon(get_editor_theme_icon(SNAME("StyleBoxGrid"))); } break; case NOTIFICATION_DRAW: { _redraw(); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index a812633480..bd653e4eed 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -845,9 +845,9 @@ void TextureRegionEditor::_notification(int p_what) { texture_preview->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("TextureRegionPreviewBG"), EditorStringName(EditorStyles))); texture_overlay->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("TextureRegionPreviewFG"), EditorStringName(EditorStyles))); - zoom_out->set_icon(get_editor_theme_icon(SNAME("ZoomLess"))); - zoom_reset->set_icon(get_editor_theme_icon(SNAME("ZoomReset"))); - zoom_in->set_icon(get_editor_theme_icon(SNAME("ZoomMore"))); + zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess"))); + zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset"))); + zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -1270,7 +1270,7 @@ bool EditorInspectorPluginTextureRegion::parse_property(Object *p_object, const if ((p_type == Variant::RECT2 || p_type == Variant::RECT2I)) { if (((Object::cast_to<Sprite2D>(p_object) || Object::cast_to<Sprite3D>(p_object) || Object::cast_to<NinePatchRect>(p_object) || Object::cast_to<StyleBoxTexture>(p_object)) && p_path == "region_rect") || (Object::cast_to<AtlasTexture>(p_object) && p_path == "region")) { Button *button = EditorInspector::create_inspector_action_button(TTR("Edit Region")); - button->set_icon(texture_region_editor->get_editor_theme_icon(SNAME("RegionEdit"))); + button->set_button_icon(texture_region_editor->get_editor_theme_icon(SNAME("RegionEdit"))); button->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorPluginTextureRegion::_region_edit).bind(p_object)); add_property_editor(p_path, button, true); } diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index cc488ff340..de75ed8c12 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -861,43 +861,43 @@ void ThemeItemImportTree::_notification(int p_what) { import_items_filter->set_right_icon(get_editor_theme_icon(SNAME("Search"))); // Bottom panel buttons. - import_collapse_types_button->set_icon(get_editor_theme_icon(SNAME("CollapseTree"))); - import_expand_types_button->set_icon(get_editor_theme_icon(SNAME("ExpandTree"))); + import_collapse_types_button->set_button_icon(get_editor_theme_icon(SNAME("CollapseTree"))); + import_expand_types_button->set_button_icon(get_editor_theme_icon(SNAME("ExpandTree"))); - import_select_all_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); - import_select_full_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); - import_deselect_all_button->set_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); + import_select_all_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); + import_select_full_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); + import_deselect_all_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); // Side panel buttons. select_colors_icon->set_texture(get_editor_theme_icon(SNAME("Color"))); - deselect_all_colors_button->set_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); - select_all_colors_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); - select_full_colors_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); + deselect_all_colors_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); + select_all_colors_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); + select_full_colors_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); select_constants_icon->set_texture(get_editor_theme_icon(SNAME("MemberConstant"))); - deselect_all_constants_button->set_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); - select_all_constants_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); - select_full_constants_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); + deselect_all_constants_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); + select_all_constants_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); + select_full_constants_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); select_fonts_icon->set_texture(get_editor_theme_icon(SNAME("FontItem"))); - deselect_all_fonts_button->set_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); - select_all_fonts_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); - select_full_fonts_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); + deselect_all_fonts_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); + select_all_fonts_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); + select_full_fonts_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); select_font_sizes_icon->set_texture(get_editor_theme_icon(SNAME("FontSize"))); - deselect_all_font_sizes_button->set_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); - select_all_font_sizes_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); - select_full_font_sizes_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); + deselect_all_font_sizes_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); + select_all_font_sizes_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); + select_full_font_sizes_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); select_icons_icon->set_texture(get_editor_theme_icon(SNAME("ImageTexture"))); - deselect_all_icons_button->set_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); - select_all_icons_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); - select_full_icons_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); + deselect_all_icons_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); + select_all_icons_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); + select_full_icons_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); select_styleboxes_icon->set_texture(get_editor_theme_icon(SNAME("StyleBoxFlat"))); - deselect_all_styleboxes_button->set_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); - select_all_styleboxes_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); - select_full_styleboxes_button->set_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); + deselect_all_styleboxes_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeDeselectAll"))); + select_all_styleboxes_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectAll"))); + select_full_styleboxes_button->set_button_icon(get_editor_theme_icon(SNAME("ThemeSelectFull"))); } break; } } @@ -1877,20 +1877,20 @@ void ThemeItemEditorDialog::_notification(int p_what) { [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { - edit_items_add_color->set_icon(get_editor_theme_icon(SNAME("Color"))); - edit_items_add_constant->set_icon(get_editor_theme_icon(SNAME("MemberConstant"))); - edit_items_add_font->set_icon(get_editor_theme_icon(SNAME("FontItem"))); - edit_items_add_font_size->set_icon(get_editor_theme_icon(SNAME("FontSize"))); - edit_items_add_icon->set_icon(get_editor_theme_icon(SNAME("ImageTexture"))); - edit_items_add_stylebox->set_icon(get_editor_theme_icon(SNAME("StyleBoxFlat"))); + edit_items_add_color->set_button_icon(get_editor_theme_icon(SNAME("Color"))); + edit_items_add_constant->set_button_icon(get_editor_theme_icon(SNAME("MemberConstant"))); + edit_items_add_font->set_button_icon(get_editor_theme_icon(SNAME("FontItem"))); + edit_items_add_font_size->set_button_icon(get_editor_theme_icon(SNAME("FontSize"))); + edit_items_add_icon->set_button_icon(get_editor_theme_icon(SNAME("ImageTexture"))); + edit_items_add_stylebox->set_button_icon(get_editor_theme_icon(SNAME("StyleBoxFlat"))); - edit_items_remove_class->set_icon(get_editor_theme_icon(SNAME("Control"))); - edit_items_remove_custom->set_icon(get_editor_theme_icon(SNAME("ThemeRemoveCustomItems"))); - edit_items_remove_all->set_icon(get_editor_theme_icon(SNAME("ThemeRemoveAllItems"))); + edit_items_remove_class->set_button_icon(get_editor_theme_icon(SNAME("Control"))); + edit_items_remove_custom->set_button_icon(get_editor_theme_icon(SNAME("ThemeRemoveCustomItems"))); + edit_items_remove_all->set_button_icon(get_editor_theme_icon(SNAME("ThemeRemoveAllItems"))); - edit_add_type_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + edit_add_type_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); - import_another_theme_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); + import_another_theme_button->set_button_icon(get_editor_theme_icon(SNAME("Folder"))); } break; } } @@ -2481,21 +2481,21 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_name_edit->hide(); Button *item_rename_button = memnew(Button); - item_rename_button->set_icon(get_editor_theme_icon(SNAME("Edit"))); + item_rename_button->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); item_rename_button->set_tooltip_text(TTR("Rename Item")); item_rename_button->set_flat(true); item_name_container->add_child(item_rename_button); item_rename_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeTypeEditor::_item_rename_cbk).bind(p_data_type, p_item_name, item_name_container)); Button *item_remove_button = memnew(Button); - item_remove_button->set_icon(get_editor_theme_icon(SNAME("Remove"))); + item_remove_button->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); item_remove_button->set_tooltip_text(TTR("Remove Item")); item_remove_button->set_flat(true); item_name_container->add_child(item_remove_button); item_remove_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeTypeEditor::_item_remove_cbk).bind(p_data_type, p_item_name)); Button *item_rename_confirm_button = memnew(Button); - item_rename_confirm_button->set_icon(get_editor_theme_icon(SNAME("ImportCheck"))); + item_rename_confirm_button->set_button_icon(get_editor_theme_icon(SNAME("ImportCheck"))); item_rename_confirm_button->set_tooltip_text(TTR("Confirm Item Rename")); item_rename_confirm_button->set_flat(true); item_name_container->add_child(item_rename_confirm_button); @@ -2503,7 +2503,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_rename_confirm_button->hide(); Button *item_rename_cancel_button = memnew(Button); - item_rename_cancel_button->set_icon(get_editor_theme_icon(SNAME("ImportFail"))); + item_rename_cancel_button->set_button_icon(get_editor_theme_icon(SNAME("ImportFail"))); item_rename_cancel_button->set_tooltip_text(TTR("Cancel Item Rename")); item_rename_cancel_button->set_flat(true); item_name_container->add_child(item_rename_cancel_button); @@ -2513,7 +2513,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_name->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); Button *item_override_button = memnew(Button); - item_override_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + item_override_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); item_override_button->set_tooltip_text(TTR("Override Item")); item_override_button->set_flat(true); item_name_container->add_child(item_override_button); @@ -2722,7 +2722,7 @@ void ThemeTypeEditor::_update_type_items() { pin_leader_button->set_flat(true); pin_leader_button->set_toggle_mode(true); pin_leader_button->set_pressed(true); - pin_leader_button->set_icon(get_editor_theme_icon(SNAME("Pin"))); + pin_leader_button->set_button_icon(get_editor_theme_icon(SNAME("Pin"))); pin_leader_button->set_tooltip_text(TTR("Unpin this StyleBox as a main style.")); item_control->add_child(pin_leader_button); pin_leader_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeTypeEditor::_on_unpin_leader_button_pressed)); @@ -2765,7 +2765,7 @@ void ThemeTypeEditor::_update_type_items() { Button *pin_leader_button = memnew(Button); pin_leader_button->set_flat(true); pin_leader_button->set_toggle_mode(true); - pin_leader_button->set_icon(get_editor_theme_icon(SNAME("Pin"))); + pin_leader_button->set_button_icon(get_editor_theme_icon(SNAME("Pin"))); pin_leader_button->set_tooltip_text(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type.")); item_control->add_child(pin_leader_button); pin_leader_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed).bind(item_editor, E.key)); @@ -3371,7 +3371,7 @@ void ThemeTypeEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - add_type_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_type_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); data_type_tabs->set_tab_icon(0, get_editor_theme_icon(SNAME("Color"))); data_type_tabs->set_tab_icon(1, get_editor_theme_icon(SNAME("MemberConstant"))); @@ -3381,7 +3381,7 @@ void ThemeTypeEditor::_notification(int p_what) { data_type_tabs->set_tab_icon(5, get_editor_theme_icon(SNAME("StyleBoxFlat"))); data_type_tabs->set_tab_icon(6, get_editor_theme_icon(SNAME("Tools"))); - type_variation_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + type_variation_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } break; } } @@ -3695,7 +3695,7 @@ void ThemeEditor::_notification(int p_what) { preview_tabs->add_theme_style_override("tab_unselected", get_theme_stylebox(SNAME("ThemeEditorPreviewBG"), EditorStringName(EditorStyles))); preview_tabs_content->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("TabContainerOdd"))); - add_preview_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + add_preview_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } break; } } diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp index 2426cec521..ea5e8a8ad7 100644 --- a/editor/plugins/theme_editor_preview.cpp +++ b/editor/plugins/theme_editor_preview.cpp @@ -211,7 +211,7 @@ void ThemeEditorPreview::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - picker_button->set_icon(get_editor_theme_icon(SNAME("ColorPick"))); + picker_button->set_button_icon(get_editor_theme_icon(SNAME("ColorPick"))); theme_cache.preview_picker_overlay = get_theme_stylebox(SNAME("preview_picker_overlay"), SNAME("ThemeEditor")); theme_cache.preview_picker_overlay_color = get_theme_color(SNAME("preview_picker_overlay_color"), SNAME("ThemeEditor")); @@ -489,7 +489,7 @@ void SceneThemeEditorPreview::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - reload_scene_button->set_icon(get_editor_theme_icon(SNAME("Reload"))); + reload_scene_button->set_button_icon(get_editor_theme_icon(SNAME("Reload"))); } break; } } diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index b806d1e042..bafacf8e36 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -496,13 +496,13 @@ void TileAtlasView::set_atlas_source(TileSet *p_tile_set, TileSetAtlasSource *p_ float TileAtlasView::get_zoom() const { return zoom_widget->get_zoom(); -}; +} void TileAtlasView::set_transform(float p_zoom, Vector2i p_panning) { zoom_widget->set_zoom(p_zoom); panning = p_panning; _update_zoom_and_panning(); -}; +} void TileAtlasView::set_padding(Side p_side, int p_padding) { ERR_FAIL_COND(p_padding < 0); @@ -618,7 +618,7 @@ void TileAtlasView::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - button_center_view->set_icon(theme_cache.center_view_icon); + button_center_view->set_button_icon(theme_cache.center_view_icon); } break; } } diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h index 8fcf942056..025df4fda0 100644 --- a/editor/plugins/tiles/tile_atlas_view.h +++ b/editor/plugins/tiles/tile_atlas_view.h @@ -135,8 +135,8 @@ public: void set_padding(Side p_side, int p_padding); // Left side. - void set_texture_grid_visible(bool p_visible) { base_tiles_texture_grid->set_visible(p_visible); }; - void set_tile_shape_grid_visible(bool p_visible) { base_tiles_shape_grid->set_visible(p_visible); }; + void set_texture_grid_visible(bool p_visible) { base_tiles_texture_grid->set_visible(p_visible); } + void set_tile_shape_grid_visible(bool p_visible) { base_tiles_shape_grid->set_visible(p_visible); } Vector2i get_atlas_tile_coords_at_pos(const Vector2 p_pos, bool p_clamp = false) const; @@ -148,7 +148,7 @@ public: } p_control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); p_control->set_mouse_filter(Control::MOUSE_FILTER_PASS); - }; + } // Right side. Vector3i get_alternative_tile_at_pos(const Vector2 p_pos) const; @@ -162,7 +162,7 @@ public: } p_control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); p_control->set_mouse_filter(Control::MOUSE_FILTER_PASS); - }; + } // Redraw everything. void queue_redraw(); diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index c6921699a4..bf53a9dfba 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -722,7 +722,7 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) void GenericTilePolygonEditor::_set_snap_option(int p_index) { current_snap_option = p_index; - button_pixel_snap->set_icon(button_pixel_snap->get_popup()->get_item_icon(p_index)); + button_pixel_snap->set_button_icon(button_pixel_snap->get_popup()->get_item_icon(p_index)); snap_subdivision->set_visible(p_index == SNAP_GRID); if (initializing) { @@ -880,16 +880,16 @@ void GenericTilePolygonEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - button_expand->set_icon(get_editor_theme_icon(SNAME("DistractionFree"))); - button_create->set_icon(get_editor_theme_icon(SNAME("CurveCreate"))); - button_edit->set_icon(get_editor_theme_icon(SNAME("CurveEdit"))); - button_delete->set_icon(get_editor_theme_icon(SNAME("CurveDelete"))); - button_center_view->set_icon(get_editor_theme_icon(SNAME("CenterView"))); - button_advanced_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + button_expand->set_button_icon(get_editor_theme_icon(SNAME("DistractionFree"))); + button_create->set_button_icon(get_editor_theme_icon(SNAME("CurveCreate"))); + button_edit->set_button_icon(get_editor_theme_icon(SNAME("CurveEdit"))); + button_delete->set_button_icon(get_editor_theme_icon(SNAME("CurveDelete"))); + button_center_view->set_button_icon(get_editor_theme_icon(SNAME("CenterView"))); + button_advanced_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); button_pixel_snap->get_popup()->set_item_icon(0, get_editor_theme_icon(SNAME("SnapDisable"))); button_pixel_snap->get_popup()->set_item_icon(1, get_editor_theme_icon(SNAME("Snap"))); button_pixel_snap->get_popup()->set_item_icon(2, get_editor_theme_icon(SNAME("SnapGrid"))); - button_pixel_snap->set_icon(button_pixel_snap->get_popup()->get_item_icon(current_snap_option)); + button_pixel_snap->set_button_icon(button_pixel_snap->get_popup()->get_item_icon(current_snap_option)); PopupMenu *p = button_advanced_menu->get_popup(); p->set_item_icon(p->get_item_index(ROTATE_RIGHT), get_editor_theme_icon(SNAME("RotateRight"))); @@ -1100,11 +1100,10 @@ void TileDataDefaultEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas_ } p_canvas_item->draw_set_transform_matrix(Transform2D()); } -}; +} void TileDataDefaultEditor::forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) { - -}; +} void TileDataDefaultEditor::forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; @@ -1362,7 +1361,7 @@ void TileDataDefaultEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - picker_button->set_icon(get_editor_theme_icon(SNAME("ColorPick"))); + picker_button->set_button_icon(get_editor_theme_icon(SNAME("ColorPick"))); tile_bool_checked = get_editor_theme_icon(SNAME("TileChecked")); tile_bool_unchecked = get_editor_theme_icon(SNAME("TileUnchecked")); } break; @@ -2868,7 +2867,7 @@ void TileDataTerrainsEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - picker_button->set_icon(get_editor_theme_icon(SNAME("ColorPick"))); + picker_button->set_button_icon(get_editor_theme_icon(SNAME("ColorPick"))); } break; } } diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h index 1426bb4c2f..312eb724ed 100644 --- a/editor/plugins/tiles/tile_data_editors.h +++ b/editor/plugins/tiles/tile_data_editors.h @@ -62,7 +62,7 @@ public: void set_tile_set(Ref<TileSet> p_tile_set); // Input to handle painting. - virtual Control *get_toolbar() { return nullptr; }; + virtual Control *get_toolbar() { return nullptr; } virtual void forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) {} virtual void forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) {} virtual void forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event) {} @@ -238,7 +238,7 @@ protected: virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, const Variant &p_new_value); public: - virtual Control *get_toolbar() override { return toolbar; }; + virtual Control *get_toolbar() override { return toolbar; } virtual void forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override; virtual void forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override; virtual void forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event) override; @@ -375,7 +375,7 @@ protected: void _notification(int p_what); public: - virtual Control *get_toolbar() override { return toolbar; }; + virtual Control *get_toolbar() override { return toolbar; } virtual void forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override; virtual void forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override; virtual void forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event) override; diff --git a/editor/plugins/tiles/tile_map_layer_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp index dcfd92f6f9..16d4ee6f68 100644 --- a/editor/plugins/tiles/tile_map_layer_editor.cpp +++ b/editor/plugins/tiles/tile_map_layer_editor.cpp @@ -503,21 +503,21 @@ void TileMapLayerEditorTilesPlugin::_scenes_list_lmb_empty_clicked(const Vector2 } void TileMapLayerEditorTilesPlugin::_update_theme() { - source_sort_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Sort"))); - select_tool_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("ToolSelect"))); - paint_tool_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Edit"))); - line_tool_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Line"))); - rect_tool_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Rectangle"))); - bucket_tool_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Bucket"))); - - picker_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("ColorPick"))); - erase_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Eraser"))); - random_tile_toggle->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("RandomNumberGenerator"))); - - transform_button_rotate_left->set_icon(tiles_bottom_panel->get_editor_theme_icon("RotateLeft")); - transform_button_rotate_right->set_icon(tiles_bottom_panel->get_editor_theme_icon("RotateRight")); - transform_button_flip_h->set_icon(tiles_bottom_panel->get_editor_theme_icon("MirrorX")); - transform_button_flip_v->set_icon(tiles_bottom_panel->get_editor_theme_icon("MirrorY")); + source_sort_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Sort"))); + select_tool_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("ToolSelect"))); + paint_tool_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Edit"))); + line_tool_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Line"))); + rect_tool_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Rectangle"))); + bucket_tool_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Bucket"))); + + picker_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("ColorPick"))); + erase_button->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Eraser"))); + random_tile_toggle->set_button_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("RandomNumberGenerator"))); + + transform_button_rotate_left->set_button_icon(tiles_bottom_panel->get_editor_theme_icon("RotateLeft")); + transform_button_rotate_right->set_button_icon(tiles_bottom_panel->get_editor_theme_icon("RotateRight")); + transform_button_flip_h->set_button_icon(tiles_bottom_panel->get_editor_theme_icon("MirrorX")); + transform_button_flip_v->set_button_icon(tiles_bottom_panel->get_editor_theme_icon("MirrorY")); missing_atlas_texture_icon = tiles_bottom_panel->get_editor_theme_icon(SNAME("TileSet")); _update_tile_set_sources_list(); @@ -1550,6 +1550,7 @@ int TileMapLayerEditorTilesPlugin::_get_transformed_alternative(int p_alternativ case TRANSFORM_ROTATE_RIGHT: { // A matrix with every possible flip/transpose combination, sorted by what comes next when you rotate. const LocalVector<bool> rotation_matrix = { + // NOLINTBEGIN(modernize-use-bool-literals) 0, 0, 0, 0, 1, 1, 1, 1, 0, @@ -1558,6 +1559,7 @@ int TileMapLayerEditorTilesPlugin::_get_transformed_alternative(int p_alternativ 0, 0, 1, 0, 1, 0, 1, 1, 1 + // NOLINTEND(modernize-use-bool-literals) }; for (int i = 0; i < 8; i++) { @@ -3486,13 +3488,13 @@ void TileMapLayerEditorTerrainsPlugin::_update_tiles_list() { } void TileMapLayerEditorTerrainsPlugin::_update_theme() { - paint_tool_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Edit"))); - line_tool_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Line"))); - rect_tool_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Rectangle"))); - bucket_tool_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Bucket"))); + paint_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Edit"))); + line_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Line"))); + rect_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Rectangle"))); + bucket_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Bucket"))); - picker_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("ColorPick"))); - erase_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Eraser"))); + picker_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("ColorPick"))); + erase_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Eraser"))); _update_tiles_list(); } @@ -3689,12 +3691,12 @@ void TileMapLayerEditor::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { missing_tile_texture = get_editor_theme_icon(SNAME("StatusWarning")); warning_pattern_texture = get_editor_theme_icon(SNAME("WarningPattern")); - advanced_menu_button->set_icon(get_editor_theme_icon(SNAME("Tools"))); - select_previous_layer->set_icon(get_editor_theme_icon(SNAME("MoveUp"))); - select_next_layer->set_icon(get_editor_theme_icon(SNAME("MoveDown"))); - select_all_layers->set_icon(get_editor_theme_icon(SNAME("FileList"))); - toggle_grid_button->set_icon(get_editor_theme_icon(SNAME("Grid"))); - toggle_highlight_selected_layer_button->set_icon(get_editor_theme_icon(SNAME("TileMapHighlightSelected"))); + advanced_menu_button->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); + select_previous_layer->set_button_icon(get_editor_theme_icon(SNAME("MoveUp"))); + select_next_layer->set_button_icon(get_editor_theme_icon(SNAME("MoveDown"))); + select_all_layers->set_button_icon(get_editor_theme_icon(SNAME("FileList"))); + toggle_grid_button->set_button_icon(get_editor_theme_icon(SNAME("Grid"))); + toggle_highlight_selected_layer_button->set_button_icon(get_editor_theme_icon(SNAME("TileMapHighlightSelected"))); } break; case NOTIFICATION_INTERNAL_PROCESS: { diff --git a/editor/plugins/tiles/tile_map_layer_editor.h b/editor/plugins/tiles/tile_map_layer_editor.h index 805af7b58e..bcba34299d 100644 --- a/editor/plugins/tiles/tile_map_layer_editor.h +++ b/editor/plugins/tiles/tile_map_layer_editor.h @@ -63,9 +63,9 @@ public: virtual Vector<TabData> get_tabs() const { return Vector<TabData>(); - }; + } - virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return false; }; + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return false; } virtual void forward_canvas_draw_over_viewport(Control *p_overlay) {} virtual void tile_set_changed() {} virtual void edit(ObjectID p_tile_map_layer_id) {} diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index b1417b2878..941d44c85e 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -996,7 +996,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() { // Create and position the button. Button *button = memnew(Button); button->set_flat(true); - button->set_icon(get_editor_theme_icon(SNAME("Add"))); + button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); button->add_theme_style_override(CoreStringName(normal), memnew(StyleBoxEmpty)); button->add_theme_style_override("hover", memnew(StyleBoxEmpty)); button->add_theme_style_override("focus", memnew(StyleBoxEmpty)); @@ -1699,7 +1699,7 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) { void TileSetAtlasSourceEditor::shortcut_input(const Ref<InputEvent> &p_event) { // Check for shortcuts. - if (ED_IS_SHORTCUT("tiles_editor/delete_tile", p_event)) { + if (ED_IS_SHORTCUT("tiles_editor/delete", p_event)) { if (tools_button_group->get_pressed_button() == tool_select_button && !selection.is_empty()) { _menu_option(TILE_DELETE); accept_event(); @@ -2441,12 +2441,12 @@ void TileSetAtlasSourceEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - tool_setup_atlas_source_button->set_icon(get_editor_theme_icon(SNAME("Tools"))); - tool_select_button->set_icon(get_editor_theme_icon(SNAME("ToolSelect"))); - tool_paint_button->set_icon(get_editor_theme_icon(SNAME("Paint"))); + tool_setup_atlas_source_button->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); + tool_select_button->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + tool_paint_button->set_button_icon(get_editor_theme_icon(SNAME("Paint"))); - tools_settings_erase_button->set_icon(get_editor_theme_icon(SNAME("Eraser"))); - tool_advanced_menu_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + tools_settings_erase_button->set_button_icon(get_editor_theme_icon(SNAME("Eraser"))); + tool_advanced_menu_button->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); outside_tiles_warning->set_texture(get_editor_theme_icon(SNAME("StatusWarning"))); resize_handle = get_editor_theme_icon(SNAME("EditorHandle")); @@ -2711,7 +2711,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_atlas_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); alternative_tile_popup_menu = memnew(PopupMenu); - alternative_tile_popup_menu->add_shortcut(ED_SHORTCUT("tiles_editor/delete_tile", TTR("Delete"), Key::KEY_DELETE), TILE_DELETE); + alternative_tile_popup_menu->add_shortcut(ED_GET_SHORTCUT("tiles_editor/delete"), TILE_DELETE); alternative_tile_popup_menu->connect(SceneStringName(id_pressed), callable_mp(this, &TileSetAtlasSourceEditor::_menu_option)); tile_atlas_view->add_child(alternative_tile_popup_menu); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index c1a8338f81..f8b65bd675 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -80,7 +80,7 @@ public: int get_id() const; void edit(Ref<TileSet> p_tile_set, Ref<TileSetAtlasSource> p_tile_set_atlas_source, int p_source_id); - Ref<TileSetAtlasSource> get_edited() { return tile_set_atlas_source; }; + Ref<TileSetAtlasSource> get_edited() { return tile_set_atlas_source; } }; // -- Proxy object for a tile, needed by the inspector -- @@ -91,7 +91,7 @@ public: TileSetAtlasSourceEditor *tiles_set_atlas_source_editor = nullptr; Ref<TileSetAtlasSource> tile_set_atlas_source; - RBSet<TileSelection> tiles = RBSet<TileSelection>(); + RBSet<TileSelection> tiles; protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -101,8 +101,8 @@ public: static void _bind_methods(); public: - Ref<TileSetAtlasSource> get_edited_tile_set_atlas_source() const { return tile_set_atlas_source; }; - RBSet<TileSelection> get_edited_tiles() const { return tiles; }; + Ref<TileSetAtlasSource> get_edited_tile_set_atlas_source() const { return tile_set_atlas_source; } + RBSet<TileSelection> get_edited_tiles() const { return tiles; } // Update the proxyed object. void edit(Ref<TileSetAtlasSource> p_tile_set_atlas_source, const RBSet<TileSelection> &p_tiles = RBSet<TileSelection>()); diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index 7e5336ce06..6f473d1b60 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -366,10 +366,10 @@ void TileSetEditor::_set_source_sort(int p_sort) { void TileSetEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - sources_delete_button->set_icon(get_editor_theme_icon(SNAME("Remove"))); - sources_add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); - source_sort_button->set_icon(get_editor_theme_icon(SNAME("Sort"))); - sources_advanced_menu_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + sources_delete_button->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); + sources_add_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + source_sort_button->set_button_icon(get_editor_theme_icon(SNAME("Sort"))); + sources_advanced_menu_button->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); missing_texture_texture = get_editor_theme_icon(SNAME("TileSet")); expanded_area->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), "Tree")); _update_sources_list(); diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index 305407efdb..e2b3c451b0 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -367,8 +367,8 @@ void TileSetScenesCollectionSourceEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - scene_tile_add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); - scene_tile_delete_button->set_icon(get_editor_theme_icon(SNAME("Remove"))); + scene_tile_add_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + scene_tile_delete_button->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); _update_scenes_list(); } break; diff --git a/editor/plugins/tool_button_editor_plugin.cpp b/editor/plugins/tool_button_editor_plugin.cpp index d9852c8694..d9a15d9a23 100644 --- a/editor/plugins/tool_button_editor_plugin.cpp +++ b/editor/plugins/tool_button_editor_plugin.cpp @@ -33,7 +33,7 @@ #include "scene/gui/button.h" void EditorInspectorToolButtonPlugin::_update_action_icon(Button *p_action_button, const String &p_action_icon) { - p_action_button->set_icon(p_action_button->get_editor_theme_icon(p_action_icon)); + p_action_button->set_button_icon(p_action_button->get_editor_theme_icon(p_action_icon)); } void EditorInspectorToolButtonPlugin::_call_action(const Variant &p_object, const StringName &p_property) { diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 4f0df1d5fc..815664c608 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -1081,7 +1081,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { set_up_ssh_public_key_input_hbc->add_child(set_up_ssh_public_key_file_dialog); Button *select_public_path_button = memnew(Button); - select_public_path_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_editor_theme_icon("Folder")); + select_public_path_button->set_button_icon(EditorNode::get_singleton()->get_gui_base()->get_editor_theme_icon("Folder")); select_public_path_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_popup_file_dialog).bind(set_up_ssh_public_key_file_dialog)); select_public_path_button->set_tooltip_text(TTR("Select SSH public key path")); set_up_ssh_public_key_input_hbc->add_child(select_public_path_button); @@ -1114,7 +1114,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { set_up_ssh_private_key_input_hbc->add_child(set_up_ssh_private_key_file_dialog); Button *select_private_path_button = memnew(Button); - select_private_path_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_editor_theme_icon("Folder")); + select_private_path_button->set_button_icon(EditorNode::get_singleton()->get_gui_base()->get_editor_theme_icon("Folder")); select_private_path_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_popup_file_dialog).bind(set_up_ssh_private_key_file_dialog)); select_private_path_button->set_tooltip_text(TTR("Select SSH private key path")); set_up_ssh_private_key_input_hbc->add_child(select_private_path_button); @@ -1159,7 +1159,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { refresh_button = memnew(Button); refresh_button->set_tooltip_text(TTR("Detect new changes")); refresh_button->set_theme_type_variation("FlatButton"); - refresh_button->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); + refresh_button->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); refresh_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_refresh_stage_area)); refresh_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_refresh_commit_list)); refresh_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_refresh_branch_list)); @@ -1179,14 +1179,14 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { discard_all_button = memnew(Button); discard_all_button->set_tooltip_text(TTR("Discard all changes")); - discard_all_button->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Close"), EditorStringName(EditorIcons))); + discard_all_button->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Close"), EditorStringName(EditorIcons))); discard_all_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_confirm_discard_all)); discard_all_button->set_theme_type_variation("FlatButton"); unstage_title->add_child(discard_all_button); stage_all_button = memnew(Button); stage_all_button->set_theme_type_variation("FlatButton"); - stage_all_button->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveDown"), EditorStringName(EditorIcons))); + stage_all_button->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveDown"), EditorStringName(EditorIcons))); stage_all_button->set_tooltip_text(TTR("Stage all changes")); unstage_title->add_child(stage_all_button); @@ -1216,7 +1216,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { unstage_all_button = memnew(Button); unstage_all_button->set_theme_type_variation("FlatButton"); - unstage_all_button->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveUp"), EditorStringName(EditorIcons))); + unstage_all_button->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveUp"), EditorStringName(EditorIcons))); unstage_all_button->set_tooltip_text(TTR("Unstage all changes")); stage_title->add_child(unstage_all_button); @@ -1411,26 +1411,26 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { fetch_button = memnew(Button); fetch_button->set_theme_type_variation("FlatButton"); fetch_button->set_tooltip_text(TTR("Fetch")); - fetch_button->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); + fetch_button->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); fetch_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_fetch)); menu_bar->add_child(fetch_button); pull_button = memnew(Button); pull_button->set_theme_type_variation("FlatButton"); pull_button->set_tooltip_text(TTR("Pull")); - pull_button->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveDown"), EditorStringName(EditorIcons))); + pull_button->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveDown"), EditorStringName(EditorIcons))); pull_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_pull)); menu_bar->add_child(pull_button); push_button = memnew(Button); push_button->set_theme_type_variation("FlatButton"); push_button->set_tooltip_text(TTR("Push")); - push_button->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveUp"), EditorStringName(EditorIcons))); + push_button->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("MoveUp"), EditorStringName(EditorIcons))); push_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_push)); menu_bar->add_child(push_button); extra_options = memnew(MenuButton); - extra_options->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons))); + extra_options->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons))); extra_options->get_popup()->connect(SNAME("about_to_popup"), callable_mp(this, &VersionControlEditorPlugin::_update_extra_options)); extra_options->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &VersionControlEditorPlugin::_extra_option_selected)); menu_bar->add_child(extra_options); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index ede8351e41..31e158bba7 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -258,7 +258,7 @@ void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p vbox->add_child(offset); VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview); - port_preview->setup(visual_shader, editor->preview_material, visual_shader->get_shader_type(), p_node_id, p_port_id, p_is_valid); + port_preview->setup(visual_shader, editor->preview_material, visual_shader->get_shader_type(), links[p_node_id].output_ports[p_port_id].type == VisualShaderNode::PORT_TYPE_VECTOR_4D, p_node_id, p_port_id, p_is_valid); port_preview->set_h_size_flags(Control::SIZE_SHRINK_CENTER); vbox->add_child(port_preview); link.preview_visible = true; @@ -554,8 +554,8 @@ void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, links.insert(p_id, { p_type, p_visual_node, p_graph_element, p_visual_node->get_output_port_for_preview() != -1, -1, HashMap<int, InputPort>(), HashMap<int, Port>(), nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } }); } -void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { - links[p_node_id].output_ports.insert(p_port, { p_button }); +void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, VisualShaderNode::PortType p_port_type, TextureButton *p_button) { + links[p_node_id].output_ports.insert(p_port, { p_port_type, p_button }); } void VisualShaderGraphPlugin::register_parameter_name(int p_node_id, LineEdit *p_parameter_name) { @@ -1138,7 +1138,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool name_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, j, false), CONNECT_DEFERRED); Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left); remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_input_port).bind(p_id, j), CONNECT_DEFERRED); hb->add_child(remove_btn); @@ -1166,7 +1166,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool if (valid_right) { if (is_group) { Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left); remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_output_port).bind(p_id, i), CONNECT_DEFERRED); hb->add_child(remove_btn); @@ -1220,7 +1220,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool preview->set_texture_pressed(editor->get_editor_theme_icon(SNAME("GuiVisibilityVisible"))); preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - register_output_port(p_id, j, preview); + register_output_port(p_id, j, port_right, preview); preview->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_preview_select_port).bind(p_id, j), CONNECT_DEFERRED); hb->add_child(preview); @@ -1472,7 +1472,7 @@ void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_ if (visual_shader.is_valid() && visual_shader->get_shader_type() == p_type) { graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); - for (const List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { + for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { connections.erase(E); break; @@ -1985,6 +1985,67 @@ bool VisualShaderEditor::_update_preview_parameter_tree() { return found; } +void VisualShaderEditor::_preview_tools_menu_option(int p_idx) { + ShaderMaterial *src_mat = nullptr; + + if (p_idx == COPY_PARAMS_FROM_MATERIAL || p_idx == PASTE_PARAMS_TO_MATERIAL) { + for (int i = EditorNode::get_singleton()->get_editor_selection_history()->get_path_size() - 1; i >= 0; i--) { + Object *object = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_selection_history()->get_path_object(i)); + ShaderMaterial *src_mat2; + if (!object) { + continue; + } + if (object->has_method("get_material_override")) { // Trying to get material from MeshInstance. + src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material_override")); + } else if (object->has_method("get_material")) { // From CanvasItem/Node2D. + src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material")); + } else { + src_mat2 = Object::cast_to<ShaderMaterial>(object); + } + + if (src_mat2 && src_mat2->get_shader().is_valid() && src_mat2->get_shader() == visual_shader) { + src_mat = src_mat2; + break; + } + } + } + + switch (p_idx) { + case COPY_PARAMS_FROM_MATERIAL: + if (src_mat) { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Copy Preview Shader Parameters From Material")); + + List<PropertyInfo> params; + preview_material->get_shader()->get_shader_uniform_list(¶ms); + for (const PropertyInfo &E : params) { + undo_redo->add_do_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, src_mat->get_shader_parameter(E.name)); + undo_redo->add_undo_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, preview_material->get_shader_parameter(E.name)); + } + + undo_redo->commit_action(); + } + break; + case PASTE_PARAMS_TO_MATERIAL: + if (src_mat) { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Paste Preview Shader Parameters To Material")); + + List<PropertyInfo> params; + preview_material->get_shader()->get_shader_uniform_list(¶ms); + for (const PropertyInfo &E : params) { + undo_redo->add_do_method(src_mat, "set_shader_parameter", E.name, preview_material->get_shader_parameter(E.name)); + undo_redo->add_undo_method(src_mat, "set_shader_parameter", E.name, src_mat->get_shader_parameter(E.name)); + } + + undo_redo->commit_action(); + } + break; + default: + break; + } +} + void VisualShaderEditor::_clear_preview_param() { selected_param_id = ""; current_prop = nullptr; @@ -2128,12 +2189,11 @@ void VisualShaderEditor::_update_nodes() { } } - Array keys = added.keys(); - keys.sort(); - - for (int i = 0; i < keys.size(); i++) { - const Variant &key = keys.get(i); + List<Variant> keys; + added.get_key_list(&keys); + keys.sort_custom<StringLikeVariantOrder>(); + for (const Variant &key : keys) { const Dictionary &value = (Dictionary)added[key]; add_custom_type(value["name"], value["type"], value["script"], value["description"], value["return_icon_type"], value["category"], value["highend"]); @@ -4065,6 +4125,7 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in int from = p_from.to_int(); int to = p_to.to_int(); + bool swap = last_to_node != -1 && Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL); if (!visual_shader->can_connect_nodes(type, from, p_from_index, to, p_to_index)) { return; @@ -4082,6 +4143,14 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); + + if (swap) { + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + } + break; } } @@ -4095,6 +4164,9 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, to); undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, to); undo_redo->commit_action(); + + last_to_node = -1; + last_to_port = -1; } void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) { @@ -4105,6 +4177,11 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from int from = p_from.to_int(); int to = p_to.to_int(); + last_to_node = to; + last_to_port = p_to_index; + + info_label->show(); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Nodes Disconnected")); undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); @@ -4116,6 +4193,10 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from undo_redo->commit_action(); } +void VisualShaderEditor::_connection_drag_ended() { + info_label->hide(); +} + void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) { from_node = p_from.to_int(); from_slot = p_from_slot; @@ -5020,8 +5101,11 @@ void VisualShaderEditor::_param_property_changed(const String &p_property, const void VisualShaderEditor::_update_current_param() { if (current_prop != nullptr) { String name = current_prop->get_meta("id"); - preview_material->set("shader_parameter/" + name, visual_shader->_get_preview_shader_parameter(name)); - + if (visual_shader->_has_preview_shader_parameter(name)) { + preview_material->set("shader_parameter/" + name, visual_shader->_get_preview_shader_parameter(name)); + } else { + preview_material->set("shader_parameter/" + name, Variant()); + } current_prop->update_property(); current_prop->update_editor_property_status(); current_prop->update_cache(); @@ -5107,8 +5191,8 @@ void VisualShaderEditor::_notification(int p_what) { param_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search"))); node_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search"))); - code_preview_button->set_icon(Control::get_editor_theme_icon(SNAME("Shader"))); - shader_preview_button->set_icon(Control::get_editor_theme_icon(SNAME("SubViewport"))); + code_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("Shader"))); + shader_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("SubViewport"))); { Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color"); @@ -5159,7 +5243,8 @@ void VisualShaderEditor::_notification(int p_what) { error_label->end_bulk_theme_override(); } - tools->set_icon(get_editor_theme_icon(SNAME("Tools"))); + tools->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); + preview_tools->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); if (is_visible_in_tree()) { _update_graph(); @@ -6306,6 +6391,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->connect(SceneStringName(gui_input), callable_mp(this, &VisualShaderEditor::_graph_gui_input)); graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty)); graph->connect("connection_from_empty", callable_mp(this, &VisualShaderEditor::_connection_from_empty)); + graph->connect("connection_drag_ended", callable_mp(this, &VisualShaderEditor::_connection_drag_ended)); graph->connect(SceneStringName(visibility_changed), callable_mp(this, &VisualShaderEditor::_visibility_changed)); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_INT); @@ -6366,6 +6452,13 @@ VisualShaderEditor::VisualShaderEditor() { graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER); + info_label = memnew(Label); + info_label->set_text(vformat(TTR("Hold %s Key To Swap Connections"), keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL))); + info_label->set_anchors_and_offsets_preset(Control::PRESET_BOTTOM_WIDE, PRESET_MODE_MINSIZE, 20); + info_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + info_label->hide(); + graph->get_top_layer()->add_child(info_label); + PanelContainer *toolbar_panel = static_cast<PanelContainer *>(graph->get_menu_hbox()->get_parent()); toolbar_panel->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE, PRESET_MODE_MINSIZE, 10); toolbar_panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); @@ -6556,11 +6649,21 @@ VisualShaderEditor::VisualShaderEditor() { VBoxContainer *params_vbox = memnew(VBoxContainer); preview_split->add_child(params_vbox); + HBoxContainer *filter_hbox = memnew(HBoxContainer); + params_vbox->add_child(filter_hbox); + param_filter = memnew(LineEdit); + filter_hbox->add_child(param_filter); param_filter->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_param_filter_changed)); param_filter->set_h_size_flags(SIZE_EXPAND_FILL); param_filter->set_placeholder(TTR("Filter Parameters")); - params_vbox->add_child(param_filter); + + preview_tools = memnew(MenuButton); + filter_hbox->add_child(preview_tools); + preview_tools->set_tooltip_text(TTR("Options")); + preview_tools->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_preview_tools_menu_option)); + preview_tools->get_popup()->add_item(TTR("Copy Parameters From Material"), COPY_PARAMS_FROM_MATERIAL); + preview_tools->get_popup()->add_item(TTR("Paste Parameters To Material"), PASTE_PARAMS_TO_MATERIAL); ScrollContainer *sc = memnew(ScrollContainer); sc->set_v_size_flags(SIZE_EXPAND_FILL); @@ -6776,8 +6879,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Grayscale", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), { VisualShaderNodeColorFunc::FUNC_GRAYSCALE }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("HSV2RGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeColorFunc::FUNC_HSV2RGB, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("LinearToSRGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from linear to sRGB color space."), { VisualShaderNodeColorFunc::FUNC_LINEAR_TO_SRGB }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("RGB2HSV", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeColorFunc::FUNC_RGB2HSV, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Sepia", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), { VisualShaderNodeColorFunc::FUNC_SEPIA }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("SRGBToLinear", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from sRGB to linear color space."), { VisualShaderNodeColorFunc::FUNC_SRGB_TO_LINEAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Burn", "Color/Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), { VisualShaderNodeColorOp::OP_BURN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Darken", "Color/Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), { VisualShaderNodeColorOp::OP_DARKEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); @@ -6923,7 +7028,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("NodePositionView", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("NodePositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("PointCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Tangent", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Vertex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view", "VIEW"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -6941,6 +7046,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("LightIsDirectional", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_is_directional", "LIGHT_IS_DIRECTIONAL"), { "light_is_directional" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Metallic", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "metallic", "METALLIC"), { "metallic" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Roughness", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness", "ROUGHNESS"), { "roughness" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenUV", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Specular", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular", "SPECULAR_LIGHT"), { "specular" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view", "VIEW"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); @@ -8032,7 +8138,15 @@ void VisualShaderNodePortPreview::_shader_changed() { set_material(mat); } -void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, int p_node, int p_port, bool p_is_valid) { +void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, bool p_has_transparency, int p_node, int p_port, bool p_is_valid) { + if (p_has_transparency) { + checkerboard = memnew(TextureRect); + checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE); + checkerboard->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); + checkerboard->set_draw_behind_parent(true); + add_child(checkerboard); + } + shader = p_shader; shader->connect_changed(callable_mp(this, &VisualShaderNodePortPreview::_shader_changed), CONNECT_DEFERRED); preview_mat = p_preview_material; @@ -8051,6 +8165,11 @@ Size2 VisualShaderNodePortPreview::get_minimum_size() const { void VisualShaderNodePortPreview::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + if (checkerboard != nullptr) { + checkerboard->set_texture(get_theme_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + } + } break; case NOTIFICATION_DRAW: { Vector<Vector2> points = { Vector2(), diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 3b2ad33304..6b7c07e5a7 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -107,6 +107,7 @@ private: }; struct Port { + VisualShaderNode::PortType type = VisualShaderNode::PORT_TYPE_SCALAR; TextureButton *preview_button = nullptr; }; @@ -141,7 +142,7 @@ public: void register_shader(VisualShader *p_visual_shader); void set_connections(const List<VisualShader::Connection> &p_connections); void register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphElement *p_graph_element); - void register_output_port(int p_id, int p_port, TextureButton *p_button); + void register_output_port(int p_id, int p_port, VisualShaderNode::PortType p_port_type, TextureButton *p_button); void register_parameter_name(int p_id, LineEdit *p_parameter_name); void register_default_input_button(int p_node_id, int p_port_id, Button *p_button); void register_expression_edit(int p_node_id, CodeEdit *p_expression_edit); @@ -220,6 +221,10 @@ class VisualShaderEditor : public ShaderEditor { Button *code_preview_button = nullptr; Button *shader_preview_button = nullptr; + int last_to_node = -1; + int last_to_port = -1; + Label *info_label = nullptr; + OptionButton *edit_type = nullptr; OptionButton *edit_type_standard = nullptr; OptionButton *edit_type_particles = nullptr; @@ -275,6 +280,7 @@ class VisualShaderEditor : public ShaderEditor { bool shader_preview_showed = true; LineEdit *param_filter = nullptr; + MenuButton *preview_tools = nullptr; String selected_param_id; Tree *parameters = nullptr; HashMap<String, PropertyInfo> parameter_props; @@ -317,6 +323,11 @@ class VisualShaderEditor : public ShaderEditor { COLLAPSE_ALL }; + enum PreviewToolsMenuOptions { + COPY_PARAMS_FROM_MATERIAL, + PASTE_PARAMS_TO_MATERIAL, + }; + #ifdef MINGW_ENABLED #undef DELETE #endif @@ -366,6 +377,7 @@ class VisualShaderEditor : public ShaderEditor { void _show_add_varying_dialog(); void _show_remove_varying_dialog(); + void _preview_tools_menu_option(int p_idx); void _clear_preview_param(); void _update_preview_parameter_list(); bool _update_preview_parameter_tree(); @@ -494,6 +506,7 @@ class VisualShaderEditor : public ShaderEditor { void _unlink_node_from_parent_frame(int p_node_id); + void _connection_drag_ended(); void _connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position); void _connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position); bool _check_node_drop_on_connection(const Vector2 &p_position, Ref<GraphEdit::Connection> *r_closest_connection, int *r_node_id = nullptr, int *r_to_port = nullptr); @@ -680,6 +693,7 @@ public: class VisualShaderNodePortPreview : public Control { GDCLASS(VisualShaderNodePortPreview, Control); + TextureRect *checkerboard = nullptr; Ref<VisualShader> shader; Ref<ShaderMaterial> preview_mat; VisualShader::Type type = VisualShader::Type::TYPE_MAX; @@ -692,7 +706,7 @@ protected: public: virtual Size2 get_minimum_size() const override; - void setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, int p_node, int p_port, bool p_is_valid); + void setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, bool p_has_transparency, int p_node, int p_port, bool p_is_valid); }; class VisualShaderConversionPlugin : public EditorResourceConversionPlugin { diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp index 3e835d5cb6..68fe013c08 100644 --- a/editor/plugins/voxel_gi_editor_plugin.cpp +++ b/editor/plugins/voxel_gi_editor_plugin.cpp @@ -185,7 +185,7 @@ VoxelGIEditorPlugin::VoxelGIEditorPlugin() { bake->set_theme_type_variation("FlatButton"); // TODO: Rework this as a dedicated toolbar control so we can hook into theme changes and update it // when the editor theme updates. - bake->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); + bake->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Bake"), EditorStringName(EditorIcons))); bake->set_text(TTR("Bake VoxelGI")); bake->connect(SceneStringName(pressed), callable_mp(this, &VoxelGIEditorPlugin::_bake)); bake_hb->add_child(bake); diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp index 76b6593f1d..3598a29fec 100644 --- a/editor/pot_generator.cpp +++ b/editor/pot_generator.cpp @@ -69,11 +69,16 @@ void POTGenerator::generate_pot(const String &p_file) { for (int i = 0; i < files.size(); i++) { Vector<String> msgids; Vector<Vector<String>> msgids_context_plural; + + Vector<String> msgids_comment; + Vector<String> msgids_context_plural_comment; + const String &file_path = files[i]; String file_extension = file_path.get_extension(); if (EditorTranslationParser::get_singleton()->can_parse(file_extension)) { EditorTranslationParser::get_singleton()->get_parser(file_extension)->parse_file(file_path, &msgids, &msgids_context_plural); + EditorTranslationParser::get_singleton()->get_parser(file_extension)->get_comments(&msgids_comment, &msgids_context_plural_comment); } else { ERR_PRINT("Unrecognized file extension " + file_extension + " in generate_pot()"); return; @@ -81,16 +86,18 @@ void POTGenerator::generate_pot(const String &p_file) { for (int j = 0; j < msgids_context_plural.size(); j++) { const Vector<String> &entry = msgids_context_plural[j]; - _add_new_msgid(entry[0], entry[1], entry[2], file_path); + const String &comment = (j < msgids_context_plural_comment.size()) ? msgids_context_plural_comment[j] : String(); + _add_new_msgid(entry[0], entry[1], entry[2], file_path, comment); } for (int j = 0; j < msgids.size(); j++) { - _add_new_msgid(msgids[j], "", "", file_path); + const String &comment = (j < msgids_comment.size()) ? msgids_comment[j] : String(); + _add_new_msgid(msgids[j], "", "", file_path, comment); } } if (GLOBAL_GET("internationalization/locale/translation_add_builtin_strings_to_pot")) { for (const Vector<String> &extractable_msgids : get_extractable_message_list()) { - _add_new_msgid(extractable_msgids[0], extractable_msgids[1], extractable_msgids[2], ""); + _add_new_msgid(extractable_msgids[0], extractable_msgids[1], extractable_msgids[2], "", ""); } } @@ -136,15 +143,25 @@ void POTGenerator::_write_to_pot(const String &p_file) { String context = v_msgid_data[i].ctx; String plural = v_msgid_data[i].plural; const HashSet<String> &locations = v_msgid_data[i].locations; + const HashSet<String> &comments = v_msgid_data[i].comments; // Put the blank line at the start, to avoid a double at the end when closing the file. file->store_line(""); + // Write comments. + bool is_first_comment = true; + for (const String &E : comments) { + if (is_first_comment) { + file->store_line("#. TRANSLATORS: " + E.replace("\n", "\n#. ")); + } else { + file->store_line("#. " + E.replace("\n", "\n#. ")); + } + is_first_comment = false; + } + // Write file locations. for (const String &E : locations) { - if (!E.is_empty()) { - file->store_line("#: " + E.trim_prefix("res://").replace("\n", "\\n")); - } + file->store_line("#: " + E.trim_prefix("res://").replace("\n", "\\n")); } // Write context. @@ -199,7 +216,7 @@ void POTGenerator::_write_msgid(Ref<FileAccess> r_file, const String &p_id, bool } } -void POTGenerator::_add_new_msgid(const String &p_msgid, const String &p_context, const String &p_plural, const String &p_location) { +void POTGenerator::_add_new_msgid(const String &p_msgid, const String &p_context, const String &p_plural, const String &p_location, const String &p_comment) { // Insert new location if msgid under same context exists already. if (all_translation_strings.has(p_msgid)) { Vector<MsgidData> &v_mdata = all_translation_strings[p_msgid]; @@ -208,18 +225,27 @@ void POTGenerator::_add_new_msgid(const String &p_msgid, const String &p_context if (!v_mdata[i].plural.is_empty() && !p_plural.is_empty() && v_mdata[i].plural != p_plural) { WARN_PRINT("Redefinition of plural message (msgid_plural), under the same message (msgid) and context (msgctxt)"); } - v_mdata.write[i].locations.insert(p_location); + if (!p_location.is_empty()) { + v_mdata.write[i].locations.insert(p_location); + } + if (!p_comment.is_empty()) { + v_mdata.write[i].comments.insert(p_comment); + } return; } } } - // Add a new entry of msgid, context, plural and location - context and plural might be empty if the inserted msgid doesn't associated - // context or plurals. + // Add a new entry. MsgidData mdata; mdata.ctx = p_context; mdata.plural = p_plural; - mdata.locations.insert(p_location); + if (!p_location.is_empty()) { + mdata.locations.insert(p_location); + } + if (!p_comment.is_empty()) { + mdata.comments.insert(p_comment); + } all_translation_strings[p_msgid].push_back(mdata); } diff --git a/editor/pot_generator.h b/editor/pot_generator.h index 8bcb2e5cac..54f4aa0652 100644 --- a/editor/pot_generator.h +++ b/editor/pot_generator.h @@ -44,13 +44,14 @@ class POTGenerator { String ctx; String plural; HashSet<String> locations; + HashSet<String> comments; }; // Store msgid as key and the additional data around the msgid - if it's under a context, has plurals and its file locations. HashMap<String, Vector<MsgidData>> all_translation_strings; void _write_to_pot(const String &p_file); void _write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural); - void _add_new_msgid(const String &p_msgid, const String &p_context, const String &p_plural, const String &p_location); + void _add_new_msgid(const String &p_msgid, const String &p_context, const String &p_plural, const String &p_location, const String &p_comment); #ifdef DEBUG_POT void _print_all_translation_strings(); diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index b295e5733e..edf3ff7296 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -716,8 +716,9 @@ Vector<String> ProjectConverter3To4::check_for_files() { directories_to_check.append(current_dir.path_join(file_name) + "/"); } else { bool proper_extension = false; - if (file_name.ends_with(".gd") || file_name.ends_with(".shader") || file_name.ends_with(".gdshader") || file_name.ends_with(".tscn") || file_name.ends_with(".tres") || file_name.ends_with(".godot") || file_name.ends_with(".cs") || file_name.ends_with(".csproj") || file_name.ends_with(".import")) + if (file_name.ends_with(".gd") || file_name.ends_with(".shader") || file_name.ends_with(".gdshader") || file_name.ends_with(".tscn") || file_name.ends_with(".tres") || file_name.ends_with(".godot") || file_name.ends_with(".cs") || file_name.ends_with(".csproj") || file_name.ends_with(".import")) { proper_extension = true; + } if (proper_extension) { collected_files.append(current_dir.path_join(file_name)); @@ -1270,7 +1271,7 @@ bool ProjectConverter3To4::test_single_array(const char *p_array[][2], bool p_ig } } return valid; -}; +} // Returns arguments from given function execution, this cannot be really done as regex. // `abc(d,e(f,g),h)` -> [d], [e(f,g)], [h] @@ -1321,8 +1322,9 @@ Vector<String> ProjectConverter3To4::parse_arguments(const String &line) { break; }; case '"': { - if (previous_character != '\\') + if (previous_character != '\\') { is_inside_string = !is_inside_string; + } } } previous_character = character; @@ -1469,7 +1471,7 @@ void ProjectConverter3To4::rename_colors(Vector<SourceLine> &source_lines, const } } } -}; +} // Convert hexadecimal colors from ARGB to RGBA void ProjectConverter3To4::convert_hexadecimal_colors(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { @@ -1566,7 +1568,7 @@ void ProjectConverter3To4::rename_classes(Vector<SourceLine> &source_lines, cons } } } -}; +} Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &lines, const RegExContainer ®_container) { Vector<String> found_renames; @@ -1618,7 +1620,7 @@ void ProjectConverter3To4::rename_gdscript_functions(Vector<SourceLine> &source_ process_gdscript_line(line, reg_container, builtin); } } -}; +} Vector<String> ProjectConverter3To4::check_for_rename_gdscript_functions(Vector<String> &lines, const RegExContainer ®_container, bool builtin) { int current_line = 1; @@ -1968,7 +1970,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- func c(var a, var b) -> func c(a, b) if (line.contains("func ") && line.contains("var ")) { int start = line.find("func "); - start = line.substr(start).find("(") + start; + start = line.substr(start).find_char('(') + start; int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); @@ -2118,12 +2120,12 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai } } // -- func _init(p_x:int).(p_x): -> func _init(p_x:int):\n\tsuper(p_x) Object # https://github.com/godotengine/godot/issues/70542 - if (line.contains(" _init(") && line.rfind(":") > 0) { + if (line.contains(" _init(") && line.rfind_char(':') > 0) { // func _init(p_arg1).(super4, super5, super6)->void: // ^--^indent ^super_start super_end^ int indent = line.count("\t", 0, line.find("func")); int super_start = line.find(".("); - int super_end = line.rfind(")"); + int super_end = line.rfind_char(')'); if (super_start > 0 && super_end > super_start) { line = line.substr(0, super_start) + line.substr(super_end + 1) + "\n" + String("\t").repeat(indent + 1) + "super" + line.substr(super_start + 1, super_end - super_start); } @@ -2438,7 +2440,7 @@ void ProjectConverter3To4::rename_csharp_functions(Vector<SourceLine> &source_li process_csharp_line(line, reg_container); } } -}; +} Vector<String> ProjectConverter3To4::check_for_rename_csharp_functions(Vector<String> &lines, const RegExContainer ®_container) { int current_line = 1; @@ -2847,7 +2849,7 @@ void ProjectConverter3To4::custom_rename(Vector<SourceLine> &source_lines, const line = reg.sub(line, to, true); } } -}; +} Vector<String> ProjectConverter3To4::check_for_custom_rename(Vector<String> &lines, const String &from, const String &to) { Vector<String> found_renames; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 30878a2488..eb5e8d2a72 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -34,8 +34,6 @@ #include "core/io/config_file.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" -#include "core/io/resource_saver.h" -#include "core/io/stream_peer_tls.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/version.h" @@ -51,12 +49,9 @@ #include "editor/project_manager/project_list.h" #include "editor/project_manager/project_tag.h" #include "editor/project_manager/quick_settings_dialog.h" -#include "editor/themes/editor_icons.h" #include "editor/themes/editor_scale.h" #include "editor/themes/editor_theme_manager.h" #include "main/main.h" -#include "scene/gui/check_box.h" -#include "scene/gui/color_rect.h" #include "scene/gui/flow_container.h" #include "scene/gui/line_edit.h" #include "scene/gui/margin_container.h" @@ -64,7 +59,6 @@ #include "scene/gui/panel_container.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/separator.h" -#include "scene/gui/texture_rect.h" #include "scene/main/window.h" #include "scene/theme/theme_db.h" #include "servers/display_server.h" @@ -224,7 +218,7 @@ void ProjectManager::_update_theme(bool p_skip_creation) { background_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("Background"), EditorStringName(EditorStyles))); main_view_container->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("TabContainer"))); - title_bar_logo->set_icon(get_editor_theme_icon(SNAME("TitleBarLogo"))); + title_bar_logo->set_button_icon(get_editor_theme_icon(SNAME("TitleBarLogo"))); _set_main_view_icon(MAIN_VIEW_PROJECTS, get_editor_theme_icon(SNAME("ProjectList"))); _set_main_view_icon(MAIN_VIEW_ASSETLIB, get_editor_theme_icon(SNAME("AssetLib"))); @@ -234,28 +228,28 @@ void ProjectManager::_update_theme(bool p_skip_creation) { loading_label->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("bold"), EditorStringName(EditorFonts))); project_list_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("project_list"), SNAME("ProjectManager"))); - empty_list_create_project->set_icon(get_editor_theme_icon(SNAME("Add"))); - empty_list_import_project->set_icon(get_editor_theme_icon(SNAME("Load"))); - empty_list_open_assetlib->set_icon(get_editor_theme_icon(SNAME("AssetLib"))); + empty_list_create_project->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + empty_list_import_project->set_button_icon(get_editor_theme_icon(SNAME("Load"))); + empty_list_open_assetlib->set_button_icon(get_editor_theme_icon(SNAME("AssetLib"))); empty_list_online_warning->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("italic"), EditorStringName(EditorFonts))); empty_list_online_warning->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("font_placeholder_color"), EditorStringName(Editor))); // Top bar. search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - quick_settings_button->set_icon(get_editor_theme_icon(SNAME("Tools"))); + quick_settings_button->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); // Sidebar. - create_btn->set_icon(get_editor_theme_icon(SNAME("Add"))); - import_btn->set_icon(get_editor_theme_icon(SNAME("Load"))); - scan_btn->set_icon(get_editor_theme_icon(SNAME("Search"))); - open_btn->set_icon(get_editor_theme_icon(SNAME("Edit"))); - run_btn->set_icon(get_editor_theme_icon(SNAME("Play"))); - rename_btn->set_icon(get_editor_theme_icon(SNAME("Rename"))); - manage_tags_btn->set_icon(get_editor_theme_icon("Script")); - erase_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); - erase_missing_btn->set_icon(get_editor_theme_icon(SNAME("Clear"))); - create_tag_btn->set_icon(get_editor_theme_icon("Add")); + create_btn->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + import_btn->set_button_icon(get_editor_theme_icon(SNAME("Load"))); + scan_btn->set_button_icon(get_editor_theme_icon(SNAME("Search"))); + open_btn->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + run_btn->set_button_icon(get_editor_theme_icon(SNAME("Play"))); + rename_btn->set_button_icon(get_editor_theme_icon(SNAME("Rename"))); + manage_tags_btn->set_button_icon(get_editor_theme_icon("Script")); + erase_btn->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); + erase_missing_btn->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); + create_tag_btn->set_button_icon(get_editor_theme_icon("Add")); tag_error->add_theme_color_override(SceneStringName(font_color), get_theme_color("error_color", EditorStringName(Editor))); tag_edit_error->add_theme_color_override(SceneStringName(font_color), get_theme_color("error_color", EditorStringName(Editor))); @@ -310,17 +304,17 @@ void ProjectManager::_set_main_view_icon(MainViewTab p_id, const Ref<Texture2D> Button *toggle_button = main_view_toggle_map[p_id]; - Ref<Texture2D> old_icon = toggle_button->get_icon(); + Ref<Texture2D> old_icon = toggle_button->get_button_icon(); if (old_icon.is_valid()) { old_icon->disconnect_changed(callable_mp((Control *)toggle_button, &Control::update_minimum_size)); } if (p_icon.is_valid()) { - toggle_button->set_icon(p_icon); + toggle_button->set_button_icon(p_icon); // Make sure the control is updated if the icon is reimported. p_icon->connect_changed(callable_mp((Control *)toggle_button, &Control::update_minimum_size)); } else { - toggle_button->set_icon(Ref<Texture2D>()); + toggle_button->set_button_icon(Ref<Texture2D>()); } } @@ -1300,15 +1294,10 @@ ProjectManager::ProjectManager() { filter_option->connect(SceneStringName(item_selected), callable_mp(this, &ProjectManager::_on_order_option_changed)); hb->add_child(filter_option); - Vector<String> sort_filter_titles; - sort_filter_titles.push_back(TTR("Last Edited")); - sort_filter_titles.push_back(TTR("Name")); - sort_filter_titles.push_back(TTR("Path")); - sort_filter_titles.push_back(TTR("Tags")); - - for (int i = 0; i < sort_filter_titles.size(); i++) { - filter_option->add_item(sort_filter_titles[i]); - } + filter_option->add_item(TTR("Last Edited")); + filter_option->add_item(TTR("Name")); + filter_option->add_item(TTR("Path")); + filter_option->add_item(TTR("Tags")); } // Project list and its sidebar. diff --git a/editor/project_manager/project_dialog.cpp b/editor/project_manager/project_dialog.cpp index 7aadb9ac3c..8750ae8714 100644 --- a/editor/project_manager/project_dialog.cpp +++ b/editor/project_manager/project_dialog.cpp @@ -825,9 +825,9 @@ void ProjectDialog::show_dialog(bool p_reset_name) { void ProjectDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - create_dir->set_icon(get_editor_theme_icon(SNAME("FolderCreate"))); - project_browse->set_icon(get_editor_theme_icon(SNAME("FolderBrowse"))); - install_browse->set_icon(get_editor_theme_icon(SNAME("FolderBrowse"))); + create_dir->set_button_icon(get_editor_theme_icon(SNAME("FolderCreate"))); + project_browse->set_button_icon(get_editor_theme_icon(SNAME("FolderBrowse"))); + install_browse->set_button_icon(get_editor_theme_icon(SNAME("FolderBrowse"))); } break; case NOTIFICATION_READY: { fdialog_project = memnew(EditorFileDialog); diff --git a/editor/project_manager/project_list.cpp b/editor/project_manager/project_list.cpp index 541ab01e62..27f04c0d0d 100644 --- a/editor/project_manager/project_list.cpp +++ b/editor/project_manager/project_list.cpp @@ -67,9 +67,9 @@ void ProjectListItemControl::_notification(int p_what) { favorite_button->set_texture_normal(get_editor_theme_icon(SNAME("Favorites"))); if (project_is_missing) { - explore_button->set_icon(get_editor_theme_icon(SNAME("FileBroken"))); + explore_button->set_button_icon(get_editor_theme_icon(SNAME("FileBroken"))); } else { - explore_button->set_icon(get_editor_theme_icon(SNAME("Load"))); + explore_button->set_button_icon(get_editor_theme_icon(SNAME("Load"))); } } break; @@ -88,7 +88,7 @@ void ProjectListItemControl::_notification(int p_what) { draw_style_box(get_theme_stylebox(SNAME("selected"), SNAME("Tree")), Rect2(Point2(), get_size())); } if (is_hovering) { - draw_style_box(get_theme_stylebox(SNAME("hover"), SNAME("Tree")), Rect2(Point2(), get_size())); + draw_style_box(get_theme_stylebox(SNAME("hovered"), SNAME("Tree")), Rect2(Point2(), get_size())); } draw_line(Point2(0, get_size().y + 1), Point2(get_size().x, get_size().y + 1), get_theme_color(SNAME("guide_color"), SNAME("Tree"))); @@ -196,12 +196,12 @@ void ProjectListItemControl::set_is_missing(bool p_missing) { if (project_is_missing) { project_icon->set_modulate(Color(1, 1, 1, 0.5)); - explore_button->set_icon(get_editor_theme_icon(SNAME("FileBroken"))); + explore_button->set_button_icon(get_editor_theme_icon(SNAME("FileBroken"))); explore_button->set_tooltip_text(TTR("Error: Project is missing on the filesystem.")); } else { project_icon->set_modulate(Color(1, 1, 1, 1.0)); - explore_button->set_icon(get_editor_theme_icon(SNAME("Load"))); + explore_button->set_button_icon(get_editor_theme_icon(SNAME("Load"))); #if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) explore_button->set_tooltip_text(TTR("Show in File Manager")); #else diff --git a/editor/project_manager/project_tag.cpp b/editor/project_manager/project_tag.cpp index 618b6555d4..e66969333c 100644 --- a/editor/project_manager/project_tag.cpp +++ b/editor/project_manager/project_tag.cpp @@ -36,7 +36,7 @@ void ProjectTag::_notification(int p_what) { if (display_close && p_what == NOTIFICATION_THEME_CHANGED) { - button->set_icon(get_theme_icon(SNAME("close"), SNAME("TabBar"))); + button->set_button_icon(get_theme_icon(SNAME("close"), SNAME("TabBar"))); } } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index f973367bed..97f1d5d641 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -31,6 +31,7 @@ #include "project_settings_editor.h" #include "core/config/project_settings.h" +#include "core/input/input_map.h" #include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" @@ -390,7 +391,7 @@ void ProjectSettingsEditor::_action_added(const String &p_name) { Dictionary action; action["events"] = Array(); - action["deadzone"] = 0.2f; + action["deadzone"] = InputMap::DEFAULT_DEADZONE; EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Add Input Action")); @@ -576,10 +577,10 @@ void ProjectSettingsEditor::_update_action_map_editor() { } void ProjectSettingsEditor::_update_theme() { - add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); - del_button->set_icon(get_editor_theme_icon(SNAME("Remove"))); + add_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + del_button->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - restart_close_button->set_icon(get_editor_theme_icon(SNAME("Close"))); + restart_close_button->set_button_icon(get_editor_theme_icon(SNAME("Close"))); restart_container->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); restart_icon->set_texture(get_editor_theme_icon(SNAME("StatusWarning"))); restart_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp index c4ebca7308..2d3cbfb1e3 100644 --- a/editor/register_editor_types.cpp +++ b/editor/register_editor_types.cpp @@ -52,6 +52,7 @@ #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_spin_slider.h" +#include "editor/gui/editor_toaster.h" #include "editor/import/3d/resource_importer_obj.h" #include "editor/import/3d/resource_importer_scene.h" #include "editor/import/editor_import_plugin.h" @@ -146,6 +147,7 @@ void register_editor_types() { GDREGISTER_CLASS(EditorSelection); GDREGISTER_CLASS(EditorFileDialog); GDREGISTER_CLASS(EditorSettings); + GDREGISTER_ABSTRACT_CLASS(EditorToaster); GDREGISTER_CLASS(EditorNode3DGizmo); GDREGISTER_CLASS(EditorNode3DGizmoPlugin); GDREGISTER_ABSTRACT_CLASS(EditorResourcePreview); diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h index 37d159b4e2..5c2ac2558d 100644 --- a/editor/rename_dialog.h +++ b/editor/rename_dialog.h @@ -49,7 +49,7 @@ class TabContainer; class RenameDialog : public ConfirmationDialog { GDCLASS(RenameDialog, ConfirmationDialog); - virtual void ok_pressed() override { rename(); }; + virtual void ok_pressed() override { rename(); } void _cancel_pressed() {} void _features_toggled(bool pressed); void _insert_text(const String &text); diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp index 90e4d74fcb..dc1198167d 100644 --- a/editor/scene_create_dialog.cpp +++ b/editor/scene_create_dialog.cpp @@ -48,10 +48,10 @@ void SceneCreateDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - select_node_button->set_icon(get_editor_theme_icon(SNAME("ClassList"))); - node_type_2d->set_icon(get_editor_theme_icon(SNAME("Node2D"))); - node_type_3d->set_icon(get_editor_theme_icon(SNAME("Node3D"))); - node_type_gui->set_icon(get_editor_theme_icon(SNAME("Control"))); + select_node_button->set_button_icon(get_editor_theme_icon(SNAME("ClassList"))); + node_type_2d->set_button_icon(get_editor_theme_icon(SNAME("Node2D"))); + node_type_3d->set_button_icon(get_editor_theme_icon(SNAME("Node3D"))); + node_type_gui->set_button_icon(get_editor_theme_icon(SNAME("Control"))); node_type_other->add_theme_icon_override(SNAME("icon"), get_editor_theme_icon(SNAME("Node"))); } break; @@ -121,9 +121,9 @@ void SceneCreateDialog::update_dialog() { const StringName root_type_name = StringName(other_type_display->get_text()); if (has_theme_icon(root_type_name, EditorStringName(EditorIcons))) { - node_type_other->set_icon(get_editor_theme_icon(root_type_name)); + node_type_other->set_button_icon(get_editor_theme_icon(root_type_name)); } else { - node_type_other->set_icon(nullptr); + node_type_other->set_button_icon(nullptr); } root_name = root_name_edit->get_text().strip_edges(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index bcab0c2883..87ba2e6875 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -126,7 +126,8 @@ void SceneTreeDock::input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT)) { - if (mb->is_pressed() && scene_tree->get_rect().has_point(scene_tree->get_local_mouse_position())) { + Tree *tree = scene_tree->get_scene_tree(); + if (mb->is_pressed() && tree->get_rect().has_point(tree->get_local_mouse_position())) { tree_clicked = true; } else if (!mb->is_pressed()) { tree_clicked = false; @@ -156,11 +157,12 @@ void SceneTreeDock::shortcut_input(const Ref<InputEvent> &p_event) { } if (ED_IS_SHORTCUT("scene_tree/rename", p_event)) { - // Prevent renaming if a button is focused - // to avoid conflict with Enter shortcut on macOS - if (!focus_owner || !Object::cast_to<BaseButton>(focus_owner)) { - _tool_selected(TOOL_RENAME); + // Prevent renaming if a button or a range is focused + // to avoid conflict with Enter shortcut on macOS. + if (focus_owner && (Object::cast_to<BaseButton>(focus_owner) || Object::cast_to<Range>(focus_owner))) { + return; } + _tool_selected(TOOL_RENAME); #ifdef MODULE_REGEX_ENABLED } else if (ED_IS_SHORTCUT("scene_tree/batch_rename", p_event)) { _tool_selected(TOOL_BATCH_RENAME); @@ -1589,7 +1591,7 @@ void SceneTreeDock::_notification(int p_what) { node_shortcuts_toggle = memnew(Button); node_shortcuts_toggle->set_flat(true); - node_shortcuts_toggle->set_icon(get_editor_theme_icon(SNAME("Favorites"))); + node_shortcuts_toggle->set_button_icon(get_editor_theme_icon(SNAME("Favorites"))); node_shortcuts_toggle->set_toggle_mode(true); node_shortcuts_toggle->set_tooltip_text(TTR("Toggle the display of favorite nodes.")); node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection")); @@ -1614,19 +1616,19 @@ void SceneTreeDock::_notification(int p_what) { button_2d = memnew(Button); beginner_node_shortcuts->add_child(button_2d); button_2d->set_text(TTR("2D Scene")); - button_2d->set_icon(get_editor_theme_icon(SNAME("Node2D"))); + button_2d->set_button_icon(get_editor_theme_icon(SNAME("Node2D"))); button_2d->connect(SceneStringName(pressed), callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_2D_SCENE, false)); button_3d = memnew(Button); beginner_node_shortcuts->add_child(button_3d); button_3d->set_text(TTR("3D Scene")); - button_3d->set_icon(get_editor_theme_icon(SNAME("Node3D"))); + button_3d->set_button_icon(get_editor_theme_icon(SNAME("Node3D"))); button_3d->connect(SceneStringName(pressed), callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_3D_SCENE, false)); button_ui = memnew(Button); beginner_node_shortcuts->add_child(button_ui); button_ui->set_text(TTR("User Interface")); - button_ui->set_icon(get_editor_theme_icon(SNAME("Control"))); + button_ui->set_button_icon(get_editor_theme_icon(SNAME("Control"))); button_ui->connect(SceneStringName(pressed), callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_USER_INTERFACE, false)); favorite_node_shortcuts = memnew(VBoxContainer); @@ -1635,13 +1637,13 @@ void SceneTreeDock::_notification(int p_what) { button_custom = memnew(Button); node_shortcuts->add_child(button_custom); button_custom->set_text(TTR("Other Node")); - button_custom->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_custom->set_button_icon(get_editor_theme_icon(SNAME("Add"))); button_custom->connect(SceneStringName(pressed), callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false)); button_clipboard = memnew(Button); node_shortcuts->add_child(button_clipboard); button_clipboard->set_text(TTR("Paste From Clipboard")); - button_clipboard->set_icon(get_editor_theme_icon(SNAME("ActionPaste"))); + button_clipboard->set_button_icon(get_editor_theme_icon(SNAME("ActionPaste"))); button_clipboard->connect(SceneStringName(pressed), callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_PASTE, false)); _update_create_root_dialog(true); @@ -1663,11 +1665,12 @@ void SceneTreeDock::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - button_add->set_icon(get_editor_theme_icon(SNAME("Add"))); - button_instance->set_icon(get_editor_theme_icon(SNAME("Instance"))); - button_create_script->set_icon(get_editor_theme_icon(SNAME("ScriptCreate"))); - button_detach_script->set_icon(get_editor_theme_icon(SNAME("ScriptRemove"))); - button_tree_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + button_add->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + button_instance->set_button_icon(get_editor_theme_icon(SNAME("Instance"))); + button_create_script->set_button_icon(get_editor_theme_icon(SNAME("ScriptCreate"))); + button_detach_script->set_button_icon(get_editor_theme_icon(SNAME("ScriptRemove"))); + button_extend_script->set_button_icon(get_editor_theme_icon(SNAME("ScriptExtend"))); + button_tree_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); filter->set_right_icon(get_editor_theme_icon(SNAME("Search"))); @@ -1678,19 +1681,19 @@ void SceneTreeDock::_notification(int p_what) { // These buttons are created on READY, because reasons... if (button_2d) { - button_2d->set_icon(get_editor_theme_icon(SNAME("Node2D"))); + button_2d->set_button_icon(get_editor_theme_icon(SNAME("Node2D"))); } if (button_3d) { - button_3d->set_icon(get_editor_theme_icon(SNAME("Node3D"))); + button_3d->set_button_icon(get_editor_theme_icon(SNAME("Node3D"))); } if (button_ui) { - button_ui->set_icon(get_editor_theme_icon(SNAME("Control"))); + button_ui->set_button_icon(get_editor_theme_icon(SNAME("Control"))); } if (button_custom) { - button_custom->set_icon(get_editor_theme_icon(SNAME("Add"))); + button_custom->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } if (button_clipboard) { - button_clipboard->set_icon(get_editor_theme_icon(SNAME("ActionPaste"))); + button_clipboard->set_button_icon(get_editor_theme_icon(SNAME("ActionPaste"))); } menu_subresources->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor))); @@ -2784,33 +2787,49 @@ void SceneTreeDock::_delete_confirm(bool p_cut) { } void SceneTreeDock::_update_script_button() { - if (!profile_allow_script_editing) { - button_create_script->hide(); - button_detach_script->hide(); - } else if (editor_selection->get_selection().size() == 0) { - button_create_script->hide(); - button_detach_script->hide(); - } else if (editor_selection->get_selection().size() == 1) { - Node *n = editor_selection->get_selected_node_list().front()->get(); - if (n->get_script().is_null()) { - button_create_script->show(); - button_detach_script->hide(); - } else { - button_create_script->hide(); - button_detach_script->show(); - } - } else { - button_create_script->hide(); + bool can_create_script = false; + bool can_detach_script = false; + bool can_extend_script = false; + + if (profile_allow_script_editing) { Array selection = editor_selection->get_selected_nodes(); + for (int i = 0; i < selection.size(); i++) { Node *n = Object::cast_to<Node>(selection[i]); - if (!n->get_script().is_null()) { - button_detach_script->show(); - return; + Ref<Script> s = n->get_script(); + Ref<Script> cts; + + if (n->has_meta(SceneStringName(_custom_type_script))) { + cts = n->get_meta(SceneStringName(_custom_type_script)); + } + + if (selection.size() == 1) { + if (s.is_valid()) { + if (cts.is_valid() && s == cts) { + can_extend_script = true; + } + } else { + can_create_script = true; + } + } + + if (s.is_valid()) { + if (cts.is_valid()) { + if (s != cts) { + can_detach_script = true; + break; + } + } else { + can_detach_script = true; + break; + } } } - button_detach_script->hide(); } + + button_create_script->set_visible(can_create_script); + button_detach_script->set_visible(can_detach_script); + button_extend_script->set_visible(can_extend_script); } void SceneTreeDock::_selection_changed() { @@ -3057,7 +3076,28 @@ void SceneTreeDock::_replace_node(Node *p_node, Node *p_by_node, bool p_keep_pro Node *newnode = p_by_node; if (p_keep_properties) { - Node *default_oldnode = Object::cast_to<Node>(ClassDB::instantiate(oldnode->get_class())); + Node *default_oldnode = nullptr; + + // If we're dealing with a custom node type, we need to create a default instance of the custom type instead of the native type for property comparison. + if (oldnode->has_meta(SceneStringName(_custom_type_script))) { + Ref<Script> cts = oldnode->get_meta(SceneStringName(_custom_type_script)); + default_oldnode = Object::cast_to<Node>(get_editor_data()->script_class_instance(cts->get_global_name())); + if (default_oldnode) { + default_oldnode->set_name(cts->get_global_name()); + get_editor_data()->instantiate_object_properties(default_oldnode); + } else { + // Legacy custom type, registered with "add_custom_type()". + // TODO: Should probably be deprecated in 4.x. + const EditorData::CustomType *custom_type = get_editor_data()->get_custom_type_by_path(cts->get_path()); + if (custom_type) { + default_oldnode = Object::cast_to<Node>(get_editor_data()->instantiate_custom_type(custom_type->name, cts->get_instance_base_type())); + } + } + } + + if (!default_oldnode) { + default_oldnode = Object::cast_to<Node>(ClassDB::instantiate(oldnode->get_class())); + } List<PropertyInfo> pinfo; oldnode->get_property_list(&pinfo); @@ -3542,6 +3582,27 @@ void SceneTreeDock::_script_dropped(const String &p_file, NodePath p_to) { undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(n)).path_join(new_node->get_name()))); undo_redo->commit_action(); } else { + // Check if dropped script is compatible. + if (n->has_meta(SceneStringName(_custom_type_script))) { + Ref<Script> ct_scr = n->get_meta(SceneStringName(_custom_type_script)); + if (!scr->inherits_script(ct_scr)) { + String custom_type_name = ct_scr->get_global_name(); + + // Legacy custom type, registered with "add_custom_type()". + if (custom_type_name.is_empty()) { + const EditorData::CustomType *custom_type = get_editor_data()->get_custom_type_by_path(ct_scr->get_path()); + if (custom_type) { + custom_type_name = custom_type->name; + } else { + custom_type_name = TTR("<unknown>"); + } + } + + WARN_PRINT_ED(vformat("Script does not extend type: '%s'.", custom_type_name)); + return; + } + } + undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, n); undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", n); undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", n); @@ -3649,6 +3710,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { Ref<Script> existing_script; bool existing_script_removable = true; + bool allow_attach_new_script = true; if (selection.size() == 1) { Node *selected = selection.front()->get(); @@ -3672,6 +3734,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (EditorNode::get_singleton()->get_object_custom_type_base(selected) == existing_script) { existing_script_removable = false; } + + if (selected->has_meta(SceneStringName(_custom_type_script))) { + allow_attach_new_script = false; + } } if (profile_allow_editing) { @@ -3692,7 +3758,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (full_selection.size() == 1) { add_separator = true; - menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ScriptCreate")), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); + if (allow_attach_new_script) { + menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ScriptCreate")), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); + } + if (existing_script.is_valid()) { menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ScriptExtend")), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT); } @@ -4269,7 +4338,7 @@ void SceneTreeDock::_update_create_root_dialog(bool p_initializing) { if (ScriptServer::is_global_class(name)) { name = ScriptServer::get_global_class_native_base(name); } - button->set_icon(EditorNode::get_singleton()->get_class_icon(name)); + button->set_button_icon(EditorNode::get_singleton()->get_class_icon(name)); button->connect(SceneStringName(pressed), callable_mp(this, &SceneTreeDock::_favorite_root_selected).bind(l)); } } @@ -4601,6 +4670,14 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec filter_hbc->add_child(button_detach_script); button_detach_script->hide(); + button_extend_script = memnew(Button); + button_extend_script->set_flat(true); + button_extend_script->connect(SceneStringName(pressed), callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_EXTEND_SCRIPT, false)); + button_extend_script->set_tooltip_text(TTR("Extend the script of the selected node.")); + button_extend_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/extend_script")); + filter_hbc->add_child(button_extend_script); + button_extend_script->hide(); + button_tree_menu = memnew(MenuButton); button_tree_menu->set_flat(false); button_tree_menu->set_theme_type_variation("FlatMenuButton"); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 05ad0f36e4..8cee2870f6 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -115,6 +115,7 @@ class SceneTreeDock : public VBoxContainer { Button *button_instance = nullptr; Button *button_create_script = nullptr; Button *button_detach_script = nullptr; + Button *button_extend_script = nullptr; MenuButton *button_tree_menu = nullptr; Button *node_shortcuts_toggle = nullptr; diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 0cb4952b04..8615836ddd 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -135,16 +135,16 @@ void ScriptCreateDialog::_notification(int p_what) { } } - path_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); - parent_browse_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); - parent_search_button->set_icon(get_editor_theme_icon(SNAME("ClassList"))); + path_button->set_button_icon(get_editor_theme_icon(SNAME("Folder"))); + parent_browse_button->set_button_icon(get_editor_theme_icon(SNAME("Folder"))); + parent_search_button->set_button_icon(get_editor_theme_icon(SNAME("ClassList"))); } break; } } void ScriptCreateDialog::_path_hbox_sorted() { if (is_visible()) { - int filename_start_pos = file_path->get_text().rfind("/") + 1; + int filename_start_pos = file_path->get_text().rfind_char('/') + 1; int filename_end_pos = file_path->get_text().get_basename().length(); if (!is_built_in) { @@ -359,6 +359,7 @@ void ScriptCreateDialog::_create_new() { alert->popup_centered(); return; } + EditorNode::get_singleton()->ensure_uid_file(lpath); } emit_signal(SNAME("script_created"), scr); diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp index 846e8867a1..33da3dd10c 100644 --- a/editor/shader_create_dialog.cpp +++ b/editor/shader_create_dialog.cpp @@ -31,6 +31,7 @@ #include "shader_create_dialog.h" #include "core/config/project_settings.h" +#include "editor/editor_node.h" #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_validation_panel.h" #include "editor/themes/editor_scale.h" @@ -74,7 +75,7 @@ void ShaderCreateDialog::_notification(int p_what) { } } - path_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); + path_button->set_button_icon(get_editor_theme_icon(SNAME("Folder"))); } break; } } @@ -102,7 +103,7 @@ void ShaderCreateDialog::_update_language_info() { void ShaderCreateDialog::_path_hbox_sorted() { if (is_visible()) { - int filename_start_pos = initial_base_path.rfind("/") + 1; + int filename_start_pos = initial_base_path.rfind_char('/') + 1; int filename_end_pos = initial_base_path.length(); if (!is_built_in) { @@ -240,6 +241,7 @@ void fog() { alert->popup_centered(); return; } + EditorNode::get_singleton()->ensure_uid_file(lpath); emit_signal(SNAME("shader_include_created"), shader_inc); } else { @@ -258,6 +260,7 @@ void fog() { alert->popup_centered(); return; } + EditorNode::get_singleton()->ensure_uid_file(lpath); } emit_signal(SNAME("shader_created"), shader); diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp index 85e5cd6ea0..a53b621097 100644 --- a/editor/shader_globals_editor.cpp +++ b/editor/shader_globals_editor.cpp @@ -438,7 +438,7 @@ void ShaderGlobalsEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - variable_add->set_icon(get_editor_theme_icon(SNAME("Add"))); + variable_add->set_button_icon(get_editor_theme_icon(SNAME("Add"))); } break; case NOTIFICATION_PREDELETE: { diff --git a/editor/surface_upgrade_tool.h b/editor/surface_upgrade_tool.h index 59745250e4..130c49dcac 100644 --- a/editor/surface_upgrade_tool.h +++ b/editor/surface_upgrade_tool.h @@ -54,9 +54,9 @@ protected: static void _bind_methods(); public: - static SurfaceUpgradeTool *get_singleton() { return singleton; }; + static SurfaceUpgradeTool *get_singleton() { return singleton; } - bool is_show_requested() const { return show_requested; }; + bool is_show_requested() const { return show_requested; } void show_popup() { _show_popup(); } void prepare_upgrade(); diff --git a/editor/themes/editor_color_map.cpp b/editor/themes/editor_color_map.cpp index 9046a8b688..3c3d755586 100644 --- a/editor/themes/editor_color_map.cpp +++ b/editor/themes/editor_color_map.cpp @@ -173,6 +173,8 @@ void EditorColorMap::create() { add_conversion_exception("OverbrightIndicator"); add_conversion_exception("MaterialPreviewCube"); add_conversion_exception("MaterialPreviewSphere"); + add_conversion_exception("MaterialPreviewQuad"); + add_conversion_exception("MaterialPreviewLight1"); add_conversion_exception("MaterialPreviewLight2"); diff --git a/editor/themes/editor_color_map.h b/editor/themes/editor_color_map.h index c1176749f2..fba39f249e 100644 --- a/editor/themes/editor_color_map.h +++ b/editor/themes/editor_color_map.h @@ -50,8 +50,8 @@ public: static void add_conversion_color_pair(const String &p_from_color, const String &p_to_color); static void add_conversion_exception(const StringName &p_icon_name); - static HashMap<Color, Color> &get_color_conversion_map() { return color_conversion_map; }; - static HashSet<StringName> &get_color_conversion_exceptions() { return color_conversion_exceptions; }; + static HashMap<Color, Color> &get_color_conversion_map() { return color_conversion_map; } + static HashSet<StringName> &get_color_conversion_exceptions() { return color_conversion_exceptions; } static void create(); static void finish(); diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp index 17bcbacfc2..a4251bfd29 100644 --- a/editor/themes/editor_theme_manager.cpp +++ b/editor/themes/editor_theme_manager.cpp @@ -633,6 +633,16 @@ void EditorThemeManager::_create_shared_styles(const Ref<EditorTheme> &p_theme, // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled). p_config.popup_style->set_corner_radius_all(0); + p_config.popup_border_style = p_config.popup_style->duplicate(); + p_config.popup_border_style->set_content_margin_all(MAX(Math::round(EDSCALE), p_config.border_width) + 2 + (p_config.base_margin * 1.5) * EDSCALE); + // Always display a border for popups like PopupMenus so they can be distinguished from their background. + p_config.popup_border_style->set_border_width_all(MAX(Math::round(EDSCALE), p_config.border_width)); + if (p_config.draw_extra_borders) { + p_config.popup_border_style->set_border_color(p_config.extra_border_color_2); + } else { + p_config.popup_border_style->set_border_color(p_config.dark_color_2); + } + p_config.window_style = p_config.popup_style->duplicate(); p_config.window_style->set_border_color(p_config.base_color); p_config.window_style->set_border_width(SIDE_TOP, 24 * EDSCALE); @@ -707,7 +717,7 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the } // PopupPanel - p_theme->set_stylebox(SceneStringName(panel), "PopupPanel", p_config.popup_style); + p_theme->set_stylebox(SceneStringName(panel), "PopupPanel", p_config.popup_border_style); } // Buttons. @@ -945,6 +955,8 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the p_theme->set_color("custom_button_font_highlight", "Tree", p_config.font_hover_color); p_theme->set_color(SceneStringName(font_color), "Tree", p_config.font_color); + p_theme->set_color("font_hovered_color", "Tree", p_config.mono_color); + p_theme->set_color("font_hovered_dimmed_color", "Tree", p_config.font_color); p_theme->set_color("font_selected_color", "Tree", p_config.mono_color); p_theme->set_color("font_disabled_color", "Tree", p_config.font_disabled_color); p_theme->set_color("font_outline_color", "Tree", p_config.font_outline_color); @@ -997,7 +1009,13 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the Ref<StyleBoxFlat> style_tree_hover = p_config.base_style->duplicate(); style_tree_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.4)); style_tree_hover->set_border_width_all(0); - p_theme->set_stylebox("hover", "Tree", style_tree_hover); + p_theme->set_stylebox("hovered", "Tree", style_tree_hover); + p_theme->set_stylebox("button_hover", "Tree", style_tree_hover); + + Ref<StyleBoxFlat> style_tree_hover_dimmed = p_config.base_style->duplicate(); + style_tree_hover_dimmed->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.2)); + style_tree_hover_dimmed->set_border_width_all(0); + p_theme->set_stylebox("hovered_dimmed", "Tree", style_tree_hover_dimmed); p_theme->set_stylebox("selected_focus", "Tree", style_tree_focus); p_theme->set_stylebox("selected", "Tree", style_tree_selected); @@ -1306,18 +1324,11 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the // PopupMenu. { - Ref<StyleBoxFlat> style_popup_menu = p_config.popup_style->duplicate(); + Ref<StyleBoxFlat> style_popup_menu = p_config.popup_border_style->duplicate(); // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted, // and it looks weird. 1px solves this. - style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE); - // Always display a border for PopupMenus so they can be distinguished from their background. - style_popup_menu->set_border_width_all(EDSCALE); - if (p_config.draw_extra_borders) { - style_popup_menu->set_border_color(p_config.extra_border_color_2); - } else { - style_popup_menu->set_border_color(p_config.dark_color_2); - } + style_popup_menu->set_content_margin_individual(Math::round(EDSCALE), 2 * EDSCALE, Math::round(EDSCALE), 2 * EDSCALE); p_theme->set_stylebox(SceneStringName(panel), "PopupMenu", style_popup_menu); Ref<StyleBoxFlat> style_menu_hover = p_config.button_style_hover->duplicate(); @@ -1327,17 +1338,17 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine)); style_popup_separator->set_color(p_config.separator_color); - style_popup_separator->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); - style_popup_separator->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_separator->set_grow_begin(Math::round(EDSCALE) - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_separator->set_grow_end(Math::round(EDSCALE) - MAX(Math::round(EDSCALE), p_config.border_width)); style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); Ref<StyleBoxLine> style_popup_labeled_separator_left(memnew(StyleBoxLine)); - style_popup_labeled_separator_left->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_labeled_separator_left->set_grow_begin(Math::round(EDSCALE) - MAX(Math::round(EDSCALE), p_config.border_width)); style_popup_labeled_separator_left->set_color(p_config.separator_color); style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); Ref<StyleBoxLine> style_popup_labeled_separator_right(memnew(StyleBoxLine)); - style_popup_labeled_separator_right->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_labeled_separator_right->set_grow_end(Math::round(EDSCALE) - MAX(Math::round(EDSCALE), p_config.border_width)); style_popup_labeled_separator_right->set_color(p_config.separator_color); style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); @@ -1846,6 +1857,12 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme p_theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); p_theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + // Game view. + p_theme->set_type_variation("GamePanel", "Panel"); + Ref<StyleBoxFlat> game_panel = p_theme->get_stylebox(SNAME("panel"), SNAME("Panel"))->duplicate(); + game_panel->set_corner_radius_all(0); + p_theme->set_stylebox(SceneStringName(panel), "GamePanel", game_panel); + // Main menu. Ref<StyleBoxFlat> menu_transparent_style = p_config.button_style->duplicate(); menu_transparent_style->set_bg_color(Color(1, 1, 1, 0)); @@ -2115,21 +2132,6 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme // EditorValidationPanel. p_theme->set_stylebox(SceneStringName(panel), "EditorValidationPanel", p_config.tree_panel_style); - - // ControlEditor. - { - p_theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel"); - - Ref<StyleBoxFlat> control_editor_popup_style = p_config.popup_style->duplicate(); - control_editor_popup_style->set_shadow_size(0); - control_editor_popup_style->set_content_margin(SIDE_LEFT, p_config.base_margin * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_TOP, p_config.base_margin * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_RIGHT, p_config.base_margin * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_BOTTOM, p_config.base_margin * EDSCALE); - control_editor_popup_style->set_border_width_all(0); - - p_theme->set_stylebox(SceneStringName(panel), "ControlEditorPopupPanel", control_editor_popup_style); - } } // Editor inspector. @@ -2504,6 +2506,7 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme p_theme->set_color("transition_icon_disabled_color", "GraphStateMachine", Color(1, 1, 1, 0.2)); p_theme->set_color("highlight_color", "GraphStateMachine", p_config.accent_color); p_theme->set_color("highlight_disabled_color", "GraphStateMachine", p_config.accent_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("focus_color", "GraphStateMachine", p_config.accent_color); p_theme->set_color("guideline_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.3)); p_theme->set_color("playback_color", "GraphStateMachine", p_config.font_color); diff --git a/editor/themes/editor_theme_manager.h b/editor/themes/editor_theme_manager.h index 5e7bd00083..ca5e1a4e2d 100644 --- a/editor/themes/editor_theme_manager.h +++ b/editor/themes/editor_theme_manager.h @@ -135,6 +135,7 @@ class EditorThemeManager { Ref<StyleBoxFlat> button_style_hover; Ref<StyleBoxFlat> popup_style; + Ref<StyleBoxFlat> popup_border_style; Ref<StyleBoxFlat> window_style; Ref<StyleBoxFlat> dialog_style; Ref<StyleBoxFlat> panel_container_style; diff --git a/editor/window_wrapper.cpp b/editor/window_wrapper.cpp index 9496ba016c..3256680416 100644 --- a/editor/window_wrapper.cpp +++ b/editor/window_wrapper.cpp @@ -390,8 +390,7 @@ void ScreenSelect::_notification(int p_what) { connect(SceneStringName(gui_input), callable_mp(this, &ScreenSelect::_handle_mouse_shortcut)); } break; case NOTIFICATION_THEME_CHANGED: { - set_icon(get_editor_theme_icon("MakeFloating")); - popup_background->add_theme_style_override(SceneStringName(panel), get_theme_stylebox("PanelForeground", EditorStringName(EditorStyles))); + set_button_icon(get_editor_theme_icon("MakeFloating")); const real_t popup_height = real_t(get_theme_font_size(SceneStringName(font_size))) * 2.0; popup->set_min_size(Size2(0, popup_height * 3)); @@ -454,14 +453,10 @@ ScreenSelect::ScreenSelect() { // Create the popup. const Size2 borders = Size2(4, 4) * EDSCALE; - popup = memnew(Popup); + popup = memnew(PopupPanel); popup->connect("popup_hide", callable_mp(static_cast<BaseButton *>(this), &ScreenSelect::set_pressed).bind(false)); add_child(popup); - popup_background = memnew(Panel); - popup_background->set_anchors_and_offsets_preset(PRESET_FULL_RECT); - popup->add_child(popup_background); - MarginContainer *popup_root = memnew(MarginContainer); popup_root->add_theme_constant_override("margin_right", borders.width); popup_root->add_theme_constant_override("margin_top", borders.height); diff --git a/editor/window_wrapper.h b/editor/window_wrapper.h index a07e95f09e..3597276de9 100644 --- a/editor/window_wrapper.h +++ b/editor/window_wrapper.h @@ -88,7 +88,6 @@ class ScreenSelect : public Button { GDCLASS(ScreenSelect, Button); Popup *popup = nullptr; - Panel *popup_background = nullptr; HBoxContainer *screen_list = nullptr; void _build_advanced_menu(); diff --git a/main/main.cpp b/main/main.cpp index 5206e9b84c..f002e22766 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -42,6 +42,7 @@ #include "core/io/dir_access.h" #include "core/io/file_access_pack.h" #include "core/io/file_access_zip.h" +#include "core/io/image.h" #include "core/io/image_loader.h" #include "core/io/ip.h" #include "core/io/resource_loader.h" @@ -629,6 +630,7 @@ void Main::print_help(const char *p_binary) { print_help_option("--generate-spirv-debug-info", "Generate SPIR-V debug information. This allows source-level shader debugging with RenderDoc.\n"); #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) print_help_option("--extra-gpu-memory-tracking", "Enables additional memory tracking (see class reference for `RenderingDevice.get_driver_and_device_memory_report()` and linked methods). Currently only implemented for Vulkan. Enabling this feature may cause crashes on some systems due to buggy drivers or bugs in the Vulkan Loader. See https://github.com/godotengine/godot/issues/95967\n"); + print_help_option("--accurate-breadcrumbs", "Force barriers between breadcrumbs. Useful for narrowing down a command causing GPU resets. Currently only implemented for Vulkan.\n"); #endif print_help_option("--remote-debug <uri>", "Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n"); print_help_option("--single-threaded-scene", "Force scene tree to run in single-threaded mode. Sub-thread groups are disabled and run on the main thread.\n"); @@ -651,7 +653,7 @@ void Main::print_help(const char *p_binary) { print_help_option("--delta-smoothing <enable>", "Enable or disable frame delta smoothing [\"enable\", \"disable\"].\n"); print_help_option("--print-fps", "Print the frames per second to the stdout.\n"); #ifdef TOOLS_ENABLED - print_help_option("--editor-pseudolocalization", "Enable pseudolocalization for the editor and the project manager.\n"); + print_help_option("--editor-pseudolocalization", "Enable pseudolocalization for the editor and the project manager.\n", CLI_OPTION_AVAILABILITY_EDITOR); #endif print_help_title("Standalone tools"); @@ -1235,8 +1237,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #endif } else if (arg == "--generate-spirv-debug-info") { Engine::singleton->generate_spirv_debug_info = true; +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) } else if (arg == "--extra-gpu-memory-tracking") { Engine::singleton->extra_gpu_memory_tracking = true; + } else if (arg == "--accurate-breadcrumbs") { + Engine::singleton->accurate_breadcrumbs = true; +#endif } else if (arg == "--tablet-driver") { if (N) { tablet_driver = N->get(); @@ -1592,7 +1598,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (arg.ends_with("project.godot")) { String path; String file = arg; - int sep = MAX(file.rfind("/"), file.rfind("\\")); + int sep = MAX(file.rfind_char('/'), file.rfind_char('\\')); if (sep == -1) { path = "."; } else { @@ -2412,6 +2418,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (bool(GLOBAL_GET("display/window/size/no_focus"))) { window_flags |= DisplayServer::WINDOW_FLAG_NO_FOCUS_BIT; } + if (bool(GLOBAL_GET("display/window/size/sharp_corners"))) { + window_flags |= DisplayServer::WINDOW_FLAG_SHARP_CORNERS_BIT; + } window_mode = (DisplayServer::WindowMode)(GLOBAL_GET("display/window/size/mode").operator int()); int initial_position_type = GLOBAL_GET("display/window/size/initial_position_type").operator int(); if (initial_position_type == 0) { // Absolute. @@ -2495,7 +2504,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name()); if (audio_driver.is_empty()) { // Specified in project.godot. - audio_driver = GLOBAL_GET("audio/driver/driver"); + if (project_manager) { + // The project manager doesn't need to play sound (TTS audio output is not emitted by Godot, but by the system itself). + // Disable audio output so it doesn't appear in the list of applications outputting sound in the OS. + // On macOS, this also prevents the project manager from inhibiting suspend. + audio_driver = "Dummy"; + } else { + audio_driver = GLOBAL_GET("audio/driver/driver"); + } } // Make sure that dummy is the last one, which it is assumed to be by design. @@ -2531,7 +2547,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph Engine::get_singleton()->set_physics_ticks_per_second(GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "physics/common/physics_ticks_per_second", PROPERTY_HINT_RANGE, "1,1000,1"), 60)); Engine::get_singleton()->set_max_physics_steps_per_frame(GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "physics/common/max_physics_steps_per_frame", PROPERTY_HINT_RANGE, "1,100,1"), 8)); Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF("physics/common/physics_jitter_fix", 0.5)); - Engine::get_singleton()->set_max_fps(GLOBAL_DEF(PropertyInfo(Variant::INT, "application/run/max_fps", PROPERTY_HINT_RANGE, "0,1000,1"), 0)); GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/driver/output_latency", PROPERTY_HINT_RANGE, "1,100,1"), 15); // Use a safer default output_latency for web to avoid audio cracking on low-end devices, especially mobile. @@ -2552,10 +2567,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->set_environment("MVK_CONFIG_LOG_LEVEL", OS::get_singleton()->_verbose_stdout ? "3" : "1"); // 1 = Errors only, 3 = Info #endif - if (max_fps >= 0) { - Engine::get_singleton()->set_max_fps(max_fps); - } - if (frame_delay == 0) { frame_delay = GLOBAL_DEF(PropertyInfo(Variant::INT, "application/run/frame_delay_msec", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), 0); if (Engine::get_singleton()->is_editor_hint()) { @@ -3001,6 +3012,13 @@ Error Main::setup2(bool p_show_boot_logo) { OS::get_singleton()->benchmark_end_measure("Servers", "Display"); } + // Max FPS needs to be set after the DisplayServer is created. + Engine::get_singleton()->set_max_fps(GLOBAL_DEF(PropertyInfo(Variant::INT, "application/run/max_fps", PROPERTY_HINT_RANGE, "0,1000,1"), 0)); + + if (max_fps >= 0) { + Engine::get_singleton()->set_max_fps(max_fps); + } + #ifdef TOOLS_ENABLED // If the editor is running in windowed mode, ensure the window rect fits // the screen in case screen count or position has changed. @@ -3197,6 +3215,10 @@ Error Main::setup2(bool p_show_boot_logo) { } id->set_emulate_mouse_from_touch(bool(GLOBAL_DEF_BASIC("input_devices/pointing/emulate_mouse_from_touch", true))); + + if (editor) { + id->set_emulate_mouse_from_touch(true); + } } OS::get_singleton()->benchmark_end_measure("Startup", "Setup Window and Boot"); @@ -3428,7 +3450,7 @@ void Main::setup_boot_logo() { if (show_logo) { //boot logo! const bool boot_logo_image = GLOBAL_DEF_BASIC("application/boot_splash/show_image", true); - const String boot_logo_path = String(GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/boot_splash/image", PROPERTY_HINT_FILE, "*.png"), String())).strip_edges(); + const String boot_logo_path = ResourceUID::ensure_path(GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/boot_splash/image", PROPERTY_HINT_FILE, "*.png"), String())).strip_edges(); const bool boot_logo_scale = GLOBAL_DEF_BASIC("application/boot_splash/fullsize", true); const bool boot_logo_filter = GLOBAL_DEF_BASIC("application/boot_splash/use_filter", true); @@ -4013,12 +4035,12 @@ int Main::start() { EditorNode *editor_node = nullptr; if (editor) { OS::get_singleton()->benchmark_begin_measure("Startup", "Editor"); - editor_node = memnew(EditorNode); if (editor_pseudolocalization) { translation_server->get_editor_domain()->set_pseudolocalization_enabled(true); } + editor_node = memnew(EditorNode); sml->get_root()->add_child(editor_node); if (!_export_preset.is_empty()) { @@ -4123,7 +4145,7 @@ int Main::start() { local_game_path = "res://" + local_game_path; } else { - int sep = local_game_path.rfind("/"); + int sep = local_game_path.rfind_char('/'); if (sep == -1) { Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -4210,14 +4232,15 @@ int Main::start() { if (project_manager) { OS::get_singleton()->benchmark_begin_measure("Startup", "Project Manager"); Engine::get_singleton()->set_editor_hint(true); - ProjectManager *pmanager = memnew(ProjectManager); - ProgressDialog *progress_dialog = memnew(ProgressDialog); - pmanager->add_child(progress_dialog); if (editor_pseudolocalization) { translation_server->get_editor_domain()->set_pseudolocalization_enabled(true); } + ProjectManager *pmanager = memnew(ProjectManager); + ProgressDialog *progress_dialog = memnew(ProgressDialog); + pmanager->add_child(progress_dialog); + sml->get_root()->add_child(pmanager); OS::get_singleton()->benchmark_end_measure("Startup", "Project Manager"); } diff --git a/main/performance.cpp b/main/performance.cpp index c73fb62b76..398511995b 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -132,11 +132,9 @@ String Performance::get_monitor_name(Monitor p_monitor) const { PNAME("physics_2d/active_objects"), PNAME("physics_2d/collision_pairs"), PNAME("physics_2d/islands"), -#ifndef _3D_DISABLED PNAME("physics_3d/active_objects"), PNAME("physics_3d/collision_pairs"), PNAME("physics_3d/islands"), -#endif // _3D_DISABLED PNAME("audio/driver/output_latency"), PNAME("navigation/active_maps"), PNAME("navigation/regions"), @@ -280,11 +278,9 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, -#ifndef _3D_DISABLED MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, -#endif // _3D_DISABLED MONITOR_TYPE_TIME, MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, diff --git a/methods.py b/methods.py index 9e881773c9..203f0dd8a5 100644 --- a/methods.py +++ b/methods.py @@ -1,5 +1,7 @@ +import atexit import contextlib import glob +import math import os import re import subprocess @@ -8,7 +10,7 @@ from collections import OrderedDict from enum import Enum from io import StringIO, TextIOWrapper from pathlib import Path -from typing import Generator, List, Optional, Union +from typing import Generator, List, Optional, Union, cast # Get the "Godot" folder name ahead of time base_folder_path = str(os.path.abspath(Path(__file__).parent)) + "/" @@ -73,21 +75,13 @@ def print_error(*values: object) -> None: def add_source_files_orig(self, sources, files, allow_gen=False): # Convert string to list of absolute paths (including expanding wildcard) - if isinstance(files, (str, bytes)): - # Keep SCons project-absolute path as they are (no wildcard support) - if files.startswith("#"): - if "*" in files: - print_error("Wildcards can't be expanded in SCons project-absolute path: '{}'".format(files)) - return - files = [files] - else: - # Exclude .gen.cpp files from globbing, to avoid including obsolete ones. - # They should instead be added manually. - skip_gen_cpp = "*" in files - dir_path = self.Dir(".").abspath - files = sorted(glob.glob(dir_path + "/" + files)) - if skip_gen_cpp and not allow_gen: - files = [f for f in files if not f.endswith(".gen.cpp")] + if isinstance(files, str): + # Exclude .gen.cpp files from globbing, to avoid including obsolete ones. + # They should instead be added manually. + skip_gen_cpp = "*" in files + files = self.Glob(files) + if skip_gen_cpp and not allow_gen: + files = [f for f in files if not str(f).endswith(".gen.cpp")] # Add each path as compiled Object following environment (self) configuration for path in files: @@ -98,35 +92,6 @@ def add_source_files_orig(self, sources, files, allow_gen=False): sources.append(obj) -# The section name is used for checking -# the hash table to see whether the folder -# is included in the SCU build. -# It will be something like "core/math". -def _find_scu_section_name(subdir): - section_path = os.path.abspath(subdir) + "/" - - folders = [] - folder = "" - - for i in range(8): - folder = os.path.dirname(section_path) - folder = os.path.basename(folder) - if folder == base_folder_only: - break - folders += [folder] - section_path += "../" - section_path = os.path.abspath(section_path) + "/" - - section_name = "" - for n in range(len(folders)): - # section_name += folders[len(folders) - n - 1] + " " - section_name += folders[len(folders) - n - 1] - if n != (len(folders) - 1): - section_name += "/" - - return section_name - - def add_source_files_scu(self, sources, files, allow_gen=False): if self["scu_build"] and isinstance(files, str): if "*." not in files: @@ -135,10 +100,8 @@ def add_source_files_scu(self, sources, files, allow_gen=False): # If the files are in a subdirectory, we want to create the scu gen # files inside this subdirectory. subdir = os.path.dirname(files) - if subdir != "": - subdir += "/" - - section_name = _find_scu_section_name(subdir) + subdir = subdir if subdir == "" else subdir + "/" + section_name = self.Dir(subdir).tpath # if the section name is in the hash table? # i.e. is it part of the SCU build? global _scu_folders @@ -277,34 +240,6 @@ def get_version_info(module_version_string="", silent=False): return version_info -def parse_cg_file(fname, uniforms, sizes, conditionals): - with open(fname, "r", encoding="utf-8") as fs: - line = fs.readline() - - while line: - if re.match(r"^\s*uniform", line): - res = re.match(r"uniform ([\d\w]*) ([\d\w]*)") - type = res.groups(1) - name = res.groups(2) - - uniforms.append(name) - - if type.find("texobj") != -1: - sizes.append(1) - else: - t = re.match(r"float(\d)x(\d)", type) - if t: - sizes.append(int(t.groups(1)) * int(t.groups(2))) - else: - t = re.match(r"float(\d)", type) - sizes.append(int(t.groups(1))) - - if line.find("[branch]") != -1: - conditionals.append(name) - - line = fs.readline() - - def get_cmdline_bool(option, default): """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line, and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings. @@ -404,10 +339,6 @@ def convert_custom_modules_path(path): return path -def disable_module(self): - self.disabled_modules.append(self.current_module) - - def module_add_dependencies(self, module, dependencies, optional=False): """ Adds dependencies for a given module. @@ -428,19 +359,21 @@ def module_check_dependencies(self, module): Meant to be used in module `can_build` methods. Returns a boolean (True if dependencies are satisfied). """ - missing_deps = [] + missing_deps = set() required_deps = self.module_dependencies[module][0] if module in self.module_dependencies else [] for dep in required_deps: opt = "module_{}_enabled".format(dep) - if opt not in self or not self[opt]: - missing_deps.append(dep) - - if missing_deps != []: - print_warning( - "Disabling '{}' module as the following dependencies are not satisfied: {}".format( - module, ", ".join(missing_deps) + if opt not in self or not self[opt] or not module_check_dependencies(self, dep): + missing_deps.add(dep) + + if missing_deps: + if module not in self.disabled_modules: + print_warning( + "Disabling '{}' module as the following dependencies are not satisfied: {}".format( + module, ", ".join(missing_deps) + ) ) - ) + self.disabled_modules.add(module) return False else: return True @@ -478,8 +411,7 @@ def use_windows_spawn_fix(self, platform=None): "shell": False, "env": env, } - if sys.version_info >= (3, 7, 0): - popen_args["text"] = True + popen_args["text"] = True proc = subprocess.Popen(cmdline, **popen_args) _, err = proc.communicate() rv = proc.wait() @@ -565,40 +497,7 @@ def detect_visual_c_compiler_version(tools_env): vc_chosen_compiler_index = -1 vc_chosen_compiler_str = "" - # Start with Pre VS 2017 checks which uses VCINSTALLDIR: - if "VCINSTALLDIR" in tools_env: - # print("Checking VCINSTALLDIR") - - # find() works with -1 so big ifs below are needed... the simplest solution, in fact - # First test if amd64 and amd64_x86 compilers are present in the path - vc_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN\\amd64;") - if vc_amd64_compiler_detection_index > -1: - vc_chosen_compiler_index = vc_amd64_compiler_detection_index - vc_chosen_compiler_str = "amd64" - - vc_amd64_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN\\amd64_x86;") - if vc_amd64_x86_compiler_detection_index > -1 and ( - vc_chosen_compiler_index == -1 or vc_chosen_compiler_index > vc_amd64_x86_compiler_detection_index - ): - vc_chosen_compiler_index = vc_amd64_x86_compiler_detection_index - vc_chosen_compiler_str = "amd64_x86" - - # Now check the 32 bit compilers - vc_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN;") - if vc_x86_compiler_detection_index > -1 and ( - vc_chosen_compiler_index == -1 or vc_chosen_compiler_index > vc_x86_compiler_detection_index - ): - vc_chosen_compiler_index = vc_x86_compiler_detection_index - vc_chosen_compiler_str = "x86" - - vc_x86_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN\\x86_amd64;") - if vc_x86_amd64_compiler_detection_index > -1 and ( - vc_chosen_compiler_index == -1 or vc_chosen_compiler_index > vc_x86_amd64_compiler_detection_index - ): - vc_chosen_compiler_index = vc_x86_amd64_compiler_detection_index - vc_chosen_compiler_str = "x86_amd64" - - # and for VS 2017 and newer we check VCTOOLSINSTALLDIR: + # VS 2017 and newer should set VCTOOLSINSTALLDIR if "VCTOOLSINSTALLDIR" in tools_env: # Newer versions have a different path available vc_amd64_compiler_detection_index = ( @@ -695,23 +594,6 @@ def glob_recursive(pattern, node="."): return results -def add_to_vs_project(env, sources): - for x in sources: - fname = env.File(x).path if isinstance(x, str) else env.File(x)[0].path - pieces = fname.split(".") - if len(pieces) > 0: - basename = pieces[0] - basename = basename.replace("\\\\", "/") - if os.path.isfile(basename + ".h"): - env.vs_incs += [basename + ".h"] - elif os.path.isfile(basename + ".hpp"): - env.vs_incs += [basename + ".hpp"] - if os.path.isfile(basename + ".c"): - env.vs_srcs += [basename + ".c"] - elif os.path.isfile(basename + ".cpp"): - env.vs_srcs += [basename + ".cpp"] - - def precious_program(env, program, sources, **args): program = env.ProgramOriginal(program, sources, **args) env.Precious(program) @@ -772,7 +654,9 @@ def detect_darwin_sdk_path(platform, env): raise -def is_vanilla_clang(env): +def is_apple_clang(env): + if env["platform"] not in ["macos", "ios"]: + return False if not using_clang(env): return False try: @@ -780,7 +664,7 @@ def is_vanilla_clang(env): except (subprocess.CalledProcessError, OSError): print_warning("Couldn't parse CXX environment variable to infer compiler version.") return False - return not version.startswith("Apple") + return version.startswith("Apple") def get_compiler_version(env): @@ -904,159 +788,165 @@ def using_emcc(env): def show_progress(env): - if env["ninja"]: - # Has its own progress/tracking tool that clashes with ours + # Progress reporting is not available in non-TTY environments since it messes with the output + # (for example, when writing to a file). Ninja has its own progress/tracking tool that clashes + # with ours. + if not env["progress"] or not sys.stdout.isatty() or env["ninja"]: return - import sys - - from SCons.Script import AlwaysBuild, Command, Progress - - screen = sys.stdout - # Progress reporting is not available in non-TTY environments since it - # messes with the output (for example, when writing to a file) - show_progress = env["progress"] and sys.stdout.isatty() - node_count = 0 - node_count_max = 0 - node_count_interval = 1 - node_count_fname = str(env.Dir("#")) + "/.scons_node_count" - - import math - - class cache_progress: - # The default is 1 GB cache - def __init__(self, path=None, limit=pow(1024, 3)): - self.path = path - self.limit = limit - if env["verbose"] and path is not None: - screen.write( - "Current cache limit is {} (used: {})\n".format( - self.convert_size(limit), self.convert_size(self.get_size(path)) - ) - ) + NODE_COUNT_FILENAME = f"{base_folder_path}.scons_node_count" + + class ShowProgress: + def __init__(self): + self.count = 0 + self.max = 0 + try: + with open(NODE_COUNT_FILENAME, "r", encoding="utf-8") as f: + self.max = int(f.readline()) + except OSError: + pass + if self.max == 0: + print("NOTE: Performing initial build, progress percentage unavailable!") def __call__(self, node, *args, **kw): - nonlocal node_count, node_count_max, node_count_interval, node_count_fname, show_progress - if show_progress: - # Print the progress percentage - node_count += node_count_interval - if node_count_max > 0 and node_count <= node_count_max: - screen.write("\r[%3d%%] " % (node_count * 100 / node_count_max)) - screen.flush() - elif node_count_max > 0 and node_count > node_count_max: - screen.write("\r[100%] ") - screen.flush() - else: - screen.write("\r[Initial build] ") - screen.flush() - - def convert_size(self, size_bytes): - if size_bytes == 0: - return "0 bytes" - size_name = ("bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") - i = int(math.floor(math.log(size_bytes, 1024))) - p = math.pow(1024, i) - s = round(size_bytes / p, 2) - return "%s %s" % (int(s) if i == 0 else s, size_name[i]) - - def get_size(self, start_path="."): - total_size = 0 - for dirpath, dirnames, filenames in os.walk(start_path): - for f in filenames: - fp = os.path.join(dirpath, f) - total_size += os.path.getsize(fp) - return total_size + self.count += 1 + if self.max != 0: + percent = int(min(self.count * 100 / self.max, 100)) + sys.stdout.write(f"\r[{percent:3d}%] ") + sys.stdout.flush() + + from SCons.Script import Progress + + progressor = ShowProgress() + Progress(progressor) def progress_finish(target, source, env): - nonlocal node_count, progressor try: - with open(node_count_fname, "w", encoding="utf-8", newline="\n") as f: - f.write("%d\n" % node_count) - except Exception: + with open(NODE_COUNT_FILENAME, "w", encoding="utf-8", newline="\n") as f: + f.write(f"{progressor.count}\n") + except OSError: pass - try: - with open(node_count_fname, "r", encoding="utf-8") as f: - node_count_max = int(f.readline()) - except Exception: - pass + env.AlwaysBuild( + env.CommandNoCache( + "progress_finish", [], env.Action(progress_finish, "Building node count database .scons_node_count") + ) + ) + + +def convert_size(size_bytes: int) -> str: + if size_bytes == 0: + return "0 bytes" + SIZE_NAMES = ["bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"] + index = math.floor(math.log(size_bytes, 1024)) + power = math.pow(1024, index) + size = round(size_bytes / power, 2) + return f"{size} {SIZE_NAMES[index]}" - cache_directory = os.environ.get("SCONS_CACHE") - # Simple cache pruning, attached to SCons' progress callback. Trim the - # cache directory to a size not larger than cache_limit. - cache_limit = float(os.getenv("SCONS_CACHE_LIMIT", 1024)) * 1024 * 1024 - progressor = cache_progress(cache_directory, cache_limit) - Progress(progressor, interval=node_count_interval) - - progress_finish_command = Command("progress_finish", [], progress_finish) - AlwaysBuild(progress_finish_command) - - -def clean_cache(env): - import atexit - import time - - class cache_clean: - def __init__(self, path=None, limit=pow(1024, 3)): - self.path = path - self.limit = limit - - def clean(self): - self.delete(self.file_list()) - - def delete(self, files): - if len(files) == 0: - return - if env["verbose"]: - # Utter something - print("Purging %d %s from cache..." % (len(files), "files" if len(files) > 1 else "file")) - [os.remove(f) for f in files] - - def file_list(self): - if self.path is None: - # Nothing to do - return [] - # Gather a list of (filename, (size, atime)) within the - # cache directory - file_stat = [(x, os.stat(x)[6:8]) for x in glob.glob(os.path.join(self.path, "*", "*"))] - if file_stat == []: - # Nothing to do - return [] - # Weight the cache files by size (assumed to be roughly - # proportional to the recompilation time) times an exponential - # decay since the ctime, and return a list with the entries - # (filename, size, weight). - current_time = time.time() - file_stat = [(x[0], x[1][0], (current_time - x[1][1])) for x in file_stat] - # Sort by the most recently accessed files (most sensible to keep) first - file_stat.sort(key=lambda x: x[2]) - # Search for the first entry where the storage limit is - # reached - sum, mark = 0, None - for i, x in enumerate(file_stat): - sum += x[1] - if sum > self.limit: - mark = i - break - if mark is None: - return [] - else: - return [x[0] for x in file_stat[mark:]] - def cache_finally(): - nonlocal cleaner +def get_size(start_path: str = ".") -> int: + total_size = 0 + for dirpath, _, filenames in os.walk(start_path): + for file in filenames: + path = os.path.join(dirpath, file) + total_size += os.path.getsize(path) + return total_size + + +def clean_cache(cache_path: str, cache_limit: int, verbose: bool): + files = glob.glob(os.path.join(cache_path, "*", "*")) + if not files: + return + + # Remove all text files, store binary files in list of (filename, size, atime). + purge = [] + texts = [] + stats = [] + for file in files: try: - cleaner.clean() - except Exception: - pass + # Save file stats to rewrite after modifying. + tmp_stat = os.stat(file) + # Failing a utf-8 decode is the easiest way to determine if a file is binary. + try: + with open(file, encoding="utf-8") as out: + out.read(1024) + except UnicodeDecodeError: + stats.append((file, *tmp_stat[6:8])) + # Restore file stats after reading. + os.utime(file, (tmp_stat[7], tmp_stat[8])) + else: + texts.append(file) + except OSError: + print_error(f'Failed to access cache file "{file}"; skipping.') + + if texts: + count = len(texts) + for file in texts: + try: + os.remove(file) + except OSError: + print_error(f'Failed to remove cache file "{file}"; skipping.') + count -= 1 + if verbose: + print("Purging %d text %s from cache..." % (count, "files" if count > 1 else "file")) + + if cache_limit: + # Sort by most recent access (most sensible to keep) first. Search for the first entry where + # the cache limit is reached. + stats.sort(key=lambda x: x[2], reverse=True) + sum = 0 + for index, stat in enumerate(stats): + sum += stat[1] + if sum > cache_limit: + purge.extend([x[0] for x in stats[index:]]) + break - cache_directory = os.environ.get("SCONS_CACHE") - # Simple cache pruning, attached to SCons' progress callback. Trim the - # cache directory to a size not larger than cache_limit. - cache_limit = float(os.getenv("SCONS_CACHE_LIMIT", 1024)) * 1024 * 1024 - cleaner = cache_clean(cache_directory, cache_limit) + if purge: + count = len(purge) + for file in purge: + try: + os.remove(file) + except OSError: + print_error(f'Failed to remove cache file "{file}"; skipping.') + count -= 1 + if verbose: + print("Purging %d %s from cache..." % (count, "files" if count > 1 else "file")) + + +def prepare_cache(env) -> None: + if env.GetOption("clean"): + return + + cache_path = "" + if env["cache_path"]: + cache_path = cast(str, env["cache_path"]) + elif os.environ.get("SCONS_CACHE"): + print_warning("Environment variable `SCONS_CACHE` is deprecated; use `cache_path` argument instead.") + cache_path = cast(str, os.environ.get("SCONS_CACHE")) + + if not cache_path: + return + + env.CacheDir(cache_path) + print(f'SCons cache enabled... (path: "{cache_path}")') + + if env["cache_limit"]: + cache_limit = float(env["cache_limit"]) + elif os.environ.get("SCONS_CACHE_LIMIT"): + print_warning("Environment variable `SCONS_CACHE_LIMIT` is deprecated; use `cache_limit` argument instead.") + cache_limit = float(os.getenv("SCONS_CACHE_LIMIT", "0")) / 1024 # Old method used MiB, convert to GiB + + # Convert GiB to bytes; treat negative numbers as 0 (unlimited). + cache_limit = max(0, int(cache_limit * 1024 * 1024 * 1024)) + if env["verbose"]: + print( + "Current cache limit is {} (used: {})".format( + convert_size(cache_limit) if cache_limit else "∞", + convert_size(get_size(cache_path)), + ) + ) - atexit.register(cache_finally) + atexit.register(clean_cache, cache_path, cache_limit, env["verbose"]) def dump(env): @@ -1127,6 +1017,30 @@ def generate_vs_project(env, original_args, project_name="godot"): return v[0] if len(v) == 1 else f"{v[0]}={v[1]}" return v + def get_dependencies(file, env, exts, headers, sources, others): + for child in file.children(): + if isinstance(child, str): + child = env.File(x) + fname = "" + try: + fname = child.path + except AttributeError: + # It's not a file. + pass + + if fname: + parts = os.path.splitext(fname) + if len(parts) > 1: + ext = parts[1].lower() + if ext in exts["sources"]: + sources += [fname] + elif ext in exts["headers"]: + headers += [fname] + elif ext in exts["others"]: + others += [fname] + + get_dependencies(child, env, exts, headers, sources, others) + filtered_args = original_args.copy() # Ignore the "vsproj" option to not regenerate the VS project on every build @@ -1188,35 +1102,35 @@ def generate_vs_project(env, original_args, project_name="godot"): sys.path.remove(tmppath) sys.modules.pop("msvs") + extensions = {} + extensions["headers"] = [".h", ".hh", ".hpp", ".hxx", ".inc"] + extensions["sources"] = [".c", ".cc", ".cpp", ".cxx", ".m", ".mm", ".java"] + extensions["others"] = [".natvis", ".glsl", ".rc"] + headers = [] headers_dirs = [] - for file in glob_recursive_2("*.h", headers_dirs): - headers.append(str(file).replace("/", "\\")) - for file in glob_recursive_2("*.hpp", headers_dirs): - headers.append(str(file).replace("/", "\\")) + for ext in extensions["headers"]: + for file in glob_recursive_2("*" + ext, headers_dirs): + headers.append(str(file).replace("/", "\\")) sources = [] sources_dirs = [] - for file in glob_recursive_2("*.cpp", sources_dirs): - sources.append(str(file).replace("/", "\\")) - for file in glob_recursive_2("*.c", sources_dirs): - sources.append(str(file).replace("/", "\\")) + for ext in extensions["sources"]: + for file in glob_recursive_2("*" + ext, sources_dirs): + sources.append(str(file).replace("/", "\\")) others = [] others_dirs = [] - for file in glob_recursive_2("*.natvis", others_dirs): - others.append(str(file).replace("/", "\\")) - for file in glob_recursive_2("*.glsl", others_dirs): - others.append(str(file).replace("/", "\\")) + for ext in extensions["others"]: + for file in glob_recursive_2("*" + ext, others_dirs): + others.append(str(file).replace("/", "\\")) skip_filters = False import hashlib import json md5 = hashlib.md5( - json.dumps(headers + headers_dirs + sources + sources_dirs + others + others_dirs, sort_keys=True).encode( - "utf-8" - ) + json.dumps(sorted(headers + headers_dirs + sources + sources_dirs + others + others_dirs)).encode("utf-8") ).hexdigest() if os.path.exists(f"{project_name}.vcxproj.filters"): @@ -1273,58 +1187,13 @@ def generate_vs_project(env, original_args, project_name="godot"): with open(f"{project_name}.vcxproj.filters", "w", encoding="utf-8", newline="\r\n") as f: f.write(filters_template) - envsources = [] - - envsources += env.core_sources - envsources += env.drivers_sources - envsources += env.main_sources - envsources += env.modules_sources - envsources += env.scene_sources - envsources += env.servers_sources - if env.editor_build: - envsources += env.editor_sources - envsources += env.platform_sources - headers_active = [] sources_active = [] others_active = [] - for x in envsources: - fname = "" - if isinstance(x, str): - fname = env.File(x).path - else: - # Some object files might get added directly as a File object and not a list. - try: - fname = env.File(x)[0].path - except Exception: - fname = x.path - pass - if fname: - fname = fname.replace("\\\\", "/") - parts = os.path.splitext(fname) - basename = parts[0] - ext = parts[1] - idx = fname.find(env["OBJSUFFIX"]) - if ext in [".h", ".hpp"]: - headers_active += [fname] - elif ext in [".c", ".cpp"]: - sources_active += [fname] - elif idx > 0: - basename = fname[:idx] - if os.path.isfile(basename + ".h"): - headers_active += [basename + ".h"] - elif os.path.isfile(basename + ".hpp"): - headers_active += [basename + ".hpp"] - elif basename.endswith(".gen") and os.path.isfile(basename[:-4] + ".h"): - headers_active += [basename[:-4] + ".h"] - if os.path.isfile(basename + ".c"): - sources_active += [basename + ".c"] - elif os.path.isfile(basename + ".cpp"): - sources_active += [basename + ".cpp"] - else: - fname = os.path.relpath(os.path.abspath(fname), env.Dir("").abspath) - others_active += [fname] + get_dependencies( + env.File(f"#bin/godot{env['PROGSUFFIX']}"), env, extensions, headers_active, sources_active, others_active + ) all_items = [] properties = [] diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html index 352046df30..b59c417d36 100644 --- a/misc/dist/html/full-size.html +++ b/misc/dist/html/full-size.html @@ -38,7 +38,7 @@ body { } #status { - background-color: #242424; + background-color: $GODOT_SPLASH_COLOR; display: flex; flex-direction: column; justify-content: center; diff --git a/misc/dist/linux/org.godotengine.Godot.appdata.xml b/misc/dist/linux/org.godotengine.Godot.appdata.xml index af647bc866..8b27b6300d 100644 --- a/misc/dist/linux/org.godotengine.Godot.appdata.xml +++ b/misc/dist/linux/org.godotengine.Godot.appdata.xml @@ -6,7 +6,7 @@ <project_license>MIT</project_license> <name>Godot Engine</name> <summary>Multi-platform 2D and 3D game engine with a feature-rich editor</summary> - <launchable type="desktop-id">org.godotengine.Godot.desktop</launchable> + <launchable type="desktop-id">org.godotengine.Godot.desktop</launchable> <description> <p> Godot is an advanced, feature-packed, multi-platform 2D and 3D game diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected index 960edd0575..506844e6d6 100644 --- a/misc/extension_api_validation/4.3-stable.expected +++ b/misc/extension_api_validation/4.3-stable.expected @@ -7,7 +7,6 @@ should instead be used to justify these changes and describe how users should wo Add new entries at the end of the file. ## Changes between 4.3-stable and 4.4-stable - GH-95374 -------- Validate extension JSON: Error: Field 'classes/ShapeCast2D/properties/collision_result': getter changed value in new API, from "_get_collision_result" to &"get_collision_result". @@ -95,3 +94,68 @@ Validate extension JSON: Error: Field 'classes/InputMap/methods/add_action/argum Default deadzone value was changed. No adjustments should be necessary. Compatibility method registered. + + +GH-97020 +-------- +Validate extension JSON: Error: Field 'classes/AnimationNode/methods/_process': is_const changed value in new API, from true to false. + +`_process` virtual method fixed to be non const instead. + + +GH-97257 +-------- +Validate extension JSON: Error: Field 'classes/EditorFeatureProfile/enums/Feature/values/FEATURE_MAX': value changed value in new API, from 8.0 to 9. + +New entry to the `EditorFeatureProfile.Feature` enum added. Those need to go before `FEATURE_MAX`, which will always cause a compatibility break. + + +GH-91201 +-------- +Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/OS/methods/read_string_from_stdin': arguments + +Added optional argument. Compatibility method registered. + + +GH-98918 +-------- +Validate extension JSON: Error: Field 'classes/FileAccess/methods/open_encrypted/arguments': size changed value in new API, from 3 to 4. + +Optional argument added to allow setting initialization vector. Compatibility method registered. + + +GH-98972 +-------- +Validate extension JSON: Error: Field 'classes/TranslationServer/methods/standardize_locale/arguments': size changed value in new API, from 1 to 2. + +Optional argument added. Compatibility method registered. + + +GH-99424 +-------- +Validate extension JSON: API was removed: builtin_classes/Projection/constants/PLANE_BOTTOM +Validate extension JSON: API was removed: builtin_classes/Projection/constants/PLANE_FAR +Validate extension JSON: API was removed: builtin_classes/Projection/constants/PLANE_LEFT +Validate extension JSON: API was removed: builtin_classes/Projection/constants/PLANE_NEAR +Validate extension JSON: API was removed: builtin_classes/Projection/constants/PLANE_RIGHT +Validate extension JSON: API was removed: builtin_classes/Projection/constants/PLANE_TOP +Validate extension JSON: API was removed: builtin_classes/Vector2/constants/AXIS_X +Validate extension JSON: API was removed: builtin_classes/Vector2/constants/AXIS_Y +Validate extension JSON: API was removed: builtin_classes/Vector2i/constants/AXIS_X +Validate extension JSON: API was removed: builtin_classes/Vector2i/constants/AXIS_Y +Validate extension JSON: API was removed: builtin_classes/Vector3/constants/AXIS_X +Validate extension JSON: API was removed: builtin_classes/Vector3/constants/AXIS_Y +Validate extension JSON: API was removed: builtin_classes/Vector3/constants/AXIS_Z +Validate extension JSON: API was removed: builtin_classes/Vector3i/constants/AXIS_X +Validate extension JSON: API was removed: builtin_classes/Vector3i/constants/AXIS_Y +Validate extension JSON: API was removed: builtin_classes/Vector3i/constants/AXIS_Z +Validate extension JSON: API was removed: builtin_classes/Vector4/constants/AXIS_W +Validate extension JSON: API was removed: builtin_classes/Vector4/constants/AXIS_X +Validate extension JSON: API was removed: builtin_classes/Vector4/constants/AXIS_Y +Validate extension JSON: API was removed: builtin_classes/Vector4/constants/AXIS_Z +Validate extension JSON: API was removed: builtin_classes/Vector4i/constants/AXIS_W +Validate extension JSON: API was removed: builtin_classes/Vector4i/constants/AXIS_X +Validate extension JSON: API was removed: builtin_classes/Vector4i/constants/AXIS_Y +Validate extension JSON: API was removed: builtin_classes/Vector4i/constants/AXIS_Z + +These constants have been replaced with corresponding enum constants. diff --git a/misc/utility/.clang-format-glsl b/misc/utility/.clang-format-glsl new file mode 100644 index 0000000000..c588df0236 --- /dev/null +++ b/misc/utility/.clang-format-glsl @@ -0,0 +1,45 @@ +# 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 +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 +JavaImportGroups: + - org.godotengine + - android + - androidx + - com.android + - com.google + - java + - javax +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: false + AtStartOfFile: false +ObjCBlockIndentWidth: 4 +PackConstructorInitializers: NextLine +RemoveSemicolon: false # Differs from base .clang-format +SpacesInLineCommentPrefix: + Minimum: 0 + Maximum: -1 +Standard: c++20 +TabWidth: 4 +UseTab: Always diff --git a/modules/SCsub b/modules/SCsub index fea2f2eeb8..09944241ea 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -63,7 +63,6 @@ register_module_types = env.CommandNoCache( ) -vs_sources = [] test_headers = [] # libmodule_<name>.a for each active module. for name, path in env.module_list.items(): @@ -75,8 +74,6 @@ for name, path in env.module_list.items(): lib = env_modules.add_library("module_%s" % name, env.modules_sources) env.Prepend(LIBS=[lib]) - if env["vsproj"]: - vs_sources += env.modules_sources if env["tests"]: # Lookup potential headers in `tests` subfolder. @@ -104,5 +101,3 @@ env.modules_sources = [] env_modules.add_source_files(env.modules_sources, register_module_types) lib = env_modules.add_library("modules", env.modules_sources) env.Prepend(LIBS=[lib]) -if env["vsproj"]: - env.modules_sources += vs_sources diff --git a/modules/basis_universal/image_compress_basisu.cpp b/modules/basis_universal/image_compress_basisu.cpp index d48ea363a7..be28d89508 100644 --- a/modules/basis_universal/image_compress_basisu.cpp +++ b/modules/basis_universal/image_compress_basisu.cpp @@ -30,6 +30,7 @@ #include "image_compress_basisu.h" +#include "core/io/image.h" #include "core/os/os.h" #include "core/string/print_string.h" #include "servers/rendering_server.h" @@ -37,13 +38,12 @@ #include <transcoder/basisu_transcoder.h> #ifdef TOOLS_ENABLED #include <encoder/basisu_comp.h> -#endif -void basis_universal_init() { -#ifdef TOOLS_ENABLED - basisu::basisu_encoder_init(); +static Mutex init_mutex; +static bool initialized = false; #endif +void basis_universal_init() { basist::basisu_transcoder_init(); } @@ -79,6 +79,13 @@ inline void _basisu_pad_mipmap(const uint8_t *p_image_mip_data, Vector<uint8_t> } Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedChannels p_channels) { + init_mutex.lock(); + if (!initialized) { + basisu::basisu_encoder_init(); + initialized = true; + } + init_mutex.unlock(); + uint64_t start_time = OS::get_singleton()->get_ticks_msec(); Ref<Image> image = p_image->duplicate(); diff --git a/modules/bcdec/image_decompress_bcdec.cpp b/modules/bcdec/image_decompress_bcdec.cpp index c76470e3cc..8a62cd2a4e 100644 --- a/modules/bcdec/image_decompress_bcdec.cpp +++ b/modules/bcdec/image_decompress_bcdec.cpp @@ -47,7 +47,6 @@ inline void bcdec_bc6h_half_u(const void *compressedBlock, void *decompressedBlo static void decompress_image(BCdecFormat format, const void *src, void *dst, const uint64_t width, const uint64_t height) { const uint8_t *src_blocks = reinterpret_cast<const uint8_t *>(src); uint8_t *dec_blocks = reinterpret_cast<uint8_t *>(dst); - uint64_t src_pos = 0, dst_pos = 0; #define DECOMPRESS_LOOP(func, block_size, color_bytesize, color_components) \ for (uint64_t y = 0; y < height; y += 4) { \ @@ -59,34 +58,96 @@ static void decompress_image(BCdecFormat format, const void *src, void *dst, con dst_pos += 3 * width * color_bytesize; \ } - switch (format) { - case BCdec_BC1: { - DECOMPRESS_LOOP(bcdec_bc1, BCDEC_BC1_BLOCK_SIZE, 4, 4) - } break; - case BCdec_BC2: { - DECOMPRESS_LOOP(bcdec_bc2, BCDEC_BC2_BLOCK_SIZE, 4, 4) - } break; - case BCdec_BC3: { - DECOMPRESS_LOOP(bcdec_bc3, BCDEC_BC3_BLOCK_SIZE, 4, 4) - } break; - case BCdec_BC4: { - DECOMPRESS_LOOP(bcdec_bc4, BCDEC_BC4_BLOCK_SIZE, 1, 1) - } break; - case BCdec_BC5: { - DECOMPRESS_LOOP(bcdec_bc5, BCDEC_BC5_BLOCK_SIZE, 2, 2) - } break; - case BCdec_BC6U: { - DECOMPRESS_LOOP(bcdec_bc6h_half_u, BCDEC_BC6H_BLOCK_SIZE, 6, 3) - } break; - case BCdec_BC6S: { - DECOMPRESS_LOOP(bcdec_bc6h_half_s, BCDEC_BC6H_BLOCK_SIZE, 6, 3) - } break; - case BCdec_BC7: { - DECOMPRESS_LOOP(bcdec_bc7, BCDEC_BC7_BLOCK_SIZE, 4, 4) - } break; +#define DECOMPRESS_LOOP_SAFE(func, block_size, color_bytesize, color_components, output) \ + for (uint64_t y = 0; y < height; y += 4) { \ + for (uint64_t x = 0; x < width; x += 4) { \ + const uint32_t yblock = MIN(height - y, 4ul); \ + const uint32_t xblock = MIN(width - x, 4ul); \ + \ + const bool incomplete = yblock < 4 && xblock < 4; \ + uint8_t *dec_out = incomplete ? output : &dec_blocks[y * 4 * width + x * color_bytesize]; \ + \ + func(&src_blocks[src_pos], dec_out, 4 * color_components); \ + src_pos += block_size; \ + \ + if (incomplete) { \ + for (uint32_t cy = 0; cy < yblock; cy++) { \ + for (uint32_t cx = 0; cx < xblock; cx++) { \ + memcpy(&dec_blocks[(y + cy) * 4 * width + (x + cx) * color_bytesize], &output[cy * 4 + cx * color_bytesize], color_bytesize); \ + } \ + } \ + } \ + } \ + } + + if (width % 4 != 0 || height % 4 != 0) { + uint64_t src_pos = 0; + + uint8_t r8_output[4 * 4]; + uint8_t rg8_output[4 * 4 * 2]; + uint8_t rgba8_output[4 * 4 * 4]; + uint8_t rgbh_output[4 * 4 * 6]; + + switch (format) { + case BCdec_BC1: { + DECOMPRESS_LOOP_SAFE(bcdec_bc1, BCDEC_BC1_BLOCK_SIZE, 4, 4, rgba8_output) + } break; + case BCdec_BC2: { + DECOMPRESS_LOOP_SAFE(bcdec_bc2, BCDEC_BC2_BLOCK_SIZE, 4, 4, rgba8_output) + } break; + case BCdec_BC3: { + DECOMPRESS_LOOP_SAFE(bcdec_bc3, BCDEC_BC3_BLOCK_SIZE, 4, 4, rgba8_output) + } break; + case BCdec_BC4: { + DECOMPRESS_LOOP_SAFE(bcdec_bc4, BCDEC_BC4_BLOCK_SIZE, 1, 1, r8_output) + } break; + case BCdec_BC5: { + DECOMPRESS_LOOP_SAFE(bcdec_bc5, BCDEC_BC5_BLOCK_SIZE, 2, 2, rg8_output) + } break; + case BCdec_BC6U: { + DECOMPRESS_LOOP_SAFE(bcdec_bc6h_half_u, BCDEC_BC6H_BLOCK_SIZE, 6, 3, rgbh_output) + } break; + case BCdec_BC6S: { + DECOMPRESS_LOOP_SAFE(bcdec_bc6h_half_s, BCDEC_BC6H_BLOCK_SIZE, 6, 3, rgbh_output) + } break; + case BCdec_BC7: { + DECOMPRESS_LOOP_SAFE(bcdec_bc7, BCDEC_BC7_BLOCK_SIZE, 4, 4, rgba8_output) + } break; + } + + } else { + uint64_t src_pos = 0, dst_pos = 0; + + switch (format) { + case BCdec_BC1: { + DECOMPRESS_LOOP(bcdec_bc1, BCDEC_BC1_BLOCK_SIZE, 4, 4) + } break; + case BCdec_BC2: { + DECOMPRESS_LOOP(bcdec_bc2, BCDEC_BC2_BLOCK_SIZE, 4, 4) + } break; + case BCdec_BC3: { + DECOMPRESS_LOOP(bcdec_bc3, BCDEC_BC3_BLOCK_SIZE, 4, 4) + } break; + case BCdec_BC4: { + DECOMPRESS_LOOP(bcdec_bc4, BCDEC_BC4_BLOCK_SIZE, 1, 1) + } break; + case BCdec_BC5: { + DECOMPRESS_LOOP(bcdec_bc5, BCDEC_BC5_BLOCK_SIZE, 2, 2) + } break; + case BCdec_BC6U: { + DECOMPRESS_LOOP(bcdec_bc6h_half_u, BCDEC_BC6H_BLOCK_SIZE, 6, 3) + } break; + case BCdec_BC6S: { + DECOMPRESS_LOOP(bcdec_bc6h_half_s, BCDEC_BC6H_BLOCK_SIZE, 6, 3) + } break; + case BCdec_BC7: { + DECOMPRESS_LOOP(bcdec_bc7, BCDEC_BC7_BLOCK_SIZE, 4, 4) + } break; + } } #undef DECOMPRESS_LOOP +#undef DECOMPRESS_LOOP_SAFE } void image_decompress_bcdec(Image *p_image) { diff --git a/modules/betsy/CrossPlatformSettings_piece_all.glsl b/modules/betsy/CrossPlatformSettings_piece_all.glsl index b7abac7fcc..001d8e63b2 100644 --- a/modules/betsy/CrossPlatformSettings_piece_all.glsl +++ b/modules/betsy/CrossPlatformSettings_piece_all.glsl @@ -1,4 +1,3 @@ - #define min3(a, b, c) min(a, min(b, c)) #define max3(a, b, c) max(a, max(b, c)) diff --git a/modules/betsy/UavCrossPlatform_piece_all.glsl b/modules/betsy/UavCrossPlatform_piece_all.glsl index 30854df637..5f074137af 100644 --- a/modules/betsy/UavCrossPlatform_piece_all.glsl +++ b/modules/betsy/UavCrossPlatform_piece_all.glsl @@ -1,4 +1,3 @@ - #define OGRE_imageLoad2D(inImage, iuv) imageLoad(inImage, int2(iuv)) #define OGRE_imageLoad2DArray(inImage, iuvw) imageLoad(inImage, int3(iuvw)) diff --git a/modules/betsy/image_compress_betsy.cpp b/modules/betsy/image_compress_betsy.cpp index 6bfe01f65c..1ad9bed721 100644 --- a/modules/betsy/image_compress_betsy.cpp +++ b/modules/betsy/image_compress_betsy.cpp @@ -37,11 +37,16 @@ #include "bc1.glsl.gen.h" #include "bc4.glsl.gen.h" #include "bc6h.glsl.gen.h" +#include "servers/display_server.h" static Mutex betsy_mutex; static BetsyCompressor *betsy = nullptr; void BetsyCompressor::_init() { + if (!DisplayServer::can_create_rendering_device()) { + return; + } + // Create local RD. RenderingContextDriver *rcd = nullptr; RenderingDevice *rd = RenderingServer::get_singleton()->create_local_rendering_device(); @@ -182,6 +187,11 @@ static String get_shader_name(BetsyFormat p_format) { Error BetsyCompressor::_compress(BetsyFormat p_format, Image *r_img) { uint64_t start_time = OS::get_singleton()->get_ticks_msec(); + // Return an error so that the compression can fall back to cpu compression + if (compress_rd == nullptr) { + return ERR_CANT_CREATE; + } + if (r_img->is_compressed()) { return ERR_INVALID_DATA; } diff --git a/modules/betsy/image_compress_betsy.h b/modules/betsy/image_compress_betsy.h index 4e0bf0538f..ab7b785803 100644 --- a/modules/betsy/image_compress_betsy.h +++ b/modules/betsy/image_compress_betsy.h @@ -91,10 +91,10 @@ class BetsyCompressor : public Object { RenderingDevice *compress_rd = nullptr; RenderingContextDriver *compress_rcd = nullptr; HashMap<String, BetsyShader> cached_shaders; - RID src_sampler = RID(); + RID src_sampler; // Format-specific resources. - RID dxt1_encoding_table_buffer = RID(); + RID dxt1_encoding_table_buffer; void _init(); void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id); diff --git a/modules/camera/camera_feed_linux.cpp b/modules/camera/camera_feed_linux.cpp index 94bb2b6ad3..3ae1b70ac9 100644 --- a/modules/camera/camera_feed_linux.cpp +++ b/modules/camera/camera_feed_linux.cpp @@ -145,7 +145,7 @@ bool CameraFeedLinux::_request_buffers() { } buffers[i].length = buffer.length; - buffers[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, buffer.m.offset); + buffers[i].start = mmap(nullptr, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, buffer.m.offset); if (buffers[i].start == MAP_FAILED) { for (unsigned int b = 0; b < i; b++) { diff --git a/modules/camera/camera_linux.cpp b/modules/camera/camera_linux.cpp index 0cfb6b7b9e..e5558bf96c 100644 --- a/modules/camera/camera_linux.cpp +++ b/modules/camera/camera_linux.cpp @@ -161,7 +161,7 @@ bool CameraLinux::_can_query_format(int p_file_descriptor, int p_type) { CameraLinux::CameraLinux() { camera_thread.start(CameraLinux::camera_thread_func, this); -}; +} CameraLinux::~CameraLinux() { exit_flag.set(); diff --git a/modules/camera/camera_macos.mm b/modules/camera/camera_macos.mm index de4f814846..bd718a0cb6 100644 --- a/modules/camera/camera_macos.mm +++ b/modules/camera/camera_macos.mm @@ -212,12 +212,12 @@ public: AVCaptureDevice *CameraFeedMacOS::get_device() const { return device; -}; +} CameraFeedMacOS::CameraFeedMacOS() { device = nullptr; capture_session = nullptr; -}; +} void CameraFeedMacOS::set_device(AVCaptureDevice *p_device) { device = p_device; @@ -231,7 +231,7 @@ void CameraFeedMacOS::set_device(AVCaptureDevice *p_device) { } else if ([p_device position] == AVCaptureDevicePositionFront) { position = CameraFeed::FEED_FRONT; }; -}; +} bool CameraFeedMacOS::activate_feed() { if (capture_session) { @@ -257,7 +257,7 @@ bool CameraFeedMacOS::activate_feed() { }; return true; -}; +} void CameraFeedMacOS::deactivate_feed() { // end camera capture if we have one @@ -265,7 +265,7 @@ void CameraFeedMacOS::deactivate_feed() { [capture_session cleanup]; capture_session = nullptr; }; -}; +} ////////////////////////////////////////////////////////////////////////// // MyDeviceNotifications - This is a little helper class gets notifications @@ -351,7 +351,7 @@ void CameraMacOS::update_feeds() { add_feed(newfeed); }; }; -}; +} CameraMacOS::CameraMacOS() { // Find available cameras we have at this time @@ -359,4 +359,4 @@ CameraMacOS::CameraMacOS() { // should only have one of these.... device_notifications = [[MyDeviceNotifications alloc] initForServer:this]; -}; +} diff --git a/modules/camera/camera_win.cpp b/modules/camera/camera_win.cpp index 755642270e..7871595d91 100644 --- a/modules/camera/camera_win.cpp +++ b/modules/camera/camera_win.cpp @@ -64,13 +64,13 @@ CameraFeedWindows::~CameraFeedWindows() { }; ///@TODO free up anything used by this -}; +} bool CameraFeedWindows::activate_feed() { ///@TODO this should activate our camera and start the process of capturing frames return true; -}; +} ///@TODO we should probably have a callback method here that is being called by the // camera API which provides frames and call back into the CameraServer to update our texture @@ -91,4 +91,4 @@ CameraWindows::CameraWindows() { add_active_cameras(); // need to add something that will react to devices being connected/removed... -}; +} diff --git a/modules/csg/editor/csg_gizmos.cpp b/modules/csg/editor/csg_gizmos.cpp index 95ffeed6c3..7e1c2e39b3 100644 --- a/modules/csg/editor/csg_gizmos.cpp +++ b/modules/csg/editor/csg_gizmos.cpp @@ -63,7 +63,7 @@ void CSGShapeEditor::edit(CSGShape3D *p_csg_shape) { void CSGShapeEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - options->set_icon(get_editor_theme_icon(SNAME("CSGCombiner3D"))); + options->set_button_icon(get_editor_theme_icon(SNAME("CSGCombiner3D"))); } break; } } @@ -278,24 +278,13 @@ void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_i if (Object::cast_to<CSGCylinder3D>(cs)) { CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); - Vector3 axis; - axis[p_id == 0 ? 0 : 1] = 1.0; - Vector3 ra, rb; - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = axis.dot(ra); - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - - if (p_id == 0) { - s->set_radius(d); - } else if (p_id == 1) { - s->set_height(d * 2.0); - } + real_t height = s->get_height(); + real_t radius = s->get_radius(); + Vector3 position; + helper->cylinder_set_handle(sg, p_id, height, radius, position); + s->set_height(height); + s->set_radius(radius); + s->set_global_position(position); } if (Object::cast_to<CSGTorus3D>(cs)) { @@ -340,32 +329,11 @@ void CSGShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int } if (Object::cast_to<CSGBox3D>(cs)) { - helper->box_commit_handle(TTR("Change Box Shape Size"), p_cancel, cs); + helper->box_commit_handle(TTR("Change CSG Box Size"), p_cancel, cs); } if (Object::cast_to<CSGCylinder3D>(cs)) { - CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); - if (p_cancel) { - if (p_id == 0) { - s->set_radius(p_restore); - } else { - s->set_height(p_restore); - } - return; - } - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - if (p_id == 0) { - ur->create_action(TTR("Change Cylinder Radius")); - ur->add_do_method(s, "set_radius", s->get_radius()); - ur->add_undo_method(s, "set_radius", p_restore); - } else { - ur->create_action(TTR("Change Cylinder Height")); - ur->add_do_method(s, "set_height", s->get_height()); - ur->add_undo_method(s, "set_height", p_restore); - } - - ur->commit_action(); + helper->cylinder_commit_handle(p_id, TTR("Change CSG Cylinder Radius"), TTR("Change CSG Cylinder Height"), p_cancel, cs); } if (Object::cast_to<CSGTorus3D>(cs)) { @@ -506,9 +474,7 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (Object::cast_to<CSGCylinder3D>(cs)) { CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); - Vector<Vector3> handles; - handles.push_back(Vector3(s->get_radius(), 0, 0)); - handles.push_back(Vector3(0, s->get_height() * 0.5, 0)); + Vector<Vector3> handles = helper->cylinder_get_handles(s->get_height(), s->get_radius()); p_gizmo->add_handles(handles, handles_material); } diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index 6ea44c5fc3..601d0e0c24 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -46,7 +46,12 @@ enum { DDPF_ALPHAONLY = 0x00000002, DDPF_FOURCC = 0x00000004, DDPF_RGB = 0x00000040, - DDPF_RG_SNORM = 0x00080000 + DDPF_RG_SNORM = 0x00080000, + DDSC2_CUBEMAP = 0x200, + DDSC2_VOLUME = 0x200000, + DX10D_1D = 2, + DX10D_2D = 3, + DX10D_3D = 4, }; enum DDSFourCC { @@ -139,6 +144,15 @@ enum DDSFormat { DDS_MAX }; +enum DDSType { + DDST_2D = 1, + DDST_CUBEMAP, + DDST_3D, + + DDST_TYPE_MASK = 0x7F, + DDST_ARRAY = 0x80, +}; + struct DDSFormatInfo { const char *name = nullptr; bool compressed = false; @@ -180,7 +194,7 @@ static const DDSFormatInfo dds_format_info[DDS_MAX] = { { "GRAYSCALE_ALPHA_4", false, 1, 1, Image::FORMAT_LA8 } }; -static DDSFormat dxgi_to_dds_format(uint32_t p_dxgi_format) { +inline DDSFormat _dxgi_to_dds_format(uint32_t p_dxgi_format) { switch (p_dxgi_format) { case DXGI_R32G32B32A32_FLOAT: { return DDS_RGBA32F; @@ -267,210 +281,23 @@ static DDSFormat dxgi_to_dds_format(uint32_t p_dxgi_format) { } } -Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - if (r_error) { - *r_error = ERR_CANT_OPEN; - } - - Error err; - Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); - if (f.is_null()) { - return Ref<Resource>(); - } - - Ref<FileAccess> fref(f); - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - - ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Unable to open DDS texture file '" + p_path + "'."); - - uint32_t magic = f->get_32(); - uint32_t hsize = f->get_32(); - uint32_t flags = f->get_32(); - uint32_t height = f->get_32(); - uint32_t width = f->get_32(); - uint32_t pitch = f->get_32(); - /* uint32_t depth = */ f->get_32(); - uint32_t mipmaps = f->get_32(); - - // Skip reserved. - for (int i = 0; i < 11; i++) { - f->get_32(); - } - - // Validate. - // We don't check DDSD_CAPS or DDSD_PIXELFORMAT, as they're mandatory when writing, - // but non-mandatory when reading (as some writers don't set them). - if (magic != DDS_MAGIC || hsize != 124) { - ERR_FAIL_V_MSG(Ref<Resource>(), "Invalid or unsupported DDS texture file '" + p_path + "'."); - } - - /* uint32_t format_size = */ f->get_32(); - uint32_t format_flags = f->get_32(); - uint32_t format_fourcc = f->get_32(); - uint32_t format_rgb_bits = f->get_32(); - uint32_t format_red_mask = f->get_32(); - uint32_t format_green_mask = f->get_32(); - uint32_t format_blue_mask = f->get_32(); - uint32_t format_alpha_mask = f->get_32(); - - /* uint32_t caps_1 = */ f->get_32(); - /* uint32_t caps_2 = */ f->get_32(); - /* uint32_t caps_3 = */ f->get_32(); - /* uint32_t caps_4 = */ f->get_32(); - - // Skip reserved. - f->get_32(); - - if (f->get_position() < 128) { - f->seek(128); - } - - DDSFormat dds_format = DDS_MAX; - - if (format_flags & DDPF_FOURCC) { - // FourCC formats. - switch (format_fourcc) { - case DDFCC_DXT1: { - dds_format = DDS_DXT1; - } break; - case DDFCC_DXT2: - case DDFCC_DXT3: { - dds_format = DDS_DXT3; - } break; - case DDFCC_DXT4: - case DDFCC_DXT5: { - dds_format = DDS_DXT5; - } break; - case DDFCC_ATI1: - case DDFCC_BC4U: { - dds_format = DDS_ATI1; - } break; - case DDFCC_ATI2: - case DDFCC_BC5U: - case DDFCC_A2XY: { - dds_format = DDS_ATI2; - } break; - case DDFCC_R16F: { - dds_format = DDS_R16F; - } break; - case DDFCC_RG16F: { - dds_format = DDS_RG16F; - } break; - case DDFCC_RGBA16F: { - dds_format = DDS_RGBA16F; - } break; - case DDFCC_R32F: { - dds_format = DDS_R32F; - } break; - case DDFCC_RG32F: { - dds_format = DDS_RG32F; - } break; - case DDFCC_RGBA32F: { - dds_format = DDS_RGBA32F; - } break; - case DDFCC_DX10: { - uint32_t dxgi_format = f->get_32(); - /* uint32_t dimension = */ f->get_32(); - /* uint32_t misc_flags_1 = */ f->get_32(); - /* uint32_t array_size = */ f->get_32(); - /* uint32_t misc_flags_2 = */ f->get_32(); - - dds_format = dxgi_to_dds_format(dxgi_format); - } break; - - default: { - ERR_FAIL_V_MSG(Ref<Resource>(), "Unrecognized or unsupported FourCC in DDS '" + p_path + "'."); - } - } - - } else if (format_flags & DDPF_RGB) { - // Channel-bitmasked formats. - if (format_flags & DDPF_ALPHAPIXELS) { - // With alpha. - if (format_rgb_bits == 32 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff && format_alpha_mask == 0xff000000) { - dds_format = DDS_BGRA8; - } else if (format_rgb_bits == 32 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000 && format_alpha_mask == 0xff000000) { - dds_format = DDS_RGBA8; - } else if (format_rgb_bits == 16 && format_red_mask == 0x00007c00 && format_green_mask == 0x000003e0 && format_blue_mask == 0x0000001f && format_alpha_mask == 0x00008000) { - dds_format = DDS_BGR5A1; - } else if (format_rgb_bits == 32 && format_red_mask == 0x3ff00000 && format_green_mask == 0xffc00 && format_blue_mask == 0x3ff && format_alpha_mask == 0xc0000000) { - dds_format = DDS_BGR10A2; - } else if (format_rgb_bits == 32 && format_red_mask == 0x3ff && format_green_mask == 0xffc00 && format_blue_mask == 0x3ff00000 && format_alpha_mask == 0xc0000000) { - dds_format = DDS_RGB10A2; - } else if (format_rgb_bits == 16 && format_red_mask == 0xf00 && format_green_mask == 0xf0 && format_blue_mask == 0xf && format_alpha_mask == 0xf000) { - dds_format = DDS_BGRA4; - } else if (format_rgb_bits == 16 && format_red_mask == 0xe0 && format_green_mask == 0x1c && format_blue_mask == 0x3 && format_alpha_mask == 0xff00) { - dds_format = DDS_B2GR3A8; - } +static Ref<Image> _dds_load_layer(Ref<FileAccess> p_file, DDSFormat p_dds_format, uint32_t p_width, uint32_t p_height, uint32_t p_mipmaps, uint32_t p_pitch, uint32_t p_flags, Vector<uint8_t> &r_src_data) { + const DDSFormatInfo &info = dds_format_info[p_dds_format]; - } else { - // Without alpha. - if (format_rgb_bits == 24 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff) { - dds_format = DDS_BGR8; - } else if (format_rgb_bits == 24 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000) { - dds_format = DDS_RGB8; - } else if (format_rgb_bits == 16 && format_red_mask == 0x0000f800 && format_green_mask == 0x000007e0 && format_blue_mask == 0x0000001f) { - dds_format = DDS_BGR565; - } else if (format_rgb_bits == 8 && format_red_mask == 0xe0 && format_green_mask == 0x1c && format_blue_mask == 0x3) { - dds_format = DDS_B2GR3; - } - } - - } else { - // Other formats. - if (format_flags & DDPF_ALPHAONLY && format_rgb_bits == 8 && format_alpha_mask == 0xff) { - // Alpha only. - dds_format = DDS_LUMINANCE; - } - } - - // Depending on the writer, luminance formats may or may not have the DDPF_RGB or DDPF_LUMINANCE flags defined, - // so we check for these formats after everything else failed. - if (dds_format == DDS_MAX) { - if (format_flags & DDPF_ALPHAPIXELS) { - // With alpha. - if (format_rgb_bits == 16 && format_red_mask == 0xff && format_alpha_mask == 0xff00) { - dds_format = DDS_LUMINANCE_ALPHA; - } else if (format_rgb_bits == 8 && format_red_mask == 0xf && format_alpha_mask == 0xf0) { - dds_format = DDS_LUMINANCE_ALPHA_4; - } - - } else { - // Without alpha. - if (format_rgb_bits == 8 && format_red_mask == 0xff) { - dds_format = DDS_LUMINANCE; - } - } - } - - // No format detected, error. - if (dds_format == DDS_MAX) { - ERR_FAIL_V_MSG(Ref<Resource>(), "Unrecognized or unsupported color layout in DDS '" + p_path + "'."); - } - - if (!(flags & DDSD_MIPMAPCOUNT)) { - mipmaps = 1; - } - - Vector<uint8_t> src_data; - - const DDSFormatInfo &info = dds_format_info[dds_format]; - uint32_t w = width; - uint32_t h = height; + uint32_t w = p_width; + uint32_t h = p_height; if (info.compressed) { // BC compressed. uint32_t size = MAX(info.divisor, w) / info.divisor * MAX(info.divisor, h) / info.divisor * info.block_size; - if (flags & DDSD_LINEARSIZE) { - ERR_FAIL_COND_V_MSG(size != pitch, Ref<Resource>(), "DDS header flags specify that a linear size of the top-level image is present, but the specified size does not match the expected value."); + if (p_flags & DDSD_LINEARSIZE) { + ERR_FAIL_COND_V_MSG(size != p_pitch, Ref<Resource>(), "DDS header flags specify that a linear size of the top-level image is present, but the specified size does not match the expected value."); } else { - ERR_FAIL_COND_V_MSG(pitch != 0, Ref<Resource>(), "DDS header flags specify that no linear size will given for the top-level image, but a non-zero linear size value is present in the header."); + ERR_FAIL_COND_V_MSG(p_pitch != 0, Ref<Resource>(), "DDS header flags specify that no linear size will given for the top-level image, but a non-zero linear size value is present in the header."); } - for (uint32_t i = 1; i < mipmaps; i++) { + for (uint32_t i = 1; i < p_mipmaps; i++) { w = MAX(1u, w >> 1); h = MAX(1u, h >> 1); @@ -478,22 +305,22 @@ Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_orig size += bsize; } - src_data.resize(size); - uint8_t *wb = src_data.ptrw(); - f->get_buffer(wb, size); + r_src_data.resize(size); + uint8_t *wb = r_src_data.ptrw(); + p_file->get_buffer(wb, size); } else { // Generic uncompressed. - uint32_t size = width * height * info.block_size; + uint32_t size = p_width * p_height * info.block_size; - for (uint32_t i = 1; i < mipmaps; i++) { + for (uint32_t i = 1; i < p_mipmaps; i++) { w = (w + 1) >> 1; h = (h + 1) >> 1; size += w * h * info.block_size; } // Calculate the space these formats will take up after decoding. - switch (dds_format) { + switch (p_dds_format) { case DDS_BGR565: size = size * 3 / 2; break; @@ -513,12 +340,11 @@ Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_orig break; } - src_data.resize(size); - uint8_t *wb = src_data.ptrw(); - f->get_buffer(wb, size); + r_src_data.resize(size); + uint8_t *wb = r_src_data.ptrw(); + p_file->get_buffer(wb, size); - // Decode nonstandard formats. - switch (dds_format) { + switch (p_dds_format) { case DDS_BGR5A1: { // To RGBA8. int colcount = size / 4; @@ -705,14 +531,282 @@ Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_orig } } - Ref<Image> img = memnew(Image(width, height, mipmaps - 1, info.format, src_data)); - Ref<ImageTexture> texture = ImageTexture::create_from_image(img); + return memnew(Image(p_width, p_height, p_mipmaps > 1, info.format, r_src_data)); +} + +Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + if (r_error) { + *r_error = ERR_CANT_OPEN; + } + + Error err; + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); + if (f.is_null()) { + return Ref<Resource>(); + } + Ref<FileAccess> fref(f); if (r_error) { - *r_error = OK; + *r_error = ERR_FILE_CORRUPT; + } + + ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), vformat("Unable to open DDS texture file '%s'.", p_path)); + + uint32_t magic = f->get_32(); + uint32_t hsize = f->get_32(); + uint32_t flags = f->get_32(); + uint32_t height = f->get_32(); + uint32_t width = f->get_32(); + uint32_t pitch = f->get_32(); + uint32_t depth = f->get_32(); + uint32_t mipmaps = f->get_32(); + + // Skip reserved. + for (int i = 0; i < 11; i++) { + f->get_32(); + } + + // Validate. + // We don't check DDSD_CAPS or DDSD_PIXELFORMAT, as they're mandatory when writing, + // but non-mandatory when reading (as some writers don't set them). + if (magic != DDS_MAGIC || hsize != 124) { + ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Invalid or unsupported DDS texture file '%s'.", p_path)); + } + + /* uint32_t format_size = */ f->get_32(); + uint32_t format_flags = f->get_32(); + uint32_t format_fourcc = f->get_32(); + uint32_t format_rgb_bits = f->get_32(); + uint32_t format_red_mask = f->get_32(); + uint32_t format_green_mask = f->get_32(); + uint32_t format_blue_mask = f->get_32(); + uint32_t format_alpha_mask = f->get_32(); + + /* uint32_t caps_1 = */ f->get_32(); + uint32_t caps_2 = f->get_32(); + /* uint32_t caps_3 = */ f->get_32(); + /* uint32_t caps_4 = */ f->get_32(); + + // Skip reserved. + f->get_32(); + + if (f->get_position() < 128) { + f->seek(128); + } + + uint32_t layer_count = 1; + uint32_t dds_type = DDST_2D; + + if (caps_2 & DDSC2_CUBEMAP) { + dds_type = DDST_CUBEMAP; + layer_count *= 6; + + } else if (caps_2 & DDSC2_VOLUME) { + dds_type = DDST_3D; + layer_count = depth; + } + + DDSFormat dds_format = DDS_MAX; + + if (format_flags & DDPF_FOURCC) { + // FourCC formats. + switch (format_fourcc) { + case DDFCC_DXT1: { + dds_format = DDS_DXT1; + } break; + case DDFCC_DXT2: + case DDFCC_DXT3: { + dds_format = DDS_DXT3; + } break; + case DDFCC_DXT4: + case DDFCC_DXT5: { + dds_format = DDS_DXT5; + } break; + case DDFCC_ATI1: + case DDFCC_BC4U: { + dds_format = DDS_ATI1; + } break; + case DDFCC_ATI2: + case DDFCC_BC5U: + case DDFCC_A2XY: { + dds_format = DDS_ATI2; + } break; + case DDFCC_R16F: { + dds_format = DDS_R16F; + } break; + case DDFCC_RG16F: { + dds_format = DDS_RG16F; + } break; + case DDFCC_RGBA16F: { + dds_format = DDS_RGBA16F; + } break; + case DDFCC_R32F: { + dds_format = DDS_R32F; + } break; + case DDFCC_RG32F: { + dds_format = DDS_RG32F; + } break; + case DDFCC_RGBA32F: { + dds_format = DDS_RGBA32F; + } break; + case DDFCC_DX10: { + uint32_t dxgi_format = f->get_32(); + uint32_t dimension = f->get_32(); + /* uint32_t misc_flags_1 = */ f->get_32(); + uint32_t array_size = f->get_32(); + /* uint32_t misc_flags_2 = */ f->get_32(); + + if (dimension == DX10D_3D) { + dds_type = DDST_3D; + layer_count = depth; + } + + if (array_size > 1) { + layer_count *= array_size; + dds_type |= DDST_ARRAY; + } + + dds_format = _dxgi_to_dds_format(dxgi_format); + } break; + + default: { + ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Unrecognized or unsupported FourCC in DDS '%s'.", p_path)); + } + } + + } else if (format_flags & DDPF_RGB) { + // Channel-bitmasked formats. + if (format_flags & DDPF_ALPHAPIXELS) { + // With alpha. + if (format_rgb_bits == 32 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff && format_alpha_mask == 0xff000000) { + dds_format = DDS_BGRA8; + } else if (format_rgb_bits == 32 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000 && format_alpha_mask == 0xff000000) { + dds_format = DDS_RGBA8; + } else if (format_rgb_bits == 16 && format_red_mask == 0x00007c00 && format_green_mask == 0x000003e0 && format_blue_mask == 0x0000001f && format_alpha_mask == 0x00008000) { + dds_format = DDS_BGR5A1; + } else if (format_rgb_bits == 32 && format_red_mask == 0x3ff00000 && format_green_mask == 0xffc00 && format_blue_mask == 0x3ff && format_alpha_mask == 0xc0000000) { + dds_format = DDS_BGR10A2; + } else if (format_rgb_bits == 32 && format_red_mask == 0x3ff && format_green_mask == 0xffc00 && format_blue_mask == 0x3ff00000 && format_alpha_mask == 0xc0000000) { + dds_format = DDS_RGB10A2; + } else if (format_rgb_bits == 16 && format_red_mask == 0xf00 && format_green_mask == 0xf0 && format_blue_mask == 0xf && format_alpha_mask == 0xf000) { + dds_format = DDS_BGRA4; + } else if (format_rgb_bits == 16 && format_red_mask == 0xe0 && format_green_mask == 0x1c && format_blue_mask == 0x3 && format_alpha_mask == 0xff00) { + dds_format = DDS_B2GR3A8; + } + + } else { + // Without alpha. + if (format_rgb_bits == 24 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff) { + dds_format = DDS_BGR8; + } else if (format_rgb_bits == 24 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000) { + dds_format = DDS_RGB8; + } else if (format_rgb_bits == 16 && format_red_mask == 0x0000f800 && format_green_mask == 0x000007e0 && format_blue_mask == 0x0000001f) { + dds_format = DDS_BGR565; + } else if (format_rgb_bits == 8 && format_red_mask == 0xe0 && format_green_mask == 0x1c && format_blue_mask == 0x3) { + dds_format = DDS_B2GR3; + } + } + + } else { + // Other formats. + if (format_flags & DDPF_ALPHAONLY && format_rgb_bits == 8 && format_alpha_mask == 0xff) { + // Alpha only. + dds_format = DDS_LUMINANCE; + } + } + + // Depending on the writer, luminance formats may or may not have the DDPF_RGB or DDPF_LUMINANCE flags defined, + // so we check for these formats after everything else failed. + if (dds_format == DDS_MAX) { + if (format_flags & DDPF_ALPHAPIXELS) { + // With alpha. + if (format_rgb_bits == 16 && format_red_mask == 0xff && format_alpha_mask == 0xff00) { + dds_format = DDS_LUMINANCE_ALPHA; + } else if (format_rgb_bits == 8 && format_red_mask == 0xf && format_alpha_mask == 0xf0) { + dds_format = DDS_LUMINANCE_ALPHA_4; + } + + } else { + // Without alpha. + if (format_rgb_bits == 8 && format_red_mask == 0xff) { + dds_format = DDS_LUMINANCE; + } + } + } + + // No format detected, error. + if (dds_format == DDS_MAX) { + ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Unrecognized or unsupported color layout in DDS '%s'.", p_path)); + } + + if (!(flags & DDSD_MIPMAPCOUNT)) { + mipmaps = 1; + } + + Vector<uint8_t> src_data; + + Vector<Ref<Image>> images; + images.resize(layer_count); + + for (uint32_t i = 0; i < layer_count; i++) { + images.write[i] = _dds_load_layer(f, dds_format, width, height, mipmaps, pitch, flags, src_data); + } + + if ((dds_type & DDST_TYPE_MASK) == DDST_2D) { + if (dds_type & DDST_ARRAY) { + Ref<Texture2DArray> texture = memnew(Texture2DArray()); + texture->create_from_images(images); + + if (r_error) { + *r_error = OK; + } + + return texture; + + } else { + if (r_error) { + *r_error = OK; + } + + return ImageTexture::create_from_image(images[0]); + } + + } else if ((dds_type & DDST_TYPE_MASK) == DDST_CUBEMAP) { + ERR_FAIL_COND_V(layer_count % 6 != 0, Ref<Resource>()); + + if (dds_type & DDST_ARRAY) { + Ref<CubemapArray> texture = memnew(CubemapArray()); + texture->create_from_images(images); + + if (r_error) { + *r_error = OK; + } + + return texture; + + } else { + Ref<Cubemap> texture = memnew(Cubemap()); + texture->create_from_images(images); + + if (r_error) { + *r_error = OK; + } + + return texture; + } + + } else if ((dds_type & DDST_TYPE_MASK) == DDST_3D) { + Ref<ImageTexture3D> texture = memnew(ImageTexture3D()); + texture->create(images[0]->get_format(), width, height, layer_count, mipmaps > 1, images); + + if (r_error) { + *r_error = OK; + } + + return texture; } - return texture; + return Ref<Resource>(); } void ResourceFormatDDS::get_recognized_extensions(List<String> *p_extensions) const { @@ -720,12 +814,12 @@ void ResourceFormatDDS::get_recognized_extensions(List<String> *p_extensions) co } bool ResourceFormatDDS::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "Texture2D"); + return ClassDB::is_parent_class(p_type, "Texture"); } String ResourceFormatDDS::get_resource_type(const String &p_path) const { if (p_path.get_extension().to_lower() == "dds") { - return "ImageTexture"; + return "Texture"; } return ""; } diff --git a/modules/enet/enet_connection.cpp b/modules/enet/enet_connection.cpp index 2ccfd5d326..9c9302a51c 100644 --- a/modules/enet/enet_connection.cpp +++ b/modules/enet/enet_connection.cpp @@ -113,7 +113,7 @@ Ref<ENetPacketPeer> ENetConnection::connect_to_host(const String &p_address, int if (peer == nullptr) { return nullptr; } - out = Ref<ENetPacketPeer>(memnew(ENetPacketPeer(peer))); + out.instantiate(peer); peers.push_back(out); return out; } diff --git a/modules/fbx/fbx_document.cpp b/modules/fbx/fbx_document.cpp index ce097092fb..d6c304d056 100644 --- a/modules/fbx/fbx_document.cpp +++ b/modules/fbx/fbx_document.cpp @@ -369,21 +369,25 @@ Error FBXDocument::_parse_nodes(Ref<FBXState> p_state) { // all skin clusters connected to the bone. for (const ufbx_connection &child_conn : fbx_node->element.connections_src) { ufbx_skin_cluster *child_cluster = ufbx_as_skin_cluster(child_conn.dst); - if (!child_cluster) + if (!child_cluster) { continue; + } ufbx_skin_deformer *child_deformer = _find_skin_deformer(child_cluster); - if (!child_deformer) + if (!child_deformer) { continue; + } // Found a skin cluster: Now iterate through all the skin clusters of the parent and // try to find one that used by the same deformer. for (const ufbx_connection &parent_conn : fbx_node->parent->element.connections_src) { ufbx_skin_cluster *parent_cluster = ufbx_as_skin_cluster(parent_conn.dst); - if (!parent_cluster) + if (!parent_cluster) { continue; + } ufbx_skin_deformer *parent_deformer = _find_skin_deformer(parent_cluster); - if (parent_deformer != child_deformer) + if (parent_deformer != child_deformer) { continue; + } // Success: Found two skin clusters from the same deformer, now we can resolve the // local bind pose from the difference between the two world-space bind poses. @@ -1389,7 +1393,7 @@ Error FBXDocument::_parse_animations(Ref<FBXState> p_state) { for (const ufbx_baked_node &fbx_baked_node : fbx_baked_anim->nodes) { const GLTFNodeIndex node = fbx_baked_node.typed_id; - GLTFAnimation::Track &track = animation->get_tracks()[node]; + GLTFAnimation::NodeTrack &track = animation->get_node_tracks()[node]; for (const ufbx_baked_vec3 &key : fbx_baked_node.translation_keys) { track.position_track.times.push_back(float(key.time)); @@ -1779,8 +1783,8 @@ void FBXDocument::_import_animation(Ref<FBXState> p_state, AnimationPlayer *p_an double anim_start_offset = p_trimming ? double(additional_animation_data["time_begin"]) : 0.0; - for (const KeyValue<int, GLTFAnimation::Track> &track_i : anim->get_tracks()) { - const GLTFAnimation::Track &track = track_i.value; + for (const KeyValue<int, GLTFAnimation::NodeTrack> &track_i : anim->get_node_tracks()) { + const GLTFAnimation::NodeTrack &track = track_i.value; //need to find the path: for skeletons, weight tracks will affect the mesh NodePath node_path; //for skeletons, transform tracks always affect bones diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 5fe47d69df..0355119442 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -4,8 +4,8 @@ Built-in GDScript constants, functions, and annotations. </brief_description> <description> - A list of GDScript-specific utility functions and annotations accessible from any script. - For the list of the global functions and constants see [@GlobalScope]. + A list of utility functions and annotations accessible from any script written in GDScript. + For the list of global functions and constants that can be accessed in any scripting language, see [@GlobalScope]. </description> <tutorials> <link title="GDScript exports">$DOCS_URL/tutorials/scripting/gdscript/gdscript_exports.html</link> @@ -61,7 +61,7 @@ <method name="convert" deprecated="Use [method @GlobalScope.type_convert] instead."> <return type="Variant" /> <param index="0" name="what" type="Variant" /> - <param index="1" name="type" type="int" /> + <param index="1" name="type" type="int" enum="Variant.Type" /> <description> Converts [param what] to [param type] in the best way possible. The [param type] uses the [enum Variant.Type] values. [codeblock] @@ -666,7 +666,19 @@ @export var car_label = "Speedy" @export var car_number = 3 [/codeblock] - [b]Note:[/b] Subgroups cannot be nested, they only provide one extra level of depth. Just like the next group ends the previous group, so do the subsequent subgroups. + [b]Note:[/b] Subgroups cannot be nested, but you can use the slash separator ([code]/[/code]) to achieve the desired effect: + [codeblock] + @export_group("Car Properties") + @export_subgroup("Wheels", "wheel_") + @export_subgroup("Wheels/Front", "front_wheel_") + @export var front_wheel_strength = 10 + @export var front_wheel_mobility = 5 + @export_subgroup("Wheels/Rear", "rear_wheel_") + @export var rear_wheel_strength = 8 + @export var rear_wheel_mobility = 3 + @export_subgroup("Wheels", "wheel_") + @export var wheel_material: PhysicsMaterial + [/codeblock] </description> </annotation> <annotation name="@export_tool_button"> diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml index 5f7a7e2915..c3fa59dc23 100644 --- a/modules/gdscript/doc_classes/GDScript.xml +++ b/modules/gdscript/doc_classes/GDScript.xml @@ -16,11 +16,10 @@ <return type="Variant" /> <description> Returns a new instance of the script. - For example: [codeblock] var MyClass = load("myclass.gd") var instance = MyClass.new() - assert(instance.get_script() == MyClass) + print(instance.get_script() == MyClass) # Prints true [/codeblock] </description> </method> diff --git a/modules/gdscript/editor/gdscript_docgen.cpp b/modules/gdscript/editor/gdscript_docgen.cpp index 32ef429b0d..3a5a88d356 100644 --- a/modules/gdscript/editor/gdscript_docgen.cpp +++ b/modules/gdscript/editor/gdscript_docgen.cpp @@ -140,7 +140,7 @@ void GDScriptDocGen::_doctype_from_gdtype(const GDType &p_gdtype, String &r_type r_enum = String(p_gdtype.native_type).replace("::", "."); if (r_enum.begins_with("res://")) { r_enum = r_enum.trim_prefix("res://"); - int dot_pos = r_enum.rfind("."); + int dot_pos = r_enum.rfind_char('.'); if (dot_pos >= 0) { r_enum = r_enum.left(dot_pos).quote() + r_enum.substr(dot_pos); } @@ -217,7 +217,7 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re List<Variant> keys; dict.get_key_list(&keys); - keys.sort(); + keys.sort_custom<StringLikeVariantOrder>(); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { if (E->prev()) { diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index d765cfa1ea..629581bd6c 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -163,7 +163,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } if (from + end_key_length > line_length) { // If it's key length and there is a '\', dont skip to highlight esc chars. - if (str.find("\\", from) >= 0) { + if (str.find_char('\\', from) >= 0) { break; } } @@ -236,7 +236,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l for (; from < line_length; from++) { if (line_length - from < end_key_length) { // Don't break if '\' to highlight esc chars. - if (str.find("\\", from) < 0) { + if (str.find_char('\\', from) < 0) { break; } } @@ -701,7 +701,9 @@ void GDScriptSyntaxHighlighter::_update_cache() { List<StringName> types; ClassDB::get_class_list(&types); for (const StringName &E : types) { - class_names[E] = types_color; + if (ClassDB::is_class_exposed(E)) { + class_names[E] = types_color; + } } /* User types. */ diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp index b31ae878ce..172ad6be9f 100644 --- a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp @@ -51,6 +51,10 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve ids = r_ids; ids_ctx_plural = r_ids_ctx_plural; + + ids_comment.clear(); + ids_ctx_plural_comment.clear(); + Ref<GDScript> gdscript = loaded_res; String source_code = gdscript->get_source_code(); @@ -62,18 +66,90 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve err = analyzer.analyze(); ERR_FAIL_COND_V_MSG(err, err, "Failed to analyze GDScript with GDScriptAnalyzer."); + comment_data = &parser.comment_data; + // Traverse through the parsed tree from GDScriptParser. GDScriptParser::ClassNode *c = parser.get_tree(); _traverse_class(c); + comment_data = nullptr; + return OK; } +void GDScriptEditorTranslationParserPlugin::get_comments(Vector<String> *r_ids_comment, Vector<String> *r_ids_ctx_plural_comment) { + r_ids_comment->append_array(ids_comment); + r_ids_ctx_plural_comment->append_array(ids_ctx_plural_comment); +} + bool GDScriptEditorTranslationParserPlugin::_is_constant_string(const GDScriptParser::ExpressionNode *p_expression) { ERR_FAIL_NULL_V(p_expression, false); return p_expression->is_constant && p_expression->reduced_value.is_string(); } +String GDScriptEditorTranslationParserPlugin::_parse_comment(int p_line, bool &r_skip) const { + // Parse inline comment. + if (comment_data->has(p_line)) { + const String stripped_comment = comment_data->get(p_line).comment.trim_prefix("#").strip_edges(); + + if (stripped_comment.begins_with("TRANSLATORS:")) { + return stripped_comment.trim_prefix("TRANSLATORS:").strip_edges(true, false); + } + if (stripped_comment == "NO_TRANSLATE" || stripped_comment.begins_with("NO_TRANSLATE:")) { + r_skip = true; + return String(); + } + } + + // Parse multiline comment. + String multiline_comment; + for (int line = p_line - 1; comment_data->has(line) && comment_data->get(line).new_line; line--) { + const String stripped_comment = comment_data->get(line).comment.trim_prefix("#").strip_edges(); + + if (stripped_comment.is_empty()) { + continue; + } + + if (multiline_comment.is_empty()) { + multiline_comment = stripped_comment; + } else { + multiline_comment = stripped_comment + "\n" + multiline_comment; + } + + if (stripped_comment.begins_with("TRANSLATORS:")) { + return multiline_comment.trim_prefix("TRANSLATORS:").strip_edges(true, false); + } + if (stripped_comment == "NO_TRANSLATE" || stripped_comment.begins_with("NO_TRANSLATE:")) { + r_skip = true; + return String(); + } + } + + return String(); +} + +void GDScriptEditorTranslationParserPlugin::_add_id(const String &p_id, int p_line) { + bool skip = false; + const String comment = _parse_comment(p_line, skip); + if (skip) { + return; + } + + ids->push_back(p_id); + ids_comment.push_back(comment); +} + +void GDScriptEditorTranslationParserPlugin::_add_id_ctx_plural(const Vector<String> &p_id_ctx_plural, int p_line) { + bool skip = false; + const String comment = _parse_comment(p_line, skip); + if (skip) { + return; + } + + ids_ctx_plural->push_back(p_id_ctx_plural); + ids_ctx_plural_comment.push_back(comment); +} + void GDScriptEditorTranslationParserPlugin::_traverse_class(const GDScriptParser::ClassNode *p_class) { for (int i = 0; i < p_class->members.size(); i++) { const GDScriptParser::ClassNode::Member &m = p_class->members[i]; @@ -253,7 +329,7 @@ void GDScriptEditorTranslationParserPlugin::_assess_assignment(const GDScriptPar if (assignee_name != StringName() && assignment_patterns.has(assignee_name) && _is_constant_string(p_assignment->assigned_value)) { // If the assignment is towards one of the extract patterns (text, tooltip_text etc.), and the value is a constant string, we collect the string. - ids->push_back(p_assignment->assigned_value->reduced_value); + _add_id(p_assignment->assigned_value->reduced_value, p_assignment->assigned_value->start_line); } else if (assignee_name == fd_filters) { // Extract from `get_node("FileDialog").filters = <filter array>`. _extract_fd_filter_array(p_assignment->assigned_value); @@ -287,7 +363,7 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C } } if (extract_id_ctx_plural) { - ids_ctx_plural->push_back(id_ctx_plural); + _add_id_ctx_plural(id_ctx_plural, p_call->start_line); } } else if (function_name == trn_func || function_name == atrn_func) { // Extract from `tr_n(id, plural, n, ctx)` or `atr_n(id, plural, n, ctx)`. @@ -307,20 +383,20 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C } } if (extract_id_ctx_plural) { - ids_ctx_plural->push_back(id_ctx_plural); + _add_id_ctx_plural(id_ctx_plural, p_call->start_line); } } else if (first_arg_patterns.has(function_name)) { if (!p_call->arguments.is_empty() && _is_constant_string(p_call->arguments[0])) { - ids->push_back(p_call->arguments[0]->reduced_value); + _add_id(p_call->arguments[0]->reduced_value, p_call->arguments[0]->start_line); } } else if (second_arg_patterns.has(function_name)) { if (p_call->arguments.size() > 1 && _is_constant_string(p_call->arguments[1])) { - ids->push_back(p_call->arguments[1]->reduced_value); + _add_id(p_call->arguments[1]->reduced_value, p_call->arguments[1]->start_line); } } else if (function_name == fd_add_filter) { // Extract the 'JPE Images' in this example - get_node("FileDialog").add_filter("*.jpg; JPE Images"). if (!p_call->arguments.is_empty()) { - _extract_fd_filter_string(p_call->arguments[0]); + _extract_fd_filter_string(p_call->arguments[0], p_call->arguments[0]->start_line); } } else if (function_name == fd_set_filter) { // Extract from `get_node("FileDialog").set_filters(<filter array>)`. @@ -330,12 +406,12 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C } } -void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression) { +void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression, int p_line) { // Extract the name in "extension ; name". if (_is_constant_string(p_expression)) { PackedStringArray arr = p_expression->reduced_value.operator String().split(";", true); ERR_FAIL_COND_MSG(arr.size() != 2, "Argument for setting FileDialog has bad format."); - ids->push_back(arr[1].strip_edges()); + _add_id(arr[1].strip_edges(), p_line); } } @@ -355,7 +431,7 @@ void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_array(const GDScr if (array_node) { for (int i = 0; i < array_node->elements.size(); i++) { - _extract_fd_filter_string(array_node->elements[i]); + _extract_fd_filter_string(array_node->elements[i], array_node->elements[i]->start_line); } } } diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.h b/modules/gdscript/editor/gdscript_translation_parser_plugin.h index 61ff81ed66..73e8f53110 100644 --- a/modules/gdscript/editor/gdscript_translation_parser_plugin.h +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.h @@ -32,16 +32,23 @@ #define GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H #include "../gdscript_parser.h" +#include "../gdscript_tokenizer.h" +#include "core/templates/hash_map.h" #include "core/templates/hash_set.h" #include "editor/editor_translation_parser.h" class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlugin { GDCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin); + const HashMap<int, GDScriptTokenizer::CommentData> *comment_data = nullptr; + Vector<String> *ids = nullptr; Vector<Vector<String>> *ids_ctx_plural = nullptr; + Vector<String> ids_comment; + Vector<String> ids_ctx_plural_comment; + // List of patterns used for extracting translation strings. StringName tr_func = "tr"; StringName trn_func = "tr_n"; @@ -57,6 +64,11 @@ class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlug static bool _is_constant_string(const GDScriptParser::ExpressionNode *p_expression); + String _parse_comment(int p_line, bool &r_skip) const; + + void _add_id(const String &p_id, int p_line); + void _add_id_ctx_plural(const Vector<String> &p_id_ctx_plural, int p_line); + void _traverse_class(const GDScriptParser::ClassNode *p_class); void _traverse_function(const GDScriptParser::FunctionNode *p_func); void _traverse_block(const GDScriptParser::SuiteNode *p_suite); @@ -65,11 +77,12 @@ class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlug void _assess_assignment(const GDScriptParser::AssignmentNode *p_assignment); void _assess_call(const GDScriptParser::CallNode *p_call); - void _extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression); + void _extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression, int p_line); void _extract_fd_filter_array(const GDScriptParser::ExpressionNode *p_expression); public: virtual Error parse_file(const String &p_path, Vector<String> *r_ids, Vector<Vector<String>> *r_ids_ctx_plural) override; + virtual void get_comments(Vector<String> *r_ids_comment, Vector<String> *r_ids_ctx_plural_comment) override; virtual void get_recognized_extensions(List<String> *r_extensions) const override; GDScriptEditorTranslationParserPlugin(); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 18f2ccc455..8c094c0ab0 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -76,9 +76,16 @@ bool GDScriptNativeClass::_get(const StringName &p_name, Variant &r_ret) const { if (ok) { r_ret = v; return true; - } else { - return false; } + + MethodBind *method = ClassDB::get_method(name, p_name); + if (method && method->is_static()) { + // Native static method. + r_ret = Callable(this, p_name); + return true; + } + + return false; } void GDScriptNativeClass::_bind_methods() { @@ -1068,6 +1075,26 @@ void GDScript::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &GDScript::_new, MethodInfo("new")); } +void GDScript::set_path_cache(const String &p_path) { + if (ResourceCache::has(p_path)) { + set_path(p_path, true); + return; + } + + if (is_root_script()) { + Script::set_path_cache(p_path); + } + + String old_path = path; + path = p_path; + path_valid = true; + GDScriptCache::move_script(old_path, p_path); + + for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) { + kv.value->set_path_cache(p_path); + } +} + void GDScript::set_path(const String &p_path, bool p_take_over) { if (is_root_script()) { Script::set_path(p_path, p_take_over); @@ -1835,14 +1862,14 @@ Variant::Type GDScriptInstance::get_property_type(const StringName &p_name, bool } void GDScriptInstance::validate_property(PropertyInfo &p_property) const { - Variant property = (Dictionary)p_property; - const Variant *args[1] = { &property }; - const GDScript *sptr = script.ptr(); while (sptr) { if (likely(sptr->valid)) { HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._validate_property); if (E) { + Variant property = (Dictionary)p_property; + const Variant *args[1] = { &property }; + Callable::CallError err; Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); if (err.error == Callable::CallError::CALL_OK) { @@ -2546,11 +2573,11 @@ void GDScriptLanguage::reload_all_scripts() { } } } -#endif +#endif // TOOLS_ENABLED } reload_scripts(scripts, true); -#endif +#endif // DEBUG_ENABLED } void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload) { @@ -2620,7 +2647,7 @@ void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload } } -#endif +#endif // TOOLS_ENABLED for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : scr->pending_reload_state) { map[F.key] = F.value; //pending to reload, use this one instead @@ -2688,7 +2715,7 @@ void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload //if instance states were saved, set them! } -#endif +#endif // DEBUG_ENABLED } void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 9bb39aac0f..006a09debb 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -300,6 +300,7 @@ public: virtual Error reload(bool p_keep_state = false) override; + virtual void set_path_cache(const String &p_path) override; virtual void set_path(const String &p_path, bool p_take_over = false) override; String get_script_path() const; Error load_source_code(const String &p_path); diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 4a3a3a4b61..af92450835 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -169,7 +169,9 @@ static GDScriptParser::DataType make_native_enum_type(const StringName &p_enum_n GDScriptParser::DataType type = make_enum_type(p_enum_name, native_base, p_meta); if (p_meta) { - type.builtin_type = Variant::NIL; // Native enum types are not Dictionaries. + // Native enum types are not dictionaries. + type.builtin_type = Variant::NIL; + type.is_pseudo_type = true; } List<StringName> enum_values; @@ -182,10 +184,29 @@ static GDScriptParser::DataType make_native_enum_type(const StringName &p_enum_n return type; } +static GDScriptParser::DataType make_builtin_enum_type(const StringName &p_enum_name, Variant::Type p_type, bool p_meta = true) { + GDScriptParser::DataType type = make_enum_type(p_enum_name, Variant::get_type_name(p_type), p_meta); + if (p_meta) { + // Built-in enum types are not dictionaries. + type.builtin_type = Variant::NIL; + type.is_pseudo_type = true; + } + + List<StringName> enum_values; + Variant::get_enumerations_for_enum(p_type, p_enum_name, &enum_values); + + for (const StringName &E : enum_values) { + type.enum_values[E] = Variant::get_enum_value(p_type, p_enum_name, E); + } + + return type; +} + static GDScriptParser::DataType make_global_enum_type(const StringName &p_enum_name, const StringName &p_base, bool p_meta = true) { GDScriptParser::DataType type = make_enum_type(p_enum_name, p_base, p_meta); if (p_meta) { - type.builtin_type = Variant::NIL; // Native enum types are not Dictionaries. + // Global enum types are not dictionaries. + type.builtin_type = Variant::NIL; type.is_pseudo_type = true; } @@ -703,8 +724,8 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type if (first == SNAME("Variant")) { if (p_type->type_chain.size() == 2) { // May be nested enum. - StringName enum_name = p_type->type_chain[1]->name; - StringName qualified_name = String(first) + ENUM_SEPARATOR + String(p_type->type_chain[1]->name); + const StringName enum_name = p_type->type_chain[1]->name; + const StringName qualified_name = String(first) + ENUM_SEPARATOR + String(p_type->type_chain[1]->name); if (CoreConstants::is_global_enum(qualified_name)) { result = make_global_enum_type(enum_name, first, true); return result; @@ -719,21 +740,34 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type result.kind = GDScriptParser::DataType::VARIANT; } else if (GDScriptParser::get_builtin_type(first) < Variant::VARIANT_MAX) { // Built-in types. - if (p_type->type_chain.size() > 1) { - push_error(R"(Built-in types don't contain nested types.)", p_type->type_chain[1]); + const Variant::Type builtin_type = GDScriptParser::get_builtin_type(first); + + if (p_type->type_chain.size() == 2) { + // May be nested enum. + const StringName enum_name = p_type->type_chain[1]->name; + if (Variant::has_enum(builtin_type, enum_name)) { + result = make_builtin_enum_type(enum_name, builtin_type, true); + return result; + } else { + push_error(vformat(R"(Name "%s" is not a nested type of "%s".)", enum_name, first), p_type->type_chain[1]); + return bad_type; + } + } else if (p_type->type_chain.size() > 2) { + push_error(R"(Built-in types only contain enum types, which do not have nested types.)", p_type->type_chain[2]); return bad_type; } + result.kind = GDScriptParser::DataType::BUILTIN; - result.builtin_type = GDScriptParser::get_builtin_type(first); + result.builtin_type = builtin_type; - if (result.builtin_type == Variant::ARRAY) { + if (builtin_type == Variant::ARRAY) { GDScriptParser::DataType container_type = type_from_metatype(resolve_datatype(p_type->get_container_type_or_null(0))); if (container_type.kind != GDScriptParser::DataType::VARIANT) { container_type.is_constant = false; result.set_container_element_type(0, container_type); } } - if (result.builtin_type == Variant::DICTIONARY) { + if (builtin_type == Variant::DICTIONARY) { GDScriptParser::DataType key_type = type_from_metatype(resolve_datatype(p_type->get_container_type_or_null(0))); if (key_type.kind != GDScriptParser::DataType::VARIANT) { key_type.is_constant = false; @@ -940,8 +974,8 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, Finally finally([&]() { ensure_cached_external_parser_for_class(member.get_datatype().class_type, p_class, "Trying to resolve datatype of class member", p_source); GDScriptParser::DataType member_type = member.get_datatype(); - if (member_type.has_container_element_type(0)) { - ensure_cached_external_parser_for_class(member_type.get_container_element_type(0).class_type, p_class, "Trying to resolve datatype of class member", p_source); + for (int i = 0; i < member_type.get_container_element_type_count(); ++i) { + ensure_cached_external_parser_for_class(member_type.get_container_element_type(i).class_type, p_class, "Trying to resolve datatype of class member", p_source); } }); @@ -3816,6 +3850,12 @@ GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const Str } Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, const GDScriptParser::ClassNode *p_from_class, const char *p_context, const GDScriptParser::Node *p_source) { + // Delicate piece of code that intentionally doesn't use the GDScript cache or `get_depended_parser_for`. + // Search dependencies for the parser that owns `p_class` and make a cache entry for it. + // Required for how we store pointers to classes owned by other parser trees and need to call `resolve_class_member` and such on the same parser tree. + // Since https://github.com/godotengine/godot/pull/94871 there can technically be multiple parsers for the same script in the same parser tree. + // Even if unlikely, getting the wrong parser could lead to strange undefined behavior without errors. + if (p_class == nullptr) { return nullptr; } @@ -3832,8 +3872,6 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_external_parser_for_class p_from_class = parser->head; } - String script_path = p_class->get_datatype().script_path; - Ref<GDScriptParserRef> parser_ref; for (const GDScriptParser::ClassNode *look_class = p_from_class; look_class != nullptr; look_class = look_class->base_type.class_type) { if (parser->has_class(look_class)) { @@ -3966,13 +4004,36 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod if (base.kind == GDScriptParser::DataType::BUILTIN) { if (base.is_meta_type) { - bool valid = true; - Variant result = Variant::get_constant_value(base.builtin_type, name, &valid); - if (valid) { + bool valid = false; + + if (Variant::has_constant(base.builtin_type, name)) { + valid = true; + + const Variant constant_value = Variant::get_constant_value(base.builtin_type, name); + p_identifier->is_constant = true; - p_identifier->reduced_value = result; - p_identifier->set_datatype(type_from_variant(result, p_identifier)); - } else if (base.is_hard_type()) { + p_identifier->reduced_value = constant_value; + p_identifier->set_datatype(type_from_variant(constant_value, p_identifier)); + } + + if (!valid) { + const StringName enum_name = Variant::get_enum_for_enumeration(base.builtin_type, name); + if (enum_name != StringName()) { + valid = true; + + p_identifier->is_constant = true; + p_identifier->reduced_value = Variant::get_enum_value(base.builtin_type, enum_name, name); + p_identifier->set_datatype(make_builtin_enum_type(enum_name, base.builtin_type, false)); + } + } + + if (!valid && Variant::has_enum(base.builtin_type, name)) { + valid = true; + + p_identifier->set_datatype(make_builtin_enum_type(name, base.builtin_type, true)); + } + + if (!valid && base.is_hard_type()) { #ifdef SUGGEST_GODOT4_RENAMES String rename_hint; if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::RENAMED_IN_GODOT_4_HINT)).booleanize()) { @@ -3981,9 +4042,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name); } } - push_error(vformat(R"(Cannot find constant "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier); + push_error(vformat(R"(Cannot find member "%s" in base "%s".%s)", name, base.to_string(), rename_hint), p_identifier); #else - push_error(vformat(R"(Cannot find constant "%s" on base "%s".)", name, base.to_string()), p_identifier); + push_error(vformat(R"(Cannot find member "%s" in base "%s".)", name, base.to_string()), p_identifier); #endif // SUGGEST_GODOT4_RENAMES } } else { @@ -4025,9 +4086,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name); } } - push_error(vformat(R"(Cannot find property "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier); + push_error(vformat(R"(Cannot find member "%s" in base "%s".%s)", name, base.to_string(), rename_hint), p_identifier); #else - push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); + push_error(vformat(R"(Cannot find member "%s" in base "%s".)", name, base.to_string()), p_identifier); #endif // SUGGEST_GODOT4_RENAMES } } @@ -5568,7 +5629,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo } else { Vector<String> names = String(p_property.class_name).split(ENUM_SEPARATOR); if (names.size() == 2) { - result = make_native_enum_type(names[1], names[0], false); + result = make_enum_type(names[1], names[0], false); result.is_constant = false; } } @@ -5805,8 +5866,6 @@ void GDScriptAnalyzer::validate_call_arg(const List<GDScriptParser::DataType> &p #ifdef DEBUG_ENABLED void GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_identifier, const String &p_context, const bool p_in_local_scope) { const StringName &name = p_identifier->name; - GDScriptParser::DataType base = parser->current_class->get_datatype(); - GDScriptParser::ClassNode *base_class = base.class_type; { List<MethodInfo> gdscript_funcs; @@ -5834,40 +5893,56 @@ void GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_identifier } } + const GDScriptParser::DataType current_class_type = parser->current_class->get_datatype(); if (p_in_local_scope) { - while (base_class != nullptr) { + GDScriptParser::ClassNode *base_class = current_class_type.class_type; + + if (base_class != nullptr) { if (base_class->has_member(name)) { parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE, p_context, p_identifier->name, base_class->get_member(name).get_type_name(), itos(base_class->get_member(name).get_line())); return; } base_class = base_class->base_type.class_type; } + + while (base_class != nullptr) { + if (base_class->has_member(name)) { + String base_class_name = base_class->get_global_name(); + if (base_class_name.is_empty()) { + base_class_name = base_class->fqcn; + } + + parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, base_class->get_member(name).get_type_name(), itos(base_class->get_member(name).get_line()), base_class_name); + return; + } + base_class = base_class->base_type.class_type; + } } - StringName parent = base.native_type; - while (parent != StringName()) { - ERR_FAIL_COND_MSG(!class_exists(parent), "Non-existent native base class."); + StringName native_base_class = current_class_type.native_type; + while (native_base_class != StringName()) { + ERR_FAIL_COND_MSG(!class_exists(native_base_class), "Non-existent native base class."); - if (ClassDB::has_method(parent, name, true)) { - parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "method", parent); + if (ClassDB::has_method(native_base_class, name, true)) { + parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "method", native_base_class); return; - } else if (ClassDB::has_signal(parent, name, true)) { - parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "signal", parent); + } else if (ClassDB::has_signal(native_base_class, name, true)) { + parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "signal", native_base_class); return; - } else if (ClassDB::has_property(parent, name, true)) { - parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "property", parent); + } else if (ClassDB::has_property(native_base_class, name, true)) { + parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "property", native_base_class); return; - } else if (ClassDB::has_integer_constant(parent, name, true)) { - parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "constant", parent); + } else if (ClassDB::has_integer_constant(native_base_class, name, true)) { + parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "constant", native_base_class); return; - } else if (ClassDB::has_enum(parent, name, true)) { - parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "enum", parent); + } else if (ClassDB::has_enum(native_base_class, name, true)) { + parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "enum", native_base_class); return; } - parent = ClassDB::get_parent_class(parent); + native_base_class = ClassDB::get_parent_class(native_base_class); } } -#endif +#endif // DEBUG_ENABLED GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, bool &r_valid, const GDScriptParser::Node *p_source) { // Unary version. diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index b77c641eb5..fb4d27caab 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -585,8 +585,25 @@ void GDScriptByteCodeGenerator::write_unary_operator(const Address &p_target, Va } void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) { - // Avoid validated evaluator for modulo and division when operands are int, since there's no check for division by zero. - if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand) && ((p_operator != Variant::OP_DIVIDE && p_operator != Variant::OP_MODULE) || p_left_operand.type.builtin_type != Variant::INT || p_right_operand.type.builtin_type != Variant::INT)) { + bool valid = HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand); + + // Avoid validated evaluator for modulo and division when operands are int or integer vector, since there's no check for division by zero. + if (valid && (p_operator == Variant::OP_DIVIDE || p_operator == Variant::OP_MODULE)) { + switch (p_left_operand.type.builtin_type) { + case Variant::INT: + valid = p_right_operand.type.builtin_type != Variant::INT; + break; + case Variant::VECTOR2I: + case Variant::VECTOR3I: + case Variant::VECTOR4I: + valid = p_right_operand.type.builtin_type != Variant::INT && p_right_operand.type.builtin_type != p_left_operand.type.builtin_type; + break; + default: + break; + } + } + + if (valid) { if (p_target.mode == Address::TEMPORARY) { Variant::Type result_type = Variant::get_operator_return_type(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type); Variant::Type temp_type = temporaries[p_target.address].type; diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 3c022412bd..fa22798edf 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -312,7 +312,7 @@ Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, Error &r_e Ref<GDScript> script; script.instantiate(); - script->set_path(p_path, true); + script->set_path_cache(p_path); if (remapped_path.get_extension().to_lower() == "gdc") { Vector<uint8_t> buffer = get_binary_tokens(remapped_path); if (buffer.is_empty()) { @@ -360,6 +360,7 @@ Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_erro return script; } } + script->set_path(p_path, true); const String remapped_path = ResourceLoader::path_remap(p_path); diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index bc063693a3..d94a6dfda2 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -790,8 +790,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += method->get_name(); text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -833,8 +834,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += method->get_name(); text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 3de1decc18..cfff20f6d3 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -43,6 +43,7 @@ #include "core/config/engine.h" #include "core/core_constants.h" #include "core/io/file_access.h" +#include "core/math/expression.h" #ifdef TOOLS_ENABLED #include "core/config/project_settings.h" @@ -427,7 +428,30 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> } String GDScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { - return ""; + List<String> names; + List<Variant> values; + debug_get_stack_level_locals(p_level, &names, &values, p_max_subitems, p_max_depth); + + Vector<String> name_vector; + for (const String &name : names) { + name_vector.push_back(name); + } + + Array value_array; + for (const Variant &value : values) { + value_array.push_back(value); + } + + Expression expression; + if (expression.parse(p_expression, name_vector) == OK) { + ScriptInstance *instance = debug_get_stack_level_instance(p_level); + if (instance) { + Variant return_val = expression.execute(value_array, instance->get_owner()); + return return_val.get_construct_string(); + } + } + + return String(); } void GDScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { @@ -1115,10 +1139,12 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, continue; } option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (member.function->parameters.size() > 0) { + if (member.function->parameters.size() > 0 || (member.function->info.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } break; case GDScriptParser::ClassNode::Member::SIGNAL: @@ -1160,6 +1186,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base if (!p_types_only && base_type.is_meta_type && base_type.kind != GDScriptParser::DataType::BUILTIN && base_type.kind != GDScriptParser::DataType::ENUM) { ScriptLanguage::CodeCompletionOption option("new", ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, ScriptLanguage::LOCATION_LOCAL); option.insert_text += "("; + option.display += U"(\u2026)"; r_result.insert(option.display, option); } @@ -1217,10 +1244,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } int location = p_recursion_depth + _get_method_location(scr->get_class_name(), E.name); ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size()) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1303,10 +1332,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } int location = p_recursion_depth + _get_method_location(type, E.name); ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size()) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1374,10 +1405,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base continue; } ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size()) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1409,8 +1442,10 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context ScriptLanguage::CodeCompletionOption option(String(E), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); if (function.arguments.size() || (function.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1457,6 +1492,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context while (*kwa) { ScriptLanguage::CodeCompletionOption option(*kwa, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); option.insert_text += "("; + option.display += U"(\u2026)"; r_result.insert(option.display, option); kwa++; } @@ -1467,6 +1503,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context for (List<StringName>::Element *E = utility_func_names.front(); E; E = E->next()) { ScriptLanguage::CodeCompletionOption option(E->get(), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); option.insert_text += "("; + option.display += U"(\u2026)"; // As all utility functions contain an argument or more, this is hardcoded here. r_result.insert(option.display, option); } @@ -3164,7 +3201,9 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c HashMap<String, ScriptLanguage::CodeCompletionOption> options; GDScriptParser::CompletionContext completion_context = parser.get_completion_context(); - completion_context.base = p_owner; + if (completion_context.current_class != nullptr && completion_context.current_class->outer == nullptr) { + completion_context.base = p_owner; + } bool is_function = false; switch (completion_context.type) { @@ -3446,7 +3485,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } String arg = arg_itr->name; if (arg.contains(":")) { - arg = arg.substr(0, arg.find(":")); + arg = arg.substr(0, arg.find_char(':')); } method_hint += arg; if (use_type_hint) { @@ -3534,13 +3573,13 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c return OK; } -#else +#else // !TOOLS_ENABLED Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptLanguage::CodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) { return OK; } -#endif +#endif // TOOLS_ENABLED //////// END COMPLETION ////////// @@ -4125,4 +4164,4 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co return ERR_CANT_RESOLVE; } -#endif +#endif // TOOLS_ENABLED diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 111a39d730..12e71004db 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -244,7 +244,7 @@ void GDScriptParser::apply_pending_warnings() { pending_warnings.clear(); } -#endif +#endif // DEBUG_ENABLED void GDScriptParser::override_completion_context(const Node *p_for_node, CompletionType p_type, Node *p_node, int p_argument) { if (!for_completion) { @@ -409,6 +409,10 @@ Error GDScriptParser::parse(const String &p_source_code, const String &p_script_ parse_program(); pop_multiline(); +#ifdef TOOLS_ENABLED + comment_data = tokenizer->get_comments(); +#endif + memdelete(text_tokenizer); tokenizer = nullptr; @@ -1624,15 +1628,17 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali valid = false; } - annotation->info = &valid_annotations[annotation->name]; + if (valid) { + annotation->info = &valid_annotations[annotation->name]; - if (!annotation->applies_to(p_valid_targets)) { - if (annotation->applies_to(AnnotationInfo::SCRIPT)) { - push_error(vformat(R"(Annotation "%s" must be at the top of the script, before "extends" and "class_name".)", annotation->name)); - } else { - push_error(vformat(R"(Annotation "%s" is not allowed in this level.)", annotation->name)); + if (!annotation->applies_to(p_valid_targets)) { + if (annotation->applies_to(AnnotationInfo::SCRIPT)) { + push_error(vformat(R"(Annotation "%s" must be at the top of the script, before "extends" and "class_name".)", annotation->name)); + } else { + push_error(vformat(R"(Annotation "%s" is not allowed in this level.)", annotation->name)); + } + valid = false; } - valid = false; } if (check(GDScriptTokenizer::Token::PARENTHESIS_OPEN)) { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 7f64ae902b..d40ba217c1 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -165,6 +165,10 @@ public: container_element_types.write[p_index] = DataType(p_type); } + _FORCE_INLINE_ int get_container_element_type_count() const { + return container_element_types.size(); + } + _FORCE_INLINE_ DataType get_container_element_type(int p_index) const { ERR_FAIL_INDEX_V(p_index, container_element_types.size(), get_variant_type()); return container_element_types[p_index]; @@ -1597,6 +1601,8 @@ public: #ifdef TOOLS_ENABLED static HashMap<String, String> theme_color_names; + + HashMap<int, GDScriptTokenizer::CommentData> comment_data; #endif // TOOLS_ENABLED GDScriptParser(); diff --git a/modules/gdscript/gdscript_tokenizer_buffer.h b/modules/gdscript/gdscript_tokenizer_buffer.h index 55df66e50f..d5d2a4d096 100644 --- a/modules/gdscript/gdscript_tokenizer_buffer.h +++ b/modules/gdscript/gdscript_tokenizer_buffer.h @@ -79,7 +79,7 @@ public: virtual bool is_past_cursor() const override; virtual void push_expression_indented_block() override; // For lambdas, or blocks inside expressions. virtual void pop_expression_indented_block() override; // For lambdas, or blocks inside expressions. - virtual bool is_text() override { return false; }; + virtual bool is_text() override { return false; } #ifdef TOOLS_ENABLED virtual const HashMap<int, CommentData> &get_comments() const override { diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index 59dd983ed2..8246069696 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -34,7 +34,6 @@ #include "core/io/resource_loader.h" #include "core/object/class_db.h" -#include "core/object/method_bind.h" #include "core/object/object.h" #include "core/templates/oa_hash_map.h" #include "core/templates/vector.h" @@ -42,101 +41,105 @@ #ifdef DEBUG_ENABLED -#define VALIDATE_ARG_COUNT(m_count) \ - if (p_arg_count < m_count) { \ - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; \ - r_error.expected = m_count; \ +#define DEBUG_VALIDATE_ARG_COUNT(m_min_count, m_max_count) \ + if (unlikely(p_arg_count < m_min_count)) { \ *r_ret = Variant(); \ + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; \ + r_error.expected = m_min_count; \ return; \ } \ - if (p_arg_count > m_count) { \ - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; \ - r_error.expected = m_count; \ + if (unlikely(p_arg_count > m_max_count)) { \ *r_ret = Variant(); \ + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; \ + r_error.expected = m_max_count; \ return; \ } -#define VALIDATE_ARG_INT(m_arg) \ - if (p_args[m_arg]->get_type() != Variant::INT) { \ +#define DEBUG_VALIDATE_ARG_TYPE(m_arg, m_type) \ + if (unlikely(!Variant::can_convert_strict(p_args[m_arg]->get_type(), m_type))) { \ + *r_ret = Variant(); \ + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \ + r_error.argument = m_arg; \ + r_error.expected = m_type; \ + return; \ + } + +#define DEBUG_VALIDATE_ARG_CUSTOM(m_arg, m_type, m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + *r_ret = m_msg; \ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \ r_error.argument = m_arg; \ - r_error.expected = Variant::INT; \ - *r_ret = Variant(); \ + r_error.expected = m_type; \ return; \ } -#define VALIDATE_ARG_NUM(m_arg) \ - if (!p_args[m_arg]->is_num()) { \ +#else // !DEBUG_ENABLED + +#define DEBUG_VALIDATE_ARG_COUNT(m_min_count, m_max_count) +#define DEBUG_VALIDATE_ARG_TYPE(m_arg, m_type) +#define DEBUG_VALIDATE_ARG_CUSTOM(m_arg, m_type, m_cond, m_msg) + +#endif // DEBUG_ENABLED + +#define VALIDATE_ARG_CUSTOM(m_arg, m_type, m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + *r_ret = m_msg; \ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \ r_error.argument = m_arg; \ - r_error.expected = Variant::FLOAT; \ - *r_ret = Variant(); \ + r_error.expected = m_type; \ return; \ } -#else - -#define VALIDATE_ARG_COUNT(m_count) -#define VALIDATE_ARG_INT(m_arg) -#define VALIDATE_ARG_NUM(m_arg) - -#endif +#define GDFUNC_FAIL_COND_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + *r_ret = m_msg; \ + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; \ + return; \ + } struct GDScriptUtilityFunctionsDefinitions { #ifndef DISABLE_DEPRECATED static inline void convert(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(2); - VALIDATE_ARG_INT(1); + DEBUG_VALIDATE_ARG_COUNT(2, 2); + DEBUG_VALIDATE_ARG_TYPE(1, Variant::INT); + int type = *p_args[1]; - if (type < 0 || type >= Variant::VARIANT_MAX) { - *r_ret = RTR("Invalid type argument to convert(), use TYPE_* constants."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::INT; - return; + DEBUG_VALIDATE_ARG_CUSTOM(1, Variant::INT, type < 0 || type >= Variant::VARIANT_MAX, + RTR("Invalid type argument to convert(), use TYPE_* constants.")); - } else { - Variant::construct(Variant::Type(type), *r_ret, p_args, 1, r_error); - if (r_error.error != Callable::CallError::CALL_OK) { - *r_ret = vformat(RTR(R"(Cannot convert "%s" to "%s".)"), Variant::get_type_name(p_args[0]->get_type()), Variant::get_type_name(Variant::Type(type))); - } - } + Variant::construct(Variant::Type(type), *r_ret, p_args, 1, r_error); } #endif // DISABLE_DEPRECATED static inline void type_exists(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(1); + DEBUG_VALIDATE_ARG_COUNT(1, 1); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::STRING_NAME); *r_ret = ClassDB::class_exists(*p_args[0]); } static inline void _char(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(1); - VALIDATE_ARG_INT(0); + DEBUG_VALIDATE_ARG_COUNT(1, 1); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::INT); char32_t result[2] = { *p_args[0], 0 }; *r_ret = String(result); } static inline void range(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + DEBUG_VALIDATE_ARG_COUNT(1, 3); switch (p_arg_count) { - case 0: { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.expected = 1; - *r_ret = Variant(); - } break; case 1: { - VALIDATE_ARG_NUM(0); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::INT); + int count = *p_args[0]; + Array arr; if (count <= 0) { *r_ret = arr; return; } + Error err = arr.resize(count); - if (err != OK) { - *r_ret = RTR("Cannot resize array."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return; - } + GDFUNC_FAIL_COND_MSG(err != OK, RTR("Cannot resize array.")); for (int i = 0; i < count; i++) { arr[i] = i; @@ -145,8 +148,8 @@ struct GDScriptUtilityFunctionsDefinitions { *r_ret = arr; } break; case 2: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::INT); + DEBUG_VALIDATE_ARG_TYPE(1, Variant::INT); int from = *p_args[0]; int to = *p_args[1]; @@ -156,30 +159,26 @@ struct GDScriptUtilityFunctionsDefinitions { *r_ret = arr; return; } + Error err = arr.resize(to - from); - if (err != OK) { - *r_ret = RTR("Cannot resize array."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return; - } + GDFUNC_FAIL_COND_MSG(err != OK, RTR("Cannot resize array.")); + for (int i = from; i < to; i++) { arr[i - from] = i; } + *r_ret = arr; } break; case 3: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::INT); + DEBUG_VALIDATE_ARG_TYPE(1, Variant::INT); + DEBUG_VALIDATE_ARG_TYPE(2, Variant::INT); int from = *p_args[0]; int to = *p_args[1]; int incr = *p_args[2]; - if (incr == 0) { - *r_ret = RTR("Step argument is zero!"); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return; - } + + VALIDATE_ARG_CUSTOM(2, Variant::INT, incr == 0, RTR("Step argument is zero!")); Array arr; if (from >= to && incr > 0) { @@ -200,12 +199,7 @@ struct GDScriptUtilityFunctionsDefinitions { } Error err = arr.resize(count); - - if (err != OK) { - *r_ret = RTR("Cannot resize array."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return; - } + GDFUNC_FAIL_COND_MSG(err != OK, RTR("Cannot resize array.")); if (incr > 0) { int idx = 0; @@ -221,138 +215,79 @@ struct GDScriptUtilityFunctionsDefinitions { *r_ret = arr; } break; - default: { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.expected = 3; - *r_ret = Variant(); - - } break; } } static inline void load(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(1); - if (!p_args[0]->is_string()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::STRING; - *r_ret = Variant(); - } else { - *r_ret = ResourceLoader::load(*p_args[0]); - } + DEBUG_VALIDATE_ARG_COUNT(1, 1); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::STRING); + *r_ret = ResourceLoader::load(*p_args[0]); } static inline void inst_to_dict(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(1); + DEBUG_VALIDATE_ARG_COUNT(1, 1); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::OBJECT); if (p_args[0]->get_type() == Variant::NIL) { *r_ret = Variant(); - } else if (p_args[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; + return; + } + + Object *obj = *p_args[0]; + if (!obj) { *r_ret = Variant(); - } else { - Object *obj = *p_args[0]; - if (!obj) { - *r_ret = Variant(); + return; + } - } else if (!obj->get_script_instance() || obj->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::DICTIONARY; - *r_ret = RTR("Not a script with an instance"); - return; - } else { - GDScriptInstance *ins = static_cast<GDScriptInstance *>(obj->get_script_instance()); - Ref<GDScript> base = ins->get_script(); - if (base.is_null()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::DICTIONARY; - *r_ret = RTR("Not based on a script"); - return; - } + VALIDATE_ARG_CUSTOM(0, Variant::OBJECT, + !obj->get_script_instance() || obj->get_script_instance()->get_language() != GDScriptLanguage::get_singleton(), + RTR("Not a script with an instance.")); - GDScript *p = base.ptr(); - String path = p->get_script_path(); - Vector<StringName> sname; + GDScriptInstance *inst = static_cast<GDScriptInstance *>(obj->get_script_instance()); - while (p->_owner) { - sname.push_back(p->local_name); - p = p->_owner; - } - sname.reverse(); + Ref<GDScript> base = inst->get_script(); + VALIDATE_ARG_CUSTOM(0, Variant::OBJECT, base.is_null(), RTR("Not based on a script.")); - if (!path.is_resource_file()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::DICTIONARY; - *r_ret = Variant(); + GDScript *p = base.ptr(); + String path = p->get_script_path(); + Vector<StringName> sname; - *r_ret = RTR("Not based on a resource file"); + while (p->_owner) { + sname.push_back(p->local_name); + p = p->_owner; + } + sname.reverse(); - return; - } + VALIDATE_ARG_CUSTOM(0, Variant::OBJECT, !path.is_resource_file(), RTR("Not based on a resource file.")); - NodePath cp(sname, Vector<StringName>(), false); + NodePath cp(sname, Vector<StringName>(), false); - Dictionary d; - d["@subpath"] = cp; - d["@path"] = path; + Dictionary d; + d["@subpath"] = cp; + d["@path"] = path; - for (const KeyValue<StringName, GDScript::MemberInfo> &E : base->member_indices) { - if (!d.has(E.key)) { - d[E.key] = ins->members[E.value.index]; - } - } - *r_ret = d; + for (const KeyValue<StringName, GDScript::MemberInfo> &E : base->member_indices) { + if (!d.has(E.key)) { + d[E.key] = inst->members[E.value.index]; } } + + *r_ret = d; } static inline void dict_to_inst(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(1); - - if (p_args[0]->get_type() != Variant::DICTIONARY) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::DICTIONARY; - *r_ret = Variant(); - - return; - } + DEBUG_VALIDATE_ARG_COUNT(1, 1); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::DICTIONARY); Dictionary d = *p_args[0]; - if (!d.has("@path")) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; - *r_ret = RTR("Invalid instance dictionary format (missing @path)"); - - return; - } + VALIDATE_ARG_CUSTOM(0, Variant::DICTIONARY, !d.has("@path"), RTR("Invalid instance dictionary format (missing @path).")); Ref<Script> scr = ResourceLoader::load(d["@path"]); - if (!scr.is_valid()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; - *r_ret = RTR("Invalid instance dictionary format (can't load script at @path)"); - return; - } + VALIDATE_ARG_CUSTOM(0, Variant::DICTIONARY, !scr.is_valid(), RTR("Invalid instance dictionary format (can't load script at @path).")); Ref<GDScript> gdscr = scr; - - if (!gdscr.is_valid()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; - *r_ret = Variant(); - *r_ret = RTR("Invalid instance dictionary format (invalid script at @path)"); - return; - } + VALIDATE_ARG_CUSTOM(0, Variant::DICTIONARY, !gdscr.is_valid(), RTR("Invalid instance dictionary format (invalid script at @path).")); NodePath sub; if (d.has("@subpath")) { @@ -361,54 +296,35 @@ struct GDScriptUtilityFunctionsDefinitions { for (int i = 0; i < sub.get_name_count(); i++) { gdscr = gdscr->subclasses[sub.get_name(i)]; - if (!gdscr.is_valid()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; - *r_ret = Variant(); - *r_ret = RTR("Invalid instance dictionary (invalid subclasses)"); - return; - } + VALIDATE_ARG_CUSTOM(0, Variant::DICTIONARY, !gdscr.is_valid(), RTR("Invalid instance dictionary (invalid subclasses).")); } - *r_ret = gdscr->_new(nullptr, -1 /*skip initializer*/, r_error); + *r_ret = gdscr->_new(nullptr, -1 /* skip initializer */, r_error); if (r_error.error != Callable::CallError::CALL_OK) { *r_ret = RTR("Cannot instantiate GDScript class."); return; } - GDScriptInstance *ins = static_cast<GDScriptInstance *>(static_cast<Object *>(*r_ret)->get_script_instance()); - Ref<GDScript> gd_ref = ins->get_script(); + GDScriptInstance *inst = static_cast<GDScriptInstance *>(static_cast<Object *>(*r_ret)->get_script_instance()); + Ref<GDScript> gd_ref = inst->get_script(); for (KeyValue<StringName, GDScript::MemberInfo> &E : gd_ref->member_indices) { if (d.has(E.key)) { - ins->members.write[E.value.index] = d[E.key]; + inst->members.write[E.value.index] = d[E.key]; } } } static inline void Color8(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - if (p_arg_count < 3) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.expected = 3; - *r_ret = Variant(); - return; - } - if (p_arg_count > 4) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.expected = 4; - *r_ret = Variant(); - return; - } - - VALIDATE_ARG_INT(0); - VALIDATE_ARG_INT(1); - VALIDATE_ARG_INT(2); + DEBUG_VALIDATE_ARG_COUNT(3, 4); + DEBUG_VALIDATE_ARG_TYPE(0, Variant::INT); + DEBUG_VALIDATE_ARG_TYPE(1, Variant::INT); + DEBUG_VALIDATE_ARG_TYPE(2, Variant::INT); Color color((int64_t)*p_args[0] / 255.0f, (int64_t)*p_args[1] / 255.0f, (int64_t)*p_args[2] / 255.0f); if (p_arg_count == 4) { - VALIDATE_ARG_INT(3); + DEBUG_VALIDATE_ARG_TYPE(3, Variant::INT); color.a = (int64_t)*p_args[3] / 255.0f; } @@ -435,7 +351,8 @@ struct GDScriptUtilityFunctionsDefinitions { } static inline void print_stack(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(0); + DEBUG_VALIDATE_ARG_COUNT(0, 0); + if (Thread::get_caller_id() != Thread::get_main_id()) { print_line("Cannot retrieve debug info outside the main thread. Thread ID: " + itos(Thread::get_caller_id())); return; @@ -449,7 +366,8 @@ struct GDScriptUtilityFunctionsDefinitions { } static inline void get_stack(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(0); + DEBUG_VALIDATE_ARG_COUNT(0, 0); + if (Thread::get_caller_id() != Thread::get_main_id()) { *r_ret = TypedArray<Dictionary>(); return; @@ -468,7 +386,7 @@ struct GDScriptUtilityFunctionsDefinitions { } static inline void len(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(1); + DEBUG_VALIDATE_ARG_COUNT(1, 1); switch (p_args[0]->get_type()) { case Variant::STRING: case Variant::STRING_NAME: { @@ -524,56 +442,34 @@ struct GDScriptUtilityFunctionsDefinitions { *r_ret = d.size(); } break; default: { + *r_ret = vformat(RTR("Value of type '%s' can't provide a length."), Variant::get_type_name(p_args[0]->get_type())); r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::NIL; - *r_ret = vformat(RTR("Value of type '%s' can't provide a length."), Variant::get_type_name(p_args[0]->get_type())); - } + } break; } } static inline void is_instance_of(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - VALIDATE_ARG_COUNT(2); + DEBUG_VALIDATE_ARG_COUNT(2, 2); if (p_args[1]->get_type() == Variant::INT) { int builtin_type = *p_args[1]; - if (builtin_type < 0 || builtin_type >= Variant::VARIANT_MAX) { - *r_ret = RTR("Invalid type argument for is_instance_of(), use TYPE_* constants for built-in types."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 1; - r_error.expected = Variant::NIL; - return; - } + DEBUG_VALIDATE_ARG_CUSTOM(1, Variant::NIL, builtin_type < 0 || builtin_type >= Variant::VARIANT_MAX, + RTR("Invalid type argument for is_instance_of(), use TYPE_* constants for built-in types.")); *r_ret = p_args[0]->get_type() == builtin_type; return; } bool was_type_freed = false; Object *type_object = p_args[1]->get_validated_object_with_check(was_type_freed); - if (was_type_freed) { - *r_ret = RTR("Type argument is a previously freed instance."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 1; - r_error.expected = Variant::NIL; - return; - } - if (!type_object) { - *r_ret = RTR("Invalid type argument for is_instance_of(), should be a TYPE_* constant, a class or a script."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 1; - r_error.expected = Variant::NIL; - return; - } + VALIDATE_ARG_CUSTOM(1, Variant::NIL, was_type_freed, RTR("Type argument is a previously freed instance.")); + VALIDATE_ARG_CUSTOM(1, Variant::NIL, !type_object, + RTR("Invalid type argument for is_instance_of(), should be a TYPE_* constant, a class or a script.")); bool was_value_freed = false; Object *value_object = p_args[0]->get_validated_object_with_check(was_value_freed); - if (was_value_freed) { - *r_ret = RTR("Value argument is a previously freed instance."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::NIL; - return; - } + VALIDATE_ARG_CUSTOM(0, Variant::NIL, was_value_freed, RTR("Value argument is a previously freed instance.")); if (!value_object) { *r_ret = false; return; @@ -618,113 +514,77 @@ struct GDScriptUtilityFunctionInfo { static OAHashMap<StringName, GDScriptUtilityFunctionInfo> utility_function_table; static List<StringName> utility_function_name_table; -static void _register_function(const String &p_name, const MethodInfo &p_method_info, GDScriptUtilityFunctions::FunctionPtr p_function, bool p_is_const) { - StringName sname(p_name); - - ERR_FAIL_COND(utility_function_table.has(sname)); +static void _register_function(const StringName &p_name, const MethodInfo &p_method_info, GDScriptUtilityFunctions::FunctionPtr p_function, bool p_is_const) { + ERR_FAIL_COND(utility_function_table.has(p_name)); GDScriptUtilityFunctionInfo function; function.function = p_function; function.info = p_method_info; function.is_constant = p_is_const; - utility_function_table.insert(sname, function); - utility_function_name_table.push_back(sname); + utility_function_table.insert(p_name, function); + utility_function_name_table.push_back(p_name); } -#define REGISTER_FUNC(m_func, m_is_const, m_return_type, ...) \ +#define REGISTER_FUNC(m_func, m_is_const, m_return, m_args, m_is_vararg, m_default_args) \ { \ String name(#m_func); \ if (name.begins_with("_")) { \ - name = name.substr(1, name.length() - 1); \ + name = name.substr(1); \ } \ - MethodInfo info = MethodInfo(name, __VA_ARGS__); \ - info.return_val.type = m_return_type; \ - _register_function(name, info, GDScriptUtilityFunctionsDefinitions::m_func, m_is_const); \ - } - -#define REGISTER_FUNC_NO_ARGS(m_func, m_is_const, m_return_type) \ - { \ - String name(#m_func); \ - if (name.begins_with("_")) { \ - name = name.substr(1, name.length() - 1); \ + MethodInfo info = m_args; \ + info.name = name; \ + info.return_val = m_return; \ + info.default_arguments = m_default_args; \ + if (m_is_vararg) { \ + info.flags |= METHOD_FLAG_VARARG; \ } \ - MethodInfo info = MethodInfo(name); \ - info.return_val.type = m_return_type; \ _register_function(name, info, GDScriptUtilityFunctionsDefinitions::m_func, m_is_const); \ } -#define REGISTER_VARARG_FUNC(m_func, m_is_const, m_return_type) \ - { \ - String name(#m_func); \ - if (name.begins_with("_")) { \ - name = name.substr(1, name.length() - 1); \ - } \ - MethodInfo info = MethodInfo(name); \ - info.return_val.type = m_return_type; \ - info.flags |= METHOD_FLAG_VARARG; \ - _register_function(name, info, GDScriptUtilityFunctionsDefinitions::m_func, m_is_const); \ - } +#define RET(m_type) \ + PropertyInfo(Variant::m_type, "") -#define REGISTER_VARIANT_FUNC(m_func, m_is_const, ...) \ - { \ - String name(#m_func); \ - if (name.begins_with("_")) { \ - name = name.substr(1, name.length() - 1); \ - } \ - MethodInfo info = MethodInfo(name, __VA_ARGS__); \ - info.return_val.type = Variant::NIL; \ - info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; \ - _register_function(name, info, GDScriptUtilityFunctionsDefinitions::m_func, m_is_const); \ - } +#define RETVAR \ + PropertyInfo(Variant::NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT) -#define REGISTER_CLASS_FUNC(m_func, m_is_const, m_return_type, ...) \ - { \ - String name(#m_func); \ - if (name.begins_with("_")) { \ - name = name.substr(1, name.length() - 1); \ - } \ - MethodInfo info = MethodInfo(name, __VA_ARGS__); \ - info.return_val.type = Variant::OBJECT; \ - info.return_val.hint = PROPERTY_HINT_RESOURCE_TYPE; \ - info.return_val.class_name = m_return_type; \ - _register_function(name, info, GDScriptUtilityFunctionsDefinitions::m_func, m_is_const); \ - } +#define RETCLS(m_class) \ + PropertyInfo(Variant::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, m_class) -#define REGISTER_FUNC_DEF(m_func, m_is_const, m_default, m_return_type, ...) \ - { \ - String name(#m_func); \ - if (name.begins_with("_")) { \ - name = name.substr(1, name.length() - 1); \ - } \ - MethodInfo info = MethodInfo(name, __VA_ARGS__); \ - info.return_val.type = m_return_type; \ - info.default_arguments.push_back(m_default); \ - _register_function(name, info, GDScriptUtilityFunctionsDefinitions::m_func, m_is_const); \ - } +#define NOARGS \ + MethodInfo() + +#define ARGS(...) \ + MethodInfo("", __VA_ARGS__) #define ARG(m_name, m_type) \ - PropertyInfo(m_type, m_name) + PropertyInfo(Variant::m_type, m_name) + +#define ARGVAR(m_name) \ + PropertyInfo(Variant::NIL, m_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT) -#define VARARG(m_name) \ - PropertyInfo(Variant::NIL, m_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT) +#define ARGTYPE(m_name) \ + PropertyInfo(Variant::INT, m_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CLASS_IS_ENUM, "Variant.Type") void GDScriptUtilityFunctions::register_functions() { + /* clang-format off */ #ifndef DISABLE_DEPRECATED - REGISTER_VARIANT_FUNC(convert, true, VARARG("what"), ARG("type", Variant::INT)); + REGISTER_FUNC( convert, true, RETVAR, ARGS( ARGVAR("what"), ARGTYPE("type") ), false, varray( )); #endif // DISABLE_DEPRECATED - REGISTER_FUNC(type_exists, true, Variant::BOOL, ARG("type", Variant::STRING_NAME)); - REGISTER_FUNC(_char, true, Variant::STRING, ARG("char", Variant::INT)); - REGISTER_VARARG_FUNC(range, false, Variant::ARRAY); - REGISTER_CLASS_FUNC(load, false, "Resource", ARG("path", Variant::STRING)); - REGISTER_FUNC(inst_to_dict, false, Variant::DICTIONARY, ARG("instance", Variant::OBJECT)); - REGISTER_FUNC(dict_to_inst, false, Variant::OBJECT, ARG("dictionary", Variant::DICTIONARY)); - REGISTER_FUNC_DEF(Color8, true, 255, Variant::COLOR, ARG("r8", Variant::INT), ARG("g8", Variant::INT), ARG("b8", Variant::INT), ARG("a8", Variant::INT)); - REGISTER_VARARG_FUNC(print_debug, false, Variant::NIL); - REGISTER_FUNC_NO_ARGS(print_stack, false, Variant::NIL); - REGISTER_FUNC_NO_ARGS(get_stack, false, Variant::ARRAY); - REGISTER_FUNC(len, true, Variant::INT, VARARG("var")); - REGISTER_FUNC(is_instance_of, true, Variant::BOOL, VARARG("value"), VARARG("type")); + REGISTER_FUNC( type_exists, true, RET(BOOL), ARGS( ARG("type", STRING_NAME) ), false, varray( )); + REGISTER_FUNC( _char, true, RET(STRING), ARGS( ARG("char", INT) ), false, varray( )); + REGISTER_FUNC( range, false, RET(ARRAY), NOARGS, true, varray( )); + REGISTER_FUNC( load, false, RETCLS("Resource"), ARGS( ARG("path", STRING) ), false, varray( )); + REGISTER_FUNC( inst_to_dict, false, RET(DICTIONARY), ARGS( ARG("instance", OBJECT) ), false, varray( )); + REGISTER_FUNC( dict_to_inst, false, RET(OBJECT), ARGS( ARG("dictionary", DICTIONARY) ), false, varray( )); + REGISTER_FUNC( Color8, true, RET(COLOR), ARGS( ARG("r8", INT), ARG("g8", INT), + ARG("b8", INT), ARG("a8", INT) ), false, varray( 255 )); + REGISTER_FUNC( print_debug, false, RET(NIL), NOARGS, true, varray( )); + REGISTER_FUNC( print_stack, false, RET(NIL), NOARGS, false, varray( )); + REGISTER_FUNC( get_stack, false, RET(ARRAY), NOARGS, false, varray( )); + REGISTER_FUNC( len, true, RET(INT), ARGS( ARGVAR("var") ), false, varray( )); + REGISTER_FUNC( is_instance_of, true, RET(BOOL), ARGS( ARGVAR("value"), ARGVAR("type") ), false, varray( )); + /* clang-format on */ } void GDScriptUtilityFunctions::unregister_functions() { diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index d8139d913a..26c5cfe23c 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -397,32 +397,36 @@ void (*type_init_function_table[])(Variant *) = { #define OPCODES_OUT \ OPSOUT: #define OPCODE_SWITCH(m_test) goto *switch_table_ops[m_test]; + #ifdef DEBUG_ENABLED #define DISPATCH_OPCODE \ last_opcode = _code_ptr[ip]; \ goto *switch_table_ops[last_opcode] -#else +#else // !DEBUG_ENABLED #define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]] -#endif +#endif // DEBUG_ENABLED + #define OPCODE_BREAK goto OPSEXIT #define OPCODE_OUT goto OPSOUT -#else +#else // !(defined(__GNUC__) || defined(__clang__)) #define OPCODES_TABLE #define OPCODE(m_op) case m_op: #define OPCODE_WHILE(m_test) while (m_test) #define OPCODES_END #define OPCODES_OUT #define DISPATCH_OPCODE continue + #ifdef _MSC_VER #define OPCODE_SWITCH(m_test) \ __assume(m_test <= OPCODE_END); \ switch (m_test) -#else +#else // !_MSC_VER #define OPCODE_SWITCH(m_test) switch (m_test) -#endif +#endif // _MSC_VER + #define OPCODE_BREAK break #define OPCODE_OUT break -#endif +#endif // defined(__GNUC__) || defined(__clang__) // Helpers for VariantInternal methods in macros. #define OP_GET_BOOL get_bool @@ -663,7 +667,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; \ } -#else +#else // !DEBUG_ENABLED #define GD_ERR_BREAK(m_cond) #define CHECK_SPACE(m_space) @@ -676,7 +680,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; \ } -#endif +#endif // DEBUG_ENABLED #define LOAD_INSTRUCTION_ARGS \ int instr_arg_count = _code_ptr[ip + 1]; \ @@ -1965,7 +1969,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a err_text = _get_call_error("function '" + methodstr + (is_callable ? "" : "' in base '" + basestr) + "'", (const Variant **)argptrs, temp_ret, err); OPCODE_BREAK; } -#endif +#endif // DEBUG_ENABLED ip += 3; } diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 4ffb4bd9d1..a601cc4993 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -61,10 +61,13 @@ String GDScriptWarning::get_message() const { return vformat(R"(The signal "%s" is declared but never explicitly used in the class.)", symbols[0]); case SHADOWED_VARIABLE: CHECK_SYMBOLS(4); - return vformat(R"(The local %s "%s" is shadowing an already-declared %s at line %s.)", symbols[0], symbols[1], symbols[2], symbols[3]); + return vformat(R"(The local %s "%s" is shadowing an already-declared %s at line %s in the current class.)", symbols[0], symbols[1], symbols[2], symbols[3]); case SHADOWED_VARIABLE_BASE_CLASS: CHECK_SYMBOLS(4); - return vformat(R"(The local %s "%s" is shadowing an already-declared %s at the base class "%s".)", symbols[0], symbols[1], symbols[2], symbols[3]); + if (symbols.size() > 4) { + return vformat(R"(The local %s "%s" is shadowing an already-declared %s at line %s in the base class "%s".)", symbols[0], symbols[1], symbols[2], symbols[3], symbols[4]); + } + return vformat(R"(The local %s "%s" is shadowing an already-declared %s in the base class "%s".)", symbols[0], symbols[1], symbols[2], symbols[3]); case SHADOWED_GLOBAL_IDENTIFIER: CHECK_SYMBOLS(3); return vformat(R"(The %s "%s" has the same name as a %s.)", symbols[0], symbols[1], symbols[2]); diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index ffcf00a830..99e9b30af5 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -53,8 +53,8 @@ public: UNUSED_PRIVATE_CLASS_VARIABLE, // Class variable is declared private ("_" prefix) but never used in the class. UNUSED_PARAMETER, // Function parameter is never used. UNUSED_SIGNAL, // Signal is defined but never explicitly used in the class. - SHADOWED_VARIABLE, // Variable name shadowed by other variable in same class. - SHADOWED_VARIABLE_BASE_CLASS, // Variable name shadowed by other variable in some base class. + SHADOWED_VARIABLE, // A local variable/constant shadows a current class member. + SHADOWED_VARIABLE_BASE_CLASS, // A local variable/constant shadows a base class member. SHADOWED_GLOBAL_IDENTIFIER, // A global class or function has the same name as variable. UNREACHABLE_CODE, // Code after a return statement. UNREACHABLE_PATTERN, // Pattern in a match statement after a catch all pattern (wildcard or bind). diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_builtin_access.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_builtin_access.gd new file mode 100644 index 0000000000..6367d50980 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_builtin_access.gd @@ -0,0 +1,2 @@ +func test(): + print(Vector3.Axis) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_builtin_access.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_builtin_access.out new file mode 100644 index 0000000000..9c476031f3 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_builtin_access.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Type "Axis" in base "Vector3" cannot be used on its own. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_global_access.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_global_access.gd new file mode 100644 index 0000000000..badcd3a83c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_global_access.gd @@ -0,0 +1,2 @@ +func test(): + print(Variant.Operator) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_global_access.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_global_access.out new file mode 100644 index 0000000000..191acade73 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_global_access.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Type "Operator" in base "Variant" cannot be used on its own. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_native_access.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_access.gd new file mode 100644 index 0000000000..e07998ddf6 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_access.gd @@ -0,0 +1,2 @@ +func test(): + print(Node.ProcessMode) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_native_access.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_access.out new file mode 100644 index 0000000000..83671fc493 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_access.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Type "ProcessMode" in base "Node" cannot be used on its own. diff --git a/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out b/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out index 94e2ec2af8..fb616f1e94 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out +++ b/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out @@ -1,2 +1,2 @@ GDTEST_OK -0 +0.0 diff --git a/modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd b/modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd index 5318d11f33..e91c7386fe 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd @@ -7,17 +7,17 @@ const const_packed_ints: PackedFloat64Array = [52] func test(): Utils.check(typeof(const_float_int) == TYPE_FLOAT) - Utils.check(str(const_float_int) == '19') + Utils.check(str(const_float_int) == '19.0') Utils.check(typeof(const_float_plus) == TYPE_FLOAT) - Utils.check(str(const_float_plus) == '34') + Utils.check(str(const_float_plus) == '34.0') Utils.check(typeof(const_float_cast) == TYPE_FLOAT) - Utils.check(str(const_float_cast) == '76') + Utils.check(str(const_float_cast) == '76.0') Utils.check(typeof(const_packed_empty) == TYPE_PACKED_FLOAT64_ARRAY) Utils.check(str(const_packed_empty) == '[]') Utils.check(typeof(const_packed_ints) == TYPE_PACKED_FLOAT64_ARRAY) - Utils.check(str(const_packed_ints) == '[52]') + Utils.check(str(const_packed_ints) == '[52.0]') Utils.check(typeof(const_packed_ints[0]) == TYPE_FLOAT) - Utils.check(str(const_packed_ints[0]) == '52') + Utils.check(str(const_packed_ints[0]) == '52.0') print('ok') diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.out b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.out index 15666c46ad..abf11548cb 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.out +++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_class_as_constant.out @@ -1,2 +1,2 @@ GDTEST_OK -4 +4.0 diff --git a/modules/gdscript/tests/scripts/analyzer/features/global_builtin_and_native_enums.gd b/modules/gdscript/tests/scripts/analyzer/features/global_builtin_and_native_enums.gd new file mode 100644 index 0000000000..4ccd7de994 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/global_builtin_and_native_enums.gd @@ -0,0 +1,28 @@ +extends Node + +@export var test_type_1 := TYPE_BOOL +@export var test_type_2 := Variant.Type.TYPE_BOOL +@export var test_type_3: Variant.Type + +@export var test_side_1 := SIDE_RIGHT +@export var test_side_2 := Side.SIDE_RIGHT +@export var test_side_3: Side + +@export var test_axis_1 := Vector3.AXIS_Y +@export var test_axis_2 := Vector3.Axis.AXIS_Y +@export var test_axis_3: Vector3.Axis + +@export var test_mode_1 := Node.PROCESS_MODE_ALWAYS +@export var test_mode_2 := Node.ProcessMode.PROCESS_MODE_ALWAYS +@export var test_mode_3: Node.ProcessMode + +func test(): + for property in get_property_list(): + if str(property.name).begins_with("test_"): + Utils.print_property_extended_info(property, self) + +func test_no_exec(): + # GH-99309 + var sprite: Sprite3D = $Sprite3D + sprite.axis = Vector3.AXIS_Y # No warning. + sprite.set_axis(Vector3.AXIS_Y) # No warning. diff --git a/modules/gdscript/tests/scripts/analyzer/features/global_builtin_and_native_enums.out b/modules/gdscript/tests/scripts/analyzer/features/global_builtin_and_native_enums.out new file mode 100644 index 0000000000..6c45dee323 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/global_builtin_and_native_enums.out @@ -0,0 +1,25 @@ +GDTEST_OK +var test_type_1: Variant.Type = 1 + hint=ENUM hint_string="Type Nil:0,Type Bool:1,Type Int:2,Type Float:3,Type String:4,Type Vector 2:5,Type Vector 2i:6,Type Rect 2:7,Type Rect 2i:8,Type Vector 3:9,Type Vector 3i:10,Type Transform 2d:11,Type Vector 4:12,Type Vector 4i:13,Type Plane:14,Type Quaternion:15,Type Aabb:16,Type Basis:17,Type Transform 3d:18,Type Projection:19,Type Color:20,Type String Name:21,Type Node Path:22,Type Rid:23,Type Object:24,Type Callable:25,Type Signal:26,Type Dictionary:27,Type Array:28,Type Packed Byte Array:29,Type Packed Int 32 Array:30,Type Packed Int 64 Array:31,Type Packed Float 32 Array:32,Type Packed Float 64 Array:33,Type Packed String Array:34,Type Packed Vector 2 Array:35,Type Packed Vector 3 Array:36,Type Packed Color Array:37,Type Packed Vector 4 Array:38,Type Max:39" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Variant.Type" +var test_type_2: Variant.Type = 1 + hint=ENUM hint_string="Type Nil:0,Type Bool:1,Type Int:2,Type Float:3,Type String:4,Type Vector 2:5,Type Vector 2i:6,Type Rect 2:7,Type Rect 2i:8,Type Vector 3:9,Type Vector 3i:10,Type Transform 2d:11,Type Vector 4:12,Type Vector 4i:13,Type Plane:14,Type Quaternion:15,Type Aabb:16,Type Basis:17,Type Transform 3d:18,Type Projection:19,Type Color:20,Type String Name:21,Type Node Path:22,Type Rid:23,Type Object:24,Type Callable:25,Type Signal:26,Type Dictionary:27,Type Array:28,Type Packed Byte Array:29,Type Packed Int 32 Array:30,Type Packed Int 64 Array:31,Type Packed Float 32 Array:32,Type Packed Float 64 Array:33,Type Packed String Array:34,Type Packed Vector 2 Array:35,Type Packed Vector 3 Array:36,Type Packed Color Array:37,Type Packed Vector 4 Array:38,Type Max:39" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Variant.Type" +var test_type_3: Variant.Type = 0 + hint=ENUM hint_string="Type Nil:0,Type Bool:1,Type Int:2,Type Float:3,Type String:4,Type Vector 2:5,Type Vector 2i:6,Type Rect 2:7,Type Rect 2i:8,Type Vector 3:9,Type Vector 3i:10,Type Transform 2d:11,Type Vector 4:12,Type Vector 4i:13,Type Plane:14,Type Quaternion:15,Type Aabb:16,Type Basis:17,Type Transform 3d:18,Type Projection:19,Type Color:20,Type String Name:21,Type Node Path:22,Type Rid:23,Type Object:24,Type Callable:25,Type Signal:26,Type Dictionary:27,Type Array:28,Type Packed Byte Array:29,Type Packed Int 32 Array:30,Type Packed Int 64 Array:31,Type Packed Float 32 Array:32,Type Packed Float 64 Array:33,Type Packed String Array:34,Type Packed Vector 2 Array:35,Type Packed Vector 3 Array:36,Type Packed Color Array:37,Type Packed Vector 4 Array:38,Type Max:39" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Variant.Type" +var test_side_1: Side = 2 + hint=ENUM hint_string="Side Left:0,Side Top:1,Side Right:2,Side Bottom:3" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Side" +var test_side_2: Side = 2 + hint=ENUM hint_string="Side Left:0,Side Top:1,Side Right:2,Side Bottom:3" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Side" +var test_side_3: Side = 0 + hint=ENUM hint_string="Side Left:0,Side Top:1,Side Right:2,Side Bottom:3" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Side" +var test_axis_1: Vector3.Axis = 1 + hint=ENUM hint_string="Axis X:0,Axis Y:1,Axis Z:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Vector3.Axis" +var test_axis_2: Vector3.Axis = 1 + hint=ENUM hint_string="Axis X:0,Axis Y:1,Axis Z:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Vector3.Axis" +var test_axis_3: Vector3.Axis = 0 + hint=ENUM hint_string="Axis X:0,Axis Y:1,Axis Z:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Vector3.Axis" +var test_mode_1: Node.ProcessMode = 3 + hint=ENUM hint_string="Process Mode Inherit:0,Process Mode Pausable:1,Process Mode When Paused:2,Process Mode Always:3,Process Mode Disabled:4" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Node.ProcessMode" +var test_mode_2: Node.ProcessMode = 3 + hint=ENUM hint_string="Process Mode Inherit:0,Process Mode Pausable:1,Process Mode When Paused:2,Process Mode Always:3,Process Mode Disabled:4" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Node.ProcessMode" +var test_mode_3: Node.ProcessMode = 0 + hint=ENUM hint_string="Process Mode Inherit:0,Process Mode Pausable:1,Process Mode When Paused:2,Process Mode Always:3,Process Mode Disabled:4" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Node.ProcessMode" diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd index fe0274c27b..eb53d0a700 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd @@ -54,39 +54,39 @@ func test(): untyped_basic.push_back(430.0) inferred_basic.push_back(263.0) typed_basic.push_back(518.0) - Utils.check(str(empty_floats) == '[705, 430, 263, 518]') - Utils.check(str(untyped_basic) == '[705, 430, 263, 518]') - Utils.check(str(inferred_basic) == '[705, 430, 263, 518]') - Utils.check(str(typed_basic) == '[705, 430, 263, 518]') + Utils.check(str(empty_floats) == '[705.0, 430.0, 263.0, 518.0]') + Utils.check(str(untyped_basic) == '[705.0, 430.0, 263.0, 518.0]') + Utils.check(str(inferred_basic) == '[705.0, 430.0, 263.0, 518.0]') + Utils.check(str(typed_basic) == '[705.0, 430.0, 263.0, 518.0]') const constant_float := 950.0 const constant_int := 170 var typed_float := 954.0 var filled_floats: Array[float] = [constant_float, constant_int, typed_float, empty_floats[1] + empty_floats[2]] - Utils.check(str(filled_floats) == '[950, 170, 954, 693]') + Utils.check(str(filled_floats) == '[950.0, 170.0, 954.0, 693.0]') Utils.check(filled_floats.get_typed_builtin() == TYPE_FLOAT) var casted_floats := [empty_floats[2] * 2] as Array[float] - Utils.check(str(casted_floats) == '[526]') + Utils.check(str(casted_floats) == '[526.0]') Utils.check(casted_floats.get_typed_builtin() == TYPE_FLOAT) var returned_floats = (func () -> Array[float]: return [554]).call() - Utils.check(str(returned_floats) == '[554]') + Utils.check(str(returned_floats) == '[554.0]') Utils.check(returned_floats.get_typed_builtin() == TYPE_FLOAT) var passed_floats = floats_identity([663.0 if randf() > 0.5 else 663.0]) - Utils.check(str(passed_floats) == '[663]') + Utils.check(str(passed_floats) == '[663.0]') Utils.check(passed_floats.get_typed_builtin() == TYPE_FLOAT) var default_floats = (func (floats: Array[float] = [364.0]): return floats).call() - Utils.check(str(default_floats) == '[364]') + Utils.check(str(default_floats) == '[364.0]') Utils.check(default_floats.get_typed_builtin() == TYPE_FLOAT) var typed_int := 556 var converted_floats: Array[float] = [typed_int] converted_floats.push_back(498) - Utils.check(str(converted_floats) == '[556, 498]') + Utils.check(str(converted_floats) == '[556.0, 498.0]') Utils.check(converted_floats.get_typed_builtin() == TYPE_FLOAT) @@ -95,7 +95,7 @@ func test(): Utils.check(constant_basic.get_typed_builtin() == TYPE_NIL) const constant_floats: Array[float] = [constant_float - constant_basic[0] - constant_int] - Utils.check(str(constant_floats) == '[552]') + Utils.check(str(constant_floats) == '[552.0]') Utils.check(constant_floats.get_typed_builtin() == TYPE_FLOAT) @@ -103,15 +103,15 @@ func test(): untyped_basic = source_floats var destination_floats: Array[float] = untyped_basic destination_floats[0] -= 0.74 - Utils.check(str(source_floats) == '[999]') - Utils.check(str(untyped_basic) == '[999]') - Utils.check(str(destination_floats) == '[999]') + Utils.check(str(source_floats) == '[999.0]') + Utils.check(str(untyped_basic) == '[999.0]') + Utils.check(str(destination_floats) == '[999.0]') Utils.check(destination_floats.get_typed_builtin() == TYPE_FLOAT) var duplicated_floats := empty_floats.duplicate().slice(2, 3) duplicated_floats[0] *= 3 - Utils.check(str(duplicated_floats) == '[789]') + Utils.check(str(duplicated_floats) == '[789.0]') Utils.check(duplicated_floats.get_typed_builtin() == TYPE_FLOAT) diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.gd index 9d3fffd1de..c9ab368f45 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.gd @@ -62,44 +62,44 @@ func test(): untyped_basic[430.0] = 34.0 inferred_basic[263.0] = 362.0 typed_basic[518.0] = 815.0 - Utils.check(str(empty_floats) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') - Utils.check(str(untyped_basic) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') - Utils.check(str(inferred_basic) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') - Utils.check(str(typed_basic) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') + Utils.check(str(empty_floats) == '{ 705.0: 507.0, 430.0: 34.0, 263.0: 362.0, 518.0: 815.0 }') + Utils.check(str(untyped_basic) == '{ 705.0: 507.0, 430.0: 34.0, 263.0: 362.0, 518.0: 815.0 }') + Utils.check(str(inferred_basic) == '{ 705.0: 507.0, 430.0: 34.0, 263.0: 362.0, 518.0: 815.0 }') + Utils.check(str(typed_basic) == '{ 705.0: 507.0, 430.0: 34.0, 263.0: 362.0, 518.0: 815.0 }') const constant_float := 950.0 const constant_int := 170 var typed_float := 954.0 var filled_floats: Dictionary[float, float] = { constant_float: constant_int, typed_float: empty_floats[430.0] + empty_floats[263.0] } - Utils.check(str(filled_floats) == '{ 950: 170, 954: 396 }') + Utils.check(str(filled_floats) == '{ 950.0: 170.0, 954.0: 396.0 }') Utils.check(filled_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(filled_floats.get_typed_value_builtin() == TYPE_FLOAT) var casted_floats := { empty_floats[263.0] * 2: empty_floats[263.0] / 2 } as Dictionary[float, float] - Utils.check(str(casted_floats) == '{ 724: 181 }') + Utils.check(str(casted_floats) == '{ 724.0: 181.0 }') Utils.check(casted_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(casted_floats.get_typed_value_builtin() == TYPE_FLOAT) var returned_floats = (func () -> Dictionary[float, float]: return { 554: 455 }).call() - Utils.check(str(returned_floats) == '{ 554: 455 }') + Utils.check(str(returned_floats) == '{ 554.0: 455.0 }') Utils.check(returned_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(returned_floats.get_typed_value_builtin() == TYPE_FLOAT) var passed_floats = floats_identity({ 663.0 if randf() > 0.5 else 663.0: 366.0 if randf() <= 0.5 else 366.0 }) - Utils.check(str(passed_floats) == '{ 663: 366 }') + Utils.check(str(passed_floats) == '{ 663.0: 366.0 }') Utils.check(passed_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(passed_floats.get_typed_value_builtin() == TYPE_FLOAT) var default_floats = (func (floats: Dictionary[float, float] = { 364.0: 463.0 }): return floats).call() - Utils.check(str(default_floats) == '{ 364: 463 }') + Utils.check(str(default_floats) == '{ 364.0: 463.0 }') Utils.check(default_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(default_floats.get_typed_value_builtin() == TYPE_FLOAT) var typed_int := 556 var converted_floats: Dictionary[float, float] = { typed_int: typed_int } converted_floats[498.0] = 894 - Utils.check(str(converted_floats) == '{ 556: 556, 498: 894 }') + Utils.check(str(converted_floats) == '{ 556.0: 556.0, 498.0: 894.0 }') Utils.check(converted_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(converted_floats.get_typed_value_builtin() == TYPE_FLOAT) @@ -110,7 +110,7 @@ func test(): Utils.check(constant_basic.get_typed_value_builtin() == TYPE_NIL) const constant_floats: Dictionary[float, float] = { constant_float - constant_basic[228] - constant_int: constant_float + constant_basic[228] + constant_int } - Utils.check(str(constant_floats) == '{ -42: 1942 }') + Utils.check(str(constant_floats) == '{ -42.0: 1942.0 }') Utils.check(constant_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(constant_floats.get_typed_value_builtin() == TYPE_FLOAT) @@ -119,9 +119,9 @@ func test(): untyped_basic = source_floats var destination_floats: Dictionary[float, float] = untyped_basic destination_floats[999.74] -= 0.999 - Utils.check(str(source_floats) == '{ 999.74: 47 }') - Utils.check(str(untyped_basic) == '{ 999.74: 47 }') - Utils.check(str(destination_floats) == '{ 999.74: 47 }') + Utils.check(str(source_floats) == '{ 999.74: 47.0 }') + Utils.check(str(untyped_basic) == '{ 999.74: 47.0 }') + Utils.check(str(destination_floats) == '{ 999.74: 47.0 }') Utils.check(destination_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(destination_floats.get_typed_value_builtin() == TYPE_FLOAT) @@ -131,7 +131,7 @@ func test(): duplicated_floats.erase(430.0) duplicated_floats.erase(518.0) duplicated_floats[263.0] *= 3 - Utils.check(str(duplicated_floats) == '{ 263: 1086 }') + Utils.check(str(duplicated_floats) == '{ 263.0: 1086.0 }') Utils.check(duplicated_floats.get_typed_key_builtin() == TYPE_FLOAT) Utils.check(duplicated_floats.get_typed_value_builtin() == TYPE_FLOAT) diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage.out b/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage.out index 0e0d607831..cfe91e00bd 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage.out +++ b/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage.out @@ -6,6 +6,6 @@ GDTEST_OK >> WARNING >> Line: 5 >> SHADOWED_VARIABLE ->> The local variable "a" is shadowing an already-declared variable at line 1. +>> The local variable "a" is shadowing an already-declared variable at line 1 in the current class. 1 2 diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_initializer.out b/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_initializer.out index 228a510490..ae0f2d8b8b 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_initializer.out +++ b/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_initializer.out @@ -10,6 +10,6 @@ GDTEST_OK >> WARNING >> Line: 5 >> SHADOWED_VARIABLE ->> The local variable "a" is shadowing an already-declared variable at line 1. +>> The local variable "a" is shadowing an already-declared variable at line 1 in the current class. 1 2 diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_loop.out b/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_loop.out index 0d20e9f7a0..101d27df9d 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_loop.out +++ b/modules/gdscript/tests/scripts/analyzer/warnings/confusable_local_usage_loop.out @@ -6,7 +6,7 @@ GDTEST_OK >> WARNING >> Line: 6 >> SHADOWED_VARIABLE ->> The local variable "a" is shadowing an already-declared variable at line 1. +>> The local variable "a" is shadowing an already-declared variable at line 1 in the current class. 1 2 1 diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out index a98d80514c..5d059b9193 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out +++ b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out @@ -2,5 +2,5 @@ GDTEST_OK >> WARNING >> Line: 4 >> SHADOWED_VARIABLE ->> The local function parameter "shadow" is shadowing an already-declared variable at line 1. +>> The local function parameter "shadow" is shadowing an already-declared variable at line 1 in the current class. shadow diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/shadowing_base.notest.gd b/modules/gdscript/tests/scripts/analyzer/warnings/shadowing_base.notest.gd new file mode 100644 index 0000000000..5819246ded --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/warnings/shadowing_base.notest.gd @@ -0,0 +1,7 @@ +class_name ShadowingBase + +const base_const_member = 1 +var base_variable_member + +func base_function_member(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd index 939e787ea5..6a16ae6bcc 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd +++ b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd @@ -1,4 +1,5 @@ class_name ShadowedClass +extends ShadowingBase var member: int = 0 @@ -7,6 +8,7 @@ var print_debug := 'print_debug' var print := 'print' @warning_ignore("unused_variable") +@warning_ignore("unused_local_constant") func test(): var Array := 'Array' var Node := 'Node' @@ -15,5 +17,8 @@ func test(): var member := 'member' var reference := 'reference' var ShadowedClass := 'ShadowedClass' + var base_variable_member + const base_function_member = 1 + var base_const_member print('warn') diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out index 8297eed4b8..075f5d3225 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out +++ b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out @@ -1,34 +1,46 @@ GDTEST_OK >> WARNING ->> Line: 5 +>> Line: 6 >> SHADOWED_GLOBAL_IDENTIFIER >> The variable "print_debug" has the same name as a built-in function. >> WARNING ->> Line: 11 +>> Line: 13 >> SHADOWED_GLOBAL_IDENTIFIER >> The variable "Array" has the same name as a built-in type. >> WARNING ->> Line: 12 +>> Line: 14 >> SHADOWED_GLOBAL_IDENTIFIER >> The variable "Node" has the same name as a native class. >> WARNING ->> Line: 13 +>> Line: 15 >> SHADOWED_GLOBAL_IDENTIFIER >> The variable "is_same" has the same name as a built-in function. >> WARNING ->> Line: 14 +>> Line: 16 >> SHADOWED_GLOBAL_IDENTIFIER >> The variable "sqrt" has the same name as a built-in function. >> WARNING ->> Line: 15 +>> Line: 17 >> SHADOWED_VARIABLE ->> The local variable "member" is shadowing an already-declared variable at line 3. +>> The local variable "member" is shadowing an already-declared variable at line 4 in the current class. >> WARNING ->> Line: 16 +>> Line: 18 >> SHADOWED_VARIABLE_BASE_CLASS ->> The local variable "reference" is shadowing an already-declared method at the base class "RefCounted". +>> The local variable "reference" is shadowing an already-declared method in the base class "RefCounted". >> WARNING ->> Line: 17 +>> Line: 19 >> SHADOWED_GLOBAL_IDENTIFIER >> The variable "ShadowedClass" has the same name as a global class defined in "shadowning.gd". +>> WARNING +>> Line: 20 +>> SHADOWED_VARIABLE_BASE_CLASS +>> The local variable "base_variable_member" is shadowing an already-declared variable at line 4 in the base class "ShadowingBase". +>> WARNING +>> Line: 21 +>> SHADOWED_VARIABLE_BASE_CLASS +>> The local constant "base_function_member" is shadowing an already-declared function at line 6 in the base class "ShadowingBase". +>> WARNING +>> Line: 22 +>> SHADOWED_VARIABLE_BASE_CLASS +>> The local variable "base_const_member" is shadowing an already-declared constant at line 3 in the base class "ShadowingBase". warn diff --git a/modules/gdscript/tests/scripts/completion/argument_options/argument_options.tscn b/modules/gdscript/tests/scripts/completion/argument_options/argument_options.tscn index d3dea6b12b..082c87e708 100644 --- a/modules/gdscript/tests/scripts/completion/argument_options/argument_options.tscn +++ b/modules/gdscript/tests/scripts/completion/argument_options/argument_options.tscn @@ -1,3 +1,16 @@ [gd_scene load_steps=1 format=3 uid="uid://dl28pdkxcjvym"] +[sub_resource type="Animation" id="Animation_d1pub"] +resource_name = "bounce" + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_gs7mj"] +_data = { +"bounce": SubResource("Animation_d1pub") +} + [node name="GetNode" type="Node"] + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_gs7mj") +} diff --git a/modules/gdscript/tests/scripts/completion/argument_options/play_inferred.cfg b/modules/gdscript/tests/scripts/completion/argument_options/play_inferred.cfg new file mode 100644 index 0000000000..ca108a18c2 --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/argument_options/play_inferred.cfg @@ -0,0 +1,6 @@ +[input] +scene="res://completion/argument_options/argument_options.tscn" +[output] +include=[ + {"display": "\"bounce\""}, +] diff --git a/modules/gdscript/tests/scripts/completion/argument_options/play_inferred.gd b/modules/gdscript/tests/scripts/completion/argument_options/play_inferred.gd new file mode 100644 index 0000000000..abeadbe5ee --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/argument_options/play_inferred.gd @@ -0,0 +1,5 @@ +@onready var anim := $AnimationPlayer + +func test(): + anim.play(➡) + pass diff --git a/modules/gdscript/tests/scripts/completion/argument_options/play_typed.cfg b/modules/gdscript/tests/scripts/completion/argument_options/play_typed.cfg new file mode 100644 index 0000000000..ca108a18c2 --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/argument_options/play_typed.cfg @@ -0,0 +1,6 @@ +[input] +scene="res://completion/argument_options/argument_options.tscn" +[output] +include=[ + {"display": "\"bounce\""}, +] diff --git a/modules/gdscript/tests/scripts/completion/argument_options/play_typed.gd b/modules/gdscript/tests/scripts/completion/argument_options/play_typed.gd new file mode 100644 index 0000000000..d11f81e985 --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/argument_options/play_typed.gd @@ -0,0 +1,5 @@ +@onready var anim: AnimationPlayer = $AnimationPlayer + +func test(): + anim.play(➡) + pass diff --git a/modules/gdscript/tests/scripts/completion/argument_options/play_untyped.cfg b/modules/gdscript/tests/scripts/completion/argument_options/play_untyped.cfg new file mode 100644 index 0000000000..ca108a18c2 --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/argument_options/play_untyped.cfg @@ -0,0 +1,6 @@ +[input] +scene="res://completion/argument_options/argument_options.tscn" +[output] +include=[ + {"display": "\"bounce\""}, +] diff --git a/modules/gdscript/tests/scripts/completion/argument_options/play_untyped.gd b/modules/gdscript/tests/scripts/completion/argument_options/play_untyped.gd new file mode 100644 index 0000000000..4ddfd21ac6 --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/argument_options/play_untyped.gd @@ -0,0 +1,5 @@ +@onready var anim = $AnimationPlayer + +func test(): + anim.play(➡) + pass diff --git a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg index e4759ac76b..a2c332adad 100644 --- a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg +++ b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg @@ -1,6 +1,6 @@ [output] include=[ - {"display": "new"}, + {"display": "new(…)"}, {"display": "SIZE_EXPAND"}, {"display": "SIZE_EXPAND_FILL"}, {"display": "SIZE_FILL"}, diff --git a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg index e4759ac76b..a2c332adad 100644 --- a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg +++ b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg @@ -1,6 +1,6 @@ [output] include=[ - {"display": "new"}, + {"display": "new(…)"}, {"display": "SIZE_EXPAND"}, {"display": "SIZE_EXPAND_FILL"}, {"display": "SIZE_FILL"}, diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg index 5f08f9c265..f2dff734b6 100644 --- a/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg +++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: identifiers.gd @@ -16,8 +16,8 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg index 5f08f9c265..f2dff734b6 100644 --- a/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg +++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: identifiers.gd @@ -16,8 +16,8 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg index 5f08f9c265..f2dff734b6 100644 --- a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg +++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: identifiers.gd @@ -16,8 +16,8 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg index 462846c9b2..e012919051 100644 --- a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg +++ b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg @@ -2,14 +2,14 @@ scene="res://completion/get_node/get_node.tscn" [output] exclude=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, - {"display": "add_child"}, + {"display": "add_child(…)"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: no_completion_in_string.gd @@ -17,8 +17,8 @@ exclude=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/self.cfg b/modules/gdscript/tests/scripts/completion/common/self.cfg index 871a404e3a..dcce1df0d0 100644 --- a/modules/gdscript/tests/scripts/completion/common/self.cfg +++ b/modules/gdscript/tests/scripts/completion/common/self.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: self.gd @@ -16,6 +16,6 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg b/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg index 72c0549d3b..d647135bc6 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg index 1894e72c65..a6118908de 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg index c8ab63f6d6..d8390ca33c 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg b/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg index 72c0549d3b..d647135bc6 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg index 502038bef7..2f747e0bac 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg @@ -3,7 +3,7 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, @@ -11,6 +11,6 @@ include=[ exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg index 1810e9fe5f..f060413898 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg @@ -3,7 +3,7 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, @@ -11,6 +11,6 @@ include=[ exclude=[ ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg index 1894e72c65..a6118908de 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg index c8ab63f6d6..d8390ca33c 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/infered.cfg b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/infered.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg b/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg b/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg b/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg b/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/infered.cfg b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/infered.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg b/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg b/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg b/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg index 81401316ec..d32bbac65e 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg @@ -1,13 +1,13 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg b/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/parser/errors/annotation_inapplicable.gd b/modules/gdscript/tests/scripts/parser/errors/annotation_inapplicable.gd new file mode 100644 index 0000000000..cfacb6a010 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/annotation_inapplicable.gd @@ -0,0 +1,3 @@ +@export +func test(): + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/annotation_inapplicable.out b/modules/gdscript/tests/scripts/parser/errors/annotation_inapplicable.out new file mode 100644 index 0000000000..ed677cd39a --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/annotation_inapplicable.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Annotation "@export" cannot be applied to a function. diff --git a/modules/gdscript/tests/scripts/parser/errors/annotation_unrecognized.gd b/modules/gdscript/tests/scripts/parser/errors/annotation_unrecognized.gd new file mode 100644 index 0000000000..a6b171a428 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/annotation_unrecognized.gd @@ -0,0 +1,3 @@ +@hello_world +func test(): + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/annotation_unrecognized.out b/modules/gdscript/tests/scripts/parser/errors/annotation_unrecognized.out new file mode 100644 index 0000000000..540e66f15b --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/annotation_unrecognized.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Unrecognized annotation: "@hello_world". diff --git a/modules/gdscript/tests/scripts/parser/features/export_arrays.out b/modules/gdscript/tests/scripts/parser/features/export_arrays.out index f1522d096f..7201d8082d 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_arrays.out +++ b/modules/gdscript/tests/scripts/parser/features/export_arrays.out @@ -80,21 +80,21 @@ var test_placeholder: Array var test_placeholder_packed: PackedStringArray hint=TYPE_STRING hint_string="<String>/<PLACEHOLDER_TEXT>:Placeholder" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_int: Array - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_int_packed_byte: PackedByteArray - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_int_packed32: PackedInt32Array - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_int_packed64: PackedInt64Array - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_int_float_step: Array - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10,0.01" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0,0.01" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_float: Array - hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<float>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_float_packed32: PackedFloat32Array - hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<float>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_float_packed64: PackedFloat64Array - hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<float>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_exp_easing: Array hint=TYPE_STRING hint_string="<float>/<EXP_EASING>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_exp_easing_packed32: PackedFloat32Array @@ -126,14 +126,14 @@ var test_weak_packed_vector3_array: PackedVector3Array var test_weak_packed_vector4_array: PackedVector4Array hint=TYPE_STRING hint_string="<Vector4>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_weak_packed_byte_array: PackedByteArray - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_weak_packed_int32_array: PackedInt32Array - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_weak_packed_int64_array: PackedInt64Array - hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<int>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_weak_packed_float32_array: PackedFloat32Array - hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<float>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_weak_packed_float64_array: PackedFloat64Array - hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=TYPE_STRING hint_string="<float>/<RANGE>:1.0,10.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_noalpha_weak_packed_color_array: PackedColorArray hint=TYPE_STRING hint_string="<Color>/<COLOR_NO_ALPHA>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.out b/modules/gdscript/tests/scripts/parser/features/export_variable.out index 0d915e00e6..c0bf4d6e06 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_variable.out +++ b/modules/gdscript/tests/scripts/parser/features/export_variable.out @@ -4,11 +4,11 @@ var test_weak_int: int = 1 var test_hard_int: int = 2 hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range: int = 100 - hint=RANGE hint_string="0,100" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=RANGE hint_string="0.0,100.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_step: int = 101 - hint=RANGE hint_string="0,100,1" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=RANGE hint_string="0.0,100.0,1.0" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_range_step_or_greater: int = 102 - hint=RANGE hint_string="0,100,1,or_greater" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" + hint=RANGE hint_string="0.0,100.0,1.0,or_greater" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_color: Color = Color(0, 0, 0, 1) hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"" var test_color_no_alpha: Color = Color(0, 0, 0, 1) diff --git a/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out b/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out index c5958365ec..d94cbe5556 100644 --- a/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out +++ b/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out @@ -13,4 +13,4 @@ true 0 -255 256 -2 +2.0 diff --git a/modules/gdscript/tests/scripts/parser/features/number_separators.out b/modules/gdscript/tests/scripts/parser/features/number_separators.out index b0d2fd94fe..9407af9cd8 100644 --- a/modules/gdscript/tests/scripts/parser/features/number_separators.out +++ b/modules/gdscript/tests/scripts/parser/features/number_separators.out @@ -13,12 +13,12 @@ GDTEST_OK --- -1234.4567 -1234.4567 --1234 --1234 +-1234.0 +-1234.0 0.4567 0.4567 --- --1234500 --1234500 --1234500 --1234500 +-1234500.0 +-1234500.0 +-1234500.0 +-1234500.0 diff --git a/modules/gdscript/tests/scripts/parser/features/operator_assign.out b/modules/gdscript/tests/scripts/parser/features/operator_assign.out index b0cb63ef59..29910adf38 100644 --- a/modules/gdscript/tests/scripts/parser/features/operator_assign.out +++ b/modules/gdscript/tests/scripts/parser/features/operator_assign.out @@ -1,2 +1,2 @@ GDTEST_OK -8 +8.0 diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.out index 75fa01f928..04df229f66 100644 --- a/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.out +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.out @@ -6,4 +6,4 @@ GDTEST_OK >> WARNING >> Line: 8 >> SHADOWED_VARIABLE ->> The local constant "TEST" is shadowing an already-declared constant at line 2. +>> The local constant "TEST" is shadowing an already-declared constant at line 2 in the current class. diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.out index aab27e78e2..4a6964f503 100644 --- a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.out +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.out @@ -6,4 +6,4 @@ GDTEST_OK >> WARNING >> Line: 8 >> SHADOWED_VARIABLE ->> The local variable "foo" is shadowing an already-declared variable at line 1. +>> The local variable "foo" is shadowing an already-declared variable at line 1 in the current class. diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.out index e3cd358126..45fb771829 100644 --- a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.out +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.out @@ -6,4 +6,4 @@ GDTEST_OK >> WARNING >> Line: 2 >> SHADOWED_VARIABLE ->> The local variable "test" is shadowing an already-declared function at line 1. +>> The local variable "test" is shadowing an already-declared function at line 1 in the current class. diff --git a/modules/gdscript/tests/scripts/runtime/errors/division_by_zero.gd b/modules/gdscript/tests/scripts/runtime/errors/division_by_zero.gd new file mode 100644 index 0000000000..ace5397f40 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/division_by_zero.gd @@ -0,0 +1,3 @@ +func test(): + var integer: int = 1 + integer /= 0 diff --git a/modules/gdscript/tests/scripts/runtime/errors/division_by_zero.out b/modules/gdscript/tests/scripts/runtime/errors/division_by_zero.out new file mode 100644 index 0000000000..6a9d11cd77 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/division_by_zero.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/division_by_zero.gd +>> 3 +>> Division by zero error in operator '/'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.gd b/modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.gd new file mode 100644 index 0000000000..99792e4e32 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.gd @@ -0,0 +1,3 @@ +func test(): + var integer: int = 1 + integer %= 0 diff --git a/modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.out b/modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.out new file mode 100644 index 0000000000..79c512888f --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/modulo_by_zero.gd +>> 3 +>> Modulo by zero error in operator '%'. diff --git a/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out b/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out index 22929bf636..04b0773991 100644 --- a/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out +++ b/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out @@ -1,7 +1,7 @@ GDTEST_OK -{ 1: (2, 0) } -{ 3: (4, 0) } -[[(5, 0)]] -[[(6, 0)]] -[[(7, 0)]] -[X: (8, 9, 7), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0, 0)] +{ 1: (2.0, 0.0) } +{ 3: (4.0, 0.0) } +[[(5.0, 0.0)]] +[[(6.0, 0.0)]] +[[(7.0, 0.0)]] +[X: (8.0, 9.0, 7.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 0.0, 0.0)] diff --git a/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out index a9ef4919cf..78ea2a2d80 100644 --- a/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out +++ b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out @@ -1,8 +1,8 @@ GDTEST_OK -x is 1 +x is 1.0 typeof x is 3 -x is 2 +x is 2.0 typeof x is 3 -x is 3 +x is 3.0 typeof x is 3 ok diff --git a/modules/gdscript/tests/scripts/runtime/features/gdscript_utility_implicit_conversion.gd b/modules/gdscript/tests/scripts/runtime/features/gdscript_utility_implicit_conversion.gd new file mode 100644 index 0000000000..59bdb6eceb --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/gdscript_utility_implicit_conversion.gd @@ -0,0 +1,12 @@ +func test(): + const COLOR = Color8(255, 0.0, false) + var false_value := false + @warning_ignore("narrowing_conversion") + var color = Color8(255, 0.0, false_value) + print(var_to_str(COLOR)) + print(var_to_str(color)) + + var string := "Node" + var string_name := &"Node" + print(type_exists(string)) + print(type_exists(string_name)) diff --git a/modules/gdscript/tests/scripts/runtime/features/gdscript_utility_implicit_conversion.out b/modules/gdscript/tests/scripts/runtime/features/gdscript_utility_implicit_conversion.out new file mode 100644 index 0000000000..00913faa49 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/gdscript_utility_implicit_conversion.out @@ -0,0 +1,5 @@ +GDTEST_OK +Color(1, 0, 0, 1) +Color(1, 0, 0, 1) +true +true diff --git a/modules/gdscript/tests/scripts/runtime/features/native_static_method_as_callable.gd b/modules/gdscript/tests/scripts/runtime/features/native_static_method_as_callable.gd new file mode 100644 index 0000000000..63d5935d1e --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/native_static_method_as_callable.gd @@ -0,0 +1,8 @@ +func get_parse_string(t: Variant): + return t.parse_string + +func test(): + var a: Callable = JSON.parse_string + var b: Callable = get_parse_string(JSON) + prints(a.call("{\"test\": \"a\"}"), a.is_valid()) + prints(b.call("{\"test\": \"b\"}"), b.is_valid()) diff --git a/modules/gdscript/tests/scripts/runtime/features/native_static_method_as_callable.out b/modules/gdscript/tests/scripts/runtime/features/native_static_method_as_callable.out new file mode 100644 index 0000000000..a2cb4b9a07 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/native_static_method_as_callable.out @@ -0,0 +1,3 @@ +GDTEST_OK +{ "test": "a" } false +{ "test": "b" } false diff --git a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out index 5b981bc8bb..1650acadb5 100644 --- a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out +++ b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.out @@ -2,16 +2,16 @@ GDTEST_OK >> WARNING >> Line: 5 >> SHADOWED_VARIABLE ->> The local function parameter "a" is shadowing an already-declared variable at line 3. +>> The local function parameter "a" is shadowing an already-declared variable at line 3 in the current class. >> WARNING >> Line: 15 >> SHADOWED_VARIABLE ->> The local function parameter "v" is shadowing an already-declared variable at line 13. +>> The local function parameter "v" is shadowing an already-declared variable at line 13 in the current class. a 1 b 1 -(1, 1) -(0, 0) -(6, 1) -(0, 0) +(1.0, 1.0) +(0.0, 0.0) +(6.0, 1.0) +(0.0, 0.0) diff --git a/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out b/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out index c51759f481..e82e31bbed 100644 --- a/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out +++ b/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out @@ -1,26 +1,26 @@ GDTEST_OK === -prop1 setter (0, 0) -prop1 setter (1, 0) +prop1 setter (0.0, 0.0) +prop1 setter (1.0, 0.0) --- prop1 setter <Inner> subprop getter -subprop setter (1, 0) +subprop setter (1.0, 0.0) === prop2 setter <Inner> subprop getter -subprop setter (1, 0) +subprop setter (1.0, 0.0) === -prop3 setter (0, 0) +prop3 setter (0.0, 0.0) prop3 getter -prop3 setter (1, 0) +prop3 setter (1.0, 0.0) --- prop3 setter <Inner> prop3 getter subprop getter -subprop setter (1, 0) +subprop setter (1.0, 0.0) === prop4 setter <Inner> prop4 getter subprop getter -subprop setter (1, 0) +subprop setter (1.0, 0.0) diff --git a/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out b/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out index 31b3b3a3a8..8617a65c33 100644 --- a/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out +++ b/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out @@ -1,4 +1,4 @@ GDTEST_OK -setting vec from (0, 0) to (2, 0) -setting vec from (0, 0) to (0, 2) -vec is (0, 0) +setting vec from (0.0, 0.0) to (2.0, 0.0) +setting vec from (0.0, 0.0) to (0.0, 2.0) +vec is (0.0, 0.0) diff --git a/modules/gdscript/tests/scripts/runtime/features/stringify.out b/modules/gdscript/tests/scripts/runtime/features/stringify.out index 7833b6e213..2463d70ef4 100644 --- a/modules/gdscript/tests/scripts/runtime/features/stringify.out +++ b/modules/gdscript/tests/scripts/runtime/features/stringify.out @@ -9,13 +9,13 @@ hello world [P: (0, 0), S: (0, 0)] (0.25, 0.25, 0.25) (0, 0, 0) -[X: (1, 0), Y: (0, 1), O: (0, 0)] -[N: (1, 2, 3), D: 4] -(1, 2, 3, 4) -[P: (0, 0, 0), S: (1, 1, 1)] -[X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1)] -[X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0, 0)] +[X: (1.0, 0.0), Y: (0.0, 1.0), O: (0.0, 0.0)] +[N: (1.0, 2.0, 3.0), D: 4] (1, 2, 3, 4) +[P: (0.0, 0.0, 0.0), S: (1.0, 1.0, 1.0)] +[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0)] +[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 0.0, 0.0)] +(1.0, 2.0, 3.0, 4.0) hello hello/world RID(0) @@ -26,10 +26,10 @@ Node::[signal]property_list_changed [255, 0, 1] [-1, 0, 1] [-1, 0, 1] -[-1, 0, 1] -[-1, 0, 1] +[-1.0, 0.0, 1.0] +[-1.0, 0.0, 1.0] ["hello", "world"] -[(1, 1), (0, 0)] -[(1, 1, 1), (0, 0, 0)] -[(1, 0, 0, 1), (0, 0, 1, 1), (0, 1, 0, 1)] +[(1.0, 1.0), (0.0, 0.0)] +[(1.0, 1.0, 1.0), (0.0, 0.0, 0.0)] +[(1.0, 0.0, 0.0, 1.0), (0.0, 0.0, 1.0, 1.0), (0.0, 1.0, 0.0, 1.0)] [(1, 1, 1, 1), (0, 0, 0, 0)] diff --git a/modules/gdscript/tests/scripts/utils.notest.gd b/modules/gdscript/tests/scripts/utils.notest.gd index fa289e442f..225bcb3008 100644 --- a/modules/gdscript/tests/scripts/utils.notest.gd +++ b/modules/gdscript/tests/scripts/utils.notest.gd @@ -1,6 +1,5 @@ class_name Utils - # `assert()` is not evaluated in non-debug builds. Do not use `assert()` # for anything other than testing the `assert()` itself. static func check(condition: Variant) -> void: diff --git a/modules/gltf/config.py b/modules/gltf/config.py index 67233db579..823b8dbec2 100644 --- a/modules/gltf/config.py +++ b/modules/gltf/config.py @@ -20,6 +20,7 @@ def get_doc_classes(): "GLTFLight", "GLTFMesh", "GLTFNode", + "GLTFObjectModelProperty", "GLTFPhysicsBody", "GLTFPhysicsShape", "GLTFSkeleton", diff --git a/modules/gltf/doc_classes/GLTFAccessor.xml b/modules/gltf/doc_classes/GLTFAccessor.xml index bc142797a3..271f098803 100644 --- a/modules/gltf/doc_classes/GLTFAccessor.xml +++ b/modules/gltf/doc_classes/GLTFAccessor.xml @@ -22,7 +22,7 @@ The offset relative to the start of the buffer view in bytes. </member> <member name="component_type" type="int" setter="set_component_type" getter="get_component_type" default="0"> - The glTF component type as an enum. Possible values are 5120 for "BYTE", 5121 for "UNSIGNED_BYTE", 5122 for "SHORT", 5123 for "UNSIGNED_SHORT", 5125 for "UNSIGNED_INT", and 5126 for "FLOAT". A value of 5125 or "UNSIGNED_INT" must not be used for any accessor that is not referenced by mesh.primitive.indices. + The glTF component type as an enum. See [enum GLTFComponentType] for possible values. Within the core glTF specification, a value of 5125 or "UNSIGNED_INT" must not be used for any accessor that is not referenced by mesh.primitive.indices. </member> <member name="count" type="int" setter="set_count" getter="get_count" default="0"> The number of elements referenced by this accessor. @@ -80,5 +80,41 @@ <constant name="TYPE_MAT4" value="6" enum="GLTFAccessorType"> Accessor type "MAT4". For the glTF object model, this maps to "float4x4", represented in the glTF JSON as an array of sixteen floats. </constant> + <constant name="COMPONENT_TYPE_NONE" value="0" enum="GLTFComponentType"> + Component type "NONE". This is not a valid component type, and is used to indicate that the component type is not set. + </constant> + <constant name="COMPONENT_TYPE_SIGNED_BYTE" value="5120" enum="GLTFComponentType"> + Component type "BYTE". The value is [code]0x1400[/code] which comes from OpenGL. This indicates data is stored in 1-byte or 8-bit signed integers. This is a core part of the glTF specification. + </constant> + <constant name="COMPONENT_TYPE_UNSIGNED_BYTE" value="5121" enum="GLTFComponentType"> + Component type "UNSIGNED_BYTE". The value is [code]0x1401[/code] which comes from OpenGL. This indicates data is stored in 1-byte or 8-bit unsigned integers. This is a core part of the glTF specification. + </constant> + <constant name="COMPONENT_TYPE_SIGNED_SHORT" value="5122" enum="GLTFComponentType"> + Component type "SHORT". The value is [code]0x1402[/code] which comes from OpenGL. This indicates data is stored in 2-byte or 16-bit signed integers. This is a core part of the glTF specification. + </constant> + <constant name="COMPONENT_TYPE_UNSIGNED_SHORT" value="5123" enum="GLTFComponentType"> + Component type "UNSIGNED_SHORT". The value is [code]0x1403[/code] which comes from OpenGL. This indicates data is stored in 2-byte or 16-bit unsigned integers. This is a core part of the glTF specification. + </constant> + <constant name="COMPONENT_TYPE_SIGNED_INT" value="5124" enum="GLTFComponentType"> + Component type "INT". The value is [code]0x1404[/code] which comes from OpenGL. This indicates data is stored in 4-byte or 32-bit signed integers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code]. + </constant> + <constant name="COMPONENT_TYPE_UNSIGNED_INT" value="5125" enum="GLTFComponentType"> + Component type "UNSIGNED_INT". The value is [code]0x1405[/code] which comes from OpenGL. This indicates data is stored in 4-byte or 32-bit unsigned integers. This is a core part of the glTF specification. + </constant> + <constant name="COMPONENT_TYPE_SINGLE_FLOAT" value="5126" enum="GLTFComponentType"> + Component type "FLOAT". The value is [code]0x1406[/code] which comes from OpenGL. This indicates data is stored in 4-byte or 32-bit floating-point numbers. This is a core part of the glTF specification. + </constant> + <constant name="COMPONENT_TYPE_DOUBLE_FLOAT" value="5130" enum="GLTFComponentType"> + Component type "DOUBLE". The value is [code]0x140A[/code] which comes from OpenGL. This indicates data is stored in 8-byte or 64-bit floating-point numbers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code]. + </constant> + <constant name="COMPONENT_TYPE_HALF_FLOAT" value="5131" enum="GLTFComponentType"> + Component type "HALF_FLOAT". The value is [code]0x140B[/code] which comes from OpenGL. This indicates data is stored in 2-byte or 16-bit floating-point numbers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code]. + </constant> + <constant name="COMPONENT_TYPE_SIGNED_LONG" value="5134" enum="GLTFComponentType"> + Component type "LONG". The value is [code]0x140E[/code] which comes from OpenGL. This indicates data is stored in 8-byte or 64-bit signed integers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code]. + </constant> + <constant name="COMPONENT_TYPE_UNSIGNED_LONG" value="5135" enum="GLTFComponentType"> + Component type "UNSIGNED_LONG". The value is [code]0x140F[/code] which comes from OpenGL. This indicates data is stored in 8-byte or 64-bit unsigned integers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code]. + </constant> </constants> </class> diff --git a/modules/gltf/doc_classes/GLTFAnimation.xml b/modules/gltf/doc_classes/GLTFAnimation.xml index d269145bbd..f11dea8ee8 100644 --- a/modules/gltf/doc_classes/GLTFAnimation.xml +++ b/modules/gltf/doc_classes/GLTFAnimation.xml @@ -13,7 +13,7 @@ <param index="0" name="extension_name" type="StringName" /> <description> Gets additional arbitrary data in this [GLTFAnimation] instance. This can be used to keep per-node state data in [GLTFDocumentExtension] classes, which is important because they are stateless. - The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is null. + The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is [code]null[/code]. </description> </method> <method name="set_additional_data"> diff --git a/modules/gltf/doc_classes/GLTFBufferView.xml b/modules/gltf/doc_classes/GLTFBufferView.xml index b7f499ad72..9c2ee3197f 100644 --- a/modules/gltf/doc_classes/GLTFBufferView.xml +++ b/modules/gltf/doc_classes/GLTFBufferView.xml @@ -34,10 +34,10 @@ The stride, in bytes, between interleaved data. If [code]-1[/code], this buffer view is not interleaved. </member> <member name="indices" type="bool" setter="set_indices" getter="get_indices" default="false"> - True if the GLTFBufferView's OpenGL GPU buffer type is an [code]ELEMENT_ARRAY_BUFFER[/code] used for vertex indices (integer constant [code]34963[/code]). False if the buffer type is any other value. See [url=https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md]Buffers, BufferViews, and Accessors[/url] for possible values. This property is set on import and used on export. + [code]true[/code] if the GLTFBufferView's OpenGL GPU buffer type is an [code]ELEMENT_ARRAY_BUFFER[/code] used for vertex indices (integer constant [code]34963[/code]). [code]false[/code] if the buffer type is any other value. See [url=https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md]Buffers, BufferViews, and Accessors[/url] for possible values. This property is set on import and used on export. </member> <member name="vertex_attributes" type="bool" setter="set_vertex_attributes" getter="get_vertex_attributes" default="false"> - True if the GLTFBufferView's OpenGL GPU buffer type is an [code]ARRAY_BUFFER[/code] used for vertex attributes (integer constant [code]34962[/code]). False if the buffer type is any other value. See [url=https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md]Buffers, BufferViews, and Accessors[/url] for possible values. This property is set on import and used on export. + [code]true[/code] if the GLTFBufferView's OpenGL GPU buffer type is an [code]ARRAY_BUFFER[/code] used for vertex attributes (integer constant [code]34962[/code]). [code]false[/code] if the buffer type is any other value. See [url=https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md]Buffers, BufferViews, and Accessors[/url] for possible values. This property is set on import and used on export. </member> </members> </class> diff --git a/modules/gltf/doc_classes/GLTFCamera.xml b/modules/gltf/doc_classes/GLTFCamera.xml index 9fce21659c..12334683ba 100644 --- a/modules/gltf/doc_classes/GLTFCamera.xml +++ b/modules/gltf/doc_classes/GLTFCamera.xml @@ -47,13 +47,13 @@ The distance to the near culling boundary for this camera relative to its local Z axis, in meters. This maps to glTF's [code]znear[/code] property. </member> <member name="fov" type="float" setter="set_fov" getter="get_fov" default="1.309"> - The FOV of the camera. This class and glTF define the camera FOV in radians, while Godot uses degrees. This maps to glTF's [code]yfov[/code] property. This value is only used for perspective cameras, when [member perspective] is true. + The FOV of the camera. This class and glTF define the camera FOV in radians, while Godot uses degrees. This maps to glTF's [code]yfov[/code] property. This value is only used for perspective cameras, when [member perspective] is [code]true[/code]. </member> <member name="perspective" type="bool" setter="set_perspective" getter="get_perspective" default="true"> - Whether or not the camera is in perspective mode. If false, the camera is in orthographic/orthogonal mode. This maps to glTF's camera [code]type[/code] property. See [member Camera3D.projection] and the glTF spec for more information. + If [code]true[/code], the camera is in perspective mode. Otherwise, the camera is in orthographic/orthogonal mode. This maps to glTF's camera [code]type[/code] property. See [member Camera3D.projection] and the glTF spec for more information. </member> <member name="size_mag" type="float" setter="set_size_mag" getter="get_size_mag" default="0.5"> - The size of the camera. This class and glTF define the camera size magnitude as a radius in meters, while Godot defines it as a diameter in meters. This maps to glTF's [code]ymag[/code] property. This value is only used for orthographic/orthogonal cameras, when [member perspective] is false. + The size of the camera. This class and glTF define the camera size magnitude as a radius in meters, while Godot defines it as a diameter in meters. This maps to glTF's [code]ymag[/code] property. This value is only used for orthographic/orthogonal cameras, when [member perspective] is [code]false[/code]. </member> </members> </class> diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml index 10534594d3..47ffc624ba 100644 --- a/modules/gltf/doc_classes/GLTFDocument.xml +++ b/modules/gltf/doc_classes/GLTFDocument.xml @@ -45,6 +45,16 @@ Takes a Godot Engine scene node and exports it and its descendants to the given [GLTFState] object through the [param state] parameter. </description> </method> + <method name="export_object_model_property" qualifiers="static"> + <return type="GLTFObjectModelProperty" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="node_path" type="NodePath" /> + <param index="2" name="godot_node" type="Node" /> + <param index="3" name="gltf_node_index" type="int" /> + <description> + Determines a mapping between the given Godot [param node_path] and the corresponding glTF Object Model JSON pointer(s) in the generated glTF file. The details of this mapping are returned in a [GLTFObjectModelProperty] object. Additional mappings can be supplied via the [method GLTFDocumentExtension._import_object_model_property] callback method. + </description> + </method> <method name="generate_buffer"> <return type="PackedByteArray" /> <param index="0" name="state" type="GLTFState" /> @@ -70,12 +80,20 @@ [b]Note:[/b] If this method is run before a GLTFDocumentExtension is registered, its extensions won't be included in the list. Be sure to only run this method after all extensions are registered. If you run this when the engine starts, consider waiting a frame before calling this method to ensure all extensions are registered. </description> </method> + <method name="import_object_model_property" qualifiers="static"> + <return type="GLTFObjectModelProperty" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="json_pointer" type="String" /> + <description> + Determines a mapping between the given glTF Object Model [param json_pointer] and the corresponding Godot node path(s) in the generated Godot scene. The details of this mapping are returned in a [GLTFObjectModelProperty] object. Additional mappings can be supplied via the [method GLTFDocumentExtension._export_object_model_property] callback method. + </description> + </method> <method name="register_gltf_document_extension" qualifiers="static"> <return type="void" /> <param index="0" name="extension" type="GLTFDocumentExtension" /> <param index="1" name="first_priority" type="bool" default="false" /> <description> - Registers the given [GLTFDocumentExtension] instance with GLTFDocument. If [param first_priority] is true, this extension will be run first. Otherwise, it will be run last. + Registers the given [GLTFDocumentExtension] instance with GLTFDocument. If [param first_priority] is [code]true[/code], this extension will be run first. Otherwise, it will be run last. [b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode]. </description> </method> diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml index b33e296e1c..abdbce7eeb 100644 --- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml +++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml @@ -30,7 +30,21 @@ <param index="3" name="node" type="Node" /> <description> Part of the export process. This method is run after [method _get_saveable_image_formats] and before [method _export_post]. If this [GLTFDocumentExtension] is used for exporting images, this runs after [method _serialize_texture_json]. - This method can be used to modify the final JSON of each node. Data should be primarily stored in [param gltf_node] prior to serializing the JSON, but the original Godot [param node] is also provided if available. The node may be null if not available, such as when exporting glTF data not generated from a Godot scene. + This method can be used to modify the final JSON of each node. Data should be primarily stored in [param gltf_node] prior to serializing the JSON, but the original Godot [Node] is also provided if available. [param node] may be [code]null[/code] if not available, such as when exporting glTF data not generated from a Godot scene. + </description> + </method> + <method name="_export_object_model_property" qualifiers="virtual"> + <return type="GLTFObjectModelProperty" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="node_path" type="NodePath" /> + <param index="2" name="godot_node" type="Node" /> + <param index="3" name="gltf_node_index" type="int" /> + <param index="4" name="target_object" type="Object" /> + <param index="5" name="target_depth" type="int" /> + <description> + Part of the export process. Allows GLTFDocumentExtension classes to provide mappings for properties of nodes in the Godot scene tree, to JSON pointers to glTF properties, as defined by the glTF object model. + Returns a [GLTFObjectModelProperty] instance that defines how the property should be mapped. If your extension can't handle the property, return [code]null[/code] or an instance without any JSON pointers (see [method GLTFObjectModelProperty.has_json_pointers]). You should use [method GLTFObjectModelProperty.set_types] to set the types, and set the JSON pointer(s) using the [member GLTFObjectModelProperty.json_pointers] property. + The parameters provide context for the property, including the NodePath, the Godot node, the GLTF node index, and the target object. The [param target_object] will be equal to [param godot_node] if no sub-object can be found, otherwise it will point to a sub-object. For example, if the path is [code]^"A/B/C/MeshInstance3D:mesh:surface_0/material:emission_intensity"[/code], it will get the node, then the mesh, and then the material, so [param target_object] will be the [Material] resource, and [param target_depth] will be 2 because 2 levels were traversed to get to the target. </description> </method> <method name="_export_post" qualifiers="virtual"> @@ -75,7 +89,7 @@ <description> Part of the import process. This method is run after [method _import_pre_generate] and before [method _import_node]. Runs when generating a Godot scene node from a GLTFNode. The returned node will be added to the scene tree. Multiple nodes can be generated in this step if they are added as a child of the returned node. - [b]Note:[/b] The [param scene_parent] parameter may be null if this is the single root node. + [b]Note:[/b] The [param scene_parent] parameter may be [code]null[/code] if this is the single root node. </description> </method> <method name="_get_image_file_extension" qualifiers="virtual"> @@ -109,6 +123,17 @@ This method can be used to make modifications to each of the generated Godot scene nodes. </description> </method> + <method name="_import_object_model_property" qualifiers="virtual"> + <return type="GLTFObjectModelProperty" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="split_json_pointer" type="PackedStringArray" /> + <param index="2" name="partial_paths" type="NodePath[]" /> + <description> + Part of the import process. Allows GLTFDocumentExtension classes to provide mappings for JSON pointers to glTF properties, as defined by the glTF object model, to properties of nodes in the Godot scene tree. + Returns a [GLTFObjectModelProperty] instance that defines how the property should be mapped. If your extension can't handle the property, return [code]null[/code] or an instance without any NodePaths (see [method GLTFObjectModelProperty.has_node_paths]). You should use [method GLTFObjectModelProperty.set_types] to set the types, and [method GLTFObjectModelProperty.append_path_to_property] function is useful for most simple cases. + In many cases, [param partial_paths] will contain the start of a path, allowing the extension to complete the path. For example, for [code]/nodes/3/extensions/MY_ext/prop[/code], Godot will pass you a NodePath that leads to node 3, so the GLTFDocumentExtension class only needs to resolve the last [code]MY_ext/prop[/code] part of the path. In this example, the extension should check [code]split.size() > 4 and split[0] == "nodes" and split[2] == "extensions" and split[3] == "MY_ext"[/code] at the start of the function to check if this JSON pointer applies to it, then it can use [param partial_paths] and handle [code]split[4][/code]. + </description> + </method> <method name="_import_post" qualifiers="virtual"> <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> diff --git a/modules/gltf/doc_classes/GLTFMesh.xml b/modules/gltf/doc_classes/GLTFMesh.xml index da73c20c1d..439078ffcc 100644 --- a/modules/gltf/doc_classes/GLTFMesh.xml +++ b/modules/gltf/doc_classes/GLTFMesh.xml @@ -15,7 +15,7 @@ <param index="0" name="extension_name" type="StringName" /> <description> Gets additional arbitrary data in this [GLTFMesh] instance. This can be used to keep per-node state data in [GLTFDocumentExtension] classes, which is important because they are stateless. - The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is null. + The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is [code]null[/code]. </description> </method> <method name="set_additional_data"> diff --git a/modules/gltf/doc_classes/GLTFNode.xml b/modules/gltf/doc_classes/GLTFNode.xml index a242a0d1d8..0fb85e4029 100644 --- a/modules/gltf/doc_classes/GLTFNode.xml +++ b/modules/gltf/doc_classes/GLTFNode.xml @@ -24,7 +24,16 @@ <param index="0" name="extension_name" type="StringName" /> <description> Gets additional arbitrary data in this [GLTFNode] instance. This can be used to keep per-node state data in [GLTFDocumentExtension] classes, which is important because they are stateless. - The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is null. + The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is [code]null[/code]. + </description> + </method> + <method name="get_scene_node_path"> + <return type="NodePath" /> + <param index="0" name="gltf_state" type="GLTFState" /> + <param index="1" name="handle_skeletons" type="bool" default="true" /> + <description> + Returns the [NodePath] that this GLTF node will have in the Godot scene tree after being imported. This is useful when importing glTF object model pointers with [GLTFObjectModelProperty], for handling extensions such as [code]KHR_animation_pointer[/code] or [code]KHR_interactivity[/code]. + If [param handle_skeletons] is [code]true[/code], paths to skeleton bone glTF nodes will be resolved properly. For example, a path that would be [code]^"A/B/C/Bone1/Bone2/Bone3"[/code] if [code]false[/code] will become [code]^"A/B/C/Skeleton3D:Bone3"[/code]. </description> </method> <method name="set_additional_data"> diff --git a/modules/gltf/doc_classes/GLTFObjectModelProperty.xml b/modules/gltf/doc_classes/GLTFObjectModelProperty.xml new file mode 100644 index 0000000000..a457d94c41 --- /dev/null +++ b/modules/gltf/doc_classes/GLTFObjectModelProperty.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="GLTFObjectModelProperty" inherits="RefCounted" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> + <brief_description> + Describes how to access a property as defined in the glTF object model. + </brief_description> + <description> + GLTFObjectModelProperty defines a mapping between a property in the glTF object model and a NodePath in the Godot scene tree. This can be used to animate properties in a glTF file using the [code]KHR_animation_pointer[/code] extension, or to access them through an engine-agnostic script such as a behavior graph as defined by the [code]KHR_interactivity[/code] extension. + The glTF property is identified by JSON pointer(s) stored in [member json_pointers], while the Godot property it maps to is defined by [member node_paths]. In most cases [member json_pointers] and [member node_paths] will each only have one item, but in some cases a single glTF JSON pointer will map to multiple Godot properties, or a single Godot property will be mapped to multiple glTF JSON pointers, or it might be a many-to-many relationship. + [Expression] objects can be used to define conversions between the data, such as when glTF defines an angle in radians and Godot uses degrees. The [member object_model_type] property defines the type of data stored in the glTF file as defined by the object model, see [enum GLTFObjectModelType] for possible values. + </description> + <tutorials> + <link title="GLTF Object Model">https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/ObjectModel.adoc</link> + <link title="KHR_animation_pointer GLTF extension">https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer</link> + </tutorials> + <methods> + <method name="append_node_path"> + <return type="void" /> + <param index="0" name="node_path" type="NodePath" /> + <description> + Appends a [NodePath] to [member node_paths]. This can be used by [GLTFDocumentExtension] classes to define how a glTF object model property maps to a Godot property, or multiple Godot properties. Prefer using [method append_path_to_property] for simple cases. Be sure to also call [method set_types] once (the order does not matter). + </description> + </method> + <method name="append_path_to_property"> + <return type="void" /> + <param index="0" name="node_path" type="NodePath" /> + <param index="1" name="prop_name" type="StringName" /> + <description> + High-level wrapper over [method append_node_path] that handles the most common cases. It constructs a new [NodePath] using [param node_path] as a base and appends [param prop_name] to the subpath. Be sure to also call [method set_types] once (the order does not matter). + </description> + </method> + <method name="get_accessor_type" qualifiers="const"> + <return type="int" enum="GLTFAccessor.GLTFAccessorType" /> + <description> + The GLTF accessor type associated with this property's [member object_model_type]. See [member GLTFAccessor.accessor_type] for possible values, and see [enum GLTFObjectModelType] for how the object model type maps to accessor types. + </description> + </method> + <method name="has_json_pointers" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if [member json_pointers] is not empty. This is used during export to determine if a [GLTFObjectModelProperty] can handle converting a Godot property to a glTF object model property. + </description> + </method> + <method name="has_node_paths" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if [member node_paths] is not empty. This is used during import to determine if a [GLTFObjectModelProperty] can handle converting a glTF object model property to a Godot property. + </description> + </method> + <method name="set_types"> + <return type="void" /> + <param index="0" name="variant_type" type="int" enum="Variant.Type" /> + <param index="1" name="obj_model_type" type="int" enum="GLTFObjectModelProperty.GLTFObjectModelType" /> + <description> + Sets the [member variant_type] and [member object_model_type] properties. This is a convenience method to set both properties at once, since they are almost always known at the same time. This method should be called once. Calling it again with the same values will have no effect. + </description> + </method> + </methods> + <members> + <member name="gltf_to_godot_expression" type="Expression" setter="set_gltf_to_godot_expression" getter="get_gltf_to_godot_expression"> + If set, this [Expression] will be used to convert the property value from the glTF object model to the value expected by the Godot property. This is useful when the glTF object model uses a different unit system, or when the data needs to be transformed in some way. If [code]null[/code], the value will be copied as-is. + </member> + <member name="godot_to_gltf_expression" type="Expression" setter="set_godot_to_gltf_expression" getter="get_godot_to_gltf_expression"> + If set, this [Expression] will be used to convert the property value from the Godot property to the value expected by the glTF object model. This is useful when the glTF object model uses a different unit system, or when the data needs to be transformed in some way. If [code]null[/code], the value will be copied as-is. + </member> + <member name="json_pointers" type="PackedStringArray[]" setter="set_json_pointers" getter="get_json_pointers" default="[]"> + The glTF object model JSON pointers used to identify the property in the glTF object model. In most cases, there will be only one item in this array, but niche cases may require multiple pointers. The items are themselves arrays which represent the JSON pointer split into its components. + </member> + <member name="node_paths" type="NodePath[]" setter="set_node_paths" getter="get_node_paths" default="[]"> + An array of [NodePath]s that point to a property, or multiple properties, in the Godot scene tree. On import, this will either be set by [GLTFDocument], or by a [GLTFDocumentExtension] class. For simple cases, use [method append_path_to_property] to add properties to this array. + In most cases [member node_paths] will only have one item, but in some cases a single glTF JSON pointer will map to multiple Godot properties. For example, a [GLTFCamera] or [GLTFLight] used on multiple glTF nodes will be represented by multiple Godot nodes. + </member> + <member name="object_model_type" type="int" setter="set_object_model_type" getter="get_object_model_type" enum="GLTFObjectModelProperty.GLTFObjectModelType" default="0"> + The type of data stored in the glTF file as defined by the object model. This is a superset of the available accessor types, and determines the accessor type. See [enum GLTFObjectModelType] for possible values. + </member> + <member name="variant_type" type="int" setter="set_variant_type" getter="get_variant_type" enum="Variant.Type" default="0"> + The type of data stored in the Godot property. This is the type of the property that the [member node_paths] point to. + </member> + </members> + <constants> + <constant name="GLTF_OBJECT_MODEL_TYPE_UNKNOWN" value="0" enum="GLTFObjectModelType"> + Unknown or not set object model type. If the object model type is set to this value, the real type still needs to be determined. + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_BOOL" value="1" enum="GLTFObjectModelType"> + Object model type "bool". Represented in the glTF JSON as a boolean, and encoded in a [GLTFAccessor] as "SCALAR". When encoded in an accessor, a value of [code]0[/code] is [code]false[/code], and any other value is [code]true[/code]. + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT" value="2" enum="GLTFObjectModelType"> + Object model type "float". Represented in the glTF JSON as a number, and encoded in a [GLTFAccessor] as "SCALAR". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT_ARRAY" value="3" enum="GLTFObjectModelType"> + Object model type "float[lb][rb]". Represented in the glTF JSON as an array of numbers, and encoded in a [GLTFAccessor] as "SCALAR". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT2" value="4" enum="GLTFObjectModelType"> + Object model type "float2". Represented in the glTF JSON as an array of two numbers, and encoded in a [GLTFAccessor] as "VEC2". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT3" value="5" enum="GLTFObjectModelType"> + Object model type "float3". Represented in the glTF JSON as an array of three numbers, and encoded in a [GLTFAccessor] as "VEC3". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT4" value="6" enum="GLTFObjectModelType"> + Object model type "float4". Represented in the glTF JSON as an array of four numbers, and encoded in a [GLTFAccessor] as "VEC4". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT2X2" value="7" enum="GLTFObjectModelType"> + Object model type "float2x2". Represented in the glTF JSON as an array of four numbers, and encoded in a [GLTFAccessor] as "MAT2". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT3X3" value="8" enum="GLTFObjectModelType"> + Object model type "float3x3". Represented in the glTF JSON as an array of nine numbers, and encoded in a [GLTFAccessor] as "MAT3". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_FLOAT4X4" value="9" enum="GLTFObjectModelType"> + Object model type "float4x4". Represented in the glTF JSON as an array of sixteen numbers, and encoded in a [GLTFAccessor] as "MAT4". + </constant> + <constant name="GLTF_OBJECT_MODEL_TYPE_INT" value="10" enum="GLTFObjectModelType"> + Object model type "int". Represented in the glTF JSON as a number, and encoded in a [GLTFAccessor] as "SCALAR". The range of values is limited to signed integers. For [code]KHR_interactivity[/code], only 32-bit integers are supported. + </constant> + </constants> +</class> diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index de7ec2a4ca..c81c2f09f0 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -17,7 +17,7 @@ <param index="0" name="extension_name" type="String" /> <param index="1" name="required" type="bool" /> <description> - Appends an extension to the list of extensions used by this glTF file during serialization. If [param required] is true, the extension will also be added to the list of required extensions. Do not run this in [method GLTFDocumentExtension._export_post], as that stage is too late to add extensions. The final list is sorted alphabetically. + Appends an extension to the list of extensions used by this glTF file during serialization. If [param required] is [code]true[/code], the extension will also be added to the list of required extensions. Do not run this in [method GLTFDocumentExtension._export_post], as that stage is too late to add extensions. The final list is sorted alphabetically. </description> </method> <method name="append_data_to_buffers"> @@ -25,7 +25,7 @@ <param index="0" name="data" type="PackedByteArray" /> <param index="1" name="deduplication" type="bool" /> <description> - Appends the given byte array data to the buffers and creates a [GLTFBufferView] for it. The index of the destination [GLTFBufferView] is returned. If [param deduplication] is true, the buffers will first be searched for duplicate data, otherwise new bytes will always be appended. + Appends the given byte array data to the buffers and creates a [GLTFBufferView] for it. The index of the destination [GLTFBufferView] is returned. If [param deduplication] is [code]true[/code], the buffers will first be searched for duplicate data, otherwise new bytes will always be appended. </description> </method> <method name="append_gltf_node"> @@ -35,7 +35,7 @@ <param index="2" name="parent_node_index" type="int" /> <description> Append the given [GLTFNode] to the state, and return its new index. This can be used to export one Godot node as multiple glTF nodes, or inject new glTF nodes at import time. On import, this must be called before [method GLTFDocumentExtension._generate_scene_node] finishes for the parent node. On export, this must be called before [method GLTFDocumentExtension._export_node] runs for the parent node. - The [param godot_scene_node] parameter is the Godot scene node that corresponds to this glTF node. This is highly recommended to be set to a valid node, but may be null if there is no corresponding Godot scene node. One Godot scene node may be used for multiple glTF nodes, so if exporting multiple glTF nodes for one Godot scene node, use the same Godot scene node for each. + The [param godot_scene_node] parameter is the Godot scene node that corresponds to this glTF node. This is highly recommended to be set to a valid node, but may be [code]null[/code] if there is no corresponding Godot scene node. One Godot scene node may be used for multiple glTF nodes, so if exporting multiple glTF nodes for one Godot scene node, use the same Godot scene node for each. The [param parent_node_index] parameter is the index of the parent [GLTFNode] in the state. If [code]-1[/code], the node will be a root node, otherwise the new node will be added to the parent's list of children. The index will also be written to the [member GLTFNode.parent] property of the new node. </description> </method> @@ -49,7 +49,7 @@ <param index="0" name="extension_name" type="StringName" /> <description> Gets additional arbitrary data in this [GLTFState] instance. This can be used to keep per-file state data in [GLTFDocumentExtension] classes, which is important because they are stateless. - The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is null. + The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is [code]null[/code]. </description> </method> <method name="get_animation_player"> @@ -306,7 +306,7 @@ The binary buffer attached to a .glb file. </member> <member name="import_as_skeleton_bones" type="bool" setter="set_import_as_skeleton_bones" getter="get_import_as_skeleton_bones" default="false"> - True to force all GLTFNodes in the document to be bones of a single Skeleton3D godot node. + If [code]true[/code], forces all GLTFNodes in the document to be bones of a single [Skeleton3D] Godot node. </member> <member name="json" type="Dictionary" setter="set_json" getter="get_json" default="{}"> The original raw JSON document corresponding to this GLTFState. diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp index 022d2e4477..872054ec2e 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp +++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp @@ -88,7 +88,7 @@ void SceneExporterGLTFPlugin::_popup_gltf_export_dialog() { } _file_dialog->set_current_file(filename + String(".gltf")); // Generate and refresh the export settings. - _export_settings->generate_property_list(_gltf_document); + _export_settings->generate_property_list(_gltf_document, root); _settings_inspector->edit(nullptr); _settings_inspector->edit(_export_settings.ptr()); // Show the file dialog. diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp index 511da078d8..c14e92c3a0 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp +++ b/modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp @@ -129,7 +129,7 @@ String get_friendly_config_prefix(Ref<GLTFDocumentExtension> p_extension) { } // Run this before popping up the export settings, because the extensions may have changed. -void EditorSceneExporterGLTFSettings::generate_property_list(Ref<GLTFDocument> p_document) { +void EditorSceneExporterGLTFSettings::generate_property_list(Ref<GLTFDocument> p_document, Node *p_root) { _property_list.clear(); _document = p_document; String image_format_hint_string = "None,PNG,JPEG"; diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_settings.h b/modules/gltf/editor/editor_scene_exporter_gltf_settings.h index 898cddfd68..aa0e54078d 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_settings.h +++ b/modules/gltf/editor/editor_scene_exporter_gltf_settings.h @@ -55,7 +55,7 @@ protected: bool _get_extension_setting(const String &p_name_str, Variant &r_ret) const; public: - void generate_property_list(Ref<GLTFDocument> p_document); + void generate_property_list(Ref<GLTFDocument> p_document, Node *p_root = nullptr); String get_copyright() const; void set_copyright(const String &p_copyright); diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 8e5a992bd4..5ba9ee3fa6 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -80,7 +80,7 @@ static bool _get_blender_version(const String &p_path, int &r_major, int &r_mino } pipe = pipe.substr(bl); pipe = pipe.replace_first("Blender ", ""); - int pp = pipe.find("."); + int pp = pipe.find_char('.'); if (pp == -1) { if (r_err) { *r_err = vformat(TTR("Couldn't extract version information from Blender executable at: %s."), p_path); @@ -96,7 +96,7 @@ static bool _get_blender_version(const String &p_path, int &r_major, int &r_mino return false; } - int pp2 = pipe.find(".", pp + 1); + int pp2 = pipe.find_char('.', pp + 1); r_minor = pp2 > pp ? pipe.substr(pp + 1, pp2 - pp - 1).to_int() : 0; return true; @@ -319,6 +319,8 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ state->set_import_as_skeleton_bones(true); } state->set_scene_name(blend_basename); + state->set_extract_path(p_path.get_base_dir()); + state->set_extract_prefix(blend_basename); err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir); if (err != OK) { if (r_err) { @@ -503,7 +505,7 @@ void EditorFileSystemImportFormatSupportQueryBlend::_browse_install() { } void EditorFileSystemImportFormatSupportQueryBlend::_update_icons() { - blender_path_browse->set_icon(blender_path_browse->get_editor_theme_icon(SNAME("FolderBrowse"))); + blender_path_browse->set_button_icon(blender_path_browse->get_editor_theme_icon(SNAME("FolderBrowse"))); } bool EditorFileSystemImportFormatSupportQueryBlend::query() { diff --git a/modules/gltf/extensions/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp index 6e611762b6..0806eee6bf 100644 --- a/modules/gltf/extensions/gltf_document_extension.cpp +++ b/modules/gltf/extensions/gltf_document_extension.cpp @@ -38,6 +38,7 @@ void GLTFDocumentExtension::_bind_methods() { GDVIRTUAL_BIND(_parse_image_data, "state", "image_data", "mime_type", "ret_image"); GDVIRTUAL_BIND(_get_image_file_extension); GDVIRTUAL_BIND(_parse_texture_json, "state", "texture_json", "ret_gltf_texture"); + GDVIRTUAL_BIND(_import_object_model_property, "state", "split_json_pointer", "partial_paths"); GDVIRTUAL_BIND(_import_post_parse, "state"); GDVIRTUAL_BIND(_import_pre_generate, "state"); GDVIRTUAL_BIND(_generate_scene_node, "state", "gltf_node", "scene_parent"); @@ -48,6 +49,7 @@ void GLTFDocumentExtension::_bind_methods() { GDVIRTUAL_BIND(_convert_scene_node, "state", "gltf_node", "scene_node"); GDVIRTUAL_BIND(_export_post_convert, "state", "root"); GDVIRTUAL_BIND(_export_preserialize, "state"); + GDVIRTUAL_BIND(_export_object_model_property, "state", "node_path", "godot_node", "gltf_node_index", "target_object", "target_depth"); GDVIRTUAL_BIND(_get_saveable_image_formats); GDVIRTUAL_BIND(_serialize_image_to_bytes, "state", "image", "image_dict", "image_format", "lossy_quality"); GDVIRTUAL_BIND(_save_image_at_path, "state", "image", "file_path", "image_format", "lossy_quality"); @@ -100,6 +102,13 @@ Error GLTFDocumentExtension::parse_texture_json(Ref<GLTFState> p_state, const Di return err; } +Ref<GLTFObjectModelProperty> GLTFDocumentExtension::import_object_model_property(Ref<GLTFState> p_state, const PackedStringArray &p_split_json_pointer, const TypedArray<NodePath> &p_partial_paths) { + Ref<GLTFObjectModelProperty> ret; + ERR_FAIL_COND_V(p_state.is_null(), ret); + GDVIRTUAL_CALL(_import_object_model_property, p_state, p_split_json_pointer, p_partial_paths, ret); + return ret; +} + Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) { ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER); Error err = OK; @@ -169,6 +178,15 @@ Error GLTFDocumentExtension::export_preserialize(Ref<GLTFState> p_state) { return err; } +Ref<GLTFObjectModelProperty> GLTFDocumentExtension::export_object_model_property(Ref<GLTFState> p_state, const NodePath &p_node_path, const Node *p_godot_node, GLTFNodeIndex p_gltf_node_index, const Object *p_target_object, int p_target_depth) { + Ref<GLTFObjectModelProperty> ret; + ERR_FAIL_COND_V(p_state.is_null(), ret); + ERR_FAIL_NULL_V(p_godot_node, ret); + ERR_FAIL_NULL_V(p_target_object, ret); + GDVIRTUAL_CALL(_export_object_model_property, p_state, p_node_path, p_godot_node, p_gltf_node_index, p_target_object, p_target_depth, ret); + return ret; +} + Vector<String> GLTFDocumentExtension::get_saveable_image_formats() { Vector<String> ret; GDVIRTUAL_CALL(_get_saveable_image_formats, ret); diff --git a/modules/gltf/extensions/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h index b70710e015..a6368ea780 100644 --- a/modules/gltf/extensions/gltf_document_extension.h +++ b/modules/gltf/extensions/gltf_document_extension.h @@ -49,6 +49,7 @@ public: virtual Error parse_image_data(Ref<GLTFState> p_state, const PackedByteArray &p_image_data, const String &p_mime_type, Ref<Image> r_image); virtual String get_image_file_extension(); virtual Error parse_texture_json(Ref<GLTFState> p_state, const Dictionary &p_texture_json, Ref<GLTFTexture> r_gltf_texture); + virtual Ref<GLTFObjectModelProperty> import_object_model_property(Ref<GLTFState> p_state, const PackedStringArray &p_split_json_pointer, const TypedArray<NodePath> &p_partial_paths); virtual Error import_post_parse(Ref<GLTFState> p_state); virtual Error import_pre_generate(Ref<GLTFState> p_state); virtual Node3D *generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent); @@ -59,6 +60,7 @@ public: virtual void convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node); virtual Error export_post_convert(Ref<GLTFState> p_state, Node *p_root); virtual Error export_preserialize(Ref<GLTFState> p_state); + virtual Ref<GLTFObjectModelProperty> export_object_model_property(Ref<GLTFState> p_state, const NodePath &p_node_path, const Node *p_godot_node, GLTFNodeIndex p_gltf_node_index, const Object *p_target_object, int p_target_depth); virtual Vector<String> get_saveable_image_formats(); virtual PackedByteArray serialize_image_to_bytes(Ref<GLTFState> p_state, Ref<Image> p_image, Dictionary p_image_dict, const String &p_image_format, float p_lossy_quality); virtual Error save_image_at_path(Ref<GLTFState> p_state, Ref<Image> p_image, const String &p_file_path, const String &p_image_format, float p_lossy_quality); @@ -73,6 +75,7 @@ public: GDVIRTUAL4R(Error, _parse_image_data, Ref<GLTFState>, PackedByteArray, String, Ref<Image>); GDVIRTUAL0R(String, _get_image_file_extension); GDVIRTUAL3R(Error, _parse_texture_json, Ref<GLTFState>, Dictionary, Ref<GLTFTexture>); + GDVIRTUAL3R(Ref<GLTFObjectModelProperty>, _import_object_model_property, Ref<GLTFState>, PackedStringArray, TypedArray<NodePath>); GDVIRTUAL1R(Error, _import_post_parse, Ref<GLTFState>); GDVIRTUAL1R(Error, _import_pre_generate, Ref<GLTFState>); GDVIRTUAL3R(Node3D *, _generate_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *); @@ -83,6 +86,7 @@ public: GDVIRTUAL3(_convert_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *); GDVIRTUAL2R(Error, _export_post_convert, Ref<GLTFState>, Node *); GDVIRTUAL1R(Error, _export_preserialize, Ref<GLTFState>); + GDVIRTUAL6R(Ref<GLTFObjectModelProperty>, _export_object_model_property, Ref<GLTFState>, NodePath, const Node *, GLTFNodeIndex, const Object *, int); GDVIRTUAL0R(Vector<String>, _get_saveable_image_formats); GDVIRTUAL5R(PackedByteArray, _serialize_image_to_bytes, Ref<GLTFState>, Ref<Image>, Dictionary, String, float); GDVIRTUAL5R(Error, _save_image_at_path, Ref<GLTFState>, Ref<Image>, String, String, float); diff --git a/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp index cde30bce18..b5edd35ad5 100644 --- a/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp +++ b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp @@ -63,6 +63,7 @@ Error GLTFDocumentExtensionConvertImporterMesh::import_post(Ref<GLTFState> p_sta mesh_instance_node_3d->set_mesh(array_mesh); mesh_instance_node_3d->set_skin(importer_mesh_3d->get_skin()); mesh_instance_node_3d->set_skeleton_path(importer_mesh_3d->get_skeleton_path()); + mesh_instance_node_3d->set_visible(importer_mesh_3d->is_visible()); node->replace_by(mesh_instance_node_3d); _copy_meta(importer_mesh_3d, mesh_instance_node_3d); _copy_meta(mesh.ptr(), array_mesh.ptr()); diff --git a/modules/gltf/extensions/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp index f6e91c1635..2bdcab2f0c 100644 --- a/modules/gltf/extensions/gltf_light.cpp +++ b/modules/gltf/extensions/gltf_light.cpp @@ -30,6 +30,7 @@ #include "gltf_light.h" +#include "../structures/gltf_object_model_property.h" #include "scene/3d/light_3d.h" void GLTFLight::_bind_methods() { @@ -62,6 +63,21 @@ void GLTFLight::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_cone_angle"), "set_outer_cone_angle", "get_outer_cone_angle"); // float } +void GLTFLight::set_cone_inner_attenuation_conversion_expressions(Ref<GLTFObjectModelProperty> &r_obj_model_prop) { + // Expression to convert glTF innerConeAngle to Godot spot_angle_attenuation. + Ref<Expression> gltf_to_godot_expr; + gltf_to_godot_expr.instantiate(); + PackedStringArray gltf_to_godot_args = { "inner_cone_angle" }; + gltf_to_godot_expr->parse("0.2 / (1.0 - inner_cone_angle / spot_angle) - 0.1", gltf_to_godot_args); + r_obj_model_prop->set_gltf_to_godot_expression(gltf_to_godot_expr); + // Expression to convert Godot spot_angle_attenuation to glTF innerConeAngle. + Ref<Expression> godot_to_gltf_expr; + godot_to_gltf_expr.instantiate(); + PackedStringArray godot_to_gltf_args = { "godot_spot_angle_att" }; + godot_to_gltf_expr->parse("spot_angle * maxf(0.0, 1.0 - (0.2 / (0.1 + godot_spot_angle_att)))", godot_to_gltf_args); + r_obj_model_prop->set_godot_to_gltf_expression(godot_to_gltf_expr); +} + Color GLTFLight::get_color() { return color; } diff --git a/modules/gltf/extensions/gltf_light.h b/modules/gltf/extensions/gltf_light.h index e0894fc8c6..3d522bd174 100644 --- a/modules/gltf/extensions/gltf_light.h +++ b/modules/gltf/extensions/gltf_light.h @@ -33,6 +33,7 @@ #include "core/io/resource.h" +class GLTFObjectModelProperty; class Light3D; // https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual @@ -54,6 +55,8 @@ private: Dictionary additional_data; public: + static void set_cone_inner_attenuation_conversion_expressions(Ref<GLTFObjectModelProperty> &r_obj_model_prop); + Color get_color(); void set_color(Color p_color); diff --git a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp index 5c26a1686b..512f25a216 100644 --- a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp +++ b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp @@ -31,8 +31,11 @@ #include "gltf_document_extension_physics.h" #include "scene/3d/physics/area_3d.h" +#include "scene/3d/physics/rigid_body_3d.h" #include "scene/3d/physics/static_body_3d.h" +using GLTFShapeIndex = int64_t; + // Import process. Error GLTFDocumentExtensionPhysics::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) { if (!p_extensions.has("OMI_collider") && !p_extensions.has("OMI_physics_body") && !p_extensions.has("OMI_physics_shape")) { @@ -105,6 +108,7 @@ Error GLTFDocumentExtensionPhysics::parse_node_extensions(Ref<GLTFState> p_state Array state_shapes = p_state->get_additional_data(StringName("GLTFPhysicsShapes")); ERR_FAIL_INDEX_V_MSG(node_shape_index, state_shapes.size(), Error::ERR_FILE_CORRUPT, "glTF Physics: On node " + p_gltf_node->get_name() + ", the shape index " + itos(node_shape_index) + " is not in the state shapes (size: " + itos(state_shapes.size()) + ")."); p_gltf_node->set_additional_data(StringName("GLTFPhysicsColliderShape"), state_shapes[node_shape_index]); + p_gltf_node->set_additional_data(StringName("GLTFPhysicsColliderShapeIndex"), node_shape_index); } else { // If this node is a collider but does not have a collider // shape, then it only serves to combine together shapes. @@ -119,6 +123,7 @@ Error GLTFDocumentExtensionPhysics::parse_node_extensions(Ref<GLTFState> p_state Array state_shapes = p_state->get_additional_data(StringName("GLTFPhysicsShapes")); ERR_FAIL_INDEX_V_MSG(node_shape_index, state_shapes.size(), Error::ERR_FILE_CORRUPT, "glTF Physics: On node " + p_gltf_node->get_name() + ", the shape index " + itos(node_shape_index) + " is not in the state shapes (size: " + itos(state_shapes.size()) + ")."); p_gltf_node->set_additional_data(StringName("GLTFPhysicsTriggerShape"), state_shapes[node_shape_index]); + p_gltf_node->set_additional_data(StringName("GLTFPhysicsTriggerShapeIndex"), node_shape_index); } else { // If this node is a trigger but does not have a trigger shape, // then it's a trigger body, what Godot calls an Area3D node. @@ -129,8 +134,8 @@ Error GLTFDocumentExtensionPhysics::parse_node_extensions(Ref<GLTFState> p_state } // If this node defines explicit member shape nodes, save this information. if (node_trigger.has("nodes")) { - Array node_trigger_nodes = node_trigger["nodes"]; - p_gltf_node->set_additional_data(StringName("GLTFPhysicsCompoundTriggerNodes"), node_trigger_nodes); + Array compound_trigger_nodes = node_trigger["nodes"]; + p_gltf_node->set_additional_data(StringName("GLTFPhysicsCompoundTriggerNodes"), compound_trigger_nodes); } } if (physics_body_ext.has("motion") || physics_body_ext.has("type")) { @@ -140,6 +145,144 @@ Error GLTFDocumentExtensionPhysics::parse_node_extensions(Ref<GLTFState> p_state return OK; } +bool _will_gltf_shape_become_subnode(Ref<GLTFState> p_state, const Ref<GLTFNode> p_gltf_node, GLTFNodeIndex p_gltf_node_index) { + if (p_gltf_node->has_additional_data(StringName("GLTFPhysicsBody"))) { + return true; + } + const TypedArray<GLTFNode> state_gltf_nodes = p_state->get_nodes(); + const GLTFNodeIndex parent_index = p_gltf_node->get_parent(); + if (parent_index == -1 || parent_index >= state_gltf_nodes.size()) { + return true; + } + const Ref<GLTFNode> parent_gltf_node = state_gltf_nodes[parent_index]; + const Variant parent_body_maybe = parent_gltf_node->get_additional_data(StringName("GLTFPhysicsBody")); + if (parent_body_maybe.get_type() != Variant::NIL) { + Ref<GLTFPhysicsBody> parent_body = parent_body_maybe; + // If the parent matches the triggerness, then this node will be generated as a shape (CollisionShape3D). + // Otherwise, if there is a mismatch, a body will be generated for this node, and a subnode will also be generated for the shape. + if (parent_body->get_body_type() == "trigger") { + return p_gltf_node->has_additional_data(StringName("GLTFPhysicsColliderShape")); + } else { + return p_gltf_node->has_additional_data(StringName("GLTFPhysicsTriggerShape")); + } + } + if (parent_gltf_node->has_additional_data(StringName("GLTFPhysicsColliderShape"))) { + return false; + } + if (parent_gltf_node->has_additional_data(StringName("GLTFPhysicsTriggerShape"))) { + return false; + } + Variant compound_trigger_maybe = parent_gltf_node->has_additional_data(StringName("GLTFPhysicsCompoundTriggerNodes")); + if (compound_trigger_maybe.get_type() != Variant::NIL) { + Array compound_trigger_nodes = compound_trigger_maybe; + // Remember, JSON only has numbers, not integers, so must cast to double. + return !compound_trigger_nodes.has((double)p_gltf_node_index); + } + return true; +} + +NodePath _get_scene_node_path_for_shape_index(Ref<GLTFState> p_state, const GLTFNodeIndex p_shape_index) { + TypedArray<GLTFNode> state_gltf_nodes = p_state->get_nodes(); + for (GLTFNodeIndex node_index = 0; node_index < state_gltf_nodes.size(); node_index++) { + const Ref<GLTFNode> gltf_node = state_gltf_nodes[node_index]; + ERR_CONTINUE(gltf_node.is_null()); + // Check if this node has a shape index and if it matches the one we are looking for. + Variant shape_index_maybe = gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShapeIndex")); + if (shape_index_maybe.get_type() != Variant::INT) { + shape_index_maybe = gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShapeIndex")); + if (shape_index_maybe.get_type() != Variant::INT) { + continue; + } + } + const GLTFShapeIndex shape_index = shape_index_maybe; + if (shape_index != p_shape_index) { + continue; + } + NodePath node_path = gltf_node->get_scene_node_path(p_state); + // At this point, we have found a node with the shape index we were looking for. + if (_will_gltf_shape_become_subnode(p_state, gltf_node, node_index)) { + Vector<StringName> sname_path = node_path.get_names(); + sname_path.append(gltf_node->get_name() + "Shape"); + node_path = NodePath(sname_path, false); + } + return node_path; + } + return NodePath(); +} + +Ref<GLTFObjectModelProperty> GLTFDocumentExtensionPhysics::import_object_model_property(Ref<GLTFState> p_state, const PackedStringArray &p_split_json_pointer, const TypedArray<NodePath> &p_partial_paths) { + Ref<GLTFObjectModelProperty> ret; + if (p_split_json_pointer.size() != 6) { + // The only properties this class cares about are exactly 6 levels deep. + return ret; + } + ret.instantiate(); + const String &prop_name = p_split_json_pointer[5]; + if (p_split_json_pointer[0] == "extensions" && p_split_json_pointer[2] == "shapes") { + if (p_split_json_pointer[1] == "OMI_physics_shape" || p_split_json_pointer[1] == "KHR_collision_shapes") { + const GLTFNodeIndex shape_index = p_split_json_pointer[3].to_int(); + NodePath node_path = _get_scene_node_path_for_shape_index(p_state, shape_index); + if (node_path.is_empty()) { + return ret; + } + String godot_prop_name = prop_name; + if (prop_name == "size") { + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (prop_name == "height" || prop_name == "radius") { + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (prop_name == "radiusBottom" || prop_name == "radiusTop") { + godot_prop_name = "radius"; + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else { + // Not something we handle, return without appending a NodePath. + return ret; + } + // Example: `A/B/C/CollisionShape3D:shape:radius`. + Vector<StringName> subnames; + subnames.append("shape"); + subnames.append(godot_prop_name); + node_path = NodePath(node_path.get_names(), subnames, false); + ret->append_node_path(node_path); + } + } else if (p_split_json_pointer[0] == "nodes" && p_split_json_pointer[2] == "extensions" && p_split_json_pointer[4] == "motion") { + if (p_split_json_pointer[3] == "OMI_physics_body" || p_split_json_pointer[3] == "KHR_physics_rigid_bodies") { + const GLTFNodeIndex node_index = p_split_json_pointer[1].to_int(); + const TypedArray<GLTFNode> all_gltf_nodes = p_state->get_nodes(); + ERR_FAIL_INDEX_V_MSG(node_index, all_gltf_nodes.size(), ret, "GLTF Physics: The node index " + itos(node_index) + " is not in the state nodes (size: " + itos(all_gltf_nodes.size()) + ")."); + const Ref<GLTFNode> gltf_node = all_gltf_nodes[node_index]; + NodePath node_path; + if (p_partial_paths.is_empty()) { + node_path = gltf_node->get_scene_node_path(p_state); + } else { + // The path is already computed for us, just grab it. + node_path = p_partial_paths[0]; + } + if (prop_name == "mass") { + ret->append_path_to_property(node_path, "mass"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (prop_name == "linearVelocity") { + ret->append_path_to_property(node_path, "linear_velocity"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (prop_name == "angularVelocity") { + ret->append_path_to_property(node_path, "angular_velocity"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (prop_name == "centerOfMass") { + ret->append_path_to_property(node_path, "center_of_mass"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (prop_name == "inertiaDiagonal") { + ret->append_path_to_property(node_path, "inertia"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (prop_name == "inertiaOrientation") { + WARN_PRINT("GLTF Physics: The 'inertiaOrientation' property is not supported by Godot."); + } else { + // Not something we handle, return without appending a NodePath. + return ret; + } + } + } + return ret; +} + void _setup_shape_mesh_resource_from_index_if_needed(Ref<GLTFState> p_state, Ref<GLTFPhysicsShape> p_gltf_shape) { GLTFMeshIndex shape_mesh_index = p_gltf_shape->get_mesh_index(); if (shape_mesh_index == -1) { @@ -434,24 +577,126 @@ Array _get_or_create_state_shapes_in_state(Ref<GLTFState> p_state) { return state_shapes; } -Dictionary _export_node_shape(Ref<GLTFState> p_state, Ref<GLTFPhysicsShape> p_physics_shape) { +GLTFShapeIndex _export_node_shape(Ref<GLTFState> p_state, Ref<GLTFPhysicsShape> p_physics_shape) { Array state_shapes = _get_or_create_state_shapes_in_state(p_state); - int size = state_shapes.size(); + GLTFShapeIndex size = state_shapes.size(); Dictionary shape_property; Dictionary shape_dict = p_physics_shape->to_dictionary(); - for (int i = 0; i < size; i++) { + for (GLTFShapeIndex i = 0; i < size; i++) { Dictionary other = state_shapes[i]; if (other == shape_dict) { // De-duplication: If we already have an identical shape, // set the shape index to the existing one and return. - shape_property["shape"] = i; - return shape_property; + return i; } } // If we don't have an identical shape, add it to the array. state_shapes.push_back(shape_dict); - shape_property["shape"] = size; - return shape_property; + return size; +} + +Error GLTFDocumentExtensionPhysics::export_preserialize(Ref<GLTFState> p_state) { + // Note: Need to do _export_node_shape before exporting animations, so export_node is too late. + TypedArray<GLTFNode> state_gltf_nodes = p_state->get_nodes(); + for (Ref<GLTFNode> gltf_node : state_gltf_nodes) { + Ref<GLTFPhysicsShape> collider_shape = gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShape")); + if (collider_shape.is_valid()) { + GLTFShapeIndex collider_shape_index = _export_node_shape(p_state, collider_shape); + gltf_node->set_additional_data(StringName("GLTFPhysicsColliderShapeIndex"), collider_shape_index); + } + Ref<GLTFPhysicsShape> trigger_shape = gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShape")); + if (trigger_shape.is_valid()) { + GLTFShapeIndex trigger_shape_index = _export_node_shape(p_state, trigger_shape); + gltf_node->set_additional_data(StringName("GLTFPhysicsTriggerShapeIndex"), trigger_shape_index); + } + } + return OK; +} + +Ref<GLTFObjectModelProperty> GLTFDocumentExtensionPhysics::export_object_model_property(Ref<GLTFState> p_state, const NodePath &p_node_path, const Node *p_godot_node, GLTFNodeIndex p_gltf_node_index, const Object *p_target_object, int p_target_depth) { + Ref<GLTFObjectModelProperty> ret; + const Vector<StringName> &path_subnames = p_node_path.get_subnames(); + if (path_subnames.is_empty()) { + return ret; + } + ret.instantiate(); + const StringName &node_prop = path_subnames[0]; + if (Object::cast_to<RigidBody3D>(p_target_object)) { + if (path_subnames.size() != 1) { + return ret; + } + // Example: `/nodes/0/extensions/OMI_physics_body/motion/mass` + PackedStringArray split_json_pointer; + split_json_pointer.append("nodes"); + split_json_pointer.append(itos(p_gltf_node_index)); + split_json_pointer.append("extensions"); + split_json_pointer.append("OMI_physics_body"); + split_json_pointer.append("motion"); + if (node_prop == StringName("mass")) { + split_json_pointer.append("mass"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (node_prop == StringName("linear_velocity")) { + split_json_pointer.append("linearVelocity"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (node_prop == StringName("angular_velocity")) { + split_json_pointer.append("angularVelocity"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (node_prop == StringName("center_of_mass")) { + split_json_pointer.append("centerOfMass"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (node_prop == StringName("inertia")) { + split_json_pointer.append("inertiaDiagonal"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else { + // Not something we handle, return without setting the JSON pointer. + return ret; + } + ret->set_json_pointers({ split_json_pointer }); + } else if (Object::cast_to<CollisionShape3D>(p_godot_node)) { + if (path_subnames.size() != 2) { + return ret; + } + // Example: `/extensions/OMI_physics_shape/shapes/0/box/size` + PackedStringArray split_json_pointer; + split_json_pointer.append("extensions"); + split_json_pointer.append("OMI_physics_shape"); + split_json_pointer.append("shapes"); + TypedArray<GLTFNode> state_gltf_nodes = p_state->get_nodes(); + ERR_FAIL_INDEX_V(p_gltf_node_index, state_gltf_nodes.size(), ret); + Ref<GLTFNode> gltf_node = state_gltf_nodes[p_gltf_node_index]; + Variant shape_index_maybe = gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShapeIndex")); + String shape_type; + if (shape_index_maybe.get_type() == Variant::INT) { + Ref<GLTFPhysicsShape> collider_shape = gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShape")); + shape_type = collider_shape->get_shape_type(); + } else { + shape_index_maybe = gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShapeIndex")); + if (shape_index_maybe.get_type() == Variant::INT) { + Ref<GLTFPhysicsShape> trigger_shape = gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShape")); + shape_type = trigger_shape->get_shape_type(); + } + } + ERR_FAIL_COND_V(shape_index_maybe.get_type() != Variant::INT, ret); + GLTFShapeIndex shape_index = shape_index_maybe; + split_json_pointer.append(itos(shape_index)); + split_json_pointer.append(shape_type); + const StringName &shape_prop = path_subnames[1]; + if (shape_prop == StringName("size")) { + split_json_pointer.append("size"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (shape_prop == StringName("radius")) { + split_json_pointer.append("radius"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (shape_prop == StringName("height")) { + split_json_pointer.append("height"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else { + // Not something we handle, return without setting the JSON pointer. + return ret; + } + ret->set_json_pointers({ split_json_pointer }); + } + return ret; } Error GLTFDocumentExtensionPhysics::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_node_json, Node *p_node) { @@ -465,13 +710,16 @@ Error GLTFDocumentExtensionPhysics::export_node(Ref<GLTFState> p_state, Ref<GLTF trigger_property["nodes"] = compound_trigger_nodes; } } - Ref<GLTFPhysicsShape> collider_shape = p_gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShape")); - if (collider_shape.is_valid()) { - physics_body_ext["collider"] = _export_node_shape(p_state, collider_shape); + Variant collider_shape_index = p_gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShapeIndex")); + if (collider_shape_index.get_type() == Variant::INT) { + Dictionary collider_dict; + collider_dict["shape"] = collider_shape_index; + physics_body_ext["collider"] = collider_dict; } - Ref<GLTFPhysicsShape> trigger_shape = p_gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShape")); - if (trigger_shape.is_valid()) { - physics_body_ext["trigger"] = _export_node_shape(p_state, trigger_shape); + Variant trigger_shape_index = p_gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShapeIndex")); + if (trigger_shape_index.get_type() == Variant::INT) { + Dictionary trigger_dict = physics_body_ext.get_or_add("trigger", {}); + trigger_dict["shape"] = trigger_shape_index; } if (!physics_body_ext.is_empty()) { Dictionary node_extensions = r_node_json["extensions"]; diff --git a/modules/gltf/extensions/physics/gltf_document_extension_physics.h b/modules/gltf/extensions/physics/gltf_document_extension_physics.h index 3d5027c0df..76a60a6375 100644 --- a/modules/gltf/extensions/physics/gltf_document_extension_physics.h +++ b/modules/gltf/extensions/physics/gltf_document_extension_physics.h @@ -43,9 +43,12 @@ public: Error import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) override; Vector<String> get_supported_extensions() override; Error parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions) override; + Ref<GLTFObjectModelProperty> import_object_model_property(Ref<GLTFState> p_state, const PackedStringArray &p_split_json_pointer, const TypedArray<NodePath> &p_partial_paths) override; Node3D *generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) override; // Export process. void convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node) override; + Error export_preserialize(Ref<GLTFState> p_state) override; + Ref<GLTFObjectModelProperty> export_object_model_property(Ref<GLTFState> p_state, const NodePath &p_node_path, const Node *p_godot_node, GLTFNodeIndex p_gltf_node_index, const Object *p_target_object, int p_target_depth) override; Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_node_json, Node *p_scene_node) override; }; diff --git a/modules/gltf/extensions/physics/gltf_physics_body.cpp b/modules/gltf/extensions/physics/gltf_physics_body.cpp index c11aa5d2ff..7c40f96e0a 100644 --- a/modules/gltf/extensions/physics/gltf_physics_body.cpp +++ b/modules/gltf/extensions/physics/gltf_physics_body.cpp @@ -193,9 +193,6 @@ Ref<GLTFPhysicsBody> GLTFPhysicsBody::from_node(const CollisionObject3D *p_body_ physics_body->angular_velocity = body->get_angular_velocity(); physics_body->center_of_mass = body->get_center_of_mass(); physics_body->inertia_diagonal = body->get_inertia(); - if (body->get_center_of_mass() != Vector3()) { - WARN_PRINT("GLTFPhysicsBody: This rigid body has a center of mass offset from the origin, which will be ignored when exporting to glTF."); - } if (cast_to<VehicleBody3D>(p_body_node)) { physics_body->body_type = PhysicsBodyType::VEHICLE; } else { diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h index c1918e5908..4d88f7c342 100644 --- a/modules/gltf/gltf_defines.h +++ b/modules/gltf/gltf_defines.h @@ -43,6 +43,7 @@ class GLTFDocumentExtension; class GLTFLight; class GLTFMesh; class GLTFNode; +class GLTFObjectModelProperty; class GLTFSkeleton; class GLTFSkin; class GLTFSpecGloss; diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 0a487430a3..2f36c29ec4 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -69,6 +69,10 @@ #include <stdlib.h> #include <cstdint> +constexpr int COMPONENT_COUNT_FOR_ACCESSOR_TYPE[7] = { + 1, 2, 3, 4, 4, 9, 16 +}; + static void _attach_extras_to_meta(const Dictionary &p_extras, Ref<Resource> p_node) { if (!p_extras.is_empty()) { p_node->set_meta("extras", p_extras); @@ -113,7 +117,7 @@ static Ref<ImporterMesh> _mesh_to_importer_mesh(Ref<Mesh> p_mesh) { mat_name = mat->get_name(); } else { // Assign default material when no material is assigned. - mat = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + mat.instantiate(); } importer_mesh->add_surface(p_mesh->surface_get_primitive_type(surface_i), array, p_mesh->surface_get_blend_shape_arrays(surface_i), p_mesh->surface_get_lods(surface_i), mat, @@ -685,7 +689,7 @@ void GLTFDocument::_compute_node_heights(Ref<GLTFState> p_state) { } static Vector<uint8_t> _parse_base64_uri(const String &p_uri) { - int start = p_uri.find(","); + int start = p_uri.find_char(','); ERR_FAIL_COND_V(start == -1, Vector<uint8_t>()); CharString substr = p_uri.substr(start + 1).ascii(); @@ -1013,7 +1017,7 @@ Error GLTFDocument::_parse_accessors(Ref<GLTFState> p_state) { accessor.instantiate(); ERR_FAIL_COND_V(!d.has("componentType"), ERR_PARSE_ERROR); - accessor->component_type = d["componentType"]; + accessor->component_type = (GLTFAccessor::GLTFComponentType)(int32_t)d["componentType"]; ERR_FAIL_COND_V(!d.has("count"), ERR_PARSE_ERROR); accessor->count = d["count"]; ERR_FAIL_COND_V(!d.has("type"), ERR_PARSE_ERROR); @@ -1050,7 +1054,7 @@ Error GLTFDocument::_parse_accessors(Ref<GLTFState> p_state) { ERR_FAIL_COND_V(!si.has("bufferView"), ERR_PARSE_ERROR); accessor->sparse_indices_buffer_view = si["bufferView"]; ERR_FAIL_COND_V(!si.has("componentType"), ERR_PARSE_ERROR); - accessor->sparse_indices_component_type = si["componentType"]; + accessor->sparse_indices_component_type = (GLTFAccessor::GLTFComponentType)(int32_t)si["componentType"]; if (si.has("byteOffset")) { accessor->sparse_indices_byte_offset = si["byteOffset"]; @@ -1082,31 +1086,39 @@ double GLTFDocument::_filter_number(double p_float) { return (double)(float)p_float; } -String GLTFDocument::_get_component_type_name(const uint32_t p_component) { +String GLTFDocument::_get_component_type_name(const GLTFAccessor::GLTFComponentType p_component) { switch (p_component) { - case GLTFDocument::COMPONENT_TYPE_BYTE: + case GLTFAccessor::COMPONENT_TYPE_NONE: + return "None"; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: return "Byte"; - case GLTFDocument::COMPONENT_TYPE_UNSIGNED_BYTE: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: return "UByte"; - case GLTFDocument::COMPONENT_TYPE_SHORT: + case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: return "Short"; - case GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: return "UShort"; - case GLTFDocument::COMPONENT_TYPE_INT: + case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: return "Int"; - case GLTFDocument::COMPONENT_TYPE_FLOAT: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: + return "UInt"; + case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: return "Float"; + case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: + return "Double"; + case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: + return "Half"; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: + return "Long"; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: + return "ULong"; } return "<Error>"; } -Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_src, const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const int p_component_type, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_accessor, const bool p_for_vertex_indices) { - const int component_count_for_type[7] = { - 1, 2, 3, 4, 4, 9, 16 - }; - - const int component_count = component_count_for_type[p_accessor_type]; +Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_src, const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const GLTFAccessor::GLTFComponentType p_component_type, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_accessor, const bool p_for_vertex_indices) { + const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type]; const int component_size = _get_component_type_size(p_component_type); ERR_FAIL_COND_V(component_size == 0, FAILED); @@ -1114,8 +1126,8 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ int skip_bytes = 0; //special case of alignments, as described in spec switch (p_component_type) { - case COMPONENT_TYPE_BYTE: - case COMPONENT_TYPE_UNSIGNED_BYTE: { + case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { if (p_accessor_type == GLTFAccessor::TYPE_MAT2) { skip_every = 2; skip_bytes = 2; @@ -1125,8 +1137,8 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ skip_bytes = 1; } } break; - case COMPONENT_TYPE_SHORT: - case COMPONENT_TYPE_UNSIGNED_SHORT: { + case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { if (p_accessor_type == GLTFAccessor::TYPE_MAT3) { skip_every = 6; skip_bytes = 4; @@ -1161,7 +1173,10 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ } switch (p_component_type) { - case COMPONENT_TYPE_BYTE: { + case GLTFAccessor::COMPONENT_TYPE_NONE: { + ERR_FAIL_V_MSG(ERR_INVALID_DATA, "glTF: Failed to encode buffer view, component type not set."); + } + case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: { Vector<int8_t> buffer; buffer.resize(p_count * component_count); int32_t dst_i = 0; @@ -1185,7 +1200,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(int8_t)); bv->byte_length = buffer.size() * sizeof(int8_t); } break; - case COMPONENT_TYPE_UNSIGNED_BYTE: { + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { Vector<uint8_t> buffer; buffer.resize(p_count * component_count); int32_t dst_i = 0; @@ -1207,7 +1222,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ gltf_buffer.append_array(buffer); bv->byte_length = buffer.size() * sizeof(uint8_t); } break; - case COMPONENT_TYPE_SHORT: { + case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: { Vector<int16_t> buffer; buffer.resize(p_count * component_count); int32_t dst_i = 0; @@ -1231,7 +1246,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(int16_t)); bv->byte_length = buffer.size() * sizeof(int16_t); } break; - case COMPONENT_TYPE_UNSIGNED_SHORT: { + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { Vector<uint16_t> buffer; buffer.resize(p_count * component_count); int32_t dst_i = 0; @@ -1255,8 +1270,28 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(uint16_t)); bv->byte_length = buffer.size() * sizeof(uint16_t); } break; - case COMPONENT_TYPE_INT: { - Vector<int> buffer; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: { + Vector<int32_t> buffer; + buffer.resize(p_count * component_count); + int32_t dst_i = 0; + for (int i = 0; i < p_count; i++) { + for (int j = 0; j < component_count; j++) { + if (skip_every && j > 0 && (j % skip_every) == 0) { + dst_i += skip_bytes; + } + double d = *p_src; + buffer.write[dst_i] = d; + p_src++; + dst_i++; + } + } + int64_t old_size = gltf_buffer.size(); + gltf_buffer.resize(old_size + (buffer.size() * sizeof(uint32_t))); + memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(uint32_t)); + bv->byte_length = buffer.size() * sizeof(uint32_t); + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: { + Vector<uint32_t> buffer; buffer.resize(p_count * component_count); int32_t dst_i = 0; for (int i = 0; i < p_count; i++) { @@ -1271,11 +1306,11 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ } } int64_t old_size = gltf_buffer.size(); - gltf_buffer.resize(old_size + (buffer.size() * sizeof(int32_t))); - memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(int32_t)); - bv->byte_length = buffer.size() * sizeof(int32_t); + gltf_buffer.resize(old_size + (buffer.size() * sizeof(uint32_t))); + memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(uint32_t)); + bv->byte_length = buffer.size() * sizeof(uint32_t); } break; - case COMPONENT_TYPE_FLOAT: { + case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: { Vector<float> buffer; buffer.resize(p_count * component_count); int32_t dst_i = 0; @@ -1295,6 +1330,71 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(float)); bv->byte_length = buffer.size() * sizeof(float); } break; + case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: { + Vector<double> buffer; + buffer.resize(p_count * component_count); + int32_t dst_i = 0; + for (int i = 0; i < p_count; i++) { + for (int j = 0; j < component_count; j++) { + if (skip_every && j > 0 && (j % skip_every) == 0) { + dst_i += skip_bytes; + } + double d = *p_src; + buffer.write[dst_i] = d; + p_src++; + dst_i++; + } + } + int64_t old_size = gltf_buffer.size(); + gltf_buffer.resize(old_size + (buffer.size() * sizeof(double))); + memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(double)); + bv->byte_length = buffer.size() * sizeof(double); + } break; + case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: { + ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "glTF: Half float not supported yet."); + } break; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: { + Vector<int64_t> buffer; + buffer.resize(p_count * component_count); + int32_t dst_i = 0; + for (int i = 0; i < p_count; i++) { + for (int j = 0; j < component_count; j++) { + if (skip_every && j > 0 && (j % skip_every) == 0) { + dst_i += skip_bytes; + } + // FIXME: This can result in precision loss because int64_t can store some values that double can't. + double d = *p_src; + buffer.write[dst_i] = d; + p_src++; + dst_i++; + } + } + int64_t old_size = gltf_buffer.size(); + gltf_buffer.resize(old_size + (buffer.size() * sizeof(int64_t))); + memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(int64_t)); + bv->byte_length = buffer.size() * sizeof(int64_t); + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: { + Vector<uint64_t> buffer; + buffer.resize(p_count * component_count); + int32_t dst_i = 0; + for (int i = 0; i < p_count; i++) { + for (int j = 0; j < component_count; j++) { + if (skip_every && j > 0 && (j % skip_every) == 0) { + dst_i += skip_bytes; + } + // FIXME: This can result in precision loss because int64_t can store some values that double can't. + double d = *p_src; + buffer.write[dst_i] = d; + p_src++; + dst_i++; + } + } + int64_t old_size = gltf_buffer.size(); + gltf_buffer.resize(old_size + (buffer.size() * sizeof(uint64_t))); + memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(uint64_t)); + bv->byte_length = buffer.size() * sizeof(uint64_t); + } break; } ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_INVALID_DATA); @@ -1309,7 +1409,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_ return OK; } -Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, const GLTFBufferViewIndex p_buffer_view, const int p_skip_every, const int p_skip_bytes, const int p_element_size, const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const int p_component_count, const int p_component_type, const int p_component_size, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex) { +Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, const GLTFBufferViewIndex p_buffer_view, const int p_skip_every, const int p_skip_bytes, const int p_element_size, const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const int p_component_count, const GLTFAccessor::GLTFComponentType p_component_type, const int p_component_size, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex) { const Ref<GLTFBufferView> bv = p_state->buffer_views[p_buffer_view]; int stride = p_element_size; @@ -1348,7 +1448,10 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c double d = 0; switch (p_component_type) { - case COMPONENT_TYPE_BYTE: { + case GLTFAccessor::COMPONENT_TYPE_NONE: { + ERR_FAIL_V_MSG(ERR_INVALID_DATA, "glTF: Failed to decode buffer view, component type not set."); + } break; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: { int8_t b = int8_t(*src); if (p_normalized) { d = (double(b) / 128.0); @@ -1356,7 +1459,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c d = double(b); } } break; - case COMPONENT_TYPE_UNSIGNED_BYTE: { + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { uint8_t b = *src; if (p_normalized) { d = (double(b) / 255.0); @@ -1364,7 +1467,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c d = double(b); } } break; - case COMPONENT_TYPE_SHORT: { + case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: { int16_t s = *(int16_t *)src; if (p_normalized) { d = (double(s) / 32768.0); @@ -1372,7 +1475,7 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c d = double(s); } } break; - case COMPONENT_TYPE_UNSIGNED_SHORT: { + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { uint16_t s = *(uint16_t *)src; if (p_normalized) { d = (double(s) / 65535.0); @@ -1380,12 +1483,27 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c d = double(s); } } break; - case COMPONENT_TYPE_INT: { - d = *(int *)src; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: { + d = *(int32_t *)src; + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: { + d = *(uint32_t *)src; } break; - case COMPONENT_TYPE_FLOAT: { + case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: { d = *(float *)src; } break; + case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: { + d = *(double *)src; + } break; + case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: { + ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "glTF: Half float not supported yet."); + } break; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: { + d = *(int64_t *)src; + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: { + d = *(uint64_t *)src; + } break; } *p_dst++ = d; @@ -1396,25 +1514,27 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c return OK; } -int GLTFDocument::_get_component_type_size(const int p_component_type) { +int GLTFDocument::_get_component_type_size(const GLTFAccessor::GLTFComponentType p_component_type) { switch (p_component_type) { - case COMPONENT_TYPE_BYTE: - case COMPONENT_TYPE_UNSIGNED_BYTE: + case GLTFAccessor::COMPONENT_TYPE_NONE: + ERR_FAIL_V(0); + case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: return 1; - break; - case COMPONENT_TYPE_SHORT: - case COMPONENT_TYPE_UNSIGNED_SHORT: + case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: + case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: return 2; - break; - case COMPONENT_TYPE_INT: - case COMPONENT_TYPE_FLOAT: + case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: + case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: return 4; - break; - default: { - ERR_FAIL_V(0); - } + case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: + case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: + return 8; } - return 0; + ERR_FAIL_V(0); } Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { @@ -1425,11 +1545,7 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> p_state, const GLTF const Ref<GLTFAccessor> a = p_state->accessors[p_accessor]; - const int component_count_for_type[7] = { - 1, 2, 3, 4, 4, 9, 16 - }; - - const int component_count = component_count_for_type[a->accessor_type]; + const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[a->accessor_type]; const int component_size = _get_component_type_size(a->component_type); ERR_FAIL_COND_V(component_size == 0, Vector<double>()); int element_size = component_count * component_size; @@ -1438,8 +1554,8 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> p_state, const GLTF int skip_bytes = 0; //special case of alignments, as described in spec switch (a->component_type) { - case COMPONENT_TYPE_BYTE: - case COMPONENT_TYPE_UNSIGNED_BYTE: { + case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { if (a->accessor_type == GLTFAccessor::TYPE_MAT2) { skip_every = 2; skip_bytes = 2; @@ -1451,8 +1567,8 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> p_state, const GLTF element_size = 12; //override for this case } } break; - case COMPONENT_TYPE_SHORT: - case COMPONENT_TYPE_UNSIGNED_SHORT: { + case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { if (a->accessor_type == GLTFAccessor::TYPE_MAT3) { skip_every = 6; skip_bytes = 4; @@ -1550,11 +1666,11 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state, } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_SCALAR; - int component_type; + GLTFAccessor::GLTFComponentType component_type; if (max_index > 65535 || p_for_vertex) { - component_type = GLTFDocument::COMPONENT_TYPE_INT; + component_type = GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT; } else { - component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT; + component_type = GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT; } accessor->max = type_max; @@ -1664,7 +1780,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> p_state, } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_VEC2; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; accessor->max = type_max; accessor->min = type_min; @@ -1717,7 +1833,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> p_state } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_VEC4; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; accessor->max = type_max; accessor->min = type_min; @@ -1784,7 +1900,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> p_sta } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_VEC4; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; accessor->max = type_max; accessor->min = type_min; @@ -1835,7 +1951,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> p_stat } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_VEC4; - const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT; accessor->max = type_max; accessor->min = type_min; @@ -1888,7 +2004,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> p } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_VEC4; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; accessor->max = type_max; accessor->min = type_min; @@ -1932,7 +2048,7 @@ Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> p_state, c return ret; } -GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> p_state, const Vector<real_t> p_attribs, const bool p_for_vertex) { +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> p_state, const Vector<double> p_attribs, const bool p_for_vertex) { if (p_attribs.size() == 0) { return -1; } @@ -1963,7 +2079,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> p_stat } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_SCALAR; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; accessor->max = type_max; accessor->min = type_min; @@ -2013,7 +2129,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> p_state, } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_VEC3; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; accessor->max = type_max; accessor->min = type_min; @@ -2089,7 +2205,7 @@ GLTFAccessorIndex GLTFDocument::_encode_sparse_accessor_as_vec3(Ref<GLTFState> p } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_VEC3; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; sparse_accessor->normalized = false; sparse_accessor->count = p_attribs.size(); @@ -2112,9 +2228,9 @@ GLTFAccessorIndex GLTFDocument::_encode_sparse_accessor_as_vec3(Ref<GLTFState> p GLTFBufferIndex buffer_view_i_indices = -1; GLTFBufferIndex buffer_view_i_values = -1; if (sparse_accessor_index_stride == 4) { - sparse_accessor->sparse_indices_component_type = GLTFDocument::COMPONENT_TYPE_INT; + sparse_accessor->sparse_indices_component_type = GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT; } else { - sparse_accessor->sparse_indices_component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT; + sparse_accessor->sparse_indices_component_type = GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT; } if (_encode_buffer_view(p_state, changed_indices.ptr(), changed_indices.size(), GLTFAccessor::TYPE_SCALAR, sparse_accessor->sparse_indices_component_type, sparse_accessor->normalized, sparse_accessor->sparse_indices_byte_offset, false, buffer_view_i_indices) != OK) { return -1; @@ -2194,7 +2310,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> p_state } int64_t size = p_state->buffers[0].size(); const GLTFAccessor::GLTFAccessorType accessor_type = GLTFAccessor::TYPE_MAT4; - const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; + const GLTFAccessor::GLTFComponentType component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT; accessor->max = type_max; accessor->min = type_min; @@ -2343,6 +2459,325 @@ Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> p_sta return ret; } +Vector<Variant> GLTFDocument::_decode_accessor_as_variant(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, Variant::Type p_variant_type, GLTFAccessor::GLTFAccessorType p_accessor_type) { + const Vector<double> attribs = _decode_accessor(p_state, p_accessor, false); + Vector<Variant> ret; + ERR_FAIL_COND_V_MSG(attribs.is_empty(), ret, "glTF: The accessor was empty."); + const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type]; + ERR_FAIL_COND_V_MSG(attribs.size() % component_count != 0, ret, "glTF: The accessor size was not a multiple of the component count."); + const int ret_size = attribs.size() / component_count; + ret.resize(ret_size); + for (int i = 0; i < ret_size; i++) { + switch (p_variant_type) { + case Variant::BOOL: { + ret.write[i] = attribs[i * component_count] != 0.0; + } break; + case Variant::INT: { + ret.write[i] = (int64_t)attribs[i * component_count]; + } break; + case Variant::FLOAT: { + ret.write[i] = attribs[i * component_count]; + } break; + case Variant::VECTOR2: + case Variant::RECT2: + case Variant::VECTOR3: + case Variant::VECTOR4: + case Variant::PLANE: + case Variant::QUATERNION: { + // General-purpose code for importing glTF accessor data with any component count into structs up to 4 `real_t`s in size. + Variant v; + switch (component_count) { + case 1: { + v = Vector4(attribs[i * component_count], 0.0f, 0.0f, 0.0f); + } break; + case 2: { + v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], 0.0f, 0.0f); + } break; + case 3: { + v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], 0.0f); + } break; + default: { + v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]); + } break; + } + // Evil hack that relies on the structure of Variant, but it's the + // only way to accomplish this without a ton of code duplication. + *(Variant::Type *)&v = p_variant_type; + ret.write[i] = v; + } break; + case Variant::VECTOR2I: + case Variant::RECT2I: + case Variant::VECTOR3I: + case Variant::VECTOR4I: { + // General-purpose code for importing glTF accessor data with any component count into structs up to 4 `int32_t`s in size. + Variant v; + switch (component_count) { + case 1: { + v = Vector4i((int32_t)attribs[i * component_count], 0, 0, 0); + } break; + case 2: { + v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], 0, 0); + } break; + case 3: { + v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], (int32_t)attribs[i * component_count + 2], 0); + } break; + default: { + v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], (int32_t)attribs[i * component_count + 2], (int32_t)attribs[i * component_count + 3]); + } break; + } + // Evil hack that relies on the structure of Variant, but it's the + // only way to accomplish this without a ton of code duplication. + *(Variant::Type *)&v = p_variant_type; + ret.write[i] = v; + } break; + // No more generalized hacks, each of the below types needs a lot of repetitive code. + case Variant::COLOR: { + Variant v; + switch (component_count) { + case 1: { + v = Color(attribs[i * component_count], 0.0f, 0.0f, 1.0f); + } break; + case 2: { + v = Color(attribs[i * component_count], attribs[i * component_count + 1], 0.0f, 1.0f); + } break; + case 3: { + v = Color(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], 1.0f); + } break; + default: { + v = Color(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]); + } break; + } + ret.write[i] = v; + } break; + case Variant::TRANSFORM2D: { + Transform2D t; + switch (component_count) { + case 4: { + t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]); + t.columns[1] = Vector2(attribs[i * component_count + 2], attribs[i * component_count + 3]); + } break; + case 9: { + t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]); + t.columns[1] = Vector2(attribs[i * component_count + 3], attribs[i * component_count + 4]); + t.columns[2] = Vector2(attribs[i * component_count + 6], attribs[i * component_count + 7]); + } break; + case 16: { + t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]); + t.columns[1] = Vector2(attribs[i * component_count + 4], attribs[i * component_count + 5]); + t.columns[2] = Vector2(attribs[i * component_count + 12], attribs[i * component_count + 13]); + } break; + } + ret.write[i] = t; + } break; + case Variant::BASIS: { + Basis b; + switch (component_count) { + case 4: { + b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 2], 0.0f); + b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 3], 0.0f); + } break; + case 9: { + b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 3], attribs[i * component_count + 6]); + b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 4], attribs[i * component_count + 7]); + b.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 5], attribs[i * component_count + 8]); + } break; + case 16: { + b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 4], attribs[i * component_count + 8]); + b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 5], attribs[i * component_count + 9]); + b.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 6], attribs[i * component_count + 10]); + } break; + } + ret.write[i] = b; + } break; + case Variant::TRANSFORM3D: { + Transform3D t; + switch (component_count) { + case 4: { + t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 2], 0.0f); + t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 3], 0.0f); + } break; + case 9: { + t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 3], attribs[i * component_count + 6]); + t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 4], attribs[i * component_count + 7]); + t.basis.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 5], attribs[i * component_count + 8]); + } break; + case 16: { + t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 4], attribs[i * component_count + 8]); + t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 5], attribs[i * component_count + 9]); + t.basis.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 6], attribs[i * component_count + 10]); + t.origin = Vector3(attribs[i * component_count + 12], attribs[i * component_count + 13], attribs[i * component_count + 14]); + } break; + } + ret.write[i] = t; + } break; + case Variant::PROJECTION: { + Projection p; + switch (component_count) { + case 4: { + p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], 0.0f, 0.0f); + p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], 0.0f, 0.0f); + } break; + case 9: { + p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], attribs[i * component_count + 2], 0.0f); + p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], attribs[i * component_count + 6], 0.0f); + p.columns[2] = Vector4(attribs[i * component_count + 8], attribs[i * component_count + 9], attribs[i * component_count + 10], 0.0f); + } break; + case 16: { + p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]); + p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], attribs[i * component_count + 6], attribs[i * component_count + 7]); + p.columns[2] = Vector4(attribs[i * component_count + 8], attribs[i * component_count + 9], attribs[i * component_count + 10], attribs[i * component_count + 11]); + p.columns[3] = Vector4(attribs[i * component_count + 12], attribs[i * component_count + 13], attribs[i * component_count + 14], attribs[i * component_count + 15]); + } break; + } + ret.write[i] = p; + } break; + default: { + ERR_FAIL_V_MSG(ret, "glTF: Cannot decode accessor as Variant of type " + Variant::get_type_name(p_variant_type) + "."); + } + } + } + return ret; +} + +GLTFAccessorIndex GLTFDocument::_encode_accessor_as_variant(Ref<GLTFState> p_state, Vector<Variant> p_attribs, Variant::Type p_variant_type, GLTFAccessor::GLTFAccessorType p_accessor_type, GLTFAccessor::GLTFComponentType p_component_type) { + const int accessor_component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type]; + Vector<double> encoded_attribs; + for (const Variant &v : p_attribs) { + switch (p_variant_type) { + case Variant::NIL: + case Variant::BOOL: + case Variant::INT: + case Variant::FLOAT: { + // For scalar values, just append them. Variant can convert all of these to double. Some padding may also be needed. + encoded_attribs.append(v); + if (unlikely(accessor_component_count > 1)) { + for (int i = 1; i < accessor_component_count; i++) { + encoded_attribs.append(0.0); + } + } + } break; + case Variant::VECTOR2: + case Variant::VECTOR2I: + case Variant::VECTOR3: + case Variant::VECTOR3I: + case Variant::VECTOR4: + case Variant::VECTOR4I: { + // Variant can handle converting Vector2/2i/3/3i/4/4i to Vector4 for us. + Vector4 vec = v; + if (likely(accessor_component_count < 5)) { + for (int i = 0; i < accessor_component_count; i++) { + encoded_attribs.append(vec[i]); + } + } + } break; + case Variant::PLANE: { + Plane p = v; + if (likely(accessor_component_count == 4)) { + encoded_attribs.append(p.normal.x); + encoded_attribs.append(p.normal.y); + encoded_attribs.append(p.normal.z); + encoded_attribs.append(p.d); + } + } break; + case Variant::QUATERNION: { + Quaternion q = v; + if (likely(accessor_component_count < 5)) { + for (int i = 0; i < accessor_component_count; i++) { + encoded_attribs.append(q[i]); + } + } + } break; + case Variant::COLOR: { + Color c = v; + if (likely(accessor_component_count < 5)) { + for (int i = 0; i < accessor_component_count; i++) { + encoded_attribs.append(c[i]); + } + } + } break; + case Variant::RECT2: + case Variant::RECT2I: { + // Variant can handle converting Rect2i to Rect2 for us. + Rect2 r = v; + if (likely(accessor_component_count == 4)) { + encoded_attribs.append(r.position.x); + encoded_attribs.append(r.position.y); + encoded_attribs.append(r.size.x); + encoded_attribs.append(r.size.y); + } + } break; + case Variant::TRANSFORM2D: + case Variant::BASIS: + case Variant::TRANSFORM3D: + case Variant::PROJECTION: { + // Variant can handle converting Transform2D/Transform3D/Basis to Projection for us. + Projection p = v; + if (accessor_component_count == 16) { + for (int i = 0; i < 4; i++) { + encoded_attribs.append(p.columns[i][0]); + encoded_attribs.append(p.columns[i][1]); + encoded_attribs.append(p.columns[i][2]); + encoded_attribs.append(p.columns[i][3]); + } + } else if (accessor_component_count == 9) { + for (int i = 0; i < 3; i++) { + encoded_attribs.append(p.columns[i][0]); + encoded_attribs.append(p.columns[i][1]); + encoded_attribs.append(p.columns[i][2]); + } + } else if (accessor_component_count == 4) { + encoded_attribs.append(p.columns[0][0]); + encoded_attribs.append(p.columns[0][1]); + encoded_attribs.append(p.columns[1][0]); + encoded_attribs.append(p.columns[1][1]); + } + } break; + default: { + ERR_FAIL_V_MSG(-1, "glTF: Cannot encode accessor from Variant of type " + Variant::get_type_name(p_variant_type) + "."); + } + } + } + // Determine the min and max values for the accessor. + Vector<double> type_max; + type_max.resize(accessor_component_count); + Vector<double> type_min; + type_min.resize(accessor_component_count); + for (int i = 0; i < encoded_attribs.size(); i++) { + if (Math::is_zero_approx(encoded_attribs[i])) { + encoded_attribs.write[i] = 0.0; + } else { + encoded_attribs.write[i] = _filter_number(encoded_attribs[i]); + } + } + for (int i = 0; i < p_attribs.size(); i++) { + _calc_accessor_min_max(i, accessor_component_count, type_max, encoded_attribs, type_min); + } + _round_min_max_components(type_min, type_max); + // Encode the data in a buffer view. + GLTFBufferIndex buffer_view_index = 0; + if (p_state->buffers.is_empty()) { + p_state->buffers.push_back(Vector<uint8_t>()); + } + const int64_t buffer_size = p_state->buffers[buffer_view_index].size(); + Error err = _encode_buffer_view(p_state, encoded_attribs.ptr(), p_attribs.size(), p_accessor_type, p_component_type, false, buffer_size, false, buffer_view_index); + if (err != OK) { + return -1; + } + // Create the accessor and fill it with the data. + Ref<GLTFAccessor> accessor; + accessor.instantiate(); + accessor->max = type_max; + accessor->min = type_min; + accessor->count = p_attribs.size(); + accessor->accessor_type = p_accessor_type; + accessor->component_type = p_component_type; + accessor->byte_offset = 0; + accessor->buffer_view = buffer_view_index; + const GLTFAccessorIndex new_accessor_index = p_state->accessors.size(); + p_state->accessors.push_back(accessor); + return new_accessor_index; +} + Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) { Array meshes; for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < p_state->meshes.size(); gltf_mesh_i++) { @@ -2778,41 +3213,42 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { Array meshes = p_state->json["meshes"]; for (GLTFMeshIndex i = 0; i < meshes.size(); i++) { print_verbose("glTF: Parsing mesh: " + itos(i)); - Dictionary d = meshes[i]; + Dictionary mesh_dict = meshes[i]; Ref<GLTFMesh> mesh; mesh.instantiate(); bool has_vertex_color = false; - ERR_FAIL_COND_V(!d.has("primitives"), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(!mesh_dict.has("primitives"), ERR_PARSE_ERROR); - Array primitives = d["primitives"]; - const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary(); + Array primitives = mesh_dict["primitives"]; + const Dictionary &extras = mesh_dict.has("extras") ? (Dictionary)mesh_dict["extras"] : Dictionary(); _attach_extras_to_meta(extras, mesh); Ref<ImporterMesh> import_mesh; import_mesh.instantiate(); String mesh_name = "mesh"; - if (d.has("name") && !String(d["name"]).is_empty()) { - mesh_name = d["name"]; + if (mesh_dict.has("name") && !String(mesh_dict["name"]).is_empty()) { + mesh_name = mesh_dict["name"]; mesh->set_original_name(mesh_name); } import_mesh->set_name(_gen_unique_name(p_state, vformat("%s_%s", p_state->scene_name, mesh_name))); mesh->set_name(import_mesh->get_name()); + TypedArray<Material> instance_materials; for (int j = 0; j < primitives.size(); j++) { uint64_t flags = RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES; - Dictionary p = primitives[j]; + Dictionary mesh_prim = primitives[j]; Array array; array.resize(Mesh::ARRAY_MAX); - ERR_FAIL_COND_V(!p.has("attributes"), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(!mesh_prim.has("attributes"), ERR_PARSE_ERROR); - Dictionary a = p["attributes"]; + Dictionary a = mesh_prim["attributes"]; Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES; - if (p.has("mode")) { - const int mode = p["mode"]; + if (mesh_prim.has("mode")) { + const int mode = mesh_prim["mode"]; ERR_FAIL_INDEX_V(mode, 7, ERR_FILE_CORRUPT); // Convert mesh.primitive.mode to Godot Mesh enum. See: // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode @@ -2843,8 +3279,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { Vector<int> indices_mapping; Vector<int> indices_rev_mapping; Vector<int> indices_vec4_mapping; - if (p.has("indices")) { - indices = _decode_accessor_as_ints(p_state, p["indices"], false); + if (mesh_prim.has("indices")) { + indices = _decode_accessor_as_ints(p_state, mesh_prim["indices"], false); const int is = indices.size(); if (primitive == Mesh::PRIMITIVE_TRIANGLES) { @@ -3046,6 +3482,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { } } array[Mesh::ARRAY_WEIGHTS] = weights; + flags |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS; } if (!indices.is_empty()) { @@ -3102,7 +3539,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { } } - if (p_state->force_disable_compression || is_mesh_2d || !a.has("POSITION") || !a.has("NORMAL") || p.has("targets") || (a.has("JOINTS_0") || a.has("JOINTS_1"))) { + if (p_state->force_disable_compression || is_mesh_2d || !a.has("POSITION") || !a.has("NORMAL") || mesh_prim.has("targets") || (a.has("JOINTS_0") || a.has("JOINTS_1"))) { flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES; } @@ -3134,9 +3571,9 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { Array morphs; // Blend shapes - if (p.has("targets")) { + if (mesh_prim.has("targets")) { print_verbose("glTF: Mesh has targets"); - const Array &targets = p["targets"]; + const Array &targets = mesh_prim["targets"]; import_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED); @@ -3267,8 +3704,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { Ref<Material> mat; String mat_name; if (!p_state->discard_meshes_and_materials) { - if (p.has("material")) { - const int material = p["material"]; + if (mesh_prim.has("material")) { + const int material = mesh_prim["material"]; ERR_FAIL_INDEX_V(material, p_state->materials.size(), ERR_FILE_CORRUPT); Ref<Material> mat3d = p_state->materials[material]; ERR_FAIL_COND_V(mat3d.is_null(), ERR_FILE_CORRUPT); @@ -3288,6 +3725,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { mat = mat3d; } ERR_FAIL_COND_V(mat.is_null(), ERR_FILE_CORRUPT); + instance_materials.append(mat); mat_name = mat->get_name(); } import_mesh->add_surface(primitive, array, morphs, @@ -3300,8 +3738,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { blend_weights.write[weight_i] = 0.0f; } - if (d.has("weights")) { - const Array &weights = d["weights"]; + if (mesh_dict.has("weights")) { + const Array &weights = mesh_dict["weights"]; for (int j = 0; j < weights.size(); j++) { if (j >= blend_weights.size()) { break; @@ -3310,6 +3748,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) { } } mesh->set_blend_weights(blend_weights); + mesh->set_instance_materials(instance_materials); mesh->set_mesh(import_mesh); p_state->meshes.push_back(mesh); @@ -3501,18 +3940,19 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const Vector< } #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() && handling == GLTFState::GLTFHandleBinary::HANDLE_BINARY_EXTRACT_TEXTURES) { - if (p_state->base_path.is_empty()) { - p_state->images.push_back(Ref<Texture2D>()); - p_state->source_images.push_back(Ref<Image>()); - } else if (p_image->get_name().is_empty()) { - WARN_PRINT(vformat("glTF: Image index '%d' couldn't be named. Skipping it.", p_index)); - p_state->images.push_back(Ref<Texture2D>()); - p_state->source_images.push_back(Ref<Image>()); + if (p_state->extract_path.is_empty()) { + WARN_PRINT("glTF: Couldn't extract image because the base and extract paths are empty. It will be loaded directly instead, uncompressed."); + } else if (p_state->extract_path.begins_with("res://.godot/imported")) { + WARN_PRINT(vformat("glTF: Extract path is in the imported directory. Image index '%d' will be loaded directly, uncompressed.", p_index)); } else { + if (p_image->get_name().is_empty()) { + WARN_PRINT(vformat("glTF: Image index '%d' did not have a name. It will be automatically given a name based on its index.", p_index)); + p_image->set_name(itos(p_index)); + } bool must_import = true; Vector<uint8_t> img_data = p_image->get_data(); Dictionary generator_parameters; - String file_path = p_state->get_base_path().path_join(p_state->filename.get_basename() + "_" + p_image->get_name()); + String file_path = p_state->get_extract_path().path_join(p_state->get_extract_prefix() + "_" + p_image->get_name()); file_path += p_file_extension.is_empty() ? ".png" : p_file_extension; if (FileAccess::exists(file_path + ".import")) { Ref<ConfigFile> config; @@ -3559,14 +3999,11 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const Vector< if (saved_image.is_valid()) { p_state->images.push_back(saved_image); p_state->source_images.push_back(saved_image->get_image()); + return; } else { - WARN_PRINT(vformat("glTF: Image index '%d' couldn't be loaded with the name: %s. Skipping it.", p_index, p_image->get_name())); - // Placeholder to keep count. - p_state->images.push_back(Ref<Texture2D>()); - p_state->source_images.push_back(Ref<Image>()); + WARN_PRINT(vformat("glTF: Image index '%d' with the name '%s' couldn't be imported. It will be loaded directly instead, uncompressed.", p_index, p_image->get_name())); } } - return; } #endif // TOOLS_ENABLED if (handling == GLTFState::GLTFHandleBinary::HANDLE_BINARY_EMBED_AS_BASISU) { @@ -3649,16 +4086,19 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p ERR_FAIL_COND_V(p_base_path.is_empty(), ERR_INVALID_PARAMETER); uri = uri.uri_decode(); uri = p_base_path.path_join(uri).replace("\\", "/"); // Fix for Windows. - // ResourceLoader will rely on the file extension to use the relevant loader. - // The spec says that if mimeType is defined, it should take precedence (e.g. - // there could be a `.png` image which is actually JPEG), but there's no easy - // API for that in Godot, so we'd have to load as a buffer (i.e. embedded in - // the material), so we only do that only as fallback. - Ref<Texture2D> texture = ResourceLoader::load(uri); - if (texture.is_valid()) { - p_state->images.push_back(texture); - p_state->source_images.push_back(texture->get_image()); - continue; + // If the image is in the .godot/imported directory, we can't use ResourceLoader. + if (!p_base_path.begins_with("res://.godot/imported")) { + // ResourceLoader will rely on the file extension to use the relevant loader. + // The spec says that if mimeType is defined, it should take precedence (e.g. + // there could be a `.png` image which is actually JPEG), but there's no easy + // API for that in Godot, so we'd have to load as a buffer (i.e. embedded in + // the material), so we only do that only as fallback. + Ref<Texture2D> texture = ResourceLoader::load(uri, "Texture2D"); + if (texture.is_valid()) { + p_state->images.push_back(texture); + p_state->source_images.push_back(texture->get_image()); + continue; + } } // mimeType is optional, but if we have it in the file extension, let's use it. // If the mimeType does not match with the file extension, either it should be @@ -4781,7 +5221,7 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { for (GLTFAnimationIndex animation_i = 0; animation_i < p_state->animations.size(); animation_i++) { Dictionary d; Ref<GLTFAnimation> gltf_animation = p_state->animations[animation_i]; - if (!gltf_animation->get_tracks().size()) { + if (gltf_animation->is_empty_of_tracks()) { continue; } @@ -4790,18 +5230,18 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { } Array channels; Array samplers; - - for (KeyValue<int, GLTFAnimation::Track> &track_i : gltf_animation->get_tracks()) { - GLTFAnimation::Track track = track_i.value; + // Serialize glTF node tracks with the vanilla glTF animation system. + for (KeyValue<int, GLTFAnimation::NodeTrack> &track_i : gltf_animation->get_node_tracks()) { + GLTFAnimation::NodeTrack track = track_i.value; if (track.position_track.times.size()) { Dictionary t; t["sampler"] = samplers.size(); Dictionary s; s["interpolation"] = interpolation_to_string(track.position_track.interpolation); - Vector<real_t> times = Variant(track.position_track.times); + Vector<double> times = track.position_track.times; s["input"] = _encode_accessor_as_floats(p_state, times, false); - Vector<Vector3> values = Variant(track.position_track.values); + Vector<Vector3> values = track.position_track.values; s["output"] = _encode_accessor_as_vec3(p_state, values, false); samplers.push_back(s); @@ -4819,7 +5259,7 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { Dictionary s; s["interpolation"] = interpolation_to_string(track.rotation_track.interpolation); - Vector<real_t> times = Variant(track.rotation_track.times); + Vector<double> times = track.rotation_track.times; s["input"] = _encode_accessor_as_floats(p_state, times, false); Vector<Quaternion> values = track.rotation_track.values; s["output"] = _encode_accessor_as_quaternions(p_state, values, false); @@ -4839,9 +5279,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { Dictionary s; s["interpolation"] = interpolation_to_string(track.scale_track.interpolation); - Vector<real_t> times = Variant(track.scale_track.times); + Vector<double> times = track.scale_track.times; s["input"] = _encode_accessor_as_floats(p_state, times, false); - Vector<Vector3> values = Variant(track.scale_track.values); + Vector<Vector3> values = track.scale_track.values; s["output"] = _encode_accessor_as_vec3(p_state, values, false); samplers.push_back(s); @@ -4864,7 +5304,7 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { Dictionary t; t["sampler"] = samplers.size(); Dictionary s; - Vector<real_t> times; + Vector<double> times; const double increment = 1.0 / p_state->get_bake_fps(); { double time = 0.0; @@ -4905,8 +5345,8 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { track.weight_tracks.write[track_idx].values = weight_track; } - Vector<real_t> all_track_times = times; - Vector<real_t> all_track_values; + Vector<double> all_track_times = times; + Vector<double> all_track_values; int32_t values_size = track.weight_tracks[0].values.size(); int32_t weight_tracks_size = track.weight_tracks.size(); all_track_values.resize(weight_tracks_size * values_size); @@ -4933,6 +5373,33 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { channels.push_back(t); } } + if (!gltf_animation->get_pointer_tracks().is_empty()) { + // Serialize glTF pointer tracks with the KHR_animation_pointer extension. + if (!p_state->extensions_used.has("KHR_animation_pointer")) { + p_state->extensions_used.push_back("KHR_animation_pointer"); + } + for (KeyValue<String, GLTFAnimation::Channel<Variant>> &pointer_track_iter : gltf_animation->get_pointer_tracks()) { + const String &json_pointer = pointer_track_iter.key; + const GLTFAnimation::Channel<Variant> &pointer_track = pointer_track_iter.value; + const Ref<GLTFObjectModelProperty> &obj_model_prop = p_state->object_model_properties[json_pointer]; + Dictionary channel; + channel["sampler"] = samplers.size(); + Dictionary channel_target; + channel_target["path"] = "pointer"; + Dictionary channel_target_ext; + Dictionary channel_target_ext_khr_anim_ptr; + channel_target_ext_khr_anim_ptr["pointer"] = json_pointer; + channel_target_ext["KHR_animation_pointer"] = channel_target_ext_khr_anim_ptr; + channel_target["extensions"] = channel_target_ext; + channel["target"] = channel_target; + channels.push_back(channel); + Dictionary sampler; + sampler["input"] = _encode_accessor_as_floats(p_state, pointer_track.times, false); + sampler["interpolation"] = interpolation_to_string(pointer_track.interpolation); + sampler["output"] = _encode_accessor_as_variant(p_state, pointer_track.values, obj_model_prop->get_variant_type(), obj_model_prop->get_accessor_type()); + samplers.push_back(sampler); + } + } if (channels.size() && samplers.size()) { d["channels"] = channels; d["samplers"] = samplers; @@ -4957,21 +5424,21 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> p_state) { const Array &animations = p_state->json["animations"]; - for (GLTFAnimationIndex i = 0; i < animations.size(); i++) { - const Dictionary &d = animations[i]; + for (GLTFAnimationIndex anim_index = 0; anim_index < animations.size(); anim_index++) { + const Dictionary &anim_dict = animations[anim_index]; Ref<GLTFAnimation> animation; animation.instantiate(); - if (!d.has("channels") || !d.has("samplers")) { + if (!anim_dict.has("channels") || !anim_dict.has("samplers")) { continue; } - Array channels = d["channels"]; - Array samplers = d["samplers"]; + Array channels = anim_dict["channels"]; + Array samplers = anim_dict["samplers"]; - if (d.has("name")) { - const String anim_name = d["name"]; + if (anim_dict.has("name")) { + const String anim_name = anim_dict["name"]; const String anim_name_lower = anim_name.to_lower(); if (anim_name_lower.begins_with("loop") || anim_name_lower.ends_with("loop") || anim_name_lower.begins_with("cycle") || anim_name_lower.ends_with("cycle")) { animation->set_loop(true); @@ -4980,46 +5447,22 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> p_state) { animation->set_name(_gen_unique_animation_name(p_state, anim_name)); } - for (int j = 0; j < channels.size(); j++) { - const Dictionary &c = channels[j]; - if (!c.has("target")) { - continue; - } - - const Dictionary &t = c["target"]; - if (!t.has("node") || !t.has("path")) { - continue; - } - - ERR_FAIL_COND_V(!c.has("sampler"), ERR_PARSE_ERROR); - const int sampler = c["sampler"]; - ERR_FAIL_INDEX_V(sampler, samplers.size(), ERR_PARSE_ERROR); - - GLTFNodeIndex node = t["node"]; - String path = t["path"]; - - ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR); - - GLTFAnimation::Track *track = nullptr; - - if (!animation->get_tracks().has(node)) { - animation->get_tracks()[node] = GLTFAnimation::Track(); - } - - track = &animation->get_tracks()[node]; - - const Dictionary &s = samplers[sampler]; - - ERR_FAIL_COND_V(!s.has("input"), ERR_PARSE_ERROR); - ERR_FAIL_COND_V(!s.has("output"), ERR_PARSE_ERROR); - - const int input = s["input"]; - const int output = s["output"]; - + for (int channel_index = 0; channel_index < channels.size(); channel_index++) { + const Dictionary &anim_channel = channels[channel_index]; + ERR_FAIL_COND_V_MSG(!anim_channel.has("sampler"), ERR_PARSE_ERROR, "glTF: Animation channel missing required 'sampler' property."); + ERR_FAIL_COND_V_MSG(!anim_channel.has("target"), ERR_PARSE_ERROR, "glTF: Animation channel missing required 'target' property."); + // Parse sampler. + const int sampler_index = anim_channel["sampler"]; + ERR_FAIL_INDEX_V(sampler_index, samplers.size(), ERR_PARSE_ERROR); + const Dictionary &sampler_dict = samplers[sampler_index]; + ERR_FAIL_COND_V(!sampler_dict.has("input"), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(!sampler_dict.has("output"), ERR_PARSE_ERROR); + const int input_time_accessor_index = sampler_dict["input"]; + const int output_value_accessor_index = sampler_dict["output"]; GLTFAnimation::Interpolation interp = GLTFAnimation::INTERP_LINEAR; int output_count = 1; - if (s.has("interpolation")) { - const String &in = s["interpolation"]; + if (sampler_dict.has("interpolation")) { + const String &in = sampler_dict["interpolation"]; if (in == "STEP") { interp = GLTFAnimation::INTERP_STEP; } else if (in == "LINEAR") { @@ -5032,52 +5475,83 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> p_state) { output_count = 3; } } + const Vector<double> times = _decode_accessor(p_state, input_time_accessor_index, false); + // Parse target. + const Dictionary &anim_target = anim_channel["target"]; + ERR_FAIL_COND_V_MSG(!anim_target.has("path"), ERR_PARSE_ERROR, "glTF: Animation channel target missing required 'path' property."); + String path = anim_target["path"]; + if (path == "pointer") { + ERR_FAIL_COND_V(!anim_target.has("extensions"), ERR_PARSE_ERROR); + Dictionary target_extensions = anim_target["extensions"]; + ERR_FAIL_COND_V(!target_extensions.has("KHR_animation_pointer"), ERR_PARSE_ERROR); + Dictionary khr_anim_ptr = target_extensions["KHR_animation_pointer"]; + ERR_FAIL_COND_V(!khr_anim_ptr.has("pointer"), ERR_PARSE_ERROR); + String anim_json_ptr = khr_anim_ptr["pointer"]; + _parse_animation_pointer(p_state, anim_json_ptr, animation, interp, times, output_value_accessor_index); + } else { + // If it's not a pointer, it's a regular animation channel from vanilla glTF (pos/rot/scale/weights). + if (!anim_target.has("node")) { + WARN_PRINT("glTF: Animation channel target missing 'node' property. Ignoring this channel."); + continue; + } - const Vector<float> times = _decode_accessor_as_floats(p_state, input, false); - if (path == "translation") { - const Vector<Vector3> positions = _decode_accessor_as_vec3(p_state, output, false); - track->position_track.interpolation = interp; - track->position_track.times = Variant(times); //convert via variant - track->position_track.values = Variant(positions); //convert via variant - } else if (path == "rotation") { - const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(p_state, output, false); - track->rotation_track.interpolation = interp; - track->rotation_track.times = Variant(times); //convert via variant - track->rotation_track.values = rotations; - } else if (path == "scale") { - const Vector<Vector3> scales = _decode_accessor_as_vec3(p_state, output, false); - track->scale_track.interpolation = interp; - track->scale_track.times = Variant(times); //convert via variant - track->scale_track.values = Variant(scales); //convert via variant - } else if (path == "weights") { - const Vector<float> weights = _decode_accessor_as_floats(p_state, output, false); - - ERR_FAIL_INDEX_V(p_state->nodes[node]->mesh, p_state->meshes.size(), ERR_PARSE_ERROR); - Ref<GLTFMesh> mesh = p_state->meshes[p_state->nodes[node]->mesh]; - ERR_CONTINUE(!mesh->get_blend_weights().size()); - const int wc = mesh->get_blend_weights().size(); - - track->weight_tracks.resize(wc); - - const int expected_value_count = times.size() * output_count * wc; - ERR_CONTINUE_MSG(weights.size() != expected_value_count, "Invalid weight data, expected " + itos(expected_value_count) + " weight values, got " + itos(weights.size()) + " instead."); - - const int wlen = weights.size() / wc; - for (int k = 0; k < wc; k++) { //separate tracks, having them together is not such a good idea - GLTFAnimation::Channel<real_t> cf; - cf.interpolation = interp; - cf.times = Variant(times); - Vector<real_t> wdata; - wdata.resize(wlen); - for (int l = 0; l < wlen; l++) { - wdata.write[l] = weights[l * wc + k]; - } + GLTFNodeIndex node = anim_target["node"]; + + ERR_FAIL_INDEX_V(node, p_state->nodes.size(), ERR_PARSE_ERROR); - cf.values = wdata; - track->weight_tracks.write[k] = cf; + GLTFAnimation::NodeTrack *track = nullptr; + + if (!animation->get_node_tracks().has(node)) { + animation->get_node_tracks()[node] = GLTFAnimation::NodeTrack(); + } + + track = &animation->get_node_tracks()[node]; + + if (path == "translation") { + const Vector<Vector3> positions = _decode_accessor_as_vec3(p_state, output_value_accessor_index, false); + track->position_track.interpolation = interp; + track->position_track.times = times; + track->position_track.values = positions; + } else if (path == "rotation") { + const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(p_state, output_value_accessor_index, false); + track->rotation_track.interpolation = interp; + track->rotation_track.times = times; + track->rotation_track.values = rotations; + } else if (path == "scale") { + const Vector<Vector3> scales = _decode_accessor_as_vec3(p_state, output_value_accessor_index, false); + track->scale_track.interpolation = interp; + track->scale_track.times = times; + track->scale_track.values = scales; + } else if (path == "weights") { + const Vector<float> weights = _decode_accessor_as_floats(p_state, output_value_accessor_index, false); + + ERR_FAIL_INDEX_V(p_state->nodes[node]->mesh, p_state->meshes.size(), ERR_PARSE_ERROR); + Ref<GLTFMesh> mesh = p_state->meshes[p_state->nodes[node]->mesh]; + const int wc = mesh->get_blend_weights().size(); + ERR_CONTINUE_MSG(wc == 0, "glTF: Animation tried to animate weights, but mesh has no weights."); + + track->weight_tracks.resize(wc); + + const int expected_value_count = times.size() * output_count * wc; + ERR_CONTINUE_MSG(weights.size() != expected_value_count, "Invalid weight data, expected " + itos(expected_value_count) + " weight values, got " + itos(weights.size()) + " instead."); + + const int wlen = weights.size() / wc; + for (int k = 0; k < wc; k++) { //separate tracks, having them together is not such a good idea + GLTFAnimation::Channel<real_t> cf; + cf.interpolation = interp; + cf.times = Variant(times); + Vector<real_t> wdata; + wdata.resize(wlen); + for (int l = 0; l < wlen; l++) { + wdata.write[l] = weights[l * wc + k]; + } + + cf.values = wdata; + track->weight_tracks.write[k] = cf; + } + } else { + WARN_PRINT("Invalid path '" + path + "'."); } - } else { - WARN_PRINT("Invalid path '" + path + "'."); } } @@ -5089,6 +5563,96 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> p_state) { return OK; } +void GLTFDocument::_parse_animation_pointer(Ref<GLTFState> p_state, const String &p_animation_json_pointer, const Ref<GLTFAnimation> p_gltf_animation, const GLTFAnimation::Interpolation p_interp, const Vector<double> &p_times, const int p_output_value_accessor_index) { + // Special case: Convert TRS animation pointers to node track pos/rot/scale. + // This is required to handle skeleton bones, and improves performance for regular nodes. + // Mark this as unlikely because TRS animation pointers are not recommended, + // since vanilla glTF animations can already animate TRS properties directly. + // But having this code exist is required to be spec-compliant and handle all test files. + // Note that TRS still needs to be handled in the general case as well, for KHR_interactivity. + const PackedStringArray split = p_animation_json_pointer.split("/", false, 3); + if (unlikely(split.size() == 3 && split[0] == "nodes" && (split[2] == "translation" || split[2] == "rotation" || split[2] == "scale" || split[2] == "matrix" || split[2] == "weights"))) { + const GLTFNodeIndex node_index = split[1].to_int(); + HashMap<int, GLTFAnimation::NodeTrack> &node_tracks = p_gltf_animation->get_node_tracks(); + if (!node_tracks.has(node_index)) { + node_tracks[node_index] = GLTFAnimation::NodeTrack(); + } + GLTFAnimation::NodeTrack *track = &node_tracks[node_index]; + if (split[2] == "translation") { + const Vector<Vector3> positions = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index, false); + track->position_track.interpolation = p_interp; + track->position_track.times = p_times; + track->position_track.values = positions; + } else if (split[2] == "rotation") { + const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(p_state, p_output_value_accessor_index, false); + track->rotation_track.interpolation = p_interp; + track->rotation_track.times = p_times; + track->rotation_track.values = rotations; + } else if (split[2] == "scale") { + const Vector<Vector3> scales = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index, false); + track->scale_track.interpolation = p_interp; + track->scale_track.times = p_times; + track->scale_track.values = scales; + } else if (split[2] == "matrix") { + const Vector<Transform3D> transforms = _decode_accessor_as_xform(p_state, p_output_value_accessor_index, false); + track->position_track.interpolation = p_interp; + track->position_track.times = p_times; + track->position_track.values.resize(transforms.size()); + track->rotation_track.interpolation = p_interp; + track->rotation_track.times = p_times; + track->rotation_track.values.resize(transforms.size()); + track->scale_track.interpolation = p_interp; + track->scale_track.times = p_times; + track->scale_track.values.resize(transforms.size()); + for (int i = 0; i < transforms.size(); i++) { + track->position_track.values.write[i] = transforms[i].get_origin(); + track->rotation_track.values.write[i] = transforms[i].basis.get_rotation_quaternion(); + track->scale_track.values.write[i] = transforms[i].basis.get_scale(); + } + } else { // if (split[2] == "weights") + const Vector<float> accessor_weights = _decode_accessor_as_floats(p_state, p_output_value_accessor_index, false); + const GLTFMeshIndex mesh_index = p_state->nodes[node_index]->mesh; + ERR_FAIL_INDEX(mesh_index, p_state->meshes.size()); + const Ref<GLTFMesh> gltf_mesh = p_state->meshes[mesh_index]; + const Vector<float> &blend_weights = gltf_mesh->get_blend_weights(); + const int blend_weight_count = gltf_mesh->get_blend_weights().size(); + const int anim_weights_size = accessor_weights.size(); + // For example, if a mesh has 2 blend weights, and the accessor provides 10 values, then there are 5 frames of animation, each with 2 blend weights. + ERR_FAIL_COND_MSG(blend_weight_count == 0 || ((anim_weights_size % blend_weight_count) != 0), "glTF: Cannot apply " + itos(accessor_weights.size()) + " weights to a mesh with " + itos(blend_weights.size()) + " blend weights."); + const int frame_count = anim_weights_size / blend_weight_count; + track->weight_tracks.resize(blend_weight_count); + for (int blend_weight_index = 0; blend_weight_index < blend_weight_count; blend_weight_index++) { + GLTFAnimation::Channel<real_t> weight_track; + weight_track.interpolation = p_interp; + weight_track.times = p_times; + weight_track.values.resize(frame_count); + for (int frame_index = 0; frame_index < frame_count; frame_index++) { + // For example, if a mesh has 2 blend weights, and the accessor provides 10 values, + // then the first frame has indices [0, 1], the second frame has [2, 3], and so on. + // Here we process all frames of one blend weight, so we want [0, 2, 4, 6, 8] or [1, 3, 5, 7, 9]. + // For the fist one we calculate 0 * 2 + 0, 1 * 2 + 0, 2 * 2 + 0, etc, then for the second 0 * 2 + 1, 1 * 2 + 1, 2 * 2 + 1, etc. + weight_track.values.write[frame_index] = accessor_weights[frame_index * blend_weight_count + blend_weight_index]; + } + track->weight_tracks.write[blend_weight_index] = weight_track; + } + } + // The special case was handled, return to skip the general case. + return; + } + // General case: Convert animation pointers to Variant value pointer tracks. + Ref<GLTFObjectModelProperty> obj_model_prop = import_object_model_property(p_state, p_animation_json_pointer); + if (obj_model_prop.is_null() || !obj_model_prop->has_node_paths()) { + // Exit quietly, `import_object_model_property` already prints a warning if the property is not found. + return; + } + HashMap<String, GLTFAnimation::Channel<Variant>> &anim_ptr_map = p_gltf_animation->get_pointer_tracks(); + GLTFAnimation::Channel<Variant> channel; + channel.interpolation = p_interp; + channel.times = p_times; + channel.values = _decode_accessor_as_variant(p_state, p_output_value_accessor_index, obj_model_prop->get_variant_type(), obj_model_prop->get_accessor_type()); + anim_ptr_map[p_animation_json_pointer] = channel; +} + void GLTFDocument::_assign_node_names(Ref<GLTFState> p_state) { for (int i = 0; i < p_state->nodes.size(); i++) { Ref<GLTFNode> gltf_node = p_state->nodes[i]; @@ -5254,46 +5818,46 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> p_state, Node *p_current, gltf_node->set_original_name(p_current->get_name()); gltf_node->set_name(_gen_unique_name(p_state, p_current->get_name())); gltf_node->merge_meta_from(p_current); - if (cast_to<Node3D>(p_current)) { - Node3D *spatial = cast_to<Node3D>(p_current); + if (Object::cast_to<Node3D>(p_current)) { + Node3D *spatial = Object::cast_to<Node3D>(p_current); _convert_spatial(p_state, spatial, gltf_node); } - if (cast_to<MeshInstance3D>(p_current)) { - MeshInstance3D *mi = cast_to<MeshInstance3D>(p_current); + if (Object::cast_to<MeshInstance3D>(p_current)) { + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_current); _convert_mesh_instance_to_gltf(mi, p_state, gltf_node); - } else if (cast_to<BoneAttachment3D>(p_current)) { - BoneAttachment3D *bone = cast_to<BoneAttachment3D>(p_current); + } else if (Object::cast_to<BoneAttachment3D>(p_current)) { + BoneAttachment3D *bone = Object::cast_to<BoneAttachment3D>(p_current); _convert_bone_attachment_to_gltf(bone, p_state, p_gltf_parent, p_gltf_root, gltf_node); return; - } else if (cast_to<Skeleton3D>(p_current)) { - Skeleton3D *skel = cast_to<Skeleton3D>(p_current); + } else if (Object::cast_to<Skeleton3D>(p_current)) { + Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_current); _convert_skeleton_to_gltf(skel, p_state, p_gltf_parent, p_gltf_root, gltf_node); // We ignore the Godot Engine node that is the skeleton. return; - } else if (cast_to<MultiMeshInstance3D>(p_current)) { - MultiMeshInstance3D *multi = cast_to<MultiMeshInstance3D>(p_current); + } else if (Object::cast_to<MultiMeshInstance3D>(p_current)) { + MultiMeshInstance3D *multi = Object::cast_to<MultiMeshInstance3D>(p_current); _convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, p_state); #ifdef MODULE_CSG_ENABLED - } else if (cast_to<CSGShape3D>(p_current)) { - CSGShape3D *shape = cast_to<CSGShape3D>(p_current); + } else if (Object::cast_to<CSGShape3D>(p_current)) { + CSGShape3D *shape = Object::cast_to<CSGShape3D>(p_current); if (shape->get_parent() && shape->is_root_shape()) { _convert_csg_shape_to_gltf(shape, p_gltf_parent, gltf_node, p_state); } #endif // MODULE_CSG_ENABLED #ifdef MODULE_GRIDMAP_ENABLED - } else if (cast_to<GridMap>(p_current)) { + } else if (Object::cast_to<GridMap>(p_current)) { GridMap *gridmap = Object::cast_to<GridMap>(p_current); _convert_grid_map_to_gltf(gridmap, p_gltf_parent, p_gltf_root, gltf_node, p_state); #endif // MODULE_GRIDMAP_ENABLED - } else if (cast_to<Camera3D>(p_current)) { + } else if (Object::cast_to<Camera3D>(p_current)) { Camera3D *camera = Object::cast_to<Camera3D>(p_current); _convert_camera_to_gltf(camera, p_state, gltf_node); - } else if (cast_to<Light3D>(p_current)) { + } else if (Object::cast_to<Light3D>(p_current)) { Light3D *light = Object::cast_to<Light3D>(p_current); _convert_light_to_gltf(light, p_state, gltf_node); - } else if (cast_to<AnimationPlayer>(p_current)) { + } else if (Object::cast_to<AnimationPlayer>(p_current)) { AnimationPlayer *animation_player = Object::cast_to<AnimationPlayer>(p_current); - _convert_animation_player_to_gltf(animation_player, p_state, p_gltf_parent, p_gltf_root, gltf_node, p_current); + p_state->animation_players.push_back(animation_player); } for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); @@ -5349,7 +5913,7 @@ void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeInd mat_name = mat->get_name(); } else { // Assign default material when no material is assigned. - mat = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + mat.instantiate(); } mesh->add_surface(csg_mesh->surface_get_primitive_type(surface_i), @@ -5371,12 +5935,6 @@ void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeInd } #endif // MODULE_CSG_ENABLED -void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *p_animation_player, Ref<GLTFState> p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) { - ERR_FAIL_NULL(p_animation_player); - p_state->animation_players.push_back(p_animation_player); - print_verbose(String("glTF: Converting animation player: ") + p_animation_player->get_name()); -} - void GLTFDocument::_check_visibility(Node *p_node, bool &r_retflag) { r_retflag = true; Node3D *spatial = Object::cast_to<Node3D>(p_node); @@ -5569,9 +6127,9 @@ void GLTFDocument::_convert_bone_attachment_to_gltf(BoneAttachment3D *p_bone_att Skeleton3D *skeleton; // Note that relative transforms to external skeletons and pose overrides are not supported. if (p_bone_attachment->get_use_external_skeleton()) { - skeleton = cast_to<Skeleton3D>(p_bone_attachment->get_node_or_null(p_bone_attachment->get_external_skeleton())); + skeleton = Object::cast_to<Skeleton3D>(p_bone_attachment->get_node_or_null(p_bone_attachment->get_external_skeleton())); } else { - skeleton = cast_to<Skeleton3D>(p_bone_attachment->get_parent()); + skeleton = Object::cast_to<Skeleton3D>(p_bone_attachment->get_parent()); } GLTFSkeletonIndex skel_gltf_i = -1; if (skeleton != nullptr && p_state->skeleton3d_to_gltf_skeleton.has(skeleton->get_instance_id())) { @@ -5854,7 +6412,7 @@ struct SceneFormatImporterGLTFInterpolate<Quaternion> { }; template <typename T> -T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) { +T GLTFDocument::_interpolate_track(const Vector<double> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) { ERR_FAIL_COND_V(p_values.is_empty(), T()); if (p_times.size() != (p_values.size() / (p_interp == GLTFAnimation::INTERP_CUBIC_SPLINE ? 3 : 1))) { ERR_PRINT_ONCE("The interpolated values are not corresponding to its times."); @@ -5925,8 +6483,433 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T ERR_FAIL_V(p_values[0]); } +NodePath GLTFDocument::_find_material_node_path(Ref<GLTFState> p_state, Ref<Material> p_material) { + int mesh_index = 0; + for (Ref<GLTFMesh> gltf_mesh : p_state->meshes) { + TypedArray<Material> materials = gltf_mesh->get_instance_materials(); + for (int mat_index = 0; mat_index < materials.size(); mat_index++) { + if (materials[mat_index] == p_material) { + for (Ref<GLTFNode> gltf_node : p_state->nodes) { + if (gltf_node->mesh == mesh_index) { + NodePath node_path = gltf_node->get_scene_node_path(p_state); + // Example: MyNode:mesh:surface_0/material:albedo_color, so we want the mesh:surface_0/material part. + Vector<StringName> subpath; + subpath.append("mesh"); + subpath.append("surface_" + itos(mat_index) + "/material"); + return NodePath(node_path.get_names(), subpath, false); + } + } + } + } + mesh_index++; + } + return NodePath(); +} + +Ref<GLTFObjectModelProperty> GLTFDocument::import_object_model_property(Ref<GLTFState> p_state, const String &p_json_pointer) { + if (p_state->object_model_properties.has(p_json_pointer)) { + return p_state->object_model_properties[p_json_pointer]; + } + Ref<GLTFObjectModelProperty> ret; + // Split the JSON pointer into its components. + const PackedStringArray split = p_json_pointer.split("/", false); + ERR_FAIL_COND_V_MSG(split.size() < 3, ret, "glTF: Cannot use JSON pointer '" + p_json_pointer + "' because it does not contain enough elements. The only animatable properties are at least 3 levels deep (ex: '/nodes/0/translation' or '/materials/0/emissiveFactor')."); + ret.instantiate(); + ret->set_json_pointers({ split }); + // Partial paths are passed to GLTFDocumentExtension classes if GLTFDocument cannot handle a given JSON pointer. + TypedArray<NodePath> partial_paths; + // Note: This might not be an integer, but in that case, we don't use this value anyway. + const int top_level_index = split[1].to_int(); + // For JSON pointers present in the core glTF Object Model, hard-code them in GLTFDocument. + // https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/ObjectModel.adoc + if (split[0] == "nodes") { + ERR_FAIL_INDEX_V_MSG(top_level_index, p_state->nodes.size(), ret, vformat("glTF: Unable to find node %d for JSON pointer '%s'.", top_level_index, p_json_pointer)); + Ref<GLTFNode> pointed_gltf_node = p_state->nodes[top_level_index]; + NodePath node_path = pointed_gltf_node->get_scene_node_path(p_state); + partial_paths.append(node_path); + // Check if it's something we should be able to handle. + const String &node_prop = split[2]; + if (node_prop == "translation") { + ret->append_path_to_property(node_path, "position"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (node_prop == "rotation") { + ret->append_path_to_property(node_path, "quaternion"); + ret->set_types(Variant::QUATERNION, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4); + } else if (node_prop == "scale") { + ret->append_path_to_property(node_path, "scale"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (node_prop == "matrix") { + ret->append_path_to_property(node_path, "transform"); + ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4); + } else if (node_prop == "globalMatrix") { + ret->append_path_to_property(node_path, "global_transform"); + ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4); + } else if (node_prop == "weights") { + if (split.size() > 3) { + const String &weight_index_string = split[3]; + ret->append_path_to_property(node_path, "blend_shapes/morph_" + weight_index_string); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } + // Else, Godot's MeshInstance3D does not expose the blend shape weights as one property. + // But that's fine, we handle this case in _parse_animation_pointer instead. + } + } else if (split[0] == "cameras") { + const String &camera_prop = split[2]; + for (Ref<GLTFNode> gltf_node : p_state->nodes) { + if (gltf_node->camera == top_level_index) { + NodePath node_path = gltf_node->get_scene_node_path(p_state); + partial_paths.append(node_path); + // Check if it's something we should be able to handle. + if (camera_prop == "orthographic" || camera_prop == "perspective") { + ERR_FAIL_COND_V(split.size() < 4, ret); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + const String &sub_prop = split[3]; + if (sub_prop == "xmag" || sub_prop == "ymag") { + ret->append_path_to_property(node_path, "size"); + } else if (sub_prop == "yfov") { + ret->append_path_to_property(node_path, "fov"); + GLTFCamera::set_fov_conversion_expressions(ret); + } else if (sub_prop == "zfar") { + ret->append_path_to_property(node_path, "far"); + } else if (sub_prop == "znear") { + ret->append_path_to_property(node_path, "near"); + } + } + } + } + } else if (split[0] == "materials") { + ERR_FAIL_INDEX_V_MSG(top_level_index, p_state->materials.size(), ret, vformat("glTF: Unable to find material %d for JSON pointer '%s'.", top_level_index, p_json_pointer)); + Ref<Material> pointed_material = p_state->materials[top_level_index]; + NodePath mat_path = _find_material_node_path(p_state, pointed_material); + if (mat_path.is_empty()) { + WARN_PRINT(vformat("glTF: Unable to find a path to the material %d for JSON pointer '%s'. This is likely bad data but it's also possible this is intentional. Continuing anyway.", top_level_index, p_json_pointer)); + } else { + partial_paths.append(mat_path); + const String &mat_prop = split[2]; + if (mat_prop == "alphaCutoff") { + ret->append_path_to_property(mat_path, "alpha_scissor_threshold"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (mat_prop == "emissiveFactor") { + ret->append_path_to_property(mat_path, "emission"); + ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (mat_prop == "extensions") { + ERR_FAIL_COND_V(split.size() < 5, ret); + const String &ext_name = split[3]; + const String &ext_prop = split[4]; + if (ext_name == "KHR_materials_emissive_strength" && ext_prop == "emissiveStrength") { + ret->append_path_to_property(mat_path, "emission_energy_multiplier"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } + } else { + ERR_FAIL_COND_V(split.size() < 4, ret); + const String &sub_prop = split[3]; + if (mat_prop == "normalTexture") { + if (sub_prop == "scale") { + ret->append_path_to_property(mat_path, "normal_scale"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } + } else if (mat_prop == "occlusionTexture") { + if (sub_prop == "strength") { + // This is the closest thing Godot has to an occlusion strength property. + ret->append_path_to_property(mat_path, "ao_light_affect"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } + } else if (mat_prop == "pbrMetallicRoughness") { + if (sub_prop == "baseColorFactor") { + ret->append_path_to_property(mat_path, "albedo_color"); + ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4); + } else if (sub_prop == "metallicFactor") { + ret->append_path_to_property(mat_path, "metallic"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (sub_prop == "roughnessFactor") { + ret->append_path_to_property(mat_path, "roughness"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (sub_prop == "baseColorTexture") { + ERR_FAIL_COND_V(split.size() < 6, ret); + const String &tex_ext_dict = split[4]; + const String &tex_ext_name = split[5]; + const String &tex_ext_prop = split[6]; + if (tex_ext_dict == "extensions" && tex_ext_name == "KHR_texture_transform") { + // Godot only supports UVs for the whole material, not per texture. + // We treat the albedo texture as the main texture, and import as UV1. + // Godot does not support texture rotation, only offset and scale. + if (tex_ext_prop == "offset") { + ret->append_path_to_property(mat_path, "uv1_offset"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT2); + } else if (tex_ext_prop == "scale") { + ret->append_path_to_property(mat_path, "uv1_scale"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT2); + } + } + } + } + } + } + } else if (split[0] == "meshes") { + for (Ref<GLTFNode> gltf_node : p_state->nodes) { + if (gltf_node->mesh == top_level_index) { + NodePath node_path = gltf_node->get_scene_node_path(p_state); + Vector<StringName> subpath; + subpath.append("mesh"); + partial_paths.append(NodePath(node_path.get_names(), subpath, false)); + break; + } + } + } else if (split[0] == "extensions") { + if (split[1] == "KHR_lights_punctual" && split[2] == "lights" && split.size() > 4) { + const int light_index = split[3].to_int(); + ERR_FAIL_INDEX_V_MSG(light_index, p_state->lights.size(), ret, vformat("glTF: Unable to find light %d for JSON pointer '%s'.", light_index, p_json_pointer)); + const String &light_prop = split[4]; + const Ref<GLTFLight> pointed_light = p_state->lights[light_index]; + for (Ref<GLTFNode> gltf_node : p_state->nodes) { + if (gltf_node->light == light_index) { + NodePath node_path = gltf_node->get_scene_node_path(p_state); + partial_paths.append(node_path); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + // Check if it's something we should be able to handle. + if (light_prop == "color") { + ret->append_path_to_property(node_path, "light_color"); + ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (light_prop == "intensity") { + ret->append_path_to_property(node_path, "light_energy"); + } else if (light_prop == "range") { + const String &light_type = p_state->lights[light_index]->light_type; + if (light_type == "spot") { + ret->append_path_to_property(node_path, "spot_range"); + } else { + ret->append_path_to_property(node_path, "omni_range"); + } + } else if (light_prop == "spot") { + ERR_FAIL_COND_V(split.size() < 6, ret); + const String &sub_prop = split[5]; + if (sub_prop == "innerConeAngle") { + ret->append_path_to_property(node_path, "spot_angle_attenuation"); + GLTFLight::set_cone_inner_attenuation_conversion_expressions(ret); + } else if (sub_prop == "outerConeAngle") { + ret->append_path_to_property(node_path, "spot_angle"); + } + } + } + } + } + } + // Additional JSON pointers can be added by GLTFDocumentExtension classes. + // We only need this if no mapping has been found yet from GLTFDocument's internal code. + // When available, we pass the partial paths to the extension to help it generate the full path. + // For example, for `/nodes/3/extensions/MY_ext/prop`, we pass a NodePath that leads to node 3, + // so the GLTFDocumentExtension class only needs to resolve the last `MY_ext/prop` part of the path. + // It should check `split.size() > 4 and split[0] == "nodes" and split[2] == "extensions" and split[3] == "MY_ext"` + // at the start of the function to check if this JSON pointer applies to it, then it can handle `split[4]`. + if (!ret->has_node_paths()) { + for (Ref<GLTFDocumentExtension> ext : all_document_extensions) { + ret = ext->import_object_model_property(p_state, split, partial_paths); + if (ret.is_valid() && ret->has_node_paths()) { + if (!ret->has_json_pointers()) { + ret->set_json_pointers({ split }); + } + break; + } + } + if (ret.is_null() || !ret->has_node_paths()) { + if (split.has("KHR_texture_transform")) { + WARN_VERBOSE(vformat("glTF: Texture transforms are only supported per material in Godot. All KHR_texture_transform properties will be ignored except for the albedo texture. Ignoring JSON pointer '%s'.", p_json_pointer)); + } else { + WARN_PRINT(vformat("glTF: Animation contained JSON pointer '%s' which could not be resolved. This property will not be animated.", p_json_pointer)); + } + } + } + p_state->object_model_properties[p_json_pointer] = ret; + return ret; +} + +Ref<GLTFObjectModelProperty> GLTFDocument::export_object_model_property(Ref<GLTFState> p_state, const NodePath &p_node_path, const Node *p_godot_node, GLTFNodeIndex p_gltf_node_index) { + Ref<GLTFObjectModelProperty> ret; + const Object *target_object = p_godot_node; + const Vector<StringName> subpath = p_node_path.get_subnames(); + ERR_FAIL_COND_V_MSG(subpath.is_empty(), ret, "glTF: Cannot export empty property. No property was specified in the NodePath: " + p_node_path); + int target_prop_depth = 0; + for (StringName subname : subpath) { + Variant target_property = target_object->get(subname); + if (target_property.get_type() == Variant::OBJECT) { + target_object = target_property; + if (target_object) { + target_prop_depth++; + continue; + } + } + break; + } + const String &target_prop = subpath[target_prop_depth]; + ret.instantiate(); + ret->set_node_paths({ p_node_path }); + Vector<PackedStringArray> split_json_pointers; + PackedStringArray split_json_pointer; + if (Object::cast_to<BaseMaterial3D>(target_object)) { + for (int i = 0; i < p_state->materials.size(); i++) { + if (p_state->materials[i].ptr() == target_object) { + split_json_pointer.append("materials"); + split_json_pointer.append(itos(i)); + if (target_prop == "alpha_scissor_threshold") { + split_json_pointer.append("alphaCutoff"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (target_prop == "emission") { + split_json_pointer.append("emissiveFactor"); + ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (target_prop == "emission_energy_multiplier") { + split_json_pointer.append("extensions"); + split_json_pointer.append("KHR_materials_emissive_strength"); + split_json_pointer.append("emissiveStrength"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (target_prop == "normal_scale") { + split_json_pointer.append("normalTexture"); + split_json_pointer.append("scale"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (target_prop == "ao_light_affect") { + split_json_pointer.append("occlusionTexture"); + split_json_pointer.append("strength"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (target_prop == "albedo_color") { + split_json_pointer.append("pbrMetallicRoughness"); + split_json_pointer.append("baseColorFactor"); + ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4); + } else if (target_prop == "metallic") { + split_json_pointer.append("pbrMetallicRoughness"); + split_json_pointer.append("metallicFactor"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (target_prop == "roughness") { + split_json_pointer.append("pbrMetallicRoughness"); + split_json_pointer.append("roughnessFactor"); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + } else if (target_prop == "uv1_offset" || target_prop == "uv1_scale") { + split_json_pointer.append("pbrMetallicRoughness"); + split_json_pointer.append("baseColorTexture"); + split_json_pointer.append("extensions"); + split_json_pointer.append("KHR_texture_transform"); + if (target_prop == "uv1_offset") { + split_json_pointer.append("offset"); + } else { + split_json_pointer.append("scale"); + } + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT2); + } else { + split_json_pointer.clear(); + } + break; + } + } + } else { + // Properties directly on Godot nodes. + Ref<GLTFNode> gltf_node = p_state->nodes[p_gltf_node_index]; + if (Object::cast_to<Camera3D>(target_object) && gltf_node->camera >= 0) { + split_json_pointer.append("cameras"); + split_json_pointer.append(itos(gltf_node->camera)); + const Camera3D *camera_node = Object::cast_to<Camera3D>(target_object); + const Camera3D::ProjectionType projection_type = camera_node->get_projection(); + if (projection_type == Camera3D::PROJECTION_PERSPECTIVE) { + split_json_pointer.append("perspective"); + } else { + split_json_pointer.append("orthographic"); + } + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + if (target_prop == "size") { + PackedStringArray xmag = split_json_pointer.duplicate(); + xmag.append("xmag"); + split_json_pointers.append(xmag); + split_json_pointer.append("ymag"); + } else if (target_prop == "fov") { + split_json_pointer.append("yfov"); + GLTFCamera::set_fov_conversion_expressions(ret); + } else if (target_prop == "far") { + split_json_pointer.append("zfar"); + } else if (target_prop == "near") { + split_json_pointer.append("znear"); + } else { + split_json_pointer.clear(); + } + } else if (Object::cast_to<Light3D>(target_object) && gltf_node->light >= 0) { + split_json_pointer.append("extensions"); + split_json_pointer.append("KHR_lights_punctual"); + split_json_pointer.append("lights"); + split_json_pointer.append(itos(gltf_node->light)); + ret->set_types(Variant::FLOAT, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT); + if (target_prop == "light_color") { + split_json_pointer.append("color"); + ret->set_types(Variant::COLOR, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (target_prop == "light_energy") { + split_json_pointer.append("intensity"); + } else if (target_prop == "spot_range") { + split_json_pointer.append("range"); + } else if (target_prop == "omni_range") { + split_json_pointer.append("range"); + } else if (target_prop == "spot_angle") { + split_json_pointer.append("spot"); + split_json_pointer.append("outerConeAngle"); + } else if (target_prop == "spot_angle_attenuation") { + split_json_pointer.append("spot"); + split_json_pointer.append("innerConeAngle"); + GLTFLight::set_cone_inner_attenuation_conversion_expressions(ret); + } else { + split_json_pointer.clear(); + } + } else if (Object::cast_to<MeshInstance3D>(target_object) && target_prop.begins_with("blend_shapes/morph_")) { + const String &weight_index_string = target_prop.trim_prefix("blend_shapes/morph_"); + split_json_pointer.append("nodes"); + split_json_pointer.append(itos(p_gltf_node_index)); + split_json_pointer.append("weights"); + split_json_pointer.append(weight_index_string); + } + // Transform properties. Check for all 3D nodes if we haven't resolved the JSON pointer yet. + // Note: Do not put this in an `else`, because otherwise this will not be reached. + if (split_json_pointer.is_empty() && Object::cast_to<Node3D>(target_object)) { + split_json_pointer.append("nodes"); + split_json_pointer.append(itos(p_gltf_node_index)); + if (target_prop == "position") { + split_json_pointer.append("translation"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (target_prop == "quaternion") { + // Note: Only Quaternion rotation can be converted from Godot in this mapping. + // Struct methods like from_euler are not accessible from the Expression class. :( + split_json_pointer.append("rotation"); + ret->set_types(Variant::QUATERNION, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4); + } else if (target_prop == "scale") { + split_json_pointer.append("scale"); + ret->set_types(Variant::VECTOR3, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT3); + } else if (target_prop == "transform") { + split_json_pointer.append("matrix"); + ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4); + } else if (target_prop == "global_transform") { + split_json_pointer.append("globalMatrix"); + ret->set_types(Variant::TRANSFORM3D, GLTFObjectModelProperty::GLTF_OBJECT_MODEL_TYPE_FLOAT4X4); + } else { + split_json_pointer.clear(); + } + } + } + // Additional JSON pointers can be added by GLTFDocumentExtension classes. + // We only need this if no mapping has been found yet from GLTFDocument's internal code. + // We pass as many pieces of information as we can to the extension to give it lots of context. + if (split_json_pointer.is_empty()) { + for (Ref<GLTFDocumentExtension> ext : all_document_extensions) { + ret = ext->export_object_model_property(p_state, p_node_path, p_godot_node, p_gltf_node_index, target_object, target_prop_depth); + if (ret.is_valid() && ret->has_json_pointers()) { + if (!ret->has_node_paths()) { + ret->set_node_paths({ p_node_path }); + } + break; + } + } + } else { + // GLTFDocument's internal code found a mapping, so set it and return it. + split_json_pointers.append(split_json_pointer); + ret->set_json_pointers(split_json_pointers); + } + return ret; +} + void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const bool p_trimming, const bool p_remove_immutable_tracks) { ERR_FAIL_COND(p_state.is_null()); + Node *scene_root = p_animation_player->get_parent(); + ERR_FAIL_NULL(scene_root); Ref<GLTFAnimation> anim = p_state->animations[p_index]; String anim_name = anim->get_name(); @@ -5947,8 +6930,8 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_ double anim_start = p_trimming ? INFINITY : 0.0; double anim_end = 0.0; - for (const KeyValue<int, GLTFAnimation::Track> &track_i : anim->get_tracks()) { - const GLTFAnimation::Track &track = track_i.value; + for (const KeyValue<int, GLTFAnimation::NodeTrack> &track_i : anim->get_node_tracks()) { + const GLTFAnimation::NodeTrack &track = track_i.value; //need to find the path: for skeletons, weight tracks will affect the mesh NodePath node_path; //for skeletons, transform tracks always affect bones @@ -5960,14 +6943,12 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_ const Ref<GLTFNode> gltf_node = p_state->nodes[track_i.key]; - Node *root = p_animation_player->get_parent(); - ERR_FAIL_NULL(root); HashMap<GLTFNodeIndex, Node *>::Iterator node_element = p_state->scene_nodes.find(node_index); ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation.", node_index)); - node_path = root->get_path_to(node_element->value); + node_path = scene_root->get_path_to(node_element->value); HashMap<GLTFNodeIndex, ImporterMeshInstance3D *>::Iterator mesh_instance_element = p_state->scene_mesh_instances.find(node_index); if (mesh_instance_element) { - mesh_instance_node_path = root->get_path_to(mesh_instance_element->value); + mesh_instance_node_path = scene_root->get_path_to(mesh_instance_element->value); } else { mesh_instance_node_path = node_path; } @@ -6201,6 +7182,56 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_ } } + for (const KeyValue<String, GLTFAnimation::Channel<Variant>> &track_iter : anim->get_pointer_tracks()) { + // Determine the property to animate. + const String json_pointer = track_iter.key; + const Ref<GLTFObjectModelProperty> prop = import_object_model_property(p_state, json_pointer); + ERR_FAIL_COND(prop.is_null()); + // Adjust the animation duration to encompass all keyframes. + const GLTFAnimation::Channel<Variant> &channel = track_iter.value; + ERR_CONTINUE_MSG(channel.times.size() != channel.values.size(), vformat("glTF: Animation pointer '%s' has mismatched keyframe times and values.", json_pointer)); + if (p_trimming) { + for (int i = 0; i < channel.times.size(); i++) { + anim_start = MIN(anim_start, channel.times[i]); + anim_end = MAX(anim_end, channel.times[i]); + } + } else { + for (int i = 0; i < channel.times.size(); i++) { + anim_end = MAX(anim_end, channel.times[i]); + } + } + // Begin converting the glTF animation to a Godot animation. + const Ref<Expression> gltf_to_godot_expr = prop->get_gltf_to_godot_expression(); + const bool is_gltf_to_godot_expr_valid = gltf_to_godot_expr.is_valid(); + for (const NodePath node_path : prop->get_node_paths()) { + // If using an expression, determine the base instance to pass to the expression. + Object *base_instance = nullptr; + if (is_gltf_to_godot_expr_valid) { + Ref<Resource> resource; + Vector<StringName> leftover_subpath; + base_instance = scene_root->get_node_and_resource(node_path, resource, leftover_subpath); + if (resource.is_valid()) { + base_instance = resource.ptr(); + } + } + // Add a track and insert all keys and values. + const int track_index = animation->get_track_count(); + animation->add_track(Animation::TYPE_VALUE); + animation->track_set_interpolation_type(track_index, GLTFAnimation::gltf_to_godot_interpolation(channel.interpolation)); + animation->track_set_path(track_index, node_path); + for (int i = 0; i < channel.times.size(); i++) { + const double time = channel.times[i]; + Variant value = channel.values[i]; + if (is_gltf_to_godot_expr_valid) { + Array inputs; + inputs.append(value); + value = gltf_to_godot_expr->execute(inputs, base_instance); + } + animation->track_insert_key(track_index, time, value); + } + } + } + animation->set_length(anim_end - anim_start); Ref<AnimationLibrary> library; @@ -6371,41 +7402,56 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> p_state, Node *p_scene } } -GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, int32_t p_track_i, GLTFNodeIndex p_node_i) { - Animation::InterpolationType interpolation = p_animation->track_get_interpolation_type(p_track_i); - - GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - if (interpolation == Animation::InterpolationType::INTERPOLATION_LINEAR) { - gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - } else if (interpolation == Animation::InterpolationType::INTERPOLATION_NEAREST) { - gltf_interpolation = GLTFAnimation::INTERP_STEP; - } else if (interpolation == Animation::InterpolationType::INTERPOLATION_CUBIC) { - gltf_interpolation = GLTFAnimation::INTERP_CUBIC_SPLINE; +GLTFNodeIndex GLTFDocument::_node_and_or_bone_to_gltf_node_index(Ref<GLTFState> p_state, const Vector<StringName> &p_node_subpath, const Node *p_godot_node) { + const Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_godot_node); + if (skeleton && p_node_subpath.size() == 1) { + // Special case: Handle skeleton bone TRS tracks. They use the format `A/B/C/Skeleton3D:bone_name`. + // We have a Skeleton3D, check if it has a bone with the same name as this subpath. + const String &bone_name = p_node_subpath[0]; + const int32_t bone_index = skeleton->find_bone(bone_name); + if (bone_index != -1) { + // A bone was found! But we still need to figure out which glTF node it corresponds to. + for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < p_state->skeletons.size(); skeleton_i++) { + const Ref<GLTFSkeleton> &skeleton_gltf = p_state->skeletons[skeleton_i]; + if (skeleton == skeleton_gltf->godot_skeleton) { + GLTFNodeIndex node_i = skeleton_gltf->godot_bone_node[bone_index]; + return node_i; + } + } + ERR_FAIL_V_MSG(-1, vformat("glTF: Found a bone %s in a Skeleton3D that wasn't in the GLTFState. Ensure that all nodes referenced by the AnimationPlayer are in the scene you are exporting.", bone_name)); + } } - Animation::TrackType track_type = p_animation->track_get_type(p_track_i); - int32_t key_count = p_animation->track_get_key_count(p_track_i); - Vector<real_t> times; - times.resize(key_count); - String path = p_animation->track_get_path(p_track_i); - for (int32_t key_i = 0; key_i < key_count; key_i++) { - times.write[key_i] = p_animation->track_get_key_time(p_track_i, key_i); + // General case: Not a skeleton bone, usually this means a normal node, or it could be the Skeleton3D itself. + for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : p_state->scene_nodes) { + if (scene_node_i.value == p_godot_node) { + return scene_node_i.key; + } } - double anim_end = p_animation->get_length(); + ERR_FAIL_V_MSG(-1, vformat("glTF: A node was animated, but it wasn't found in the GLTFState. Ensure that all nodes referenced by the AnimationPlayer are in the scene you are exporting.")); +} + +bool GLTFDocument::_convert_animation_node_track(Ref<GLTFState> p_state, GLTFAnimation::NodeTrack &p_gltf_node_track, const Ref<Animation> &p_godot_animation, int32_t p_godot_anim_track_index, Vector<double> &p_times) { + GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::godot_to_gltf_interpolation(p_godot_animation, p_godot_anim_track_index); + const Animation::TrackType track_type = p_godot_animation->track_get_type(p_godot_anim_track_index); + const int32_t key_count = p_godot_animation->track_get_key_count(p_godot_anim_track_index); + const NodePath node_path = p_godot_animation->track_get_path(p_godot_anim_track_index); + const Vector<StringName> subpath = node_path.get_subnames(); + double anim_end = p_godot_animation->get_length(); if (track_type == Animation::TYPE_SCALE_3D) { if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - p_track.scale_track.times.clear(); - p_track.scale_track.values.clear(); + p_gltf_node_track.scale_track.times.clear(); + p_gltf_node_track.scale_track.values.clear(); // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. const double increment = 1.0 / p_state->get_bake_fps(); double time = 0.0; bool last = false; while (true) { Vector3 scale; - Error err = p_animation->try_scale_track_interpolate(p_track_i, time, &scale); + Error err = p_godot_animation->try_scale_track_interpolate(p_godot_anim_track_index, time, &scale); ERR_CONTINUE(err != OK); - p_track.scale_track.values.push_back(scale); - p_track.scale_track.times.push_back(time); + p_gltf_node_track.scale_track.values.push_back(scale); + p_gltf_node_track.scale_track.times.push_back(time); if (last) { break; } @@ -6416,31 +7462,31 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta } } } else { - p_track.scale_track.times = times; - p_track.scale_track.interpolation = gltf_interpolation; - p_track.scale_track.values.resize(key_count); + p_gltf_node_track.scale_track.times = p_times; + p_gltf_node_track.scale_track.interpolation = gltf_interpolation; + p_gltf_node_track.scale_track.values.resize(key_count); for (int32_t key_i = 0; key_i < key_count; key_i++) { Vector3 scale; - Error err = p_animation->scale_track_get_key(p_track_i, key_i, &scale); + Error err = p_godot_animation->scale_track_get_key(p_godot_anim_track_index, key_i, &scale); ERR_CONTINUE(err != OK); - p_track.scale_track.values.write[key_i] = scale; + p_gltf_node_track.scale_track.values.write[key_i] = scale; } } } else if (track_type == Animation::TYPE_POSITION_3D) { if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - p_track.position_track.times.clear(); - p_track.position_track.values.clear(); + p_gltf_node_track.position_track.times.clear(); + p_gltf_node_track.position_track.values.clear(); // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. const double increment = 1.0 / p_state->get_bake_fps(); double time = 0.0; bool last = false; while (true) { Vector3 scale; - Error err = p_animation->try_position_track_interpolate(p_track_i, time, &scale); + Error err = p_godot_animation->try_position_track_interpolate(p_godot_anim_track_index, time, &scale); ERR_CONTINUE(err != OK); - p_track.position_track.values.push_back(scale); - p_track.position_track.times.push_back(time); + p_gltf_node_track.position_track.values.push_back(scale); + p_gltf_node_track.position_track.times.push_back(time); if (last) { break; } @@ -6451,31 +7497,31 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta } } } else { - p_track.position_track.times = times; - p_track.position_track.values.resize(key_count); - p_track.position_track.interpolation = gltf_interpolation; + p_gltf_node_track.position_track.times = p_times; + p_gltf_node_track.position_track.values.resize(key_count); + p_gltf_node_track.position_track.interpolation = gltf_interpolation; for (int32_t key_i = 0; key_i < key_count; key_i++) { Vector3 position; - Error err = p_animation->position_track_get_key(p_track_i, key_i, &position); + Error err = p_godot_animation->position_track_get_key(p_godot_anim_track_index, key_i, &position); ERR_CONTINUE(err != OK); - p_track.position_track.values.write[key_i] = position; + p_gltf_node_track.position_track.values.write[key_i] = position; } } } else if (track_type == Animation::TYPE_ROTATION_3D) { if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - p_track.rotation_track.times.clear(); - p_track.rotation_track.values.clear(); + p_gltf_node_track.rotation_track.times.clear(); + p_gltf_node_track.rotation_track.values.clear(); // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. const double increment = 1.0 / p_state->get_bake_fps(); double time = 0.0; bool last = false; while (true) { Quaternion rotation; - Error err = p_animation->try_rotation_track_interpolate(p_track_i, time, &rotation); + Error err = p_godot_animation->try_rotation_track_interpolate(p_godot_anim_track_index, time, &rotation); ERR_CONTINUE(err != OK); - p_track.rotation_track.values.push_back(rotation); - p_track.rotation_track.times.push_back(time); + p_gltf_node_track.rotation_track.values.push_back(rotation); + p_gltf_node_track.rotation_track.times.push_back(time); if (last) { break; } @@ -6486,306 +7532,326 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta } } } else { - p_track.rotation_track.times = times; - p_track.rotation_track.values.resize(key_count); - p_track.rotation_track.interpolation = gltf_interpolation; + p_gltf_node_track.rotation_track.times = p_times; + p_gltf_node_track.rotation_track.values.resize(key_count); + p_gltf_node_track.rotation_track.interpolation = gltf_interpolation; for (int32_t key_i = 0; key_i < key_count; key_i++) { Quaternion rotation; - Error err = p_animation->rotation_track_get_key(p_track_i, key_i, &rotation); + Error err = p_godot_animation->rotation_track_get_key(p_godot_anim_track_index, key_i, &rotation); ERR_CONTINUE(err != OK); - p_track.rotation_track.values.write[key_i] = rotation; - } - } - } else if (track_type == Animation::TYPE_VALUE) { - if (path.contains(":position")) { - p_track.position_track.interpolation = gltf_interpolation; - p_track.position_track.times = times; - p_track.position_track.values.resize(key_count); - - if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { - gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - p_track.position_track.times.clear(); - p_track.position_track.values.clear(); - // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. - const double increment = 1.0 / p_state->get_bake_fps(); - double time = 0.0; - bool last = false; - while (true) { - Vector3 position; - Error err = p_animation->try_position_track_interpolate(p_track_i, time, &position); - ERR_CONTINUE(err != OK); - p_track.position_track.values.push_back(position); - p_track.position_track.times.push_back(time); - if (last) { - break; + p_gltf_node_track.rotation_track.values.write[key_i] = rotation; + } + } + } else if (subpath.size() > 0) { + const StringName &node_prop = subpath[0]; + if (track_type == Animation::TYPE_VALUE) { + if (node_prop == "position") { + p_gltf_node_track.position_track.interpolation = gltf_interpolation; + p_gltf_node_track.position_track.times = p_times; + p_gltf_node_track.position_track.values.resize(key_count); + + if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { + gltf_interpolation = GLTFAnimation::INTERP_LINEAR; + p_gltf_node_track.position_track.times.clear(); + p_gltf_node_track.position_track.values.clear(); + // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. + const double increment = 1.0 / p_state->get_bake_fps(); + double time = 0.0; + bool last = false; + while (true) { + Vector3 position; + Error err = p_godot_animation->try_position_track_interpolate(p_godot_anim_track_index, time, &position); + ERR_CONTINUE(err != OK); + p_gltf_node_track.position_track.values.push_back(position); + p_gltf_node_track.position_track.times.push_back(time); + if (last) { + break; + } + time += increment; + if (time >= anim_end) { + last = true; + time = anim_end; + } } - time += increment; - if (time >= anim_end) { - last = true; - time = anim_end; + } else { + for (int32_t key_i = 0; key_i < key_count; key_i++) { + Vector3 position = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i); + p_gltf_node_track.position_track.values.write[key_i] = position; } } - } else { - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 position = p_animation->track_get_key_value(p_track_i, key_i); - p_track.position_track.values.write[key_i] = position; - } - } - } else if (path.contains(":rotation")) { - p_track.rotation_track.interpolation = gltf_interpolation; - p_track.rotation_track.times = times; - p_track.rotation_track.values.resize(key_count); - if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { - gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - p_track.rotation_track.times.clear(); - p_track.rotation_track.values.clear(); - // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. - const double increment = 1.0 / p_state->get_bake_fps(); - double time = 0.0; - bool last = false; - while (true) { - Quaternion rotation; - Error err = p_animation->try_rotation_track_interpolate(p_track_i, time, &rotation); - ERR_CONTINUE(err != OK); - p_track.rotation_track.values.push_back(rotation); - p_track.rotation_track.times.push_back(time); - if (last) { - break; + } else if (node_prop == "rotation" || node_prop == "rotation_degrees" || node_prop == "quaternion") { + p_gltf_node_track.rotation_track.interpolation = gltf_interpolation; + p_gltf_node_track.rotation_track.times = p_times; + p_gltf_node_track.rotation_track.values.resize(key_count); + if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { + gltf_interpolation = GLTFAnimation::INTERP_LINEAR; + p_gltf_node_track.rotation_track.times.clear(); + p_gltf_node_track.rotation_track.values.clear(); + // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. + const double increment = 1.0 / p_state->get_bake_fps(); + double time = 0.0; + bool last = false; + while (true) { + Quaternion rotation; + Error err = p_godot_animation->try_rotation_track_interpolate(p_godot_anim_track_index, time, &rotation); + ERR_CONTINUE(err != OK); + p_gltf_node_track.rotation_track.values.push_back(rotation); + p_gltf_node_track.rotation_track.times.push_back(time); + if (last) { + break; + } + time += increment; + if (time >= anim_end) { + last = true; + time = anim_end; + } } - time += increment; - if (time >= anim_end) { - last = true; - time = anim_end; + } else { + for (int32_t key_i = 0; key_i < key_count; key_i++) { + Quaternion rotation_quaternion; + if (node_prop == "quaternion") { + rotation_quaternion = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i); + } else { + Vector3 rotation_euler = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i); + if (node_prop == "rotation_degrees") { + rotation_euler *= Math_TAU / 360.0; + } + rotation_quaternion = Quaternion::from_euler(rotation_euler); + } + p_gltf_node_track.rotation_track.values.write[key_i] = rotation_quaternion; } } - } else { - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i); - p_track.rotation_track.values.write[key_i] = Quaternion::from_euler(rotation_radian); + } else if (node_prop == "scale") { + p_gltf_node_track.scale_track.interpolation = gltf_interpolation; + p_gltf_node_track.scale_track.times = p_times; + p_gltf_node_track.scale_track.values.resize(key_count); + + if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { + gltf_interpolation = GLTFAnimation::INTERP_LINEAR; + p_gltf_node_track.scale_track.times.clear(); + p_gltf_node_track.scale_track.values.clear(); + // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. + const double increment = 1.0 / p_state->get_bake_fps(); + double time = 0.0; + bool last = false; + while (true) { + Vector3 scale; + Error err = p_godot_animation->try_scale_track_interpolate(p_godot_anim_track_index, time, &scale); + ERR_CONTINUE(err != OK); + p_gltf_node_track.scale_track.values.push_back(scale); + p_gltf_node_track.scale_track.times.push_back(time); + if (last) { + break; + } + time += increment; + if (time >= anim_end) { + last = true; + time = anim_end; + } + } + } else { + for (int32_t key_i = 0; key_i < key_count; key_i++) { + Vector3 scale_track = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i); + p_gltf_node_track.scale_track.values.write[key_i] = scale_track; + } } - } - } else if (path.contains(":scale")) { - p_track.scale_track.times = times; - p_track.scale_track.interpolation = gltf_interpolation; - - p_track.scale_track.values.resize(key_count); - p_track.scale_track.interpolation = gltf_interpolation; - - if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { - gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - p_track.scale_track.times.clear(); - p_track.scale_track.values.clear(); - // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. - const double increment = 1.0 / p_state->get_bake_fps(); - double time = 0.0; - bool last = false; - while (true) { - Vector3 scale; - Error err = p_animation->try_scale_track_interpolate(p_track_i, time, &scale); - ERR_CONTINUE(err != OK); - p_track.scale_track.values.push_back(scale); - p_track.scale_track.times.push_back(time); - if (last) { - break; + } else if (node_prop == "transform") { + p_gltf_node_track.position_track.interpolation = gltf_interpolation; + p_gltf_node_track.position_track.times = p_times; + p_gltf_node_track.position_track.values.resize(key_count); + p_gltf_node_track.rotation_track.interpolation = gltf_interpolation; + p_gltf_node_track.rotation_track.times = p_times; + p_gltf_node_track.rotation_track.values.resize(key_count); + p_gltf_node_track.scale_track.interpolation = gltf_interpolation; + p_gltf_node_track.scale_track.times = p_times; + p_gltf_node_track.scale_track.values.resize(key_count); + if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) { + gltf_interpolation = GLTFAnimation::INTERP_LINEAR; + p_gltf_node_track.position_track.times.clear(); + p_gltf_node_track.position_track.values.clear(); + p_gltf_node_track.rotation_track.times.clear(); + p_gltf_node_track.rotation_track.values.clear(); + p_gltf_node_track.scale_track.times.clear(); + p_gltf_node_track.scale_track.values.clear(); + // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. + const double increment = 1.0 / p_state->get_bake_fps(); + double time = 0.0; + bool last = false; + while (true) { + Vector3 position; + Quaternion rotation; + Vector3 scale; + Error err = p_godot_animation->try_position_track_interpolate(p_godot_anim_track_index, time, &position); + ERR_CONTINUE(err != OK); + err = p_godot_animation->try_rotation_track_interpolate(p_godot_anim_track_index, time, &rotation); + ERR_CONTINUE(err != OK); + err = p_godot_animation->try_scale_track_interpolate(p_godot_anim_track_index, time, &scale); + ERR_CONTINUE(err != OK); + p_gltf_node_track.position_track.values.push_back(position); + p_gltf_node_track.position_track.times.push_back(time); + p_gltf_node_track.rotation_track.values.push_back(rotation); + p_gltf_node_track.rotation_track.times.push_back(time); + p_gltf_node_track.scale_track.values.push_back(scale); + p_gltf_node_track.scale_track.times.push_back(time); + if (last) { + break; + } + time += increment; + if (time >= anim_end) { + last = true; + time = anim_end; + } } - time += increment; - if (time >= anim_end) { - last = true; - time = anim_end; + } else { + for (int32_t key_i = 0; key_i < key_count; key_i++) { + Transform3D transform = p_godot_animation->track_get_key_value(p_godot_anim_track_index, key_i); + p_gltf_node_track.position_track.values.write[key_i] = transform.get_origin(); + p_gltf_node_track.rotation_track.values.write[key_i] = transform.basis.get_rotation_quaternion(); + p_gltf_node_track.scale_track.values.write[key_i] = transform.basis.get_scale(); } } } else { - for (int32_t key_i = 0; key_i < key_count; key_i++) { - Vector3 scale_track = p_animation->track_get_key_value(p_track_i, key_i); - p_track.scale_track.values.write[key_i] = scale_track; - } - } - } - } else if (track_type == Animation::TYPE_BEZIER) { - const int32_t keys = anim_end * p_state->get_bake_fps(); - if (path.contains(":scale")) { - if (!p_track.scale_track.times.size()) { - p_track.scale_track.interpolation = gltf_interpolation; - Vector<real_t> new_times; - new_times.resize(keys); - for (int32_t key_i = 0; key_i < keys; key_i++) { - new_times.write[key_i] = key_i / p_state->get_bake_fps(); - } - p_track.scale_track.times = new_times; + // This is a Value track animating a property, but not a TRS property, so it can't be converted into a node track. + return false; + } + } else if (track_type == Animation::TYPE_BEZIER) { + const int32_t keys = anim_end * p_state->get_bake_fps(); + if (node_prop == "scale") { + if (p_gltf_node_track.scale_track.times.is_empty()) { + p_gltf_node_track.scale_track.interpolation = gltf_interpolation; + Vector<double> new_times; + new_times.resize(keys); + for (int32_t key_i = 0; key_i < keys; key_i++) { + new_times.write[key_i] = key_i / p_state->get_bake_fps(); + } + p_gltf_node_track.scale_track.times = new_times; - p_track.scale_track.values.resize(keys); + p_gltf_node_track.scale_track.values.resize(keys); - for (int32_t key_i = 0; key_i < keys; key_i++) { - p_track.scale_track.values.write[key_i] = Vector3(1.0f, 1.0f, 1.0f); - } + for (int32_t key_i = 0; key_i < keys; key_i++) { + p_gltf_node_track.scale_track.values.write[key_i] = Vector3(1.0f, 1.0f, 1.0f); + } - for (int32_t key_i = 0; key_i < keys; key_i++) { - Vector3 bezier_track = p_track.scale_track.values[key_i]; - if (path.contains(":scale:x")) { - bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); - } else if (path.contains(":scale:y")) { - bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); - } else if (path.contains(":scale:z")) { - bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); + for (int32_t key_i = 0; key_i < keys; key_i++) { + Vector3 bezier_track = p_gltf_node_track.scale_track.values[key_i]; + if (subpath.size() == 2) { + if (subpath[1] == StringName("x")) { + bezier_track.x = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } else if (subpath[1] == StringName("y")) { + bezier_track.y = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } else if (subpath[1] == StringName("z")) { + bezier_track.z = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } + } + p_gltf_node_track.scale_track.values.write[key_i] = bezier_track; } - p_track.scale_track.values.write[key_i] = bezier_track; } - } - } else if (path.contains(":position")) { - if (!p_track.position_track.times.size()) { - p_track.position_track.interpolation = gltf_interpolation; - Vector<real_t> new_times; - new_times.resize(keys); - for (int32_t key_i = 0; key_i < keys; key_i++) { - new_times.write[key_i] = key_i / p_state->get_bake_fps(); + } else if (node_prop == "position") { + if (p_gltf_node_track.position_track.times.is_empty()) { + p_gltf_node_track.position_track.interpolation = gltf_interpolation; + Vector<double> new_times; + new_times.resize(keys); + for (int32_t key_i = 0; key_i < keys; key_i++) { + new_times.write[key_i] = key_i / p_state->get_bake_fps(); + } + p_gltf_node_track.position_track.times = new_times; + + p_gltf_node_track.position_track.values.resize(keys); } - p_track.position_track.times = new_times; - p_track.position_track.values.resize(keys); - } + for (int32_t key_i = 0; key_i < keys; key_i++) { + Vector3 bezier_track = p_gltf_node_track.position_track.values[key_i]; + if (subpath.size() == 2) { + if (subpath[1] == StringName("x")) { + bezier_track.x = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } else if (subpath[1] == StringName("y")) { + bezier_track.y = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } else if (subpath[1] == StringName("z")) { + bezier_track.z = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } + } + p_gltf_node_track.position_track.values.write[key_i] = bezier_track; + } + } else if (node_prop == "quaternion") { + if (p_gltf_node_track.rotation_track.times.is_empty()) { + p_gltf_node_track.rotation_track.interpolation = gltf_interpolation; + Vector<double> new_times; + new_times.resize(keys); + for (int32_t key_i = 0; key_i < keys; key_i++) { + new_times.write[key_i] = key_i / p_state->get_bake_fps(); + } + p_gltf_node_track.rotation_track.times = new_times; - for (int32_t key_i = 0; key_i < keys; key_i++) { - Vector3 bezier_track = p_track.position_track.values[key_i]; - if (path.contains(":position:x")) { - bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); - } else if (path.contains(":position:y")) { - bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); - } else if (path.contains(":position:z")) { - bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); + p_gltf_node_track.rotation_track.values.resize(keys); } - p_track.position_track.values.write[key_i] = bezier_track; - } - } else if (path.contains(":rotation")) { - if (!p_track.rotation_track.times.size()) { - p_track.rotation_track.interpolation = gltf_interpolation; - Vector<real_t> new_times; - new_times.resize(keys); for (int32_t key_i = 0; key_i < keys; key_i++) { - new_times.write[key_i] = key_i / p_state->get_bake_fps(); - } - p_track.rotation_track.times = new_times; - - p_track.rotation_track.values.resize(keys); - } - for (int32_t key_i = 0; key_i < keys; key_i++) { - Quaternion bezier_track = p_track.rotation_track.values[key_i]; - if (path.contains(":rotation:x")) { - bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); - } else if (path.contains(":rotation:y")) { - bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); - } else if (path.contains(":rotation:z")) { - bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); - } else if (path.contains(":rotation:w")) { - bezier_track.w = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps()); + Quaternion bezier_track = p_gltf_node_track.rotation_track.values[key_i]; + if (subpath.size() == 2) { + if (subpath[1] == StringName("x")) { + bezier_track.x = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } else if (subpath[1] == StringName("y")) { + bezier_track.y = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } else if (subpath[1] == StringName("z")) { + bezier_track.z = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } else if (subpath[1] == StringName("w")) { + bezier_track.w = p_godot_animation->bezier_track_interpolate(p_godot_anim_track_index, key_i / p_state->get_bake_fps()); + } + } + p_gltf_node_track.rotation_track.values.write[key_i] = bezier_track; } - p_track.rotation_track.values.write[key_i] = bezier_track; + } else { + // This is a Bezier track animating a property, but not a TRS property, so it can't be converted into a node track. + return false; } + } else { + // This property track isn't a Value track or Bezier track, so it can't be converted into a node track. + return false; } + } else { + // This isn't a TRS track or a property track, so it can't be converted into a node track. + return false; } - return p_track; + // If we reached this point, the track was some kind of TRS track and was successfully converted. + // All failure paths should return false before this point to indicate this + // isn't a node track so it can be handled by KHR_animation_pointer instead. + return true; } -void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, String p_animation_track_name) { +void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const String &p_animation_track_name) { Ref<Animation> animation = p_animation_player->get_animation(p_animation_track_name); Ref<GLTFAnimation> gltf_animation; gltf_animation.instantiate(); gltf_animation->set_original_name(p_animation_track_name); gltf_animation->set_name(_gen_unique_name(p_state, p_animation_track_name)); - for (int32_t track_i = 0; track_i < animation->get_track_count(); track_i++) { - if (!animation->track_is_enabled(track_i)) { + HashMap<int, GLTFAnimation::NodeTrack> &node_tracks = gltf_animation->get_node_tracks(); + for (int32_t track_index = 0; track_index < animation->get_track_count(); track_index++) { + if (!animation->track_is_enabled(track_index)) { continue; } - String final_track_path = animation->track_get_path(track_i); - Node *animation_base_node = p_animation_player->get_parent(); - ERR_CONTINUE_MSG(!animation_base_node, "Cannot get the parent of the animation player."); - if (String(final_track_path).contains(":position")) { - const Vector<String> node_suffix = String(final_track_path).split(":position"); - const NodePath path = node_suffix[0]; - const Node *node = animation_base_node->get_node_or_null(path); - ERR_CONTINUE_MSG(!node, "Cannot get the node from a position path."); - for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : p_state->scene_nodes) { - if (position_scene_node_i.value == node) { - GLTFNodeIndex node_index = position_scene_node_i.key; - HashMap<int, GLTFAnimation::Track>::Iterator position_track_i = gltf_animation->get_tracks().find(node_index); - GLTFAnimation::Track track; - if (position_track_i) { - track = position_track_i->value; - } - track = _convert_animation_track(p_state, track, animation, track_i, node_index); - gltf_animation->get_tracks().insert(node_index, track); - } - } - } else if (String(final_track_path).contains(":rotation_degrees")) { - const Vector<String> node_suffix = String(final_track_path).split(":rotation_degrees"); - const NodePath path = node_suffix[0]; - const Node *node = animation_base_node->get_node_or_null(path); - ERR_CONTINUE_MSG(!node, "Cannot get the node from a rotation degrees path."); - for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : p_state->scene_nodes) { - if (rotation_degree_scene_node_i.value == node) { - GLTFNodeIndex node_index = rotation_degree_scene_node_i.key; - HashMap<int, GLTFAnimation::Track>::Iterator rotation_degree_track_i = gltf_animation->get_tracks().find(node_index); - GLTFAnimation::Track track; - if (rotation_degree_track_i) { - track = rotation_degree_track_i->value; - } - track = _convert_animation_track(p_state, track, animation, track_i, node_index); - gltf_animation->get_tracks().insert(node_index, track); - } - } - } else if (String(final_track_path).contains(":scale")) { - const Vector<String> node_suffix = String(final_track_path).split(":scale"); - const NodePath path = node_suffix[0]; - const Node *node = animation_base_node->get_node_or_null(path); - ERR_CONTINUE_MSG(!node, "Cannot get the node from a scale path."); - for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : p_state->scene_nodes) { - if (scale_scene_node_i.value == node) { - GLTFNodeIndex node_index = scale_scene_node_i.key; - HashMap<int, GLTFAnimation::Track>::Iterator scale_track_i = gltf_animation->get_tracks().find(node_index); - GLTFAnimation::Track track; - if (scale_track_i) { - track = scale_track_i->value; - } - track = _convert_animation_track(p_state, track, animation, track_i, node_index); - gltf_animation->get_tracks().insert(node_index, track); - } - } - } else if (String(final_track_path).contains(":transform")) { - const Vector<String> node_suffix = String(final_track_path).split(":transform"); - const NodePath path = node_suffix[0]; - const Node *node = animation_base_node->get_node_or_null(path); - ERR_CONTINUE_MSG(!node, "Cannot get the node from a transform path."); - for (const KeyValue<GLTFNodeIndex, Node *> &transform_track_i : p_state->scene_nodes) { - if (transform_track_i.value == node) { - GLTFAnimation::Track track; - track = _convert_animation_track(p_state, track, animation, track_i, transform_track_i.key); - gltf_animation->get_tracks().insert(transform_track_i.key, track); - } - } - } else if (String(final_track_path).contains(":") && animation->track_get_type(track_i) == Animation::TYPE_BLEND_SHAPE) { - const Vector<String> node_suffix = String(final_track_path).split(":"); - const NodePath path = node_suffix[0]; - const String suffix = node_suffix[1]; - Node *node = animation_base_node->get_node_or_null(path); - ERR_CONTINUE_MSG(!node, "Cannot get the node from a blend shape path."); - MeshInstance3D *mi = cast_to<MeshInstance3D>(node); - if (!mi) { - continue; - } - Ref<Mesh> mesh = mi->get_mesh(); + // Get the Godot node and the glTF node index for the animation track. + const NodePath track_path = animation->track_get_path(track_index); + const Node *anim_player_parent = p_animation_player->get_parent(); + const Node *animated_node = anim_player_parent->get_node_or_null(track_path); + ERR_CONTINUE_MSG(!animated_node, "glTF: Cannot get node for animated track using path: " + String(track_path)); + const GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::godot_to_gltf_interpolation(animation, track_index); + // First, check if it's a Blend Shape track. + if (animation->track_get_type(track_index) == Animation::TYPE_BLEND_SHAPE) { + const MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(animated_node); + ERR_CONTINUE_MSG(!mesh_instance, "glTF: Animation had a Blend Shape track, but the node wasn't a MeshInstance3D. Ignoring this track."); + Ref<Mesh> mesh = mesh_instance->get_mesh(); ERR_CONTINUE(mesh.is_null()); int32_t mesh_index = -1; for (const KeyValue<GLTFNodeIndex, Node *> &mesh_track_i : p_state->scene_nodes) { - if (mesh_track_i.value == node) { + if (mesh_track_i.value == animated_node) { mesh_index = mesh_track_i.key; } } ERR_CONTINUE(mesh_index == -1); - HashMap<int, GLTFAnimation::Track> &tracks = gltf_animation->get_tracks(); - GLTFAnimation::Track track = gltf_animation->get_tracks().has(mesh_index) ? gltf_animation->get_tracks()[mesh_index] : GLTFAnimation::Track(); - if (!tracks.has(mesh_index)) { + GLTFAnimation::NodeTrack track = node_tracks.has(mesh_index) ? node_tracks[mesh_index] : GLTFAnimation::NodeTrack(); + if (!node_tracks.has(mesh_index)) { for (int32_t shape_i = 0; shape_i < mesh->get_blend_shape_count(); shape_i++) { String shape_name = mesh->get_blend_shape_name(shape_i); - NodePath shape_path = String(path) + ":" + shape_name; + NodePath shape_path = NodePath(track_path.get_names(), { shape_name }, false); int32_t shape_track_i = animation->find_track(shape_path, Animation::TYPE_BLEND_SHAPE); if (shape_track_i == -1) { GLTFAnimation::Channel<real_t> weight; @@ -6797,15 +7863,6 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p track.weight_tracks.push_back(weight); continue; } - Animation::InterpolationType interpolation = animation->track_get_interpolation_type(track_i); - GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - if (interpolation == Animation::InterpolationType::INTERPOLATION_LINEAR) { - gltf_interpolation = GLTFAnimation::INTERP_LINEAR; - } else if (interpolation == Animation::InterpolationType::INTERPOLATION_NEAREST) { - gltf_interpolation = GLTFAnimation::INTERP_STEP; - } else if (interpolation == Animation::InterpolationType::INTERPOLATION_CUBIC) { - gltf_interpolation = GLTFAnimation::INTERP_CUBIC_SPLINE; - } int32_t key_count = animation->track_get_key_count(shape_track_i); GLTFAnimation::Channel<real_t> weight; weight.interpolation = gltf_interpolation; @@ -6819,64 +7876,74 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p } track.weight_tracks.push_back(weight); } - tracks[mesh_index] = track; - } - } else if (String(final_track_path).contains(":")) { - //Process skeleton - const Vector<String> node_suffix = String(final_track_path).split(":"); - const String &node = node_suffix[0]; - const NodePath node_path = node; - const String &suffix = node_suffix[1]; - Node *godot_node = animation_base_node->get_node_or_null(node_path); - if (!godot_node) { - continue; - } - Skeleton3D *skeleton = cast_to<Skeleton3D>(animation_base_node->get_node_or_null(node)); - if (!skeleton) { - continue; - } - GLTFSkeletonIndex skeleton_gltf_i = -1; - for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < p_state->skeletons.size(); skeleton_i++) { - if (p_state->skeletons[skeleton_i]->godot_skeleton == cast_to<Skeleton3D>(godot_node)) { - skeleton = p_state->skeletons[skeleton_i]->godot_skeleton; - skeleton_gltf_i = skeleton_i; - ERR_CONTINUE(!skeleton); - Ref<GLTFSkeleton> skeleton_gltf = p_state->skeletons[skeleton_gltf_i]; - int32_t bone = skeleton->find_bone(suffix); - ERR_CONTINUE_MSG(bone == -1, vformat("Cannot find the bone %s.", suffix)); - if (!skeleton_gltf->godot_bone_node.has(bone)) { - continue; - } - GLTFNodeIndex node_i = skeleton_gltf->godot_bone_node[bone]; - HashMap<int, GLTFAnimation::Track>::Iterator property_track_i = gltf_animation->get_tracks().find(node_i); - GLTFAnimation::Track track; - if (property_track_i) { - track = property_track_i->value; - } - track = _convert_animation_track(p_state, track, animation, track_i, node_i); - gltf_animation->get_tracks()[node_i] = track; - } - } - } else if (!String(final_track_path).contains(":")) { - ERR_CONTINUE(!animation_base_node); - Node *godot_node = animation_base_node->get_node_or_null(final_track_path); - ERR_CONTINUE_MSG(!godot_node, vformat("Cannot get the node from a skeleton path %s.", final_track_path)); - for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : p_state->scene_nodes) { - if (scene_node_i.value == godot_node) { - GLTFNodeIndex node_i = scene_node_i.key; - HashMap<int, GLTFAnimation::Track>::Iterator node_track_i = gltf_animation->get_tracks().find(node_i); - GLTFAnimation::Track track; - if (node_track_i) { - track = node_track_i->value; - } - track = _convert_animation_track(p_state, track, animation, track_i, node_i); - gltf_animation->get_tracks()[node_i] = track; - break; - } + node_tracks[mesh_index] = track; } + continue; } - } - if (gltf_animation->get_tracks().size()) { + // If it's not a Blend Shape track, it must either be a TRS track, a property Value track, or something we can't handle. + // For the cases we can handle, we will need to know the glTF node index, glTF interpolation, and the times of the track. + const Vector<StringName> subnames = track_path.get_subnames(); + const GLTFNodeIndex node_i = _node_and_or_bone_to_gltf_node_index(p_state, subnames, animated_node); + ERR_CONTINUE_MSG(node_i == -1, "glTF: Cannot get glTF node index for animated track using path: " + String(track_path)); + const int anim_key_count = animation->track_get_key_count(track_index); + Vector<double> times; + times.resize(anim_key_count); + for (int32_t key_i = 0; key_i < anim_key_count; key_i++) { + times.write[key_i] = animation->track_get_key_time(track_index, key_i); + } + // Try converting the track to a TRS glTF node track. This will only succeed if the Godot animation is a TRS track. + const HashMap<int, GLTFAnimation::NodeTrack>::Iterator node_track_iter = node_tracks.find(node_i); + GLTFAnimation::NodeTrack track; + if (node_track_iter) { + track = node_track_iter->value; + } + if (_convert_animation_node_track(p_state, track, animation, track_index, times)) { + // If the track was successfully converted, save it and continue to the next track. + node_tracks[node_i] = track; + continue; + } + // If the track wasn't a TRS track or Blend Shape track, it might be a Value track animating a property. + // Then this is something that we need to handle with KHR_animation_pointer. + Ref<GLTFObjectModelProperty> obj_model_prop = export_object_model_property(p_state, track_path, animated_node, node_i); + if (obj_model_prop.is_valid() && obj_model_prop->has_json_pointers()) { + // Insert the property track into the KHR_animation_pointer pointer tracks. + GLTFAnimation::Channel<Variant> channel; + channel.interpolation = gltf_interpolation; + channel.times = times; + channel.values.resize(anim_key_count); + // If using an expression, determine the base instance to pass to the expression. + const Ref<Expression> godot_to_gltf_expr = obj_model_prop->get_godot_to_gltf_expression(); + const bool is_godot_to_gltf_expr_valid = godot_to_gltf_expr.is_valid(); + Object *base_instance = nullptr; + if (is_godot_to_gltf_expr_valid) { + Ref<Resource> resource; + Vector<StringName> leftover_subpath; + base_instance = anim_player_parent->get_node_and_resource(track_path, resource, leftover_subpath); + if (resource.is_valid()) { + base_instance = resource.ptr(); + } + } + // Convert the Godot animation values into glTF animation values (still Variant). + for (int32_t key_i = 0; key_i < anim_key_count; key_i++) { + Variant value = animation->track_get_key_value(track_index, key_i); + if (is_godot_to_gltf_expr_valid) { + Array inputs; + inputs.append(value); + value = godot_to_gltf_expr->execute(inputs, base_instance); + } + channel.values.write[key_i] = value; + } + // Use the JSON pointer to insert the property track into the pointer tracks. There will usually be just one JSON pointer. + HashMap<String, GLTFAnimation::Channel<Variant>> &pointer_tracks = gltf_animation->get_pointer_tracks(); + Vector<PackedStringArray> split_json_pointers = obj_model_prop->get_json_pointers(); + for (const PackedStringArray &split_json_pointer : split_json_pointers) { + String json_pointer_str = "/" + String("/").join(split_json_pointer); + p_state->object_model_properties[json_pointer_str] = obj_model_prop; + pointer_tracks[json_pointer_str] = channel; + } + } + } + if (!gltf_animation->is_empty_of_tracks()) { p_state->animations.push_back(gltf_animation); } } @@ -7075,6 +8142,9 @@ void GLTFDocument::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lossy_quality"), "set_lossy_quality", "get_lossy_quality"); ADD_PROPERTY(PropertyInfo(Variant::INT, "root_node_mode"), "set_root_node_mode", "get_root_node_mode"); + ClassDB::bind_static_method("GLTFDocument", D_METHOD("import_object_model_property", "state", "json_pointer"), &GLTFDocument::import_object_model_property); + ClassDB::bind_static_method("GLTFDocument", D_METHOD("export_object_model_property", "state", "node_path", "godot_node", "gltf_node_index"), &GLTFDocument::export_object_model_property); + ClassDB::bind_static_method("GLTFDocument", D_METHOD("register_gltf_document_extension", "extension", "first_priority"), &GLTFDocument::register_gltf_document_extension, DEFVAL(false)); ClassDB::bind_static_method("GLTFDocument", D_METHOD("unregister_gltf_document_extension", "extension"), @@ -7136,6 +8206,7 @@ HashSet<String> GLTFDocument::get_supported_gltf_extensions_hashset() { // If the extension is supported directly in GLTFDocument, list it here. // Other built-in extensions are supported by GLTFDocumentExtension classes. supported_extensions.insert("GODOT_single_root"); + supported_extensions.insert("KHR_animation_pointer"); supported_extensions.insert("KHR_lights_punctual"); supported_extensions.insert("KHR_materials_emissive_strength"); supported_extensions.insert("KHR_materials_pbrSpecularGlossiness"); @@ -7313,6 +8384,10 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_se err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->get_import_as_skeleton_bones() ? p_state->root_nodes : Vector<GLTFNodeIndex>()); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + /* ASSIGN SCENE NODE NAMES */ + // This must be run AFTER determining skeletons, and BEFORE parsing animations. + _assign_node_names(p_state); + /* PARSE MESHES (we have enough info now) */ err = _parse_meshes(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); @@ -7329,9 +8404,6 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_se err = _parse_animations(p_state); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - /* ASSIGN SCENE NAMES */ - _assign_node_names(p_state); - return OK; } @@ -7350,7 +8422,7 @@ PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> p_state) { Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_path) { Ref<GLTFState> state = p_state; ERR_FAIL_COND_V(state.is_null(), ERR_INVALID_PARAMETER); - state->base_path = p_path.get_base_dir(); + state->set_base_path(p_path.get_base_dir()); state->filename = p_path.get_file(); Error err = _serialize(state); if (err != OK) { @@ -7463,7 +8535,7 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa Ref<FileAccessMemory> file_access; file_access.instantiate(); file_access->open_custom(p_bytes.ptr(), p_bytes.size()); - state->base_path = p_base_path.get_base_dir(); + state->set_base_path(p_base_path.get_base_dir()); err = _parse(p_state, state->base_path, file_access); ERR_FAIL_COND_V(err != OK, err); for (Ref<GLTFDocumentExtension> ext : document_extensions) { @@ -7480,7 +8552,7 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> p_state, uint if (state == Ref<GLTFState>()) { state.instantiate(); } - state->filename = p_path.get_file().get_basename(); + state->set_filename(p_path.get_file().get_basename()); state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; state->force_generate_tangents = p_flags & GLTF_IMPORT_GENERATE_TANGENT_ARRAYS; @@ -7488,13 +8560,13 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> p_state, uint Error err; Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err); - ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat(R"(Can't open file at path "%s")", p_path)); ERR_FAIL_COND_V(file.is_null(), ERR_FILE_CANT_OPEN); String base_path = p_base_path; if (base_path.is_empty()) { base_path = p_path.get_base_dir(); } - state->base_path = base_path; + state->set_base_path(base_path); err = _parse(p_state, base_path, file); ERR_FAIL_COND_V(err != OK, err); for (Ref<GLTFDocumentExtension> ext : document_extensions) { diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index d347d49102..a6d6caa3f0 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -56,13 +56,6 @@ public: enum { ARRAY_BUFFER = 34962, ELEMENT_ARRAY_BUFFER = 34963, - - COMPONENT_TYPE_BYTE = 5120, - COMPONENT_TYPE_UNSIGNED_BYTE = 5121, - COMPONENT_TYPE_SHORT = 5122, - COMPONENT_TYPE_UNSIGNED_SHORT = 5123, - COMPONENT_TYPE_INT = 5125, - COMPONENT_TYPE_FLOAT = 5126, }; enum { TEXTURE_TYPE_GENERIC = 0, @@ -95,6 +88,10 @@ public: static Vector<String> get_supported_gltf_extensions(); static HashSet<String> get_supported_gltf_extensions_hashset(); + static NodePath _find_material_node_path(Ref<GLTFState> p_state, Ref<Material> p_material); + static Ref<GLTFObjectModelProperty> import_object_model_property(Ref<GLTFState> p_state, const String &p_json_pointer); + static Ref<GLTFObjectModelProperty> export_object_model_property(Ref<GLTFState> p_state, const NodePath &p_node_path, const Node *p_godot_node, GLTFNodeIndex p_gltf_node_index); + void set_naming_version(int p_version); int get_naming_version() const; void set_image_format(const String &p_image_format); @@ -109,8 +106,8 @@ private: void _build_parent_hierachy(Ref<GLTFState> p_state); double _filter_number(double p_float); void _round_min_max_components(Vector<double> &r_type_min, Vector<double> &r_type_max); - String _get_component_type_name(const uint32_t p_component); - int _get_component_type_size(const int p_component_type); + String _get_component_type_name(const GLTFAccessor::GLTFComponentType p_component_type); + int _get_component_type_size(const GLTFAccessor::GLTFComponentType p_component_type); Error _parse_scenes(Ref<GLTFState> p_state); Error _parse_nodes(Ref<GLTFState> p_state); String _get_accessor_type_name(const GLTFAccessor::GLTFAccessorType p_accessor_type); @@ -140,7 +137,7 @@ private: const int p_skip_every, const int p_skip_bytes, const int p_element_size, const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const int p_component_count, - const int p_component_type, const int p_component_size, + const GLTFAccessor::GLTFComponentType p_component_type, const int p_component_size, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex); Vector<double> _decode_accessor(Ref<GLTFState> p_state, @@ -178,6 +175,15 @@ private: Vector<Transform3D> _decode_accessor_as_xform(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex); + Vector<Variant> _decode_accessor_as_variant(Ref<GLTFState> p_state, + const GLTFAccessorIndex p_accessor, + Variant::Type p_variant_type, + GLTFAccessor::GLTFAccessorType p_accessor_type); + GLTFAccessorIndex _encode_accessor_as_variant(Ref<GLTFState> p_state, + Vector<Variant> p_attribs, + Variant::Type p_variant_type, + GLTFAccessor::GLTFAccessorType p_accessor_type, + GLTFAccessor::GLTFComponentType p_component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT); Error _parse_meshes(Ref<GLTFState> p_state); Error _serialize_textures(Ref<GLTFState> p_state); Error _serialize_texture_samplers(Ref<GLTFState> p_state); @@ -205,6 +211,7 @@ private: Error _parse_cameras(Ref<GLTFState> p_state); Error _parse_lights(Ref<GLTFState> p_state); Error _parse_animations(Ref<GLTFState> p_state); + void _parse_animation_pointer(Ref<GLTFState> p_state, const String &p_animation_json_pointer, const Ref<GLTFAnimation> p_gltf_animation, const GLTFAnimation::Interpolation p_interp, const Vector<double> &p_times, const int p_output_value_accessor_index); Error _serialize_animations(Ref<GLTFState> p_state); BoneAttachment3D *_generate_bone_attachment(Ref<GLTFState> p_state, Skeleton3D *p_skeleton, @@ -216,7 +223,7 @@ private: Node3D *_generate_spatial(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index); void _assign_node_names(Ref<GLTFState> p_state); template <typename T> - T _interpolate_track(const Vector<real_t> &p_times, const Vector<T> &p_values, + T _interpolate_track(const Vector<double> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp); GLTFAccessorIndex _encode_accessor_as_quaternions(Ref<GLTFState> p_state, @@ -229,7 +236,7 @@ private: const Vector<Color> p_attribs, const bool p_for_vertex); GLTFAccessorIndex _encode_accessor_as_floats(Ref<GLTFState> p_state, - const Vector<real_t> p_attribs, + const Vector<double> p_attribs, const bool p_for_vertex); GLTFAccessorIndex _encode_accessor_as_vec2(Ref<GLTFState> p_state, const Vector<Vector2> p_attribs, @@ -269,7 +276,7 @@ private: const bool p_for_vertex); Error _encode_buffer_view(Ref<GLTFState> p_state, const double *p_src, const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, - const int p_component_type, const bool p_normalized, + const GLTFAccessor::GLTFComponentType p_component_type, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_accessor, const bool p_for_indices = false); @@ -280,11 +287,6 @@ private: Error _serialize_nodes(Ref<GLTFState> p_state); Error _serialize_scenes(Ref<GLTFState> p_state); String interpolation_to_string(const GLTFAnimation::Interpolation p_interp); - GLTFAnimation::Track _convert_animation_track(Ref<GLTFState> p_state, - GLTFAnimation::Track p_track, - Ref<Animation> p_animation, - int32_t p_track_i, - GLTFNodeIndex p_node_i); Error _encode_buffer_bins(Ref<GLTFState> p_state, const String &p_path); Error _encode_buffer_glb(Ref<GLTFState> p_state, const String &p_path); PackedByteArray _serialize_glb_buffer(Ref<GLTFState> p_state, Error *r_err); @@ -342,11 +344,6 @@ public: void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> p_gltf_node, Ref<GLTFState> p_state); #endif // MODULE_CSG_ENABLED - void _convert_animation_player_to_gltf( - AnimationPlayer *p_animation_player, Ref<GLTFState> p_state, - GLTFNodeIndex p_gltf_current, - GLTFNodeIndex p_gltf_root_index, - Ref<GLTFNode> p_gltf_node, Node *p_scene_parent); void _check_visibility(Node *p_node, bool &r_retflag); void _convert_camera_to_gltf(Camera3D *p_camera, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node); @@ -377,7 +374,15 @@ public: Ref<GLTFNode> p_gltf_node); GLTFMeshIndex _convert_mesh_to_gltf(Ref<GLTFState> p_state, MeshInstance3D *p_mesh_instance); - void _convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, String p_animation_track_name); + + GLTFNodeIndex _node_and_or_bone_to_gltf_node_index(Ref<GLTFState> p_state, const Vector<StringName> &p_node_subpath, const Node *p_godot_node); + bool _convert_animation_node_track(Ref<GLTFState> p_state, + GLTFAnimation::NodeTrack &p_gltf_node_track, + const Ref<Animation> &p_godot_animation, + int32_t p_godot_anim_track_index, + Vector<double> &p_times); + void _convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const String &p_animation_track_name); + Error _serialize(Ref<GLTFState> p_state); Error _parse(Ref<GLTFState> p_state, String p_path, Ref<FileAccess> p_file); }; diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 7763874d02..2488e73d08 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -397,8 +397,27 @@ String GLTFState::get_base_path() { return base_path; } -void GLTFState::set_base_path(String p_base_path) { +void GLTFState::set_base_path(const String &p_base_path) { base_path = p_base_path; + if (extract_path.is_empty()) { + extract_path = p_base_path; + } +} + +String GLTFState::get_extract_path() { + return extract_path; +} + +void GLTFState::set_extract_path(const String &p_extract_path) { + extract_path = p_extract_path; +} + +String GLTFState::get_extract_prefix() { + return extract_prefix; +} + +void GLTFState::set_extract_prefix(const String &p_extract_prefix) { + extract_prefix = p_extract_prefix; } String GLTFState::get_filename() const { @@ -407,6 +426,9 @@ String GLTFState::get_filename() const { void GLTFState::set_filename(const String &p_filename) { filename = p_filename; + if (extract_prefix.is_empty()) { + extract_prefix = p_filename.get_basename(); + } } Variant GLTFState::get_additional_data(const StringName &p_extension_name) { diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 7954049192..d667cf8858 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -38,6 +38,7 @@ #include "structures/gltf_camera.h" #include "structures/gltf_mesh.h" #include "structures/gltf_node.h" +#include "structures/gltf_object_model_property.h" #include "structures/gltf_skeleton.h" #include "structures/gltf_skin.h" #include "structures/gltf_texture.h" @@ -48,9 +49,12 @@ class GLTFState : public Resource { GDCLASS(GLTFState, Resource); friend class GLTFDocument; + friend class GLTFNode; protected: String base_path; + String extract_path; + String extract_prefix; String filename; Dictionary json; int major_version = 0; @@ -100,6 +104,7 @@ protected: Vector<Ref<GLTFAnimation>> animations; HashMap<GLTFNodeIndex, Node *> scene_nodes; HashMap<GLTFNodeIndex, ImporterMeshInstance3D *> scene_mesh_instances; + HashMap<String, Ref<GLTFObjectModelProperty>> object_model_properties; HashMap<ObjectID, GLTFSkeletonIndex> skeleton3d_to_gltf_skeleton; HashMap<ObjectID, HashMap<ObjectID, GLTFSkinIndex>> skin_and_skeleton3d_to_gltf_skin; @@ -186,7 +191,13 @@ public: void set_scene_name(String p_scene_name); String get_base_path(); - void set_base_path(String p_base_path); + void set_base_path(const String &p_base_path); + + String get_extract_path(); + void set_extract_path(const String &p_extract_path); + + String get_extract_prefix(); + void set_extract_prefix(const String &p_extract_prefix); String get_filename() const; void set_filename(const String &p_filename); diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index 53e9f2b84c..fbc3ae611c 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -37,6 +37,7 @@ #include "extensions/physics/gltf_document_extension_physics.h" #include "gltf_document.h" #include "gltf_state.h" +#include "structures/gltf_object_model_property.h" #ifdef TOOLS_ENABLED #include "editor/editor_import_blend_runner.h" @@ -112,6 +113,7 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(GLTFLight); GDREGISTER_CLASS(GLTFMesh); GDREGISTER_CLASS(GLTFNode); + GDREGISTER_CLASS(GLTFObjectModelProperty); GDREGISTER_CLASS(GLTFPhysicsBody); GDREGISTER_CLASS(GLTFPhysicsShape); GDREGISTER_CLASS(GLTFSkeleton); diff --git a/modules/gltf/structures/gltf_accessor.cpp b/modules/gltf/structures/gltf_accessor.cpp index 1ebc00a514..300fce09ff 100644 --- a/modules/gltf/structures/gltf_accessor.cpp +++ b/modules/gltf/structures/gltf_accessor.cpp @@ -39,6 +39,19 @@ void GLTFAccessor::_bind_methods() { BIND_ENUM_CONSTANT(TYPE_MAT3); BIND_ENUM_CONSTANT(TYPE_MAT4); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_NONE); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_SIGNED_BYTE); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_UNSIGNED_BYTE); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_SIGNED_SHORT); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_UNSIGNED_SHORT); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_SIGNED_INT); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_UNSIGNED_INT); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_SINGLE_FLOAT); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_DOUBLE_FLOAT); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_HALF_FLOAT); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_SIGNED_LONG); + BIND_ENUM_CONSTANT(COMPONENT_TYPE_UNSIGNED_LONG); + ClassDB::bind_method(D_METHOD("get_buffer_view"), &GLTFAccessor::get_buffer_view); ClassDB::bind_method(D_METHOD("set_buffer_view", "buffer_view"), &GLTFAccessor::set_buffer_view); ClassDB::bind_method(D_METHOD("get_byte_offset"), &GLTFAccessor::get_byte_offset); @@ -108,7 +121,7 @@ int GLTFAccessor::get_component_type() { } void GLTFAccessor::set_component_type(int p_component_type) { - component_type = p_component_type; + component_type = (GLTFComponentType)p_component_type; } bool GLTFAccessor::get_normalized() { @@ -188,7 +201,7 @@ int GLTFAccessor::get_sparse_indices_component_type() { } void GLTFAccessor::set_sparse_indices_component_type(int p_sparse_indices_component_type) { - sparse_indices_component_type = p_sparse_indices_component_type; + sparse_indices_component_type = (GLTFComponentType)p_sparse_indices_component_type; } int GLTFAccessor::get_sparse_values_buffer_view() { diff --git a/modules/gltf/structures/gltf_accessor.h b/modules/gltf/structures/gltf_accessor.h index 1a3a2cb494..b00e6a0f92 100644 --- a/modules/gltf/structures/gltf_accessor.h +++ b/modules/gltf/structures/gltf_accessor.h @@ -50,10 +50,25 @@ public: TYPE_MAT4, }; + enum GLTFComponentType { + COMPONENT_TYPE_NONE = 0, + COMPONENT_TYPE_SIGNED_BYTE = 5120, + COMPONENT_TYPE_UNSIGNED_BYTE = 5121, + COMPONENT_TYPE_SIGNED_SHORT = 5122, + COMPONENT_TYPE_UNSIGNED_SHORT = 5123, + COMPONENT_TYPE_SIGNED_INT = 5124, + COMPONENT_TYPE_UNSIGNED_INT = 5125, + COMPONENT_TYPE_SINGLE_FLOAT = 5126, + COMPONENT_TYPE_DOUBLE_FLOAT = 5130, + COMPONENT_TYPE_HALF_FLOAT = 5131, + COMPONENT_TYPE_SIGNED_LONG = 5134, + COMPONENT_TYPE_UNSIGNED_LONG = 5135, + }; + private: GLTFBufferViewIndex buffer_view = -1; int byte_offset = 0; - int component_type = 0; + GLTFComponentType component_type = COMPONENT_TYPE_NONE; bool normalized = false; int count = 0; GLTFAccessorType accessor_type = GLTFAccessorType::TYPE_SCALAR; @@ -62,7 +77,7 @@ private: int sparse_count = 0; int sparse_indices_buffer_view = 0; int sparse_indices_byte_offset = 0; - int sparse_indices_component_type = 0; + GLTFComponentType sparse_indices_component_type = COMPONENT_TYPE_NONE; int sparse_values_buffer_view = 0; int sparse_values_byte_offset = 0; @@ -117,5 +132,6 @@ public: }; VARIANT_ENUM_CAST(GLTFAccessor::GLTFAccessorType); +VARIANT_ENUM_CAST(GLTFAccessor::GLTFComponentType); #endif // GLTF_ACCESSOR_H diff --git a/modules/gltf/structures/gltf_animation.cpp b/modules/gltf/structures/gltf_animation.cpp index 94fda8e2f5..adc0354c4b 100644 --- a/modules/gltf/structures/gltf_animation.cpp +++ b/modules/gltf/structures/gltf_animation.cpp @@ -42,6 +42,34 @@ void GLTFAnimation::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "get_loop"); // bool } +GLTFAnimation::Interpolation GLTFAnimation::godot_to_gltf_interpolation(const Ref<Animation> &p_godot_animation, int32_t p_godot_anim_track_index) { + Animation::InterpolationType interpolation = p_godot_animation->track_get_interpolation_type(p_godot_anim_track_index); + switch (interpolation) { + case Animation::INTERPOLATION_LINEAR: + case Animation::INTERPOLATION_LINEAR_ANGLE: + return INTERP_LINEAR; + case Animation::INTERPOLATION_NEAREST: + return INTERP_STEP; + case Animation::INTERPOLATION_CUBIC: + case Animation::INTERPOLATION_CUBIC_ANGLE: + return INTERP_CUBIC_SPLINE; + } + return INTERP_LINEAR; +} + +Animation::InterpolationType GLTFAnimation::gltf_to_godot_interpolation(Interpolation p_gltf_interpolation) { + switch (p_gltf_interpolation) { + case INTERP_LINEAR: + return Animation::INTERPOLATION_LINEAR; + case INTERP_STEP: + return Animation::INTERPOLATION_NEAREST; + case INTERP_CATMULLROMSPLINE: + case INTERP_CUBIC_SPLINE: + return Animation::INTERPOLATION_CUBIC; + } + return Animation::INTERPOLATION_LINEAR; +} + String GLTFAnimation::get_original_name() { return original_name; } @@ -58,8 +86,16 @@ void GLTFAnimation::set_loop(bool p_val) { loop = p_val; } -HashMap<int, GLTFAnimation::Track> &GLTFAnimation::get_tracks() { - return tracks; +HashMap<int, GLTFAnimation::NodeTrack> &GLTFAnimation::get_node_tracks() { + return node_tracks; +} + +HashMap<String, GLTFAnimation::Channel<Variant>> &GLTFAnimation::get_pointer_tracks() { + return pointer_tracks; +} + +bool GLTFAnimation::is_empty_of_tracks() const { + return node_tracks.is_empty() && pointer_tracks.is_empty(); } GLTFAnimation::GLTFAnimation() { diff --git a/modules/gltf/structures/gltf_animation.h b/modules/gltf/structures/gltf_animation.h index afc9784895..6b692d06e6 100644 --- a/modules/gltf/structures/gltf_animation.h +++ b/modules/gltf/structures/gltf_animation.h @@ -50,33 +50,41 @@ public: template <typename T> struct Channel { Interpolation interpolation = INTERP_LINEAR; - Vector<real_t> times; + Vector<double> times; Vector<T> values; }; - struct Track { + struct NodeTrack { Channel<Vector3> position_track; Channel<Quaternion> rotation_track; Channel<Vector3> scale_track; Vector<Channel<real_t>> weight_tracks; }; + String original_name; + bool loop = false; + HashMap<int, NodeTrack> node_tracks; + HashMap<String, Channel<Variant>> pointer_tracks; + Dictionary additional_data; + public: + static Interpolation godot_to_gltf_interpolation(const Ref<Animation> &p_godot_animation, int32_t p_godot_anim_track_index); + static Animation::InterpolationType gltf_to_godot_interpolation(Interpolation p_gltf_interpolation); + String get_original_name(); void set_original_name(String p_name); bool get_loop() const; void set_loop(bool p_val); - HashMap<int, GLTFAnimation::Track> &get_tracks(); + + HashMap<int, GLTFAnimation::NodeTrack> &get_node_tracks(); + HashMap<String, GLTFAnimation::Channel<Variant>> &get_pointer_tracks(); + bool is_empty_of_tracks() const; + Variant get_additional_data(const StringName &p_extension_name); void set_additional_data(const StringName &p_extension_name, Variant p_additional_data); - GLTFAnimation(); -private: - String original_name; - bool loop = false; - HashMap<int, Track> tracks; - Dictionary additional_data; + GLTFAnimation(); }; #endif // GLTF_ANIMATION_H diff --git a/modules/gltf/structures/gltf_camera.cpp b/modules/gltf/structures/gltf_camera.cpp index 863e1df967..2960ec351d 100644 --- a/modules/gltf/structures/gltf_camera.cpp +++ b/modules/gltf/structures/gltf_camera.cpp @@ -30,6 +30,7 @@ #include "gltf_camera.h" +#include "gltf_object_model_property.h" #include "scene/3d/camera_3d.h" void GLTFCamera::_bind_methods() { @@ -57,6 +58,21 @@ void GLTFCamera::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth_near"), "set_depth_near", "get_depth_near"); } +void GLTFCamera::set_fov_conversion_expressions(Ref<GLTFObjectModelProperty> &r_obj_model_prop) { + // Expression to convert glTF yfov in radians to Godot fov in degrees. + Ref<Expression> gltf_to_godot_expr; + gltf_to_godot_expr.instantiate(); + PackedStringArray gltf_to_godot_args = { "yfov_rad" }; + gltf_to_godot_expr->parse("rad_to_deg(yfov_rad)", gltf_to_godot_args); + r_obj_model_prop->set_gltf_to_godot_expression(gltf_to_godot_expr); + // Expression to convert Godot fov in degrees to glTF yfov in radians. + Ref<Expression> godot_to_gltf_expr; + godot_to_gltf_expr.instantiate(); + PackedStringArray godot_to_gltf_args = { "fov_deg" }; + godot_to_gltf_expr->parse("deg_to_rad(fov_deg)", godot_to_gltf_args); + r_obj_model_prop->set_godot_to_gltf_expression(godot_to_gltf_expr); +} + Ref<GLTFCamera> GLTFCamera::from_node(const Camera3D *p_camera) { Ref<GLTFCamera> c; c.instantiate(); diff --git a/modules/gltf/structures/gltf_camera.h b/modules/gltf/structures/gltf_camera.h index 1a583c82cc..497b6cd4f1 100644 --- a/modules/gltf/structures/gltf_camera.h +++ b/modules/gltf/structures/gltf_camera.h @@ -34,6 +34,7 @@ #include "core/io/resource.h" class Camera3D; +class GLTFObjectModelProperty; // Reference and test file: // https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_015_SimpleCameras.md @@ -54,6 +55,8 @@ protected: static void _bind_methods(); public: + static void set_fov_conversion_expressions(Ref<GLTFObjectModelProperty> &r_obj_model_prop); + bool get_perspective() const { return perspective; } void set_perspective(bool p_val) { perspective = p_val; } real_t get_fov() const { return fov; } diff --git a/modules/gltf/structures/gltf_node.cpp b/modules/gltf/structures/gltf_node.cpp index ccee5e8ca4..1626313551 100644 --- a/modules/gltf/structures/gltf_node.cpp +++ b/modules/gltf/structures/gltf_node.cpp @@ -30,6 +30,8 @@ #include "gltf_node.h" +#include "../gltf_state.h" + void GLTFNode::_bind_methods() { ClassDB::bind_method(D_METHOD("get_original_name"), &GLTFNode::get_original_name); ClassDB::bind_method(D_METHOD("set_original_name", "original_name"), &GLTFNode::set_original_name); @@ -60,6 +62,7 @@ void GLTFNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_light", "light"), &GLTFNode::set_light); ClassDB::bind_method(D_METHOD("get_additional_data", "extension_name"), &GLTFNode::get_additional_data); ClassDB::bind_method(D_METHOD("set_additional_data", "extension_name", "additional_data"), &GLTFNode::set_additional_data); + ClassDB::bind_method(D_METHOD("get_scene_node_path", "gltf_state", "handle_skeletons"), &GLTFNode::get_scene_node_path, DEFVAL(true)); ADD_PROPERTY(PropertyInfo(Variant::STRING, "original_name"), "set_original_name", "get_original_name"); // String ADD_PROPERTY(PropertyInfo(Variant::INT, "parent"), "set_parent", "get_parent"); // GLTFNodeIndex @@ -187,6 +190,48 @@ Variant GLTFNode::get_additional_data(const StringName &p_extension_name) { return additional_data[p_extension_name]; } +bool GLTFNode::has_additional_data(const StringName &p_extension_name) { + return additional_data.has(p_extension_name); +} + void GLTFNode::set_additional_data(const StringName &p_extension_name, Variant p_additional_data) { additional_data[p_extension_name] = p_additional_data; } + +NodePath GLTFNode::get_scene_node_path(Ref<GLTFState> p_state, bool p_handle_skeletons) { + Vector<StringName> path; + Vector<StringName> subpath; + Ref<GLTFNode> current_gltf_node = this; + const int gltf_node_count = p_state->nodes.size(); + if (p_handle_skeletons && skeleton != -1) { + // Special case for skeleton nodes, skip all bones so that the path is to the Skeleton3D node. + // A path that would otherwise be `A/B/C/Bone1/Bone2/Bone3` becomes `A/B/C/Skeleton3D:Bone3`. + subpath.append(get_name()); + // The generated Skeleton3D node will be named Skeleton3D, so add it to the path. + path.append("Skeleton3D"); + do { + const int parent_index = current_gltf_node->get_parent(); + ERR_FAIL_INDEX_V(parent_index, gltf_node_count, NodePath()); + current_gltf_node = p_state->nodes[parent_index]; + } while (current_gltf_node->skeleton != -1); + } + const bool is_godot_single_root = p_state->extensions_used.has("GODOT_single_root"); + while (true) { + const int parent_index = current_gltf_node->get_parent(); + if (is_godot_single_root && parent_index == -1) { + // For GODOT_single_root scenes, the root glTF node becomes the Godot scene root, so it + // should not be included in the path. Ex: A/B/C, A is single root, we want B/C only. + break; + } + path.insert(0, current_gltf_node->get_name()); + if (!is_godot_single_root && parent_index == -1) { + break; + } + ERR_FAIL_INDEX_V(parent_index, gltf_node_count, NodePath()); + current_gltf_node = p_state->nodes[parent_index]; + } + if (unlikely(path.is_empty())) { + path.append("."); + } + return NodePath(path, subpath, false); +} diff --git a/modules/gltf/structures/gltf_node.h b/modules/gltf/structures/gltf_node.h index f3f6bfa2f1..f72b65a003 100644 --- a/modules/gltf/structures/gltf_node.h +++ b/modules/gltf/structures/gltf_node.h @@ -103,7 +103,10 @@ public: void set_light(GLTFLightIndex p_light); Variant get_additional_data(const StringName &p_extension_name); + bool has_additional_data(const StringName &p_extension_name); void set_additional_data(const StringName &p_extension_name, Variant p_additional_data); + + NodePath get_scene_node_path(Ref<GLTFState> p_state, bool p_handle_skeletons = true); }; #endif // GLTF_NODE_H diff --git a/modules/gltf/structures/gltf_object_model_property.cpp b/modules/gltf/structures/gltf_object_model_property.cpp new file mode 100644 index 0000000000..d405c362db --- /dev/null +++ b/modules/gltf/structures/gltf_object_model_property.cpp @@ -0,0 +1,173 @@ +/**************************************************************************/ +/* gltf_object_model_property.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gltf_object_model_property.h" + +#include "../gltf_template_convert.h" + +void GLTFObjectModelProperty::_bind_methods() { + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_UNKNOWN); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_BOOL); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT_ARRAY); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT2); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT3); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT4); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT2X2); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT3X3); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_FLOAT4X4); + BIND_ENUM_CONSTANT(GLTF_OBJECT_MODEL_TYPE_INT); + + ClassDB::bind_method(D_METHOD("append_node_path", "node_path"), &GLTFObjectModelProperty::append_node_path); + ClassDB::bind_method(D_METHOD("append_path_to_property", "node_path", "prop_name"), &GLTFObjectModelProperty::append_path_to_property); + + ClassDB::bind_method(D_METHOD("get_accessor_type"), &GLTFObjectModelProperty::get_accessor_type); + ClassDB::bind_method(D_METHOD("get_gltf_to_godot_expression"), &GLTFObjectModelProperty::get_gltf_to_godot_expression); + ClassDB::bind_method(D_METHOD("set_gltf_to_godot_expression", "gltf_to_godot_expr"), &GLTFObjectModelProperty::set_gltf_to_godot_expression); + ClassDB::bind_method(D_METHOD("get_godot_to_gltf_expression"), &GLTFObjectModelProperty::get_godot_to_gltf_expression); + ClassDB::bind_method(D_METHOD("set_godot_to_gltf_expression", "godot_to_gltf_expr"), &GLTFObjectModelProperty::set_godot_to_gltf_expression); + ClassDB::bind_method(D_METHOD("get_node_paths"), &GLTFObjectModelProperty::get_node_paths); + ClassDB::bind_method(D_METHOD("has_node_paths"), &GLTFObjectModelProperty::has_node_paths); + ClassDB::bind_method(D_METHOD("set_node_paths", "node_paths"), &GLTFObjectModelProperty::set_node_paths); + ClassDB::bind_method(D_METHOD("get_object_model_type"), &GLTFObjectModelProperty::get_object_model_type); + ClassDB::bind_method(D_METHOD("set_object_model_type", "type"), &GLTFObjectModelProperty::set_object_model_type); + ClassDB::bind_method(D_METHOD("get_json_pointers"), &GLTFObjectModelProperty::get_json_pointers_bind); + ClassDB::bind_method(D_METHOD("has_json_pointers"), &GLTFObjectModelProperty::has_json_pointers); + ClassDB::bind_method(D_METHOD("set_json_pointers", "json_pointers"), &GLTFObjectModelProperty::set_json_pointers_bind); + ClassDB::bind_method(D_METHOD("get_variant_type"), &GLTFObjectModelProperty::get_variant_type); + ClassDB::bind_method(D_METHOD("set_variant_type", "variant_type"), &GLTFObjectModelProperty::set_variant_type); + ClassDB::bind_method(D_METHOD("set_types", "variant_type", "obj_model_type"), &GLTFObjectModelProperty::set_types); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gltf_to_godot_expression", PROPERTY_HINT_RESOURCE_TYPE, "Expression"), "set_gltf_to_godot_expression", "get_gltf_to_godot_expression"); // Ref<Expression> + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "godot_to_gltf_expression", PROPERTY_HINT_RESOURCE_TYPE, "Expression"), "set_godot_to_gltf_expression", "get_godot_to_gltf_expression"); // Ref<Expression> + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "node_paths", PROPERTY_HINT_TYPE_STRING, "NodePath"), "set_node_paths", "get_node_paths"); // TypedArray<NodePath> + ADD_PROPERTY(PropertyInfo(Variant::INT, "object_model_type"), "set_object_model_type", "get_object_model_type"); // GLTFObjectModelType + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "json_pointers"), "set_json_pointers", "get_json_pointers"); // TypedArray<PackedStringArray> + ADD_PROPERTY(PropertyInfo(Variant::INT, "variant_type"), "set_variant_type", "get_variant_type"); // Variant::Type +} + +void GLTFObjectModelProperty::append_node_path(const NodePath &p_node_path) { + node_paths.push_back(p_node_path); +} + +void GLTFObjectModelProperty::append_path_to_property(const NodePath &p_node_path, const StringName &p_prop_name) { + Vector<StringName> node_names = p_node_path.get_names(); + Vector<StringName> subpath = p_node_path.get_subnames(); + subpath.append(p_prop_name); + node_paths.push_back(NodePath(node_names, subpath, false)); +} + +GLTFAccessor::GLTFAccessorType GLTFObjectModelProperty::get_accessor_type() const { + switch (object_model_type) { + case GLTF_OBJECT_MODEL_TYPE_FLOAT2: + return GLTFAccessor::TYPE_VEC2; + case GLTF_OBJECT_MODEL_TYPE_FLOAT3: + return GLTFAccessor::TYPE_VEC3; + case GLTF_OBJECT_MODEL_TYPE_FLOAT4: + return GLTFAccessor::TYPE_VEC4; + case GLTF_OBJECT_MODEL_TYPE_FLOAT2X2: + return GLTFAccessor::TYPE_MAT2; + case GLTF_OBJECT_MODEL_TYPE_FLOAT3X3: + return GLTFAccessor::TYPE_MAT3; + case GLTF_OBJECT_MODEL_TYPE_FLOAT4X4: + return GLTFAccessor::TYPE_MAT4; + default: + return GLTFAccessor::TYPE_SCALAR; + } +} + +Ref<Expression> GLTFObjectModelProperty::get_gltf_to_godot_expression() const { + return gltf_to_godot_expr; +} + +void GLTFObjectModelProperty::set_gltf_to_godot_expression(Ref<Expression> p_gltf_to_godot_expr) { + gltf_to_godot_expr = p_gltf_to_godot_expr; +} + +Ref<Expression> GLTFObjectModelProperty::get_godot_to_gltf_expression() const { + return godot_to_gltf_expr; +} + +void GLTFObjectModelProperty::set_godot_to_gltf_expression(Ref<Expression> p_godot_to_gltf_expr) { + godot_to_gltf_expr = p_godot_to_gltf_expr; +} + +TypedArray<NodePath> GLTFObjectModelProperty::get_node_paths() const { + return node_paths; +} + +bool GLTFObjectModelProperty::has_node_paths() const { + return !node_paths.is_empty(); +} + +void GLTFObjectModelProperty::set_node_paths(TypedArray<NodePath> p_node_paths) { + node_paths = p_node_paths; +} + +GLTFObjectModelProperty::GLTFObjectModelType GLTFObjectModelProperty::get_object_model_type() const { + return object_model_type; +} + +void GLTFObjectModelProperty::set_object_model_type(GLTFObjectModelType p_type) { + object_model_type = p_type; +} + +Vector<PackedStringArray> GLTFObjectModelProperty::get_json_pointers() const { + return json_pointers; +} + +bool GLTFObjectModelProperty::has_json_pointers() const { + return !json_pointers.is_empty(); +} + +void GLTFObjectModelProperty::set_json_pointers(const Vector<PackedStringArray> &p_json_pointers) { + json_pointers = p_json_pointers; +} + +TypedArray<PackedStringArray> GLTFObjectModelProperty::get_json_pointers_bind() const { + return GLTFTemplateConvert::to_array(json_pointers); +} + +void GLTFObjectModelProperty::set_json_pointers_bind(const TypedArray<PackedStringArray> &p_json_pointers) { + GLTFTemplateConvert::set_from_array(json_pointers, p_json_pointers); +} + +Variant::Type GLTFObjectModelProperty::get_variant_type() const { + return variant_type; +} + +void GLTFObjectModelProperty::set_variant_type(Variant::Type p_variant_type) { + variant_type = p_variant_type; +} + +void GLTFObjectModelProperty::set_types(Variant::Type p_variant_type, GLTFObjectModelType p_obj_model_type) { + variant_type = p_variant_type; + object_model_type = p_obj_model_type; +} diff --git a/modules/gltf/structures/gltf_object_model_property.h b/modules/gltf/structures/gltf_object_model_property.h new file mode 100644 index 0000000000..d8a4ed420a --- /dev/null +++ b/modules/gltf/structures/gltf_object_model_property.h @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* gltf_object_model_property.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GLTF_OBJECT_MODEL_PROPERTY_H +#define GLTF_OBJECT_MODEL_PROPERTY_H + +#include "core/math/expression.h" +#include "core/variant/typed_array.h" +#include "gltf_accessor.h" + +// Object model: https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/ObjectModel.adoc +// KHR_animation_pointer: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer + +class GLTFObjectModelProperty : public RefCounted { + GDCLASS(GLTFObjectModelProperty, RefCounted); + +public: + enum GLTFObjectModelType { + GLTF_OBJECT_MODEL_TYPE_UNKNOWN, + GLTF_OBJECT_MODEL_TYPE_BOOL, + GLTF_OBJECT_MODEL_TYPE_FLOAT, + GLTF_OBJECT_MODEL_TYPE_FLOAT_ARRAY, + GLTF_OBJECT_MODEL_TYPE_FLOAT2, + GLTF_OBJECT_MODEL_TYPE_FLOAT3, + GLTF_OBJECT_MODEL_TYPE_FLOAT4, + GLTF_OBJECT_MODEL_TYPE_FLOAT2X2, + GLTF_OBJECT_MODEL_TYPE_FLOAT3X3, + GLTF_OBJECT_MODEL_TYPE_FLOAT4X4, + GLTF_OBJECT_MODEL_TYPE_INT, + }; + +private: + Ref<Expression> gltf_to_godot_expr; + Ref<Expression> godot_to_gltf_expr; + TypedArray<NodePath> node_paths; + GLTFObjectModelType object_model_type = GLTF_OBJECT_MODEL_TYPE_UNKNOWN; + Vector<PackedStringArray> json_pointers; + Variant::Type variant_type = Variant::NIL; + +protected: + static void _bind_methods(); + +public: + void append_node_path(const NodePath &p_node_path); + void append_path_to_property(const NodePath &p_node_path, const StringName &p_prop_name); + + GLTFAccessor::GLTFAccessorType get_accessor_type() const; + + Ref<Expression> get_gltf_to_godot_expression() const; + void set_gltf_to_godot_expression(Ref<Expression> p_gltf_to_godot_expr); + + Ref<Expression> get_godot_to_gltf_expression() const; + void set_godot_to_gltf_expression(Ref<Expression> p_godot_to_gltf_expr); + + TypedArray<NodePath> get_node_paths() const; + bool has_node_paths() const; + void set_node_paths(TypedArray<NodePath> p_node_paths); + + GLTFObjectModelType get_object_model_type() const; + void set_object_model_type(GLTFObjectModelType p_type); + + Vector<PackedStringArray> get_json_pointers() const; + bool has_json_pointers() const; + void set_json_pointers(const Vector<PackedStringArray> &p_json_pointers); + + TypedArray<PackedStringArray> get_json_pointers_bind() const; + void set_json_pointers_bind(const TypedArray<PackedStringArray> &p_json_pointers); + + Variant::Type get_variant_type() const; + void set_variant_type(Variant::Type p_variant_type); + + void set_types(Variant::Type p_variant_type, GLTFObjectModelType p_obj_model_type); +}; + +VARIANT_ENUM_CAST(GLTFObjectModelProperty::GLTFObjectModelType); + +#endif // GLTF_OBJECT_MODEL_PROPERTY_H diff --git a/modules/gltf/tests/test_gltf_extras.h b/modules/gltf/tests/test_gltf_extras.h index 37c8f6925c..73ef02e9f1 100644 --- a/modules/gltf/tests/test_gltf_extras.h +++ b/modules/gltf/tests/test_gltf_extras.h @@ -91,7 +91,7 @@ static Node *_gltf_export_then_import(Node *p_root, String &p_tempfilebase) { options["gltf/naming_version"] = 1; // Process gltf file, note that this generates `.scn` resource from the 2nd argument. - err = import_scene->import(p_tempfilebase + ".gltf", p_tempfilebase, options, nullptr, nullptr, nullptr); + err = import_scene->import(0, p_tempfilebase + ".gltf", p_tempfilebase, options, nullptr, nullptr, nullptr); CHECK_MESSAGE(err == OK, "GLTF import failed."); ResourceImporterScene::remove_scene_importer(import_gltf); diff --git a/modules/godot_physics_2d/godot_joints_2d.cpp b/modules/godot_physics_2d/godot_joints_2d.cpp index 5c76eb9dad..d5a779ebb5 100644 --- a/modules/godot_physics_2d/godot_joints_2d.cpp +++ b/modules/godot_physics_2d/godot_joints_2d.cpp @@ -311,7 +311,7 @@ bool GodotPinJoint2D::get_flag(PhysicsServer2D::PinJointFlag p_flag) const { return motor_enabled; } } - ERR_FAIL_V(0); + ERR_FAIL_V(false); } GodotPinJoint2D::GodotPinJoint2D(const Vector2 &p_pos, GodotBody2D *p_body_a, GodotBody2D *p_body_b) : diff --git a/modules/godot_physics_2d/godot_joints_2d.h b/modules/godot_physics_2d/godot_joints_2d.h index c6a1fdb692..54884e112a 100644 --- a/modules/godot_physics_2d/godot_joints_2d.h +++ b/modules/godot_physics_2d/godot_joints_2d.h @@ -70,7 +70,7 @@ public: body->remove_constraint(this, i); } } - }; + } }; class GodotPinJoint2D : public GodotJoint2D { diff --git a/modules/godot_physics_2d/godot_physics_server_2d.cpp b/modules/godot_physics_2d/godot_physics_server_2d.cpp index 8df17992ea..2516ed3616 100644 --- a/modules/godot_physics_2d/godot_physics_server_2d.cpp +++ b/modules/godot_physics_2d/godot_physics_server_2d.cpp @@ -116,7 +116,7 @@ void GodotPhysicsServer2D::shape_set_data(RID p_shape, const Variant &p_data) { GodotShape2D *shape = shape_owner.get_or_null(p_shape); ERR_FAIL_NULL(shape); shape->set_data(p_data); -}; +} void GodotPhysicsServer2D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { GodotShape2D *shape = shape_owner.get_or_null(p_shape); @@ -128,14 +128,14 @@ PhysicsServer2D::ShapeType GodotPhysicsServer2D::shape_get_type(RID p_shape) con const GodotShape2D *shape = shape_owner.get_or_null(p_shape); ERR_FAIL_NULL_V(shape, SHAPE_CUSTOM); return shape->get_type(); -}; +} Variant GodotPhysicsServer2D::shape_get_data(RID p_shape) const { const GodotShape2D *shape = shape_owner.get_or_null(p_shape); ERR_FAIL_NULL_V(shape, Variant()); ERR_FAIL_COND_V(!shape->is_configured(), Variant()); return shape->get_data(); -}; +} real_t GodotPhysicsServer2D::shape_get_custom_solver_bias(RID p_shape) const { const GodotShape2D *shape = shape_owner.get_or_null(p_shape); @@ -226,7 +226,7 @@ RID GodotPhysicsServer2D::space_create() { area->set_priority(-1); return id; -}; +} void GodotPhysicsServer2D::space_set_active(RID p_space, bool p_active) { GodotSpace2D *space = space_owner.get_or_null(p_space); @@ -445,13 +445,13 @@ void GodotPhysicsServer2D::area_set_param(RID p_area, AreaParameter p_param, con GodotArea2D *area = area_owner.get_or_null(p_area); ERR_FAIL_NULL(area); area->set_param(p_param, p_value); -}; +} void GodotPhysicsServer2D::area_set_transform(RID p_area, const Transform2D &p_transform) { GodotArea2D *area = area_owner.get_or_null(p_area); ERR_FAIL_NULL(area); area->set_transform(p_transform); -}; +} Variant GodotPhysicsServer2D::area_get_param(RID p_area, AreaParameter p_param) const { if (space_owner.owns(p_area)) { @@ -462,14 +462,14 @@ Variant GodotPhysicsServer2D::area_get_param(RID p_area, AreaParameter p_param) ERR_FAIL_NULL_V(area, Variant()); return area->get_param(p_param); -}; +} Transform2D GodotPhysicsServer2D::area_get_transform(RID p_area) const { GodotArea2D *area = area_owner.get_or_null(p_area); ERR_FAIL_NULL_V(area, Transform2D()); return area->get_transform(); -}; +} void GodotPhysicsServer2D::area_set_pickable(RID p_area, bool p_pickable) { GodotArea2D *area = area_owner.get_or_null(p_area); @@ -551,7 +551,7 @@ void GodotPhysicsServer2D::body_set_space(RID p_body, RID p_space) { body->clear_constraint_list(); body->set_space(space); -}; +} RID GodotPhysicsServer2D::body_get_space(RID p_body) const { GodotBody2D *body = body_owner.get_or_null(p_body); @@ -562,7 +562,7 @@ RID GodotPhysicsServer2D::body_get_space(RID p_body) const { return RID(); } return space->get_self(); -}; +} void GodotPhysicsServer2D::body_set_mode(RID p_body, BodyMode p_mode) { GodotBody2D *body = body_owner.get_or_null(p_body); @@ -570,14 +570,14 @@ void GodotPhysicsServer2D::body_set_mode(RID p_body, BodyMode p_mode) { FLUSH_QUERY_CHECK(body); body->set_mode(p_mode); -}; +} PhysicsServer2D::BodyMode GodotPhysicsServer2D::body_get_mode(RID p_body) const { GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, BODY_MODE_STATIC); return body->get_mode(); -}; +} void GodotPhysicsServer2D::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) { GodotBody2D *body = body_owner.get_or_null(p_body); @@ -902,7 +902,7 @@ void GodotPhysicsServer2D::body_set_axis_velocity(RID p_body, const Vector2 &p_a v += p_axis_velocity; body->set_linear_velocity(v); body->wakeup(); -}; +} void GodotPhysicsServer2D::body_add_collision_exception(RID p_body, RID p_body_b) { GodotBody2D *body = body_owner.get_or_null(p_body); @@ -910,7 +910,7 @@ void GodotPhysicsServer2D::body_add_collision_exception(RID p_body, RID p_body_b body->add_exception(p_body_b); body->wakeup(); -}; +} void GodotPhysicsServer2D::body_remove_collision_exception(RID p_body, RID p_body_b) { GodotBody2D *body = body_owner.get_or_null(p_body); @@ -918,7 +918,7 @@ void GodotPhysicsServer2D::body_remove_collision_exception(RID p_body, RID p_bod body->remove_exception(p_body_b); body->wakeup(); -}; +} void GodotPhysicsServer2D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { GodotBody2D *body = body_owner.get_or_null(p_body); @@ -927,31 +927,31 @@ void GodotPhysicsServer2D::body_get_collision_exceptions(RID p_body, List<RID> * for (int i = 0; i < body->get_exceptions().size(); i++) { p_exceptions->push_back(body->get_exceptions()[i]); } -}; +} void GodotPhysicsServer2D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL(body); -}; +} real_t GodotPhysicsServer2D::body_get_contacts_reported_depth_threshold(RID p_body) const { GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, 0); return 0; -}; +} void GodotPhysicsServer2D::body_set_omit_force_integration(RID p_body, bool p_omit) { GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL(body); body->set_omit_force_integration(p_omit); -}; +} bool GodotPhysicsServer2D::body_is_omitting_force_integration(RID p_body) const { GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, false); return body->get_omit_force_integration(); -}; +} void GodotPhysicsServer2D::body_set_max_contacts_reported(RID p_body, int p_contacts) { GodotBody2D *body = body_owner.get_or_null(p_body); @@ -1169,8 +1169,8 @@ void GodotPhysicsServer2D::pin_joint_set_flag(RID p_joint, PinJointFlag p_flag, bool GodotPhysicsServer2D::pin_joint_get_flag(RID p_joint, PinJointFlag p_flag) const { GodotJoint2D *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_NULL_V(joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0); + ERR_FAIL_NULL_V(joint, false); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, false); GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(joint); return pin_joint->get_flag(p_flag); diff --git a/modules/godot_physics_2d/godot_space_2d.cpp b/modules/godot_physics_2d/godot_space_2d.cpp index 2966818beb..df3c9d8265 100644 --- a/modules/godot_physics_2d/godot_space_2d.cpp +++ b/modules/godot_physics_2d/godot_space_2d.cpp @@ -342,7 +342,7 @@ bool GodotPhysicsDirectSpaceState2D::collide_shape(const ShapeParameters &p_para } GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); - ERR_FAIL_NULL_V(shape, 0); + ERR_FAIL_NULL_V(shape, false); Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion @@ -439,7 +439,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) { GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); - ERR_FAIL_NULL_V(shape, 0); + ERR_FAIL_NULL_V(shape, false); real_t margin = MAX(p_parameters.margin, TEST_MOTION_MARGIN_MIN_VALUE); diff --git a/modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp b/modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp index c53c8481f4..2adbb51297 100644 --- a/modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp +++ b/modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp @@ -76,8 +76,9 @@ struct _CollectorCallback { Vector3 *prev_axis = nullptr; _FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B, Vector3 p_normal) { - if (p_normal.dot(p_point_B - p_point_A) < 0) + if (p_normal.dot(p_point_B - p_point_A) < 0) { p_normal = -p_normal; + } if (swap) { callback(p_point_B, 0, p_point_A, 0, -p_normal, userdata); } else { @@ -175,10 +176,11 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_ // The normal should be perpendicular to both edges. Vector3 normal = rel_A.cross(rel_B); real_t normal_len = normal.length(); - if (normal_len > 1e-3) + if (normal_len > 1e-3) { normal /= normal_len; - else + } else { normal = p_callback->normal; + } p_callback->call(closest_A, closest_B, normal); } @@ -784,8 +786,9 @@ static void analytic_sphere_collision(const Vector3 &p_origin_a, real_t p_radius // Calculate the sphere overlap, and bail if not overlapping real_t overlap = p_radius_a + p_radius_b - b_to_a_len; - if (overlap < 0) + if (overlap < 0) { return; + } // Report collision p_collector->collided = true; diff --git a/modules/godot_physics_3d/godot_physics_server_3d.cpp b/modules/godot_physics_3d/godot_physics_server_3d.cpp index 6d0949acbe..ad55e415e6 100644 --- a/modules/godot_physics_3d/godot_physics_server_3d.cpp +++ b/modules/godot_physics_3d/godot_physics_server_3d.cpp @@ -106,7 +106,7 @@ void GodotPhysicsServer3D::shape_set_data(RID p_shape, const Variant &p_data) { GodotShape3D *shape = shape_owner.get_or_null(p_shape); ERR_FAIL_NULL(shape); shape->set_data(p_data); -}; +} void GodotPhysicsServer3D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { GodotShape3D *shape = shape_owner.get_or_null(p_shape); @@ -118,14 +118,14 @@ PhysicsServer3D::ShapeType GodotPhysicsServer3D::shape_get_type(RID p_shape) con const GodotShape3D *shape = shape_owner.get_or_null(p_shape); ERR_FAIL_NULL_V(shape, SHAPE_CUSTOM); return shape->get_type(); -}; +} Variant GodotPhysicsServer3D::shape_get_data(RID p_shape) const { const GodotShape3D *shape = shape_owner.get_or_null(p_shape); ERR_FAIL_NULL_V(shape, Variant()); ERR_FAIL_COND_V(!shape->is_configured(), Variant()); return shape->get_data(); -}; +} void GodotPhysicsServer3D::shape_set_margin(RID p_shape, real_t p_margin) { } @@ -156,7 +156,7 @@ RID GodotPhysicsServer3D::space_create() { space->set_static_global_body(sgb); return id; -}; +} void GodotPhysicsServer3D::space_set_active(RID p_space, bool p_active) { GodotSpace3D *space = space_owner.get_or_null(p_space); @@ -354,13 +354,13 @@ void GodotPhysicsServer3D::area_set_param(RID p_area, AreaParameter p_param, con GodotArea3D *area = area_owner.get_or_null(p_area); ERR_FAIL_NULL(area); area->set_param(p_param, p_value); -}; +} void GodotPhysicsServer3D::area_set_transform(RID p_area, const Transform3D &p_transform) { GodotArea3D *area = area_owner.get_or_null(p_area); ERR_FAIL_NULL(area); area->set_transform(p_transform); -}; +} Variant GodotPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param) const { if (space_owner.owns(p_area)) { @@ -371,14 +371,14 @@ Variant GodotPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param) ERR_FAIL_NULL_V(area, Variant()); return area->get_param(p_param); -}; +} Transform3D GodotPhysicsServer3D::area_get_transform(RID p_area) const { GodotArea3D *area = area_owner.get_or_null(p_area); ERR_FAIL_NULL_V(area, Transform3D()); return area->get_transform(); -}; +} void GodotPhysicsServer3D::area_set_collision_layer(RID p_area, uint32_t p_layer) { GodotArea3D *area = area_owner.get_or_null(p_area); @@ -444,7 +444,7 @@ RID GodotPhysicsServer3D::body_create() { RID rid = body_owner.make_rid(body); body->set_self(rid); return rid; -}; +} void GodotPhysicsServer3D::body_set_space(RID p_body, RID p_space) { GodotBody3D *body = body_owner.get_or_null(p_body); @@ -462,7 +462,7 @@ void GodotPhysicsServer3D::body_set_space(RID p_body, RID p_space) { body->clear_constraint_map(); body->set_space(space); -}; +} RID GodotPhysicsServer3D::body_get_space(RID p_body) const { GodotBody3D *body = body_owner.get_or_null(p_body); @@ -473,21 +473,21 @@ RID GodotPhysicsServer3D::body_get_space(RID p_body) const { return RID(); } return space->get_self(); -}; +} void GodotPhysicsServer3D::body_set_mode(RID p_body, BodyMode p_mode) { GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL(body); body->set_mode(p_mode); -}; +} PhysicsServer3D::BodyMode GodotPhysicsServer3D::body_get_mode(RID p_body) const { GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, BODY_MODE_STATIC); return body->get_mode(); -}; +} void GodotPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) { GodotBody3D *body = body_owner.get_or_null(p_body); @@ -826,7 +826,7 @@ void GodotPhysicsServer3D::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool bool GodotPhysicsServer3D::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { const GodotBody3D *body = body_owner.get_or_null(p_body); - ERR_FAIL_NULL_V(body, 0); + ERR_FAIL_NULL_V(body, false); return body->is_axis_locked(p_axis); } @@ -836,7 +836,7 @@ void GodotPhysicsServer3D::body_add_collision_exception(RID p_body, RID p_body_b body->add_exception(p_body_b); body->wakeup(); -}; +} void GodotPhysicsServer3D::body_remove_collision_exception(RID p_body, RID p_body_b) { GodotBody3D *body = body_owner.get_or_null(p_body); @@ -844,7 +844,7 @@ void GodotPhysicsServer3D::body_remove_collision_exception(RID p_body, RID p_bod body->remove_exception(p_body_b); body->wakeup(); -}; +} void GodotPhysicsServer3D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { GodotBody3D *body = body_owner.get_or_null(p_body); @@ -853,31 +853,31 @@ void GodotPhysicsServer3D::body_get_collision_exceptions(RID p_body, List<RID> * for (int i = 0; i < body->get_exceptions().size(); i++) { p_exceptions->push_back(body->get_exceptions()[i]); } -}; +} void GodotPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL(body); -}; +} real_t GodotPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const { GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, 0); return 0; -}; +} void GodotPhysicsServer3D::body_set_omit_force_integration(RID p_body, bool p_omit) { GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL(body); body->set_omit_force_integration(p_omit); -}; +} bool GodotPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const { GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, false); return body->get_omit_force_integration(); -}; +} void GodotPhysicsServer3D::body_set_max_contacts_reported(RID p_body, int p_contacts) { GodotBody3D *body = body_owner.get_or_null(p_body); @@ -1770,4 +1770,4 @@ GodotPhysicsServer3D::GodotPhysicsServer3D(bool p_using_threads) { GodotBroadPhase3D::create_func = GodotBroadPhase3DBVH::_create; using_threads = p_using_threads; -}; +} diff --git a/modules/godot_physics_3d/godot_shape_3d.cpp b/modules/godot_physics_3d/godot_shape_3d.cpp index 70b6bcf19e..4356ebe2f2 100644 --- a/modules/godot_physics_3d/godot_shape_3d.cpp +++ b/modules/godot_physics_3d/godot_shape_3d.cpp @@ -1133,8 +1133,9 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) { max_support = s; } } - if (!extreme_vertices.has(best_vertex)) + if (!extreme_vertices.has(best_vertex)) { extreme_vertices.push_back(best_vertex); + } } } } @@ -1995,7 +1996,11 @@ bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vect Vector3 bounds_from = p_begin / BOUNDS_CHUNK_SIZE; Vector3 bounds_to = p_end / BOUNDS_CHUNK_SIZE; Vector3 bounds_offset = local_origin / BOUNDS_CHUNK_SIZE; - return _intersect_grid_segment(_heightmap_chunk_cull_segment, bounds_from, bounds_to, bounds_grid_width, bounds_grid_depth, bounds_offset, r_point, r_normal); + // Plus 1 here to width and depth of the chunk because _intersect_grid_segment() is used by cell level as well, + // and in _intersect_grid_segment() the loop will exit 1 early because for cell point triangle lookup, it dose x + 1, z + 1 etc for the vertex. + int bounds_width = bounds_grid_width + 1; + int bounds_depth = bounds_grid_depth + 1; + return _intersect_grid_segment(_heightmap_chunk_cull_segment, bounds_from, bounds_to, bounds_width, bounds_depth, bounds_offset, r_point, r_normal); } } diff --git a/modules/godot_physics_3d/godot_soft_body_3d.cpp b/modules/godot_physics_3d/godot_soft_body_3d.cpp index 7284076a47..e8be227d09 100644 --- a/modules/godot_physics_3d/godot_soft_body_3d.cpp +++ b/modules/godot_physics_3d/godot_soft_body_3d.cpp @@ -1121,7 +1121,7 @@ struct AABBQueryResult { _FORCE_INLINE_ bool operator()(void *p_data) { return result_callback(soft_body->get_node_index(p_data), userdata); - }; + } }; void GodotSoftBody3D::query_aabb(const AABB &p_aabb, GodotSoftBody3D::QueryResultCallback p_result_callback, void *p_userdata) { @@ -1140,7 +1140,7 @@ struct RayQueryResult { _FORCE_INLINE_ bool operator()(void *p_data) { return result_callback(soft_body->get_face_index(p_data), userdata); - }; + } }; void GodotSoftBody3D::query_ray(const Vector3 &p_from, const Vector3 &p_to, GodotSoftBody3D::QueryResultCallback p_result_callback, void *p_userdata) { diff --git a/modules/godot_physics_3d/godot_space_3d.cpp b/modules/godot_physics_3d/godot_space_3d.cpp index 9a6ba776b4..9f82a87f85 100644 --- a/modules/godot_physics_3d/godot_space_3d.cpp +++ b/modules/godot_physics_3d/godot_space_3d.cpp @@ -385,7 +385,7 @@ bool GodotPhysicsDirectSpaceState3D::collide_shape(const ShapeParameters &p_para } GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); - ERR_FAIL_NULL_V(shape, 0); + ERR_FAIL_NULL_V(shape, false); AABB aabb = p_parameters.transform.xform(shape->get_aabb()); aabb = aabb.grow(p_parameters.margin); @@ -511,7 +511,7 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect bool GodotPhysicsDirectSpaceState3D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) { GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); - ERR_FAIL_NULL_V(shape, 0); + ERR_FAIL_NULL_V(shape, false); real_t margin = MAX(p_parameters.margin, TEST_MOTION_MARGIN_MIN_VALUE); diff --git a/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp b/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp index 226f8a0f7f..5f9cf9de49 100644 --- a/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp +++ b/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp @@ -647,7 +647,7 @@ void GodotGeneric6DOFJoint3D::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6 } bool GodotGeneric6DOFJoint3D::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const { - ERR_FAIL_INDEX_V(p_axis, 3, 0); + ERR_FAIL_INDEX_V(p_axis, 3, false); switch (p_flag) { case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: { return m_linearLimits.enable_limit[p_axis]; diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index 4c11565c51..0d522a0562 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -34,11 +34,14 @@ #include "core/input/input.h" #include "core/os/keyboard.h" +#include "editor/editor_command_palette.h" #include "editor/editor_main_screen.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/gui/editor_bottom_panel.h" +#include "editor/gui/editor_zoom_widget.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "editor/themes/editor_scale.h" #include "scene/3d/camera_3d.h" @@ -84,16 +87,10 @@ void GridMapEditor::_menu_option(int p_option) { } if (edit_axis != new_axis) { - int item1 = options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL); - int item2 = options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL); if (edit_axis == Vector3::AXIS_Y) { - options->get_popup()->set_item_text(item1, TTR("Next Plane")); - options->get_popup()->set_item_text(item2, TTR("Previous Plane")); - spin_box_label->set_text(TTR("Plane:")); + floor->set_tooltip_text("Change Grid Plane"); } else if (new_axis == Vector3::AXIS_Y) { - options->get_popup()->set_item_text(item1, TTR("Next Floor")); - options->get_popup()->set_item_text(item2, TTR("Previous Floor")); - spin_box_label->set_text(TTR("Floor:")); + floor->set_tooltip_text("Change Grid Floor"); } } edit_axis = Vector3::Axis(new_axis); @@ -251,14 +248,22 @@ void GridMapEditor::_menu_option(int p_option) { void GridMapEditor::_update_cursor_transform() { cursor_transform = Transform3D(); cursor_transform.origin = cursor_origin; - cursor_transform.basis = node->get_basis_with_orthogonal_index(cursor_rot); cursor_transform.basis *= node->get_cell_scale(); cursor_transform = node->get_global_transform() * cursor_transform; - if (selected_palette >= 0) { - if (node && !node->get_mesh_library().is_null()) { + if (mode_buttons_group->get_pressed_button() == paint_mode_button) { + // Rotation is only applied in paint mode, we don't want the cursor box to rotate otherwise. + cursor_transform.basis = node->get_basis_with_orthogonal_index(cursor_rot); + if (selected_palette >= 0 && node && node->get_mesh_library().is_valid()) { cursor_transform *= node->get_mesh_library()->get_item_mesh_transform(selected_palette); } + } else { + Transform3D xf; + xf.scale(node->get_cell_size()); + xf.origin.x = node->get_center_x() ? -node->get_cell_size().x / 2 : 0; + xf.origin.y = node->get_center_y() ? -node->get_cell_size().y / 2 : 0; + xf.origin.z = node->get_center_z() ? -node->get_cell_size().z / 2 : 0; + cursor_transform *= xf; } if (cursor_instance.is_valid()) { @@ -301,7 +306,7 @@ void GridMapEditor::_update_selection_transform() { xf2.basis.scale(scale); xf2.origin = position; - RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], node->get_global_transform() * xf2); } } } @@ -336,25 +341,22 @@ void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const if (is_visible_in_tree()) { _update_selection_transform(); } - - options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_CLEAR), !selection.active); - options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_CUT), !selection.active); - options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_DUPLICATE), !selection.active); - options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_FILL), !selection.active); } bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click) { if (!spatial_editor) { return false; } - - if (selected_palette < 0 && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE) { + if (input_action == INPUT_TRANSFORM) { + return false; + } + if (selected_palette < 0 && input_action != INPUT_NONE && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE) { return false; } if (mesh_library.is_null()) { return false; } - if (input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE && !mesh_library->has_item(selected_palette)) { + if (input_action != INPUT_NONE && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE && !mesh_library->has_item(selected_palette)) { return false; } @@ -405,13 +407,17 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b cursor_origin = (Vector3(cell[0], cell[1], cell[2]) + Vector3(0.5 * node->get_center_x(), 0.5 * node->get_center_y(), 0.5 * node->get_center_z())) * node->get_cell_size(); cursor_visible = true; - if (input_action == INPUT_SELECT || input_action == INPUT_PASTE) { + if (input_action == INPUT_PASTE) { cursor_visible = false; } _update_cursor_transform(); } + if (input_action == INPUT_NONE) { + return false; + } + if (input_action == INPUT_PASTE) { paste_indicator.current = Vector3i(cell[0], cell[1], cell[2]); _update_paste_indicator(); @@ -604,7 +610,18 @@ void GridMapEditor::_do_paste() { } if (reselect) { - undo_redo->add_do_method(this, "_set_selection", true, paste_indicator.begin + ofs, paste_indicator.end + ofs); + // We need to rotate the paste_indicator to find the selection begin and end: + Vector3 temp_end = rot.xform(paste_indicator.end - paste_indicator.begin) + paste_indicator.begin + ofs; + Vector3 temp_begin = paste_indicator.begin + ofs; + // _set_selection expects that selection_begin is the corner closer to the origin: + for (int i = 0; i < 3; ++i) { + if (temp_begin[i] > temp_end[i]) { + float p = temp_begin[i]; + temp_begin[i] = temp_end[i]; + temp_end[i] = p; + } + } + undo_redo->add_do_method(this, "_set_selection", true, temp_begin, temp_end); undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end); } @@ -613,13 +630,92 @@ void GridMapEditor::_do_paste() { _clear_clipboard_data(); } +void GridMapEditor::_show_viewports_transform_gizmo(bool p_value) { + Dictionary new_state; + new_state["transform_gizmo"] = p_value; + for (uint32_t i = 0; i < Node3DEditor::VIEWPORTS_COUNT; i++) { + Node3DEditorViewport *viewport = Node3DEditor::get_singleton()->get_editor_viewport(i); + viewport->set_state(new_state); + } +} + EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<InputEvent> &p_event) { if (!node) { return EditorPlugin::AFTER_GUI_INPUT_PASS; } - Ref<InputEventMouseButton> mb = p_event; + Ref<InputEventKey> k = p_event; + if (k.is_valid() && k->is_pressed() && !k->is_echo()) { + // Transform mode (toggle button): + // If we are in Transform mode we pass the events to the 3D editor, + // but if the Transform mode shortcut is pressed again, we go back to Selection mode. + if (mode_buttons_group->get_pressed_button() == transform_mode_button) { + if (transform_mode_button->get_shortcut().is_valid() && transform_mode_button->get_shortcut()->matches_event(p_event)) { + select_mode_button->set_pressed(true); + accept_event(); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } + return EditorPlugin::AFTER_GUI_INPUT_PASS; + } + // Tool modes and tool actions: + for (BaseButton *b : viewport_shortcut_buttons) { + if (b->is_disabled()) { + continue; + } + + if (b->get_shortcut().is_valid() && b->get_shortcut()->matches_event(p_event)) { + if (b->is_toggle_mode()) { + b->set_pressed(b->get_button_group().is_valid() || !b->is_pressed()); + } else { + // Can't press a button without toggle mode, so just emit the signal directly. + b->emit_signal(SceneStringName(pressed)); + } + accept_event(); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } + } + // Hard key actions: + if (k->get_keycode() == Key::ESCAPE) { + if (input_action == INPUT_PASTE) { + _clear_clipboard_data(); + input_action = INPUT_NONE; + _update_paste_indicator(); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } else if (selection.active) { + _set_selection(false); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } else { + input_action = INPUT_NONE; + update_palette(); + _update_cursor_instance(); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } + } + // Options menu shortcuts: + Ref<Shortcut> ed_shortcut = ED_GET_SHORTCUT("grid_map/previous_floor"); + if (ed_shortcut.is_valid() && ed_shortcut->matches_event(p_event)) { + accept_event(); + _menu_option(MENU_OPTION_PREV_LEVEL); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } + ed_shortcut = ED_GET_SHORTCUT("grid_map/next_floor"); + if (ed_shortcut.is_valid() && ed_shortcut->matches_event(p_event)) { + accept_event(); + _menu_option(MENU_OPTION_NEXT_LEVEL); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } + for (int i = 0; i < options->get_popup()->get_item_count(); ++i) { + const Ref<Shortcut> &shortcut = options->get_popup()->get_item_shortcut(i); + if (shortcut.is_valid() && shortcut->matches_event(p_event)) { + // Consume input to avoid conflicts with other plugins. + accept_event(); + _menu_option(options->get_popup()->get_item_id(i)); + return EditorPlugin::AFTER_GUI_INPUT_STOP; + } + } + } + Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { if (mb->get_button_index() == MouseButton::WHEEL_UP && (mb->is_command_or_control_pressed())) { if (mb->is_pressed()) { @@ -645,14 +741,17 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D input_action = INPUT_NONE; _update_paste_indicator(); return EditorPlugin::AFTER_GUI_INPUT_STOP; - } else if (mb->is_shift_pressed() && can_edit) { + } else if (mode_buttons_group->get_pressed_button() == select_mode_button && can_edit) { input_action = INPUT_SELECT; last_selection = selection; - } else if (mb->is_command_or_control_pressed() && can_edit) { + } else if (mode_buttons_group->get_pressed_button() == pick_mode_button && can_edit) { input_action = INPUT_PICK; - } else { + } else if (mode_buttons_group->get_pressed_button() == paint_mode_button && can_edit) { input_action = INPUT_PAINT; set_items.clear(); + } else if (mode_buttons_group->get_pressed_button() == erase_mode_button && can_edit) { + input_action = INPUT_ERASE; + set_items.clear(); } } else if (mb->get_button_index() == MouseButton::RIGHT) { if (input_action == INPUT_PASTE) { @@ -663,9 +762,6 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D } else if (selection.active) { _set_selection(false); return EditorPlugin::AFTER_GUI_INPUT_STOP; - } else { - input_action = INPUT_ERASE; - set_items.clear(); } } else { return EditorPlugin::AFTER_GUI_INPUT_PASS; @@ -676,7 +772,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D } return EditorPlugin::AFTER_GUI_INPUT_PASS; } else { - if ((mb->get_button_index() == MouseButton::RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == MouseButton::LEFT && input_action == INPUT_PAINT)) { + if ((mb->get_button_index() == MouseButton::LEFT && input_action == INPUT_ERASE) || (mb->get_button_index() == MouseButton::LEFT && input_action == INPUT_PAINT)) { if (set_items.size()) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("GridMap Paint")); @@ -731,42 +827,6 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D return EditorPlugin::AFTER_GUI_INPUT_PASS; } - Ref<InputEventKey> k = p_event; - - if (k.is_valid()) { - if (k->is_pressed()) { - if (k->get_keycode() == Key::ESCAPE) { - if (input_action == INPUT_PASTE) { - _clear_clipboard_data(); - input_action = INPUT_NONE; - _update_paste_indicator(); - return EditorPlugin::AFTER_GUI_INPUT_STOP; - } else if (selection.active) { - _set_selection(false); - return EditorPlugin::AFTER_GUI_INPUT_STOP; - } else { - selected_palette = -1; - mesh_library_palette->deselect_all(); - update_palette(); - _update_cursor_instance(); - return EditorPlugin::AFTER_GUI_INPUT_STOP; - } - } - - // Consume input to avoid conflicts with other plugins. - if (k.is_valid() && k->is_pressed() && !k->is_echo()) { - for (int i = 0; i < options->get_popup()->get_item_count(); ++i) { - const Ref<Shortcut> &shortcut = options->get_popup()->get_item_shortcut(i); - if (shortcut.is_valid() && shortcut->matches_event(p_event)) { - accept_event(); - _menu_option(options->get_popup()->get_item_id(i)); - return EditorPlugin::AFTER_GUI_INPUT_STOP; - } - } - } - } - } - Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { if (pan_gesture->is_alt_pressed() && pan_gesture->is_command_or_control_pressed()) { @@ -833,11 +893,13 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) { // Zoom in/out using Ctrl + mouse wheel if (mb.is_valid() && mb->is_pressed() && mb->is_command_or_control_pressed()) { if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { - size_slider->set_value(size_slider->get_value() + 0.2); + zoom_widget->set_zoom(zoom_widget->get_zoom() + 0.2); + zoom_widget->emit_signal(SNAME("zoom_changed"), zoom_widget->get_zoom()); } if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { - size_slider->set_value(size_slider->get_value() - 0.2); + zoom_widget->set_zoom(zoom_widget->get_zoom() - 0.2); + zoom_widget->emit_signal(SNAME("zoom_changed"), zoom_widget->get_zoom()); } } } @@ -855,9 +917,9 @@ void GridMapEditor::update_palette() { if (display_mode == DISPLAY_THUMBNAIL) { mesh_library_palette->set_max_columns(0); mesh_library_palette->set_icon_mode(ItemList::ICON_MODE_TOP); - mesh_library_palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1.5)); + mesh_library_palette->set_fixed_column_width(min_size * MAX(zoom_widget->get_zoom(), 1.5)); } else if (display_mode == DISPLAY_LIST) { - mesh_library_palette->set_max_columns(1); + mesh_library_palette->set_max_columns(0); mesh_library_palette->set_icon_mode(ItemList::ICON_MODE_LEFT); mesh_library_palette->set_fixed_column_width(0); } @@ -938,6 +1000,11 @@ void GridMapEditor::_update_mesh_library() { } update_palette(); + // Make sure we select the first tile as default possible. + if (mesh_library_palette->get_current() == -1 && mesh_library_palette->get_item_count() > 0) { + mesh_library_palette->set_current(0); + selected_palette = mesh_library_palette->get_item_metadata(0); + } // Update the cursor and grid in case the library is changed or removed. _update_cursor_instance(); update_grid(); @@ -1058,10 +1125,22 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { } void GridMapEditor::_update_theme() { - options->set_icon(get_theme_icon(SNAME("GridMap"), EditorStringName(EditorIcons))); + transform_mode_button->set_button_icon(get_theme_icon(SNAME("ToolMove"), EditorStringName(EditorIcons))); + select_mode_button->set_button_icon(get_theme_icon(SNAME("ToolSelect"), EditorStringName(EditorIcons))); + erase_mode_button->set_button_icon(get_theme_icon(SNAME("Eraser"), EditorStringName(EditorIcons))); + paint_mode_button->set_button_icon(get_theme_icon(SNAME("Paint"), EditorStringName(EditorIcons))); + pick_mode_button->set_button_icon(get_theme_icon(SNAME("ColorPick"), EditorStringName(EditorIcons))); + fill_action_button->set_button_icon(get_theme_icon(SNAME("Bucket"), EditorStringName(EditorIcons))); + move_action_button->set_button_icon(get_theme_icon(SNAME("ActionCut"), EditorStringName(EditorIcons))); + duplicate_action_button->set_button_icon(get_theme_icon(SNAME("ActionCopy"), EditorStringName(EditorIcons))); + delete_action_button->set_button_icon(get_theme_icon(SNAME("Clear"), EditorStringName(EditorIcons))); + rotate_x_button->set_button_icon(get_theme_icon(SNAME("RotateLeft"), EditorStringName(EditorIcons))); + rotate_y_button->set_button_icon(get_theme_icon(SNAME("ToolRotate"), EditorStringName(EditorIcons))); + rotate_z_button->set_button_icon(get_theme_icon(SNAME("RotateRight"), EditorStringName(EditorIcons))); search_box->set_right_icon(get_theme_icon(SNAME("Search"), EditorStringName(EditorIcons))); - mode_thumbnail->set_icon(get_theme_icon(SNAME("FileThumbnail"), EditorStringName(EditorIcons))); - mode_list->set_icon(get_theme_icon(SNAME("FileList"), EditorStringName(EditorIcons))); + mode_thumbnail->set_button_icon(get_theme_icon(SNAME("FileThumbnail"), EditorStringName(EditorIcons))); + mode_list->set_button_icon(get_theme_icon(SNAME("FileList"), EditorStringName(EditorIcons))); + options->set_button_icon(get_theme_icon(SNAME("Tools"), EditorStringName(EditorIcons))); } void GridMapEditor::_notification(int p_what) { @@ -1076,6 +1155,9 @@ void GridMapEditor::_notification(int p_what) { RenderingServer::get_singleton()->instance_set_layer_mask(selection_level_instance[i], 1 << Node3DEditorViewport::MISC_TOOL_LAYER); } + cursor_instance = RenderingServer::get_singleton()->instance_create2(cursor_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); + RenderingServer::get_singleton()->instance_set_layer_mask(cursor_instance, 1 << Node3DEditorViewport::MISC_TOOL_LAYER); + RenderingServer::get_singleton()->instance_set_visible(cursor_instance, false); selection_instance = RenderingServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); RenderingServer::get_singleton()->instance_set_layer_mask(selection_instance, 1 << Node3DEditorViewport::MISC_TOOL_LAYER); paste_instance = RenderingServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); @@ -1097,8 +1179,10 @@ void GridMapEditor::_notification(int p_what) { RenderingServer::get_singleton()->free(selection_level_instance[i]); } + RenderingServer::get_singleton()->free(cursor_instance); RenderingServer::get_singleton()->free(selection_instance); RenderingServer::get_singleton()->free(paste_instance); + cursor_instance = RID(); selection_instance = RID(); paste_instance = RID(); } break; @@ -1144,15 +1228,32 @@ void GridMapEditor::_update_cursor_instance() { } cursor_instance = RID(); - if (selected_palette >= 0) { - if (node && !node->get_mesh_library().is_null()) { + if (mode_buttons_group->get_pressed_button() == paint_mode_button) { + if (selected_palette >= 0 && node && node->get_mesh_library().is_valid()) { Ref<Mesh> mesh = node->get_mesh_library()->get_item_mesh(selected_palette); if (!mesh.is_null() && mesh->get_rid().is_valid()) { cursor_instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world_3d()->get_scenario()); - RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); } } + } else if (mode_buttons_group->get_pressed_button() == select_mode_button) { + cursor_inner_mat->set_albedo(Color(default_color, 0.2)); + cursor_outer_mat->set_albedo(Color(default_color, 0.8)); + cursor_instance = RenderingServer::get_singleton()->instance_create2(cursor_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); + } else if (mode_buttons_group->get_pressed_button() == erase_mode_button) { + cursor_inner_mat->set_albedo(Color(erase_color, 0.2)); + cursor_outer_mat->set_albedo(Color(erase_color, 0.8)); + cursor_instance = RenderingServer::get_singleton()->instance_create2(cursor_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); + } else if (mode_buttons_group->get_pressed_button() == pick_mode_button) { + cursor_inner_mat->set_albedo(Color(pick_color, 0.2)); + cursor_outer_mat->set_albedo(Color(pick_color, 0.8)); + cursor_instance = RenderingServer::get_singleton()->instance_create2(cursor_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); } + _update_cursor_transform(); +} + +void GridMapEditor::_on_tool_mode_changed() { + _show_viewports_transform_gizmo(mode_buttons_group->get_pressed_button() == transform_mode_button); + _update_cursor_instance(); } void GridMapEditor::_item_selected_cbk(int idx) { @@ -1182,80 +1283,26 @@ void GridMapEditor::_bind_methods() { } GridMapEditor::GridMapEditor() { - ED_SHORTCUT("grid_map/previous_floor", TTR("Previous Floor"), Key::Q, true); - ED_SHORTCUT("grid_map/next_floor", TTR("Next Floor"), Key::E, true); - ED_SHORTCUT("grid_map/edit_x_axis", TTR("Edit X Axis"), Key::Z, true); - ED_SHORTCUT("grid_map/edit_y_axis", TTR("Edit Y Axis"), Key::X, true); - ED_SHORTCUT("grid_map/edit_z_axis", TTR("Edit Z Axis"), Key::C, true); - ED_SHORTCUT("grid_map/cursor_rotate_x", TTR("Cursor Rotate X"), Key::A, true); - ED_SHORTCUT("grid_map/cursor_rotate_y", TTR("Cursor Rotate Y"), Key::S, true); - ED_SHORTCUT("grid_map/cursor_rotate_z", TTR("Cursor Rotate Z"), Key::D, true); - ED_SHORTCUT("grid_map/cursor_back_rotate_x", TTR("Cursor Back Rotate X"), KeyModifierMask::SHIFT + Key::A, true); - ED_SHORTCUT("grid_map/cursor_back_rotate_y", TTR("Cursor Back Rotate Y"), KeyModifierMask::SHIFT + Key::S, true); - ED_SHORTCUT("grid_map/cursor_back_rotate_z", TTR("Cursor Back Rotate Z"), KeyModifierMask::SHIFT + Key::D, true); - ED_SHORTCUT("grid_map/cursor_clear_rotation", TTR("Cursor Clear Rotation"), Key::W, true); - ED_SHORTCUT("grid_map/paste_selects", TTR("Paste Selects")); - ED_SHORTCUT("grid_map/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::CTRL + Key::C); - ED_SHORTCUT("grid_map/cut_selection", TTR("Cut Selection"), KeyModifierMask::CTRL + Key::X); - ED_SHORTCUT("grid_map/clear_selection", TTR("Clear Selection"), Key::KEY_DELETE); - ED_SHORTCUT("grid_map/fill_selection", TTR("Fill Selection"), KeyModifierMask::CTRL + Key::F); - - int mw = EDITOR_GET("editors/grid_map/palette_min_width"); - Control *ec = memnew(Control); - ec->set_custom_minimum_size(Size2(mw, 0) * EDSCALE); - add_child(ec); - - spatial_editor_hb = memnew(HBoxContainer); - spatial_editor_hb->set_h_size_flags(SIZE_EXPAND_FILL); - spatial_editor_hb->set_alignment(BoxContainer::ALIGNMENT_END); - Node3DEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); - - spin_box_label = memnew(Label); - spin_box_label->set_text(TTR("Floor:")); - spatial_editor_hb->add_child(spin_box_label); - - floor = memnew(SpinBox); - floor->set_min(-32767); - floor->set_max(32767); - floor->set_step(1); - floor->get_line_edit()->add_theme_constant_override("minimum_character_width", 16); - - spatial_editor_hb->add_child(floor); - floor->connect(SceneStringName(value_changed), callable_mp(this, &GridMapEditor::_floor_changed)); - floor->connect(SceneStringName(mouse_exited), callable_mp(this, &GridMapEditor::_floor_mouse_exited)); - floor->get_line_edit()->connect(SceneStringName(mouse_exited), callable_mp(this, &GridMapEditor::_floor_mouse_exited)); - - spatial_editor_hb->add_child(memnew(VSeparator)); + ED_SHORTCUT("grid_map/previous_floor", TTR("Previous Floor"), Key::KEY_1, true); + ED_SHORTCUT("grid_map/next_floor", TTR("Next Floor"), Key::KEY_3, true); + ED_SHORTCUT("grid_map/edit_x_axis", TTR("Edit X Axis"), KeyModifierMask::SHIFT + Key::Z, true); + ED_SHORTCUT("grid_map/edit_y_axis", TTR("Edit Y Axis"), KeyModifierMask::SHIFT + Key::X, true); + ED_SHORTCUT("grid_map/edit_z_axis", TTR("Edit Z Axis"), KeyModifierMask::SHIFT + Key::C, true); + ED_SHORTCUT("grid_map/keep_selected", TTR("Keep Selection")); + ED_SHORTCUT("grid_map/clear_rotation", TTR("Clear Rotation")); options = memnew(MenuButton); - spatial_editor_hb->add_child(options); - spatial_editor_hb->hide(); - - options->set_text(TTR("Grid Map")); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/previous_floor"), MENU_OPTION_PREV_LEVEL); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/next_floor"), MENU_OPTION_NEXT_LEVEL); + options->set_theme_type_variation("FlatButton"); options->get_popup()->add_separator(); options->get_popup()->add_radio_check_shortcut(ED_GET_SHORTCUT("grid_map/edit_x_axis"), MENU_OPTION_X_AXIS); options->get_popup()->add_radio_check_shortcut(ED_GET_SHORTCUT("grid_map/edit_y_axis"), MENU_OPTION_Y_AXIS); options->get_popup()->add_radio_check_shortcut(ED_GET_SHORTCUT("grid_map/edit_z_axis"), MENU_OPTION_Z_AXIS); options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_Y_AXIS), true); options->get_popup()->add_separator(); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cursor_rotate_x"), MENU_OPTION_CURSOR_ROTATE_X); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cursor_rotate_y"), MENU_OPTION_CURSOR_ROTATE_Y); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cursor_rotate_z"), MENU_OPTION_CURSOR_ROTATE_Z); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cursor_back_rotate_x"), MENU_OPTION_CURSOR_BACK_ROTATE_X); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cursor_back_rotate_y"), MENU_OPTION_CURSOR_BACK_ROTATE_Y); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cursor_back_rotate_z"), MENU_OPTION_CURSOR_BACK_ROTATE_Z); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cursor_clear_rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION); - options->get_popup()->add_separator(); // TRANSLATORS: This is a toggle to select after pasting the new content. - options->get_popup()->add_check_shortcut(ED_GET_SHORTCUT("grid_map/paste_selects"), MENU_OPTION_PASTE_SELECTS); - options->get_popup()->add_separator(); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/duplicate_selection"), MENU_OPTION_SELECTION_DUPLICATE); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/cut_selection"), MENU_OPTION_SELECTION_CUT); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/clear_selection"), MENU_OPTION_SELECTION_CLEAR); - options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/fill_selection"), MENU_OPTION_SELECTION_FILL); - + options->get_popup()->add_shortcut(ED_GET_SHORTCUT("grid_map/clear_rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION); + options->get_popup()->add_check_shortcut(ED_GET_SHORTCUT("grid_map/keep_selected"), MENU_OPTION_PASTE_SELECTS); + options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_PASTE_SELECTS), true); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Settings..."), MENU_OPTION_GRIDMAP_SETTINGS); @@ -1275,40 +1322,186 @@ GridMapEditor::GridMapEditor() { options->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &GridMapEditor::_menu_option)); - HBoxContainer *hb = memnew(HBoxContainer); - add_child(hb); - hb->set_h_size_flags(SIZE_EXPAND_FILL); + toolbar = memnew(HBoxContainer); + add_child(toolbar); + toolbar->set_h_size_flags(SIZE_EXPAND_FILL); + + HBoxContainer *mode_buttons = memnew(HBoxContainer); + toolbar->add_child(mode_buttons); + mode_buttons_group.instantiate(); + + transform_mode_button = memnew(Button); + transform_mode_button->set_theme_type_variation("FlatButton"); + transform_mode_button->set_toggle_mode(true); + transform_mode_button->set_button_group(mode_buttons_group); + transform_mode_button->set_shortcut(ED_SHORTCUT("grid_map/transform_tool", TTR("Transform"), Key::T, true)); + transform_mode_button->connect(SceneStringName(toggled), + callable_mp(this, &GridMapEditor::_on_tool_mode_changed).unbind(1)); + mode_buttons->add_child(transform_mode_button); + viewport_shortcut_buttons.push_back(transform_mode_button); + VSeparator *vsep = memnew(VSeparator); + mode_buttons->add_child(vsep); + + select_mode_button = memnew(Button); + select_mode_button->set_theme_type_variation("FlatButton"); + select_mode_button->set_toggle_mode(true); + select_mode_button->set_button_group(mode_buttons_group); + select_mode_button->set_shortcut(ED_SHORTCUT("grid_map/selection_tool", TTR("Selection"), Key::Q, true)); + select_mode_button->connect(SceneStringName(toggled), + callable_mp(this, &GridMapEditor::_on_tool_mode_changed).unbind(1)); + mode_buttons->add_child(select_mode_button); + viewport_shortcut_buttons.push_back(select_mode_button); + + erase_mode_button = memnew(Button); + erase_mode_button->set_theme_type_variation("FlatButton"); + erase_mode_button->set_toggle_mode(true); + erase_mode_button->set_button_group(mode_buttons_group); + erase_mode_button->set_shortcut(ED_SHORTCUT("grid_map/erase_tool", TTR("Erase"), Key::W, true)); + mode_buttons->add_child(erase_mode_button); + erase_mode_button->connect(SceneStringName(toggled), + callable_mp(this, &GridMapEditor::_on_tool_mode_changed).unbind(1)); + viewport_shortcut_buttons.push_back(erase_mode_button); + + paint_mode_button = memnew(Button); + paint_mode_button->set_theme_type_variation("FlatButton"); + paint_mode_button->set_toggle_mode(true); + paint_mode_button->set_button_group(mode_buttons_group); + paint_mode_button->set_shortcut(ED_SHORTCUT("grid_map/paint_tool", TTR("Paint"), Key::E, true)); + paint_mode_button->connect(SceneStringName(toggled), + callable_mp(this, &GridMapEditor::_on_tool_mode_changed).unbind(1)); + mode_buttons->add_child(paint_mode_button); + viewport_shortcut_buttons.push_back(paint_mode_button); + + pick_mode_button = memnew(Button); + pick_mode_button->set_theme_type_variation("FlatButton"); + pick_mode_button->set_toggle_mode(true); + pick_mode_button->set_button_group(mode_buttons_group); + pick_mode_button->set_shortcut(ED_SHORTCUT("grid_map/pick_tool", TTR("Pick"), Key::R, true)); + pick_mode_button->connect(SceneStringName(toggled), + callable_mp(this, &GridMapEditor::_on_tool_mode_changed).unbind(1)); + mode_buttons->add_child(pick_mode_button); + viewport_shortcut_buttons.push_back(pick_mode_button); + + vsep = memnew(VSeparator); + toolbar->add_child(vsep); + + HBoxContainer *action_buttons = memnew(HBoxContainer); + toolbar->add_child(action_buttons); + + fill_action_button = memnew(Button); + fill_action_button->set_theme_type_variation("FlatButton"); + fill_action_button->set_shortcut(ED_SHORTCUT("grid_map/fill_tool", TTR("Fill"), Key::Z, true)); + fill_action_button->connect(SceneStringName(pressed), + callable_mp(this, &GridMapEditor::_menu_option).bind(MENU_OPTION_SELECTION_FILL)); + action_buttons->add_child(fill_action_button); + viewport_shortcut_buttons.push_back(fill_action_button); + + move_action_button = memnew(Button); + move_action_button->set_theme_type_variation("FlatButton"); + move_action_button->set_shortcut(ED_SHORTCUT("grid_map/move_tool", TTR("Move"), Key::X, true)); + move_action_button->connect(SceneStringName(pressed), + callable_mp(this, &GridMapEditor::_menu_option).bind(MENU_OPTION_SELECTION_CUT)); + action_buttons->add_child(move_action_button); + viewport_shortcut_buttons.push_back(move_action_button); + + duplicate_action_button = memnew(Button); + duplicate_action_button->set_theme_type_variation("FlatButton"); + duplicate_action_button->set_shortcut(ED_SHORTCUT("grid_map/duplicate_tool", TTR("Duplicate"), Key::C, true)); + duplicate_action_button->connect(SceneStringName(pressed), + callable_mp(this, &GridMapEditor::_menu_option).bind(MENU_OPTION_SELECTION_DUPLICATE)); + action_buttons->add_child(duplicate_action_button); + viewport_shortcut_buttons.push_back(duplicate_action_button); + + delete_action_button = memnew(Button); + delete_action_button->set_theme_type_variation("FlatButton"); + delete_action_button->set_shortcut(ED_SHORTCUT("grid_map/delete_tool", TTR("Delete"), Key::V, true)); + delete_action_button->connect(SceneStringName(pressed), + callable_mp(this, &GridMapEditor::_menu_option).bind(MENU_OPTION_SELECTION_CLEAR)); + action_buttons->add_child(delete_action_button); + viewport_shortcut_buttons.push_back(delete_action_button); + + vsep = memnew(VSeparator); + toolbar->add_child(vsep); + + HBoxContainer *rotation_buttons = memnew(HBoxContainer); + toolbar->add_child(rotation_buttons); + + rotate_x_button = memnew(Button); + rotate_x_button->set_theme_type_variation("FlatButton"); + rotate_x_button->set_shortcut(ED_SHORTCUT("grid_map/cursor_rotate_x", TTR("Cursor Rotate X"), Key::A, true)); + rotate_x_button->connect(SceneStringName(pressed), + callable_mp(this, &GridMapEditor::_menu_option).bind(MENU_OPTION_CURSOR_ROTATE_X)); + rotation_buttons->add_child(rotate_x_button); + viewport_shortcut_buttons.push_back(rotate_x_button); + + rotate_y_button = memnew(Button); + rotate_y_button->set_theme_type_variation("FlatButton"); + rotate_y_button->set_shortcut(ED_SHORTCUT("grid_map/cursor_rotate_y", TTR("Cursor Rotate Y"), Key::S, true)); + rotate_y_button->connect(SceneStringName(pressed), + callable_mp(this, &GridMapEditor::_menu_option).bind(MENU_OPTION_CURSOR_ROTATE_Y)); + rotation_buttons->add_child(rotate_y_button); + viewport_shortcut_buttons.push_back(rotate_y_button); + + rotate_z_button = memnew(Button); + rotate_z_button->set_theme_type_variation("FlatButton"); + rotate_z_button->set_shortcut(ED_SHORTCUT("grid_map/cursor_rotate_z", TTR("Cursor Rotate Z"), Key::D, true)); + rotate_z_button->connect(SceneStringName(pressed), + callable_mp(this, &GridMapEditor::_menu_option).bind(MENU_OPTION_CURSOR_ROTATE_Z)); + rotation_buttons->add_child(rotate_z_button); + viewport_shortcut_buttons.push_back(rotate_z_button); + + // Wide empty separation control. (like BoxContainer::add_spacer()) + Control *c = memnew(Control); + c->set_mouse_filter(MOUSE_FILTER_PASS); + c->set_h_size_flags(SIZE_EXPAND_FILL); + toolbar->add_child(c); + + floor = memnew(SpinBox); + floor->set_min(-32767); + floor->set_max(32767); + floor->set_step(1); + floor->set_tooltip_text( + vformat(TTR("Change Grid Floor:\nPrevious Plane (%s)\nNext Plane (%s)"), + ED_GET_SHORTCUT("grid_map/previous_floor")->get_as_text(), + ED_GET_SHORTCUT("grid_map/next_floor")->get_as_text())); + toolbar->add_child(floor); + floor->get_line_edit()->add_theme_constant_override("minimum_character_width", 2); + floor->get_line_edit()->set_context_menu_enabled(false); + floor->connect(SceneStringName(value_changed), callable_mp(this, &GridMapEditor::_floor_changed)); + floor->connect(SceneStringName(mouse_exited), callable_mp(this, &GridMapEditor::_floor_mouse_exited)); + floor->get_line_edit()->connect(SceneStringName(mouse_exited), callable_mp(this, &GridMapEditor::_floor_mouse_exited)); search_box = memnew(LineEdit); - search_box->set_h_size_flags(SIZE_EXPAND_FILL); + search_box->add_theme_constant_override("minimum_character_width", 10); search_box->set_placeholder(TTR("Filter Meshes")); search_box->set_clear_button_enabled(true); - hb->add_child(search_box); + toolbar->add_child(search_box); search_box->connect(SceneStringName(text_changed), callable_mp(this, &GridMapEditor::_text_changed)); search_box->connect(SceneStringName(gui_input), callable_mp(this, &GridMapEditor::_sbox_input)); + zoom_widget = memnew(EditorZoomWidget); + toolbar->add_child(zoom_widget); + zoom_widget->setup_zoom_limits(0.2, 4); + zoom_widget->set_zoom(1.0); + zoom_widget->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT, Control::PRESET_MODE_MINSIZE, 2 * EDSCALE); + zoom_widget->connect("zoom_changed", callable_mp(this, &GridMapEditor::_icon_size_changed)); + zoom_widget->set_shortcut_context(this); + mode_thumbnail = memnew(Button); mode_thumbnail->set_theme_type_variation("FlatButton"); mode_thumbnail->set_toggle_mode(true); mode_thumbnail->set_pressed(true); - hb->add_child(mode_thumbnail); + toolbar->add_child(mode_thumbnail); mode_thumbnail->connect(SceneStringName(pressed), callable_mp(this, &GridMapEditor::_set_display_mode).bind(DISPLAY_THUMBNAIL)); mode_list = memnew(Button); mode_list->set_theme_type_variation("FlatButton"); mode_list->set_toggle_mode(true); mode_list->set_pressed(false); - hb->add_child(mode_list); + toolbar->add_child(mode_list); mode_list->connect(SceneStringName(pressed), callable_mp(this, &GridMapEditor::_set_display_mode).bind(DISPLAY_LIST)); - size_slider = memnew(HSlider); - size_slider->set_h_size_flags(SIZE_EXPAND_FILL); - size_slider->set_min(0.2f); - size_slider->set_max(4.0f); - size_slider->set_step(0.1f); - size_slider->set_value(1.0f); - size_slider->connect(SceneStringName(value_changed), callable_mp(this, &GridMapEditor::_icon_size_changed)); - add_child(size_slider); + toolbar->add_child(options); mesh_library_palette = memnew(ItemList); mesh_library_palette->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); @@ -1330,6 +1523,7 @@ GridMapEditor::GridMapEditor() { edit_floor[1] = -1; edit_floor[2] = -1; + cursor_mesh = RenderingServer::get_singleton()->mesh_create(); selection_mesh = RenderingServer::get_singleton()->mesh_create(); paste_mesh = RenderingServer::get_singleton()->mesh_create(); @@ -1405,20 +1599,32 @@ GridMapEditor::GridMapEditor() { Array d; d.resize(RS::ARRAY_MAX); + default_color = Color(0.0, 0.565, 1.0); // blue 0.7, 0.7, 1.0 + erase_color = Color(1.0, 0.2, 0.2); // red + pick_color = Color(1, 0.7, 0); // orange/yellow + + cursor_inner_mat.instantiate(); + cursor_inner_mat->set_albedo(Color(default_color, 0.2)); + cursor_inner_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + cursor_inner_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + cursor_inner_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + + cursor_outer_mat.instantiate(); + cursor_outer_mat->set_albedo(Color(default_color, 0.8)); + cursor_outer_mat->set_on_top_of_alpha(); + cursor_outer_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + cursor_outer_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + cursor_outer_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + inner_mat.instantiate(); - inner_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.2)); + inner_mat->set_albedo(Color(default_color, 0.2)); inner_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); inner_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); inner_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); - d[RS::ARRAY_VERTEX] = triangles; - RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, RS::PRIMITIVE_TRIANGLES, d); - RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); - outer_mat.instantiate(); - outer_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.8)); + outer_mat->set_albedo(Color(default_color, 0.8)); outer_mat->set_on_top_of_alpha(); - outer_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); outer_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); outer_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); @@ -1429,6 +1635,18 @@ GridMapEditor::GridMapEditor() { selection_floor_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); selection_floor_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + d[RS::ARRAY_VERTEX] = triangles; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(cursor_mesh, RS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(cursor_mesh, 0, cursor_inner_mat->get_rid()); + + d[RS::ARRAY_VERTEX] = lines; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(cursor_mesh, RS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(cursor_mesh, 1, cursor_outer_mat->get_rid()); + + d[RS::ARRAY_VERTEX] = triangles; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, RS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); + d[RS::ARRAY_VERTEX] = lines; RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, RS::PRIMITIVE_LINES, d); RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); @@ -1471,9 +1689,6 @@ GridMapEditor::~GridMapEditor() { if (grid_instance[i].is_valid()) { RenderingServer::get_singleton()->free(grid_instance[i]); } - if (cursor_instance.is_valid()) { - RenderingServer::get_singleton()->free(cursor_instance); - } if (selection_level_instance[i].is_valid()) { RenderingServer::get_singleton()->free(selection_level_instance[i]); } @@ -1482,6 +1697,11 @@ GridMapEditor::~GridMapEditor() { } } + RenderingServer::get_singleton()->free(cursor_mesh); + if (cursor_instance.is_valid()) { + RenderingServer::get_singleton()->free(cursor_instance); + } + RenderingServer::get_singleton()->free(selection_mesh); if (selection_instance.is_valid()) { RenderingServer::get_singleton()->free(selection_instance); @@ -1493,24 +1713,6 @@ GridMapEditor::~GridMapEditor() { } } -void GridMapEditorPlugin::_notification(int p_what) { - switch (p_what) { - case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - if (!EditorSettings::get_singleton()->check_changed_settings_in_group("editors/grid_map")) { - break; - } - switch ((int)EDITOR_GET("editors/grid_map/editor_side")) { - case 0: { // Left. - Node3DEditor::get_singleton()->move_control_to_left_panel(grid_map_editor); - } break; - case 1: { // Right. - Node3DEditor::get_singleton()->move_control_to_right_panel(grid_map_editor); - } break; - } - } break; - } -} - void GridMapEditorPlugin::edit(Object *p_object) { grid_map_editor->edit(Object::cast_to<GridMap>(p_object)); } @@ -1521,27 +1723,33 @@ bool GridMapEditorPlugin::handles(Object *p_object) const { void GridMapEditorPlugin::make_visible(bool p_visible) { if (p_visible) { - grid_map_editor->show(); - grid_map_editor->spatial_editor_hb->show(); + BaseButton *button = grid_map_editor->mode_buttons_group->get_pressed_button(); + if (button == nullptr) { + grid_map_editor->select_mode_button->set_pressed(true); + } + grid_map_editor->_on_tool_mode_changed(); + panel_button->show(); + EditorNode::get_bottom_panel()->make_item_visible(grid_map_editor); grid_map_editor->set_process(true); } else { - grid_map_editor->spatial_editor_hb->hide(); - grid_map_editor->hide(); + grid_map_editor->_show_viewports_transform_gizmo(true); + panel_button->hide(); + if (grid_map_editor->is_visible_in_tree()) { + EditorNode::get_bottom_panel()->hide_bottom_panel(); + } grid_map_editor->set_process(false); } } GridMapEditorPlugin::GridMapEditorPlugin() { grid_map_editor = memnew(GridMapEditor); - switch ((int)EDITOR_GET("editors/grid_map/editor_side")) { - case 0: { // Left. - Node3DEditor::get_singleton()->add_control_to_left_panel(grid_map_editor); - } break; - case 1: { // Right. - Node3DEditor::get_singleton()->add_control_to_right_panel(grid_map_editor); - } break; - } + grid_map_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + grid_map_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + grid_map_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); grid_map_editor->hide(); + + panel_button = EditorNode::get_bottom_panel()->add_item(TTR("GridMap"), grid_map_editor, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_grid_map_bottom_panel", TTR("Toggle GridMap Bottom Panel"))); + panel_button->hide(); } GridMapEditorPlugin::~GridMapEditorPlugin() { diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h index 4294c93c93..2d43a5c830 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.h +++ b/modules/gridmap/editor/grid_map_editor_plugin.h @@ -44,6 +44,9 @@ class ConfirmationDialog; class MenuButton; class Node3DEditorPlugin; +class ButtonGroup; +class EditorZoomWidget; +class BaseButton; class GridMapEditor : public VBoxContainer { GDCLASS(GridMapEditor, VBoxContainer); @@ -54,6 +57,7 @@ class GridMapEditor : public VBoxContainer { enum InputAction { INPUT_NONE, + INPUT_TRANSFORM, INPUT_PAINT, INPUT_ERASE, INPUT_PICK, @@ -71,11 +75,31 @@ class GridMapEditor : public VBoxContainer { MenuButton *options = nullptr; SpinBox *floor = nullptr; double accumulated_floor_delta = 0.0; + + HBoxContainer *toolbar = nullptr; + List<BaseButton *> viewport_shortcut_buttons; + Ref<ButtonGroup> mode_buttons_group; + // mode + Button *transform_mode_button = nullptr; + Button *select_mode_button = nullptr; + Button *erase_mode_button = nullptr; + Button *paint_mode_button = nullptr; + Button *pick_mode_button = nullptr; + // action + Button *fill_action_button = nullptr; + Button *move_action_button = nullptr; + Button *duplicate_action_button = nullptr; + Button *delete_action_button = nullptr; + // rotation + Button *rotate_x_button = nullptr; + Button *rotate_y_button = nullptr; + Button *rotate_z_button = nullptr; + + EditorZoomWidget *zoom_widget = nullptr; Button *mode_thumbnail = nullptr; Button *mode_list = nullptr; LineEdit *search_box = nullptr; HSlider *size_slider = nullptr; - HBoxContainer *spatial_editor_hb = nullptr; ConfirmationDialog *settings_dialog = nullptr; VBoxContainer *settings_vbc = nullptr; SpinBox *settings_pick_distance = nullptr; @@ -102,6 +126,7 @@ class GridMapEditor : public VBoxContainer { RID grid[3]; RID grid_instance[3]; + RID cursor_mesh; RID cursor_instance; RID selection_mesh; RID selection_instance; @@ -119,7 +144,12 @@ class GridMapEditor : public VBoxContainer { List<ClipboardItem> clipboard_items; + Color default_color; + Color erase_color; + Color pick_color; Ref<StandardMaterial3D> indicator_mat; + Ref<StandardMaterial3D> cursor_inner_mat; + Ref<StandardMaterial3D> cursor_outer_mat; Ref<StandardMaterial3D> inner_mat; Ref<StandardMaterial3D> outer_mat; Ref<StandardMaterial3D> selection_floor_mat; @@ -196,6 +226,7 @@ class GridMapEditor : public VBoxContainer { void _item_selected_cbk(int idx); void _update_cursor_transform(); void _update_cursor_instance(); + void _on_tool_mode_changed(); void _update_theme(); void _text_changed(const String &p_text); @@ -208,6 +239,7 @@ class GridMapEditor : public VBoxContainer { void _set_clipboard_data(); void _update_paste_indicator(); void _do_paste(); + void _show_viewports_transform_gizmo(bool p_value); void _update_selection_transform(); void _validate_selection(); void _set_selection(bool p_active, const Vector3 &p_begin = Vector3(), const Vector3 &p_end = Vector3()); @@ -238,9 +270,7 @@ class GridMapEditorPlugin : public EditorPlugin { GDCLASS(GridMapEditorPlugin, EditorPlugin); GridMapEditor *grid_map_editor = nullptr; - -protected: - void _notification(int p_what); + Button *panel_button = nullptr; public: virtual EditorPlugin::AfterGUIInput forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) override { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); } diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 71171be3f1..0588ba034a 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -801,8 +801,8 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) { if (!g.navigation_debug_edge_connections_instance.is_valid()) { g.navigation_debug_edge_connections_instance = RenderingServer::get_singleton()->instance_create(); } - if (!g.navigation_debug_edge_connections_mesh.is_valid()) { - g.navigation_debug_edge_connections_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (g.navigation_debug_edge_connections_mesh.is_null()) { + g.navigation_debug_edge_connections_mesh.instantiate(); } _update_octant_navigation_debug_edge_connections_mesh(p_key); @@ -1386,8 +1386,8 @@ void GridMap::_update_octant_navigation_debug_edge_connections_mesh(const Octant g.navigation_debug_edge_connections_instance = RenderingServer::get_singleton()->instance_create(); } - if (!g.navigation_debug_edge_connections_mesh.is_valid()) { - g.navigation_debug_edge_connections_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (g.navigation_debug_edge_connections_mesh.is_null()) { + g.navigation_debug_edge_connections_mesh.instantiate(); } g.navigation_debug_edge_connections_mesh->clear_surfaces(); diff --git a/modules/interactive_music/doc_classes/AudioStreamInteractive.xml b/modules/interactive_music/doc_classes/AudioStreamInteractive.xml index 17448724d1..d47d6ecde6 100644 --- a/modules/interactive_music/doc_classes/AudioStreamInteractive.xml +++ b/modules/interactive_music/doc_classes/AudioStreamInteractive.xml @@ -119,7 +119,7 @@ <param index="0" name="from_clip" type="int" /> <param index="1" name="to_clip" type="int" /> <description> - Return true if a given transition exists (was added via [method add_transition]). + Returns [code]true[/code] if a given transition exists (was added via [method add_transition]). </description> </method> <method name="is_transition_holding_previous" qualifiers="const"> diff --git a/modules/interactive_music/editor/audio_stream_interactive_editor_plugin.cpp b/modules/interactive_music/editor/audio_stream_interactive_editor_plugin.cpp index fcb477995f..a29646e4a3 100644 --- a/modules/interactive_music/editor/audio_stream_interactive_editor_plugin.cpp +++ b/modules/interactive_music/editor/audio_stream_interactive_editor_plugin.cpp @@ -396,7 +396,7 @@ void EditorInspectorPluginAudioStreamInteractive::_edit(Object *p_object) { void EditorInspectorPluginAudioStreamInteractive::parse_end(Object *p_object) { if (Object::cast_to<AudioStreamInteractive>(p_object)) { Button *button = EditorInspector::create_inspector_action_button(TTR("Edit Transitions")); - button->set_icon(audio_stream_interactive_transition_editor->get_editor_theme_icon(SNAME("Blend"))); + button->set_button_icon(audio_stream_interactive_transition_editor->get_editor_theme_icon(SNAME("Blend"))); button->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorPluginAudioStreamInteractive::_edit).bind(p_object)); add_custom_control(button); } diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 8ba6f9e2ba..bd71e29d0a 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -247,7 +247,9 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ } if (p_step_function) { - p_step_function(0.1, RTR("Determining optimal atlas size"), p_bake_userdata, true); + if (p_step_function(0.1, RTR("Determining optimal atlas size"), p_bake_userdata, true)) { + return BAKE_ERROR_USER_ABORTED; + } } atlas_size = Size2i(max, max); @@ -324,7 +326,9 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ emission_images.resize(atlas_slices); if (p_step_function) { - p_step_function(0.2, RTR("Blitting albedo and emission"), p_bake_userdata, true); + if (p_step_function(0.2, RTR("Blitting albedo and emission"), p_bake_userdata, true)) { + return BAKE_ERROR_USER_ABORTED; + } } for (int i = 0; i < atlas_slices; i++) { @@ -1013,7 +1017,9 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh if (p_step_function) { int percent = (s + 1) * 100 / p_atlas_slices; float p = float(s) / p_atlas_slices * 0.1; - p_step_function(0.8 + p, vformat(RTR("Denoising %d%%"), percent), p_bake_userdata, false); + if (p_step_function(0.8 + p, vformat(RTR("Denoising %d%%"), percent), p_bake_userdata, false)) { + return BAKE_ERROR_USER_ABORTED; + } } } @@ -1265,7 +1271,15 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->buffer_update(bake_parameters_buffer, 0, sizeof(BakeParameters), &bake_parameters); if (p_step_function) { - p_step_function(0.47, RTR("Preparing shaders"), p_bake_userdata, true); + if (p_step_function(0.47, RTR("Preparing shaders"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } //shaders @@ -1497,7 +1511,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->sync(); if (p_step_function) { - p_step_function(0.49, RTR("Un-occluding geometry"), p_bake_userdata, true); + if (p_step_function(0.49, RTR("Un-occluding geometry"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } PushConstant push_constant; @@ -1539,7 +1563,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d } if (p_step_function) { - p_step_function(0.5, RTR("Plot direct lighting"), p_bake_userdata, true); + if (p_step_function(0.5, RTR("Plot direct lighting"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } // Set ray count to the quality used for direct light and bounces. @@ -1699,7 +1733,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->sync(); if (p_step_function) { - p_step_function(0.6, RTR("Integrate indirect lighting"), p_bake_userdata, true); + if (p_step_function(0.6, RTR("Integrate indirect lighting"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } int count = 0; @@ -1738,7 +1782,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d int total = (atlas_slices * x_regions * y_regions * ray_iterations); int percent = count * 100 / total; float p = float(count) / total * 0.1; - p_step_function(0.6 + p, vformat(RTR("Integrate indirect lighting %d%%"), percent), p_bake_userdata, false); + if (p_step_function(0.6 + p, vformat(RTR("Integrate indirect lighting %d%%"), percent), p_bake_userdata, false)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } } } @@ -1754,7 +1808,20 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d light_probe_buffer = rd->storage_buffer_create(sizeof(float) * 4 * 9 * probe_positions.size()); if (p_step_function) { - p_step_function(0.7, RTR("Baking light probes"), p_bake_userdata, true); + if (p_step_function(0.7, RTR("Baking light probes"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + if (probe_positions.size() > 0) { + rd->free(light_probe_buffer); + } + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } Vector<RD::Uniform> uniforms; @@ -1822,7 +1889,20 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d if (p_step_function) { int percent = i * 100 / ray_iterations; float p = float(i) / ray_iterations * 0.1; - p_step_function(0.7 + p, vformat(RTR("Integrating light probes %d%%"), percent), p_bake_userdata, false); + if (p_step_function(0.7 + p, vformat(RTR("Integrating light probes %d%%"), percent), p_bake_userdata, false)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + if (probe_positions.size() > 0) { + rd->free(light_probe_buffer); + } + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } } } @@ -1844,7 +1924,20 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d if (p_use_denoiser) { if (p_step_function) { - p_step_function(0.8, RTR("Denoising"), p_bake_userdata, true); + if (p_step_function(0.8, RTR("Denoising"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + if (probe_positions.size() > 0) { + rd->free(light_probe_buffer); + } + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } { diff --git a/modules/lightmapper_rd/lm_common_inc.glsl b/modules/lightmapper_rd/lm_common_inc.glsl index 98d11b9e69..962e444911 100644 --- a/modules/lightmapper_rd/lm_common_inc.glsl +++ b/modules/lightmapper_rd/lm_common_inc.glsl @@ -1,4 +1,3 @@ - /* SET 0, static data that does not change between any call */ layout(set = 0, binding = 0) uniform BakeParameters { diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h index 5e1da550d7..d24f00723f 100644 --- a/modules/mbedtls/crypto_mbedtls.h +++ b/modules/mbedtls/crypto_mbedtls.h @@ -57,7 +57,7 @@ public: virtual Error save(const String &p_path, bool p_public_only); virtual String save_to_string(bool p_public_only); virtual Error load_from_string(const String &p_string_key, bool p_public_only); - virtual bool is_public_only() const { return public_only; }; + virtual bool is_public_only() const { return public_only; } CryptoKeyMbedTLS() { mbedtls_pk_init(&pkey); diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp index b4200410fb..3af66f6d83 100644 --- a/modules/mbedtls/stream_peer_mbedtls.cpp +++ b/modules/mbedtls/stream_peer_mbedtls.cpp @@ -166,21 +166,24 @@ Error StreamPeerMbedTLS::put_partial_data(const uint8_t *p_data, int p_bytes, in return OK; } - int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_data, p_bytes); - if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { - // Non blocking IO - ret = 0; - } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - // Clean close - disconnect_from_stream(); - return ERR_FILE_EOF; - } else if (ret <= 0) { - TLSContextMbedTLS::print_mbedtls_error(ret); - disconnect_from_stream(); - return ERR_CONNECTION_ERROR; - } + do { + int ret = mbedtls_ssl_write(tls_ctx->get_context(), &p_data[r_sent], p_bytes - r_sent); + if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + // Non blocking IO. + break; + } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + // Clean close + disconnect_from_stream(); + return ERR_FILE_EOF; + } else if (ret <= 0) { + TLSContextMbedTLS::print_mbedtls_error(ret); + disconnect_from_stream(); + return ERR_CONNECTION_ERROR; + } + r_sent += ret; + + } while (r_sent < p_bytes); - r_sent = ret; return OK; } @@ -209,20 +212,25 @@ Error StreamPeerMbedTLS::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r r_received = 0; - int ret = mbedtls_ssl_read(tls_ctx->get_context(), p_buffer, p_bytes); - if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { - ret = 0; // non blocking io - } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - // Clean close - disconnect_from_stream(); - return ERR_FILE_EOF; - } else if (ret <= 0) { - TLSContextMbedTLS::print_mbedtls_error(ret); - disconnect_from_stream(); - return ERR_CONNECTION_ERROR; - } + do { + int ret = mbedtls_ssl_read(tls_ctx->get_context(), &p_buffer[r_received], p_bytes - r_received); + if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + // Non blocking IO. + break; + } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + // Clean close + disconnect_from_stream(); + return ERR_FILE_EOF; + } else if (ret <= 0) { + TLSContextMbedTLS::print_mbedtls_error(ret); + disconnect_from_stream(); + return ERR_CONNECTION_ERROR; + } + + r_received += ret; + + } while (r_received < p_bytes); - r_received = ret; return OK; } diff --git a/modules/meshoptimizer/register_types.cpp b/modules/meshoptimizer/register_types.cpp index 781f928f66..ebfe5d9c5b 100644 --- a/modules/meshoptimizer/register_types.cpp +++ b/modules/meshoptimizer/register_types.cpp @@ -40,10 +40,10 @@ void initialize_meshoptimizer_module(ModuleInitializationLevel p_level) { } SurfaceTool::optimize_vertex_cache_func = meshopt_optimizeVertexCache; + SurfaceTool::optimize_vertex_fetch_remap_func = meshopt_optimizeVertexFetchRemap; SurfaceTool::simplify_func = meshopt_simplify; SurfaceTool::simplify_with_attrib_func = meshopt_simplifyWithAttributes; SurfaceTool::simplify_scale_func = meshopt_simplifyScale; - SurfaceTool::simplify_sloppy_func = meshopt_simplifySloppy; SurfaceTool::generate_remap_func = meshopt_generateVertexRemap; SurfaceTool::remap_vertex_func = meshopt_remapVertexBuffer; SurfaceTool::remap_index_func = meshopt_remapIndexBuffer; @@ -55,9 +55,9 @@ void uninitialize_meshoptimizer_module(ModuleInitializationLevel p_level) { } SurfaceTool::optimize_vertex_cache_func = nullptr; + SurfaceTool::optimize_vertex_fetch_remap_func = nullptr; SurfaceTool::simplify_func = nullptr; SurfaceTool::simplify_scale_func = nullptr; - SurfaceTool::simplify_sloppy_func = nullptr; SurfaceTool::generate_remap_func = nullptr; SurfaceTool::remap_vertex_func = nullptr; SurfaceTool::remap_index_func = nullptr; diff --git a/modules/minimp3/doc_classes/ResourceImporterMP3.xml b/modules/minimp3/doc_classes/ResourceImporterMP3.xml index 72868623c7..fc0ec3682b 100644 --- a/modules/minimp3/doc_classes/ResourceImporterMP3.xml +++ b/modules/minimp3/doc_classes/ResourceImporterMP3.xml @@ -13,15 +13,15 @@ </tutorials> <members> <member name="bar_beats" type="int" setter="" getter="" default="4"> - The number of bars within a single beat in the audio track. This is only relevant for music that wishes to make use of interactive music functionality (not implemented yet), not sound effects. + The number of bars within a single beat in the audio track. This is only relevant for music that wishes to make use of interactive music functionality, not sound effects. A more convenient editor for [member bar_beats] is provided in the [b]Advanced Import Settings[/b] dialog, as it lets you preview your changes without having to reimport the audio. </member> <member name="beat_count" type="int" setter="" getter="" default="0"> - The beat count of the audio track. This is only relevant for music that wishes to make use of interactive music functionality (not implemented yet), not sound effects. + The beat count of the audio track. This is only relevant for music that wishes to make use of interactive music functionality, not sound effects. A more convenient editor for [member beat_count] is provided in the [b]Advanced Import Settings[/b] dialog, as it lets you preview your changes without having to reimport the audio. </member> <member name="bpm" type="float" setter="" getter="" default="0"> - The Beats Per Minute of the audio track. This should match the BPM measure that was used to compose the track. This is only relevant for music that wishes to make use of interactive music functionality (not implemented yet), not sound effects. + The beats per minute of the audio track. This should match the BPM measure that was used to compose the track. This is only relevant for music that wishes to make use of interactive music functionality, not sound effects. A more convenient editor for [member bpm] is provided in the [b]Advanced Import Settings[/b] dialog, as it lets you preview your changes without having to reimport the audio. </member> <member name="loop" type="bool" setter="" getter="" default="false"> diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index e4b54ef050..f1f0a771ad 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -115,7 +115,7 @@ Ref<AudioStreamMP3> ResourceImporterMP3::import_mp3(const String &p_path) { return mp3_stream; } -Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterMP3::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { bool loop = p_options["loop"]; float loop_offset = p_options["loop_offset"]; double bpm = p_options["bpm"]; diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h index 2df44deaea..35cc761eb4 100644 --- a/modules/minimp3/resource_importer_mp3.h +++ b/modules/minimp3/resource_importer_mp3.h @@ -57,7 +57,9 @@ public: #endif static Ref<AudioStreamMP3> import_mp3(const String &p_path); - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterMP3(); }; diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index f27281866a..e5f1a940ec 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -37,11 +37,11 @@ StringName MobileVRInterface::get_name() const { return "Native mobile"; -}; +} uint32_t MobileVRInterface::get_capabilities() const { return XRInterface::XR_STEREO; -}; +} Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) { // Our magnetometer doesn't give us nice clean data. @@ -98,7 +98,7 @@ Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) { }; return mag_scaled; -}; +} Basis MobileVRInterface::combine_acc_mag(const Vector3 &p_grav, const Vector3 &p_magneto) { // yup, stock standard cross product solution... @@ -117,7 +117,7 @@ Basis MobileVRInterface::combine_acc_mag(const Vector3 &p_grav, const Vector3 &p acc_mag_m3.rows[2] = magneto; return acc_mag_m3; -}; +} void MobileVRInterface::set_position_from_sensors() { _THREAD_SAFE_METHOD_ @@ -215,7 +215,7 @@ void MobileVRInterface::set_position_from_sensors() { head_transform.basis = orientation.orthonormalized(); last_ticks = ticks; -}; +} void MobileVRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("set_eye_height", "eye_height"), &MobileVRInterface::set_eye_height); @@ -280,51 +280,51 @@ Rect2 MobileVRInterface::get_offset_rect() const { void MobileVRInterface::set_iod(const double p_iod) { intraocular_dist = p_iod; -}; +} double MobileVRInterface::get_iod() const { return intraocular_dist; -}; +} void MobileVRInterface::set_display_width(const double p_display_width) { display_width = p_display_width; -}; +} double MobileVRInterface::get_display_width() const { return display_width; -}; +} void MobileVRInterface::set_display_to_lens(const double p_display_to_lens) { display_to_lens = p_display_to_lens; -}; +} double MobileVRInterface::get_display_to_lens() const { return display_to_lens; -}; +} void MobileVRInterface::set_oversample(const double p_oversample) { oversample = p_oversample; -}; +} double MobileVRInterface::get_oversample() const { return oversample; -}; +} void MobileVRInterface::set_k1(const double p_k1) { k1 = p_k1; -}; +} double MobileVRInterface::get_k1() const { return k1; -}; +} void MobileVRInterface::set_k2(const double p_k2) { k2 = p_k2; -}; +} double MobileVRInterface::get_k2() const { return k2; -}; +} float MobileVRInterface::get_vrs_min_radius() const { return xr_vrs.get_vrs_min_radius(); @@ -345,7 +345,7 @@ void MobileVRInterface::set_vrs_strength(float p_vrs_strength) { uint32_t MobileVRInterface::get_view_count() { // needs stereo... return 2; -}; +} XRInterface::TrackingStatus MobileVRInterface::get_tracking_status() const { return tracking_state; @@ -353,7 +353,7 @@ XRInterface::TrackingStatus MobileVRInterface::get_tracking_status() const { bool MobileVRInterface::is_initialized() const { return (initialized); -}; +} bool MobileVRInterface::initialize() { XRServer *xr_server = XRServer::get_singleton(); @@ -387,7 +387,7 @@ bool MobileVRInterface::initialize() { }; return true; -}; +} void MobileVRInterface::uninitialize() { if (initialized) { @@ -408,7 +408,7 @@ void MobileVRInterface::uninitialize() { initialized = false; }; -}; +} Dictionary MobileVRInterface::get_system_info() { Dictionary dict; @@ -442,7 +442,7 @@ Size2 MobileVRInterface::get_render_target_size() { target_size.y *= oversample; return target_size; -}; +} Transform3D MobileVRInterface::get_camera_transform() { _THREAD_SAFE_METHOD_ @@ -463,7 +463,7 @@ Transform3D MobileVRInterface::get_camera_transform() { } return transform_for_eye; -}; +} Transform3D MobileVRInterface::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) { _THREAD_SAFE_METHOD_ @@ -497,7 +497,7 @@ Transform3D MobileVRInterface::get_transform_for_view(uint32_t p_view, const Tra }; return transform_for_eye; -}; +} Projection MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { _THREAD_SAFE_METHOD_ @@ -508,7 +508,7 @@ Projection MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_ eye.set_for_hmd(p_view + 1, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far); return eye; -}; +} Vector<BlitToScreen> MobileVRInterface::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) { _THREAD_SAFE_METHOD_ @@ -571,7 +571,7 @@ void MobileVRInterface::process() { head->set_pose("default", head_transform, Vector3(), Vector3(), tracking_confidence); } }; -}; +} RID MobileVRInterface::get_vrs_texture() { PackedVector2Array eye_foci; @@ -597,4 +597,4 @@ MobileVRInterface::~MobileVRInterface() { if (is_initialized()) { uninitialize(); }; -}; +} diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index 490b1c393c..d054ef14b3 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -97,19 +97,19 @@ private: float floor_decimals(const float p_value, const float p_decimals) { float power_of_10 = pow(10.0f, p_decimals); return floor(p_value * power_of_10) / power_of_10; - }; + } Vector3 floor_decimals(const Vector3 &p_vector, const float p_decimals) { return Vector3(floor_decimals(p_vector.x, p_decimals), floor_decimals(p_vector.y, p_decimals), floor_decimals(p_vector.z, p_decimals)); - }; + } Vector3 low_pass(const Vector3 &p_vector, const Vector3 &p_last_vector, const float p_factor) { return p_vector + (p_factor * (p_last_vector - p_vector)); - }; + } Vector3 scrub(const Vector3 &p_vector, const Vector3 &p_last_vector, const float p_decimals, const float p_factor) { return low_pass(floor_decimals(p_vector, p_decimals), p_last_vector, p_factor); - }; + } void set_position_from_sensors(); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 3d12994469..ec9c123f8d 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -500,8 +500,8 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() } _recursion_flag_ = true; SCOPE_EXIT { - _recursion_flag_ = false; - }; + _recursion_flag_ = false; // clang-format off + }; // clang-format on if (!gdmono || !gdmono->is_runtime_initialized()) { return Vector<StackInfo>(); @@ -2817,7 +2817,7 @@ Ref<Resource> ResourceFormatLoaderCSharpScript::load(const String &p_path, const if (p_path.begins_with("csharp://")) { // This is a virtual path used by generic types, extract the real path. real_path = "res://" + p_path.trim_prefix("csharp://"); - real_path = real_path.substr(0, real_path.rfind(":")); + real_path = real_path.substr(0, real_path.rfind_char(':')); } Ref<CSharpScript> scr; @@ -2826,7 +2826,7 @@ Ref<Resource> ResourceFormatLoaderCSharpScript::load(const String &p_path, const GDMonoCache::managed_callbacks.ScriptManagerBridge_GetOrCreateScriptBridgeForPath(&p_path, &scr); ERR_FAIL_COND_V_MSG(scr.is_null(), Ref<Resource>(), "Could not create C# script '" + real_path + "'."); } else { - scr = Ref<CSharpScript>(memnew(CSharpScript)); + scr.instantiate(); } #if defined(DEBUG_ENABLED) || defined(TOOLS_ENABLED) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ExportDiagnosticsTests.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ExportDiagnosticsTests.cs index 6425c723dd..fe511d67ef 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ExportDiagnosticsTests.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ExportDiagnosticsTests.cs @@ -74,4 +74,31 @@ public class ExportDiagnosticsTests } ); } + + [Fact] + public async void ExportToolButtonInNonToolClass() + { + await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify( + new string[] { "ExportDiagnostics_GD0108.cs" }, + new string[] { "ExportDiagnostics_GD0108_ScriptProperties.generated.cs" } + ); + } + + [Fact] + public async void ExportAndExportToolButtonOnSameMember() + { + await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify( + new string[] { "ExportDiagnostics_GD0109.cs" }, + new string[] { "ExportDiagnostics_GD0109_ScriptProperties.generated.cs" } + ); + } + + [Fact] + public async void ExportToolButtonOnNonCallable() + { + await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify( + new string[] { "ExportDiagnostics_GD0110.cs" }, + new string[] { "ExportDiagnostics_GD0110_ScriptProperties.generated.cs" } + ); + } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs index 724fb164e0..9693cba9ce 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs @@ -66,4 +66,13 @@ public class ScriptPropertiesGeneratorTests "AbstractGenericNode(Of T)_ScriptProperties.generated.cs" ); } + + [Fact] + public async void ExportedButtons() + { + await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify( + "ExportedToolButtons.cs", + "ExportedToolButtons_ScriptProperties.generated.cs" + ); + } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs index 188972e6fe..5af859c06b 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs @@ -32,9 +32,9 @@ partial class EventSignals add => backing_MySignal += value; remove => backing_MySignal -= value; } - protected void OnMySignal(string str, int num) + protected void EmitSignalMySignal(string @str, int @num) { - EmitSignal(SignalName.MySignal, str, num); + EmitSignal(SignalName.MySignal, @str, @num); } /// <inheritdoc/> [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0108_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0108_ScriptProperties.generated.cs new file mode 100644 index 0000000000..77114a7c93 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0108_ScriptProperties.generated.cs @@ -0,0 +1,48 @@ +using Godot; +using Godot.NativeInterop; + +partial class ExportDiagnostics_GD0108 +{ +#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword + /// <summary> + /// Cached StringNames for the properties and fields contained in this class, for fast lookup. + /// </summary> + public new class PropertyName : global::Godot.Node.PropertyName { + /// <summary> + /// Cached name for the 'MyButton' field. + /// </summary> + public new static readonly global::Godot.StringName @MyButton = "MyButton"; + } + /// <inheritdoc/> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value) + { + if (name == PropertyName.@MyButton) { + this.@MyButton = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value); + return true; + } + return base.SetGodotClassPropertyValue(name, value); + } + /// <inheritdoc/> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value) + { + if (name == PropertyName.@MyButton) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton); + return true; + } + return base.GetGodotClassPropertyValue(name, out value); + } + /// <summary> + /// Get the property information for all the properties declared in this class. + /// This method is used by Godot to register the available properties in the editor. + /// Do not call this method. + /// </summary> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList() + { + var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>(); + return properties; + } +#pragma warning restore CS0109 +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0109_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0109_ScriptProperties.generated.cs new file mode 100644 index 0000000000..fc4547f2c1 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0109_ScriptProperties.generated.cs @@ -0,0 +1,48 @@ +using Godot; +using Godot.NativeInterop; + +partial class ExportDiagnostics_GD0109 +{ +#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword + /// <summary> + /// Cached StringNames for the properties and fields contained in this class, for fast lookup. + /// </summary> + public new class PropertyName : global::Godot.Node.PropertyName { + /// <summary> + /// Cached name for the 'MyButton' field. + /// </summary> + public new static readonly global::Godot.StringName @MyButton = "MyButton"; + } + /// <inheritdoc/> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value) + { + if (name == PropertyName.@MyButton) { + this.@MyButton = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value); + return true; + } + return base.SetGodotClassPropertyValue(name, value); + } + /// <inheritdoc/> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value) + { + if (name == PropertyName.@MyButton) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton); + return true; + } + return base.GetGodotClassPropertyValue(name, out value); + } + /// <summary> + /// Get the property information for all the properties declared in this class. + /// This method is used by Godot to register the available properties in the editor. + /// Do not call this method. + /// </summary> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList() + { + var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>(); + return properties; + } +#pragma warning restore CS0109 +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0110_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0110_ScriptProperties.generated.cs new file mode 100644 index 0000000000..d1aac17557 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0110_ScriptProperties.generated.cs @@ -0,0 +1,48 @@ +using Godot; +using Godot.NativeInterop; + +partial class ExportDiagnostics_GD0110 +{ +#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword + /// <summary> + /// Cached StringNames for the properties and fields contained in this class, for fast lookup. + /// </summary> + public new class PropertyName : global::Godot.Node.PropertyName { + /// <summary> + /// Cached name for the 'MyButton' field. + /// </summary> + public new static readonly global::Godot.StringName @MyButton = "MyButton"; + } + /// <inheritdoc/> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value) + { + if (name == PropertyName.@MyButton) { + this.@MyButton = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value); + return true; + } + return base.SetGodotClassPropertyValue(name, value); + } + /// <inheritdoc/> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value) + { + if (name == PropertyName.@MyButton) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.@MyButton); + return true; + } + return base.GetGodotClassPropertyValue(name, out value); + } + /// <summary> + /// Get the property information for all the properties declared in this class. + /// This method is used by Godot to register the available properties in the editor. + /// Do not call this method. + /// </summary> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList() + { + var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>(); + return properties; + } +#pragma warning restore CS0109 +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs index c734dc7be1..ffde135930 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs @@ -807,7 +807,7 @@ partial class ExportedFields properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@_fieldRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); - properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)38, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); + properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.@_fieldEmptyInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); return properties; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs index 0de840aa34..94d447f61a 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs @@ -925,7 +925,7 @@ partial class ExportedProperties properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@PropertyRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); - properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)38, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); + properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); return properties; } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedToolButtons_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedToolButtons_ScriptProperties.generated.cs new file mode 100644 index 0000000000..6e4ad1f13e --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedToolButtons_ScriptProperties.generated.cs @@ -0,0 +1,48 @@ +using Godot; +using Godot.NativeInterop; + +partial class ExportedToolButtons +{ +#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword + /// <summary> + /// Cached StringNames for the properties and fields contained in this class, for fast lookup. + /// </summary> + public new class PropertyName : global::Godot.GodotObject.PropertyName { + /// <summary> + /// Cached name for the 'MyButton1' property. + /// </summary> + public new static readonly global::Godot.StringName @MyButton1 = "MyButton1"; + /// <summary> + /// Cached name for the 'MyButton2' property. + /// </summary> + public new static readonly global::Godot.StringName @MyButton2 = "MyButton2"; + } + /// <inheritdoc/> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value) + { + if (name == PropertyName.@MyButton1) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton1); + return true; + } + if (name == PropertyName.@MyButton2) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton2); + return true; + } + return base.GetGodotClassPropertyValue(name, out value); + } + /// <summary> + /// Get the property information for all the properties declared in this class. + /// This method is used by Godot to register the available properties in the editor. + /// Do not call this method. + /// </summary> + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList() + { + var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>(); + properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButton1, hint: (global::Godot.PropertyHint)39, hintString: "Click me!", usage: (global::Godot.PropertyUsageFlags)4, exported: true)); + properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButton2, hint: (global::Godot.PropertyHint)39, hintString: "Click me!,ColorRect", usage: (global::Godot.PropertyUsageFlags)4, exported: true)); + return properties; + } +#pragma warning restore CS0109 +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0108.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0108.cs new file mode 100644 index 0000000000..6fde2e5957 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0108.cs @@ -0,0 +1,8 @@ +using Godot; +using Godot.Collections; + +public partial class ExportDiagnostics_GD0108 : Node +{ + [ExportToolButton("")] + public Callable {|GD0108:MyButton|}; +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0109.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0109.cs new file mode 100644 index 0000000000..80a04cd641 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0109.cs @@ -0,0 +1,9 @@ +using Godot; +using Godot.Collections; + +[Tool] +public partial class ExportDiagnostics_GD0109 : Node +{ + [Export, ExportToolButton("")] + public Callable {|GD0109:MyButton|}; +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0110.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0110.cs new file mode 100644 index 0000000000..586bf6c19e --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0110.cs @@ -0,0 +1,9 @@ +using Godot; +using Godot.Collections; + +[Tool] +public partial class ExportDiagnostics_GD0110 : Node +{ + [ExportToolButton("")] + public string {|GD0110:MyButton|}; +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedToolButtons.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedToolButtons.cs new file mode 100644 index 0000000000..91c14387c5 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedToolButtons.cs @@ -0,0 +1,12 @@ +using Godot; +using System; + +[Tool] +public partial class ExportedToolButtons : GodotObject +{ + [ExportToolButton("Click me!")] + public Callable MyButton1 => Callable.From(() => { GD.Print("Clicked MyButton1!"); }); + + [ExportToolButton("Click me!", Icon = "ColorRect")] + public Callable MyButton2 => Callable.From(() => { GD.Print("Clicked MyButton2!"); }); +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md index 7286853f7a..90c8491177 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md @@ -3,3 +3,6 @@ Rule ID | Category | Severity | Notes --------|----------|----------|-------------------- GD0003 | Usage | Error | ScriptPathAttributeGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0003.html) +GD0108 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0108.html) +GD0109 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0109.html) +GD0110 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0110.html) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs index ad7962e7df..8da0818e42 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs @@ -107,6 +107,36 @@ namespace Godot.SourceGenerators "Types not derived from Node should not export Node members. Node export is only supported in Node-derived classes.", helpLinkUri: string.Format(_helpLinkFormat, "GD0107")); + public static readonly DiagnosticDescriptor OnlyToolClassesShouldUseExportToolButtonRule = + new DiagnosticDescriptor(id: "GD0108", + title: "The exported tool button is not in a tool class", + messageFormat: "The exported tool button '{0}' is not in a tool class", + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + "The exported tool button is not in a tool class. Annotate the class with the '[Tool]' attribute, or remove the '[ExportToolButton]' attribute.", + helpLinkUri: string.Format(_helpLinkFormat, "GD0108")); + + public static readonly DiagnosticDescriptor ExportToolButtonShouldNotBeUsedWithExportRule = + new DiagnosticDescriptor(id: "GD0109", + title: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute", + messageFormat: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute on '{0}'", + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + "The '[ExportToolButton]' attribute cannot be used with the '[Export]' attribute. Remove one of the attributes.", + helpLinkUri: string.Format(_helpLinkFormat, "GD0109")); + + public static readonly DiagnosticDescriptor ExportToolButtonIsNotCallableRule = + new DiagnosticDescriptor(id: "GD0110", + title: "The exported tool button is not a Callable", + messageFormat: "The exported tool button '{0}' is not a Callable", + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + "The exported tool button is not a Callable. The '[ExportToolButton]' attribute is only supported on members of type Callable.", + helpLinkUri: string.Format(_helpLinkFormat, "GD0110")); + public static readonly DiagnosticDescriptor SignalDelegateMissingSuffixRule = new DiagnosticDescriptor(id: "GD0201", title: "The name of the delegate must end with 'EventHandler'", diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs index 62fa7b0a36..46c446169a 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs @@ -287,6 +287,12 @@ namespace Godot.SourceGenerators public static bool IsGodotGlobalClassAttribute(this INamedTypeSymbol symbol) => symbol.FullQualifiedNameOmitGlobal() == GodotClasses.GlobalClassAttr; + public static bool IsGodotExportToolButtonAttribute(this INamedTypeSymbol symbol) + => symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ExportToolButtonAttr; + + public static bool IsGodotToolAttribute(this INamedTypeSymbol symbol) + => symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ToolAttr; + public static bool IsSystemFlagsAttribute(this INamedTypeSymbol symbol) => symbol.FullQualifiedNameOmitGlobal() == GodotClasses.SystemFlagsAttr; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs index af39a54b0b..f6de09e25b 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs @@ -9,10 +9,12 @@ namespace Godot.SourceGenerators public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute"; public const string ExportGroupAttr = "Godot.ExportGroupAttribute"; public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute"; + public const string ExportToolButtonAttr = "Godot.ExportToolButtonAttribute"; public const string SignalAttr = "Godot.SignalAttribute"; public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute"; public const string GodotClassNameAttr = "Godot.GodotClassNameAttribute"; public const string GlobalClassAttr = "Godot.GlobalClassAttribute"; + public const string ToolAttr = "Godot.ToolAttribute"; public const string SystemFlagsAttr = "System.FlagsAttribute"; } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs index bb4c4824e7..d77ebc3cec 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs @@ -89,7 +89,8 @@ namespace Godot.SourceGenerators Password = 36, LayersAvoidance = 37, DictionaryType = 38, - Max = 39 + ToolButton = 39, + Max = 40 } [Flags] diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs index 0f86b3b91c..a8033914e7 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs @@ -69,6 +69,7 @@ namespace Godot.SourceGenerators bool hasNamespace = classNs.Length != 0; bool isInnerClass = symbol.ContainingType != null; + bool isToolClass = symbol.GetAttributes().Any(a => a.AttributeClass?.IsGodotToolAttribute() ?? false); string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint() + "_ScriptProperties.generated"; @@ -277,6 +278,16 @@ namespace Godot.SourceGenerators if (propertyInfo == null) continue; + if (propertyInfo.Value.Hint == PropertyHint.ToolButton && !isToolClass) + { + context.ReportDiagnostic(Diagnostic.Create( + Common.OnlyToolClassesShouldUseExportToolButtonRule, + member.Symbol.Locations.FirstLocationWithSourceTreeOrDefault(), + member.Symbol.ToDisplayString() + )); + continue; + } + AppendPropertyInfo(source, propertyInfo.Value); } @@ -418,47 +429,82 @@ namespace Godot.SourceGenerators var exportAttr = memberSymbol.GetAttributes() .FirstOrDefault(a => a.AttributeClass?.IsGodotExportAttribute() ?? false); + var exportToolButtonAttr = memberSymbol.GetAttributes() + .FirstOrDefault(a => a.AttributeClass?.IsGodotExportToolButtonAttribute() ?? false); + + if (exportAttr != null && exportToolButtonAttr != null) + { + context.ReportDiagnostic(Diagnostic.Create( + Common.ExportToolButtonShouldNotBeUsedWithExportRule, + memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(), + memberSymbol.ToDisplayString() + )); + return null; + } + var propertySymbol = memberSymbol as IPropertySymbol; var fieldSymbol = memberSymbol as IFieldSymbol; if (exportAttr != null && propertySymbol != null) { - if (propertySymbol.GetMethod == null) + if (propertySymbol.GetMethod == null || propertySymbol.SetMethod == null || propertySymbol.SetMethod.IsInitOnly) { - // This should never happen, as we filtered WriteOnly properties, but just in case. - context.ReportDiagnostic(Diagnostic.Create( - Common.ExportedPropertyIsWriteOnlyRule, - propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(), - propertySymbol.ToDisplayString() - )); + // Exports can be neither read-only nor write-only but the diagnostic errors for properties are already + // reported by ScriptPropertyDefValGenerator.cs so just quit early here. return null; } + } + + if (exportToolButtonAttr != null && propertySymbol != null && propertySymbol.GetMethod == null) + { + context.ReportDiagnostic(Diagnostic.Create( + Common.ExportedPropertyIsWriteOnlyRule, + propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(), + propertySymbol.ToDisplayString() + )); + return null; + } + + var memberType = propertySymbol?.Type ?? fieldSymbol!.Type; + + var memberVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(marshalType)!.Value; + string memberName = memberSymbol.Name; + + string? hintString = null; - if (propertySymbol.SetMethod == null || propertySymbol.SetMethod.IsInitOnly) + if (exportToolButtonAttr != null) + { + if (memberVariantType != VariantType.Callable) { - // This should never happen, as we filtered ReadOnly properties, but just in case. context.ReportDiagnostic(Diagnostic.Create( - Common.ExportedMemberIsReadOnlyRule, - propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(), - propertySymbol.ToDisplayString() + Common.ExportToolButtonIsNotCallableRule, + memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(), + memberSymbol.ToDisplayString() )); return null; } - } - var memberType = propertySymbol?.Type ?? fieldSymbol!.Type; + hintString = exportToolButtonAttr.ConstructorArguments[0].Value?.ToString() ?? ""; + foreach (var namedArgument in exportToolButtonAttr.NamedArguments) + { + if (namedArgument is { Key: "Icon", Value.Value: string { Length: > 0 } }) + { + hintString += $",{namedArgument.Value.Value}"; + } + } - var memberVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(marshalType)!.Value; - string memberName = memberSymbol.Name; + return new PropertyInfo(memberVariantType, memberName, PropertyHint.ToolButton, + hintString: hintString, PropertyUsageFlags.Editor, exported: true); + } if (exportAttr == null) { return new PropertyInfo(memberVariantType, memberName, PropertyHint.None, - hintString: null, PropertyUsageFlags.ScriptVariable, exported: false); + hintString: hintString, PropertyUsageFlags.ScriptVariable, exported: false); } if (!TryGetMemberExportHint(typeCache, memberType, exportAttr, memberVariantType, - isTypeArgument: false, out var hint, out var hintString)) + isTypeArgument: false, out var hint, out hintString)) { var constructorArguments = exportAttr.ConstructorArguments; @@ -735,8 +781,18 @@ namespace Godot.SourceGenerators return false; // Non-generic Dictionary, so there's no hint to add Debug.Assert(elementTypes.Length == 2); - var keyElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[0], typeCache)!.Value; - var keyElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(keyElementMarshalType)!.Value; + var keyElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[0], typeCache); + var valueElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[1], typeCache); + + if (keyElementMarshalType == null || valueElementMarshalType == null) + { + // To maintain compatibility with previous versions of Godot before 4.4, + // we must preserve the old behavior for generic dictionaries with non-marshallable + // generic type arguments. + return false; + } + + var keyElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(keyElementMarshalType.Value)!.Value; var keyIsPresetHint = false; var keyHintString = (string?)null; @@ -763,8 +819,7 @@ namespace Godot.SourceGenerators } } - var valueElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[1], typeCache)!.Value; - var valueElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(valueElementMarshalType)!.Value; + var valueElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(valueElementMarshalType.Value)!.Value; var valueIsPresetHint = false; var valueHintString = (string?)null; @@ -791,7 +846,7 @@ namespace Godot.SourceGenerators } } - hint = PropertyHint.DictionaryType; + hint = PropertyHint.TypeString; hintString = keyHintString != null && valueHintString != null ? $"{keyHintString};{valueHintString}" : null; return hintString != null; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs index 0dda43ab4c..c7a7415851 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs @@ -282,7 +282,7 @@ namespace Godot.SourceGenerators .Append(" -= value;\n") .Append("}\n"); - // Generate On{EventName} method to raise the event + // Generate EmitSignal{EventName} method to raise the event var invokeMethodSymbol = signalDelegate.InvokeMethodData.Method; int paramCount = invokeMethodSymbol.Parameters.Length; @@ -291,11 +291,11 @@ namespace Godot.SourceGenerators "private" : "protected"; - source.Append($" {raiseMethodModifiers} void On{signalName}("); + source.Append($" {raiseMethodModifiers} void EmitSignal{signalName}("); for (int i = 0; i < paramCount; i++) { var paramSymbol = invokeMethodSymbol.Parameters[i]; - source.Append($"{paramSymbol.Type.FullQualifiedNameIncludeGlobal()} {paramSymbol.Name}"); + source.Append($"{paramSymbol.Type.FullQualifiedNameIncludeGlobal()} @{paramSymbol.Name}"); if (i < paramCount - 1) { source.Append(", "); @@ -310,11 +310,11 @@ namespace Godot.SourceGenerators if (paramSymbol.Type.TypeKind == TypeKind.Enum) { var underlyingType = ((INamedTypeSymbol)paramSymbol.Type).EnumUnderlyingType; - source.Append($", ({underlyingType.FullQualifiedNameIncludeGlobal()}){paramSymbol.Name}"); + source.Append($", ({underlyingType.FullQualifiedNameIncludeGlobal()})@{paramSymbol.Name}"); continue; } - source.Append($", {paramSymbol.Name}"); + source.Append($", @{paramSymbol.Name}"); } source.Append(");\n"); source.Append(" }\n"); diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 788b46ab9a..74e04b46a1 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -177,7 +177,7 @@ namespace GodotTools private static readonly string[] VsCodeNames = { - "code", "code-oss", "vscode", "vscode-oss", "visual-studio-code", "visual-studio-code-oss" + "code", "code-oss", "vscode", "vscode-oss", "visual-studio-code", "visual-studio-code-oss", "codium" }; [UsedImplicitly] @@ -330,7 +330,7 @@ namespace GodotTools args.Add("-b"); args.Add(vscodeBundleId); - // The reusing of existing windows made by the 'open' command might not choose a wubdiw that is + // The reusing of existing windows made by the 'open' command might not choose a window that is // editing our folder. It's better to ask for a new window and let VSCode do the window management. args.Add("-n"); @@ -339,6 +339,28 @@ namespace GodotTools args.Add("--args"); } + + // Try VSCodium as a fallback if Visual Studio Code can't be found. + if (!macOSAppBundleInstalled) + { + const string VscodiumBundleId = "com.vscodium.codium"; + macOSAppBundleInstalled = Internal.IsMacOSAppBundleInstalled(VscodiumBundleId); + + if (macOSAppBundleInstalled) + { + args.Add("-b"); + args.Add(VscodiumBundleId); + + // The reusing of existing windows made by the 'open' command might not choose a window that is + // editing our folder. It's better to ask for a new window and let VSCode do the window management. + args.Add("-n"); + + // The open process must wait until the application finishes (which is instant in VSCode's case) + args.Add("--wait-apps"); + + args.Add("--args"); + } + } } args.Add(Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath)!); @@ -361,7 +383,7 @@ namespace GodotTools { if (!macOSAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) { - GD.PushError("Cannot find code editor: VSCode"); + GD.PushError("Cannot find code editor: Visual Studio Code or VSCodium"); return Error.FileNotFound; } @@ -371,7 +393,7 @@ namespace GodotTools { if (string.IsNullOrEmpty(_vsCodePath)) { - GD.PushError("Cannot find code editor: VSCode"); + GD.PushError("Cannot find code editor: Visual Studio Code or VSCodium"); return Error.FileNotFound; } @@ -384,7 +406,7 @@ namespace GodotTools } catch (Exception e) { - GD.PushError($"Error when trying to run code editor: VSCode. Exception message: '{e.Message}'"); + GD.PushError($"Error when trying to run code editor: Visual Studio Code or VSCodium. Exception message: '{e.Message}'"); } break; @@ -550,7 +572,7 @@ namespace GodotTools { settingsHintStr += $",Visual Studio:{(int)ExternalEditorId.VisualStudio}" + $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + - $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + + $",Visual Studio Code and VSCodium:{(int)ExternalEditorId.VsCode}" + $",JetBrains Rider and Fleet:{(int)ExternalEditorId.Rider}" + $",Custom:{(int)ExternalEditorId.CustomEditor}"; } @@ -558,14 +580,14 @@ namespace GodotTools { settingsHintStr += $",Visual Studio:{(int)ExternalEditorId.VisualStudioForMac}" + $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + - $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + + $",Visual Studio Code and VSCodium:{(int)ExternalEditorId.VsCode}" + $",JetBrains Rider and Fleet:{(int)ExternalEditorId.Rider}" + $",Custom:{(int)ExternalEditorId.CustomEditor}"; } else if (OS.IsUnixLike) { settingsHintStr += $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + - $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + + $",Visual Studio Code and VSCodium:{(int)ExternalEditorId.VsCode}" + $",JetBrains Rider and Fleet:{(int)ExternalEditorId.Rider}" + $",Custom:{(int)ExternalEditorId.CustomEditor}"; } diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 946e997c1b..d0797282de 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -190,7 +190,7 @@ String BindingsGenerator::bbcode_to_text(const String &p_bbcode, const TypeInter int pos = 0; while (pos < bbcode.length()) { - int brk_pos = bbcode.find("[", pos); + int brk_pos = bbcode.find_char('[', pos); if (brk_pos < 0) { brk_pos = bbcode.length(); @@ -210,7 +210,7 @@ String BindingsGenerator::bbcode_to_text(const String &p_bbcode, const TypeInter break; } - int brk_end = bbcode.find("]", brk_pos + 1); + int brk_end = bbcode.find_char(']', brk_pos + 1); if (brk_end == -1) { String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos); @@ -239,7 +239,7 @@ String BindingsGenerator::bbcode_to_text(const String &p_bbcode, const TypeInter output.append("["); pos = brk_pos + 1; } else if (tag.begins_with("method ") || tag.begins_with("constructor ") || tag.begins_with("operator ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ") || tag.begins_with("param ")) { - const int tag_end = tag.find(" "); + const int tag_end = tag.find_char(' '); const String link_tag = tag.substr(0, tag_end); const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" "); @@ -385,7 +385,7 @@ String BindingsGenerator::bbcode_to_text(const String &p_bbcode, const TypeInter pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "url") { - int end = bbcode.find("[", brk_end); + int end = bbcode.find_char('[', brk_end); if (end == -1) { end = bbcode.length(); } @@ -403,7 +403,7 @@ String BindingsGenerator::bbcode_to_text(const String &p_bbcode, const TypeInter pos = brk_end + 1; tag_stack.push_front("url"); } else if (tag == "img") { - int end = bbcode.find("[", brk_end); + int end = bbcode.find_char('[', brk_end); if (end == -1) { end = bbcode.length(); } @@ -455,7 +455,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf int pos = 0; while (pos < bbcode.length()) { - int brk_pos = bbcode.find("[", pos); + int brk_pos = bbcode.find_char('[', pos); if (brk_pos < 0) { brk_pos = bbcode.length(); @@ -488,7 +488,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf break; } - int brk_end = bbcode.find("]", brk_pos + 1); + int brk_end = bbcode.find_char(']', brk_pos + 1); if (brk_end == -1) { if (!line_del) { @@ -551,7 +551,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append("["); pos = brk_pos + 1; } else if (tag.begins_with("method ") || tag.begins_with("constructor ") || tag.begins_with("operator ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ") || tag.begins_with("param ")) { - const int tag_end = tag.find(" "); + const int tag_end = tag.find_char(' '); const String link_tag = tag.substr(0, tag_end); const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" "); @@ -696,7 +696,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "code" || tag.begins_with("code ")) { - int end = bbcode.find("[", brk_end); + int end = bbcode.find_char('[', brk_end); if (end == -1) { end = bbcode.length(); } @@ -751,7 +751,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "url") { - int end = bbcode.find("[", brk_end); + int end = bbcode.find_char('[', brk_end); if (end == -1) { end = bbcode.length(); } @@ -772,7 +772,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf pos = brk_end + 1; tag_stack.push_front("url"); } else if (tag == "img") { - int end = bbcode.find("[", brk_end); + int end = bbcode.find_char('[', brk_end); if (end == -1) { end = bbcode.length(); } @@ -1619,7 +1619,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { bool enum_in_static_class = false; - if (enum_proxy_name.find(".") > 0) { + if (enum_proxy_name.find_char('.') > 0) { enum_in_static_class = true; String enum_class_name = enum_proxy_name.get_slicec('.', 0); enum_proxy_name = enum_proxy_name.get_slicec('.', 1); @@ -3275,10 +3275,10 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf p_output.append(CLOSE_BLOCK_L1); - // Generate On{EventName} method to raise the event. + // Generate EmitSignal{EventName} method to raise the event. if (!p_itype.is_singleton) { p_output.append(MEMBER_BEGIN "protected void "); - p_output << "On" << p_isignal.proxy_name; + p_output << "EmitSignal" << p_isignal.proxy_name; if (is_parameterless) { p_output.append("()\n" OPEN_BLOCK_L1 INDENT2); p_output << "EmitSignal(SignalName." << p_isignal.proxy_name << ");\n"; @@ -4372,9 +4372,45 @@ bool BindingsGenerator::_populate_object_type_interfaces() { return true; } +static String _get_vector2_cs_ctor_args(const Vector2 &p_vec2) { + return String::num_real(p_vec2.x, true) + "f, " + + String::num_real(p_vec2.y, true) + "f"; +} + +static String _get_vector3_cs_ctor_args(const Vector3 &p_vec3) { + return String::num_real(p_vec3.x, true) + "f, " + + String::num_real(p_vec3.y, true) + "f, " + + String::num_real(p_vec3.z, true) + "f"; +} + +static String _get_vector4_cs_ctor_args(const Vector4 &p_vec4) { + return String::num_real(p_vec4.x, true) + "f, " + + String::num_real(p_vec4.y, true) + "f, " + + String::num_real(p_vec4.z, true) + "f, " + + String::num_real(p_vec4.w, true) + "f"; +} + +static String _get_vector2i_cs_ctor_args(const Vector2i &p_vec2i) { + return itos(p_vec2i.x) + ", " + itos(p_vec2i.y); +} + +static String _get_vector3i_cs_ctor_args(const Vector3i &p_vec3i) { + return itos(p_vec3i.x) + ", " + itos(p_vec3i.y) + ", " + itos(p_vec3i.z); +} + +static String _get_vector4i_cs_ctor_args(const Vector4i &p_vec4i) { + return itos(p_vec4i.x) + ", " + itos(p_vec4i.y) + ", " + itos(p_vec4i.z) + ", " + itos(p_vec4i.w); +} + +static String _get_color_cs_ctor_args(const Color &p_color) { + return String::num(p_color.r, 4) + "f, " + + String::num(p_color.g, 4) + "f, " + + String::num(p_color.b, 4) + "f, " + + String::num(p_color.a, 4) + "f"; +} + bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg) { r_iarg.def_param_value = p_val; - r_iarg.default_argument = p_val.operator String(); switch (p_val.get_type()) { case Variant::NIL: @@ -4387,10 +4423,14 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar break; case Variant::INT: if (r_iarg.type.cname != name_cache.type_int) { - r_iarg.default_argument = "(%s)(" + r_iarg.default_argument + ")"; + r_iarg.default_argument = "(%s)(" + p_val.operator String() + ")"; + } else { + r_iarg.default_argument = p_val.operator String(); } break; case Variant::FLOAT: + r_iarg.default_argument = p_val.operator String(); + if (r_iarg.type.cname == name_cache.type_float) { r_iarg.default_argument += "f"; } @@ -4400,7 +4440,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar case Variant::NODE_PATH: if (r_iarg.type.cname == name_cache.type_StringName || r_iarg.type.cname == name_cache.type_NodePath) { if (r_iarg.default_argument.length() > 0) { - r_iarg.default_argument = "(%s)\"" + r_iarg.default_argument + "\""; + r_iarg.default_argument = "(%s)\"" + p_val.operator String() + "\""; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; } else { // No need for a special `in` statement to change `null` to `""`. Marshaling takes care of this already. @@ -4408,40 +4448,62 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar } } else { CRASH_COND(r_iarg.type.cname != name_cache.type_String); - r_iarg.default_argument = "\"" + r_iarg.default_argument + "\""; + r_iarg.default_argument = "\"" + p_val.operator String() + "\""; } break; case Variant::PLANE: { Plane plane = p_val.operator Plane(); - r_iarg.default_argument = "new Plane(new Vector3" + plane.normal.operator String() + ", " + rtos(plane.d) + ")"; + r_iarg.default_argument = "new Plane(new Vector3(" + + _get_vector3_cs_ctor_args(plane.normal) + "), " + rtos(plane.d) + "f)"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; case Variant::AABB: { AABB aabb = p_val.operator ::AABB(); - r_iarg.default_argument = "new Aabb(new Vector3" + aabb.position.operator String() + ", new Vector3" + aabb.size.operator String() + ")"; + r_iarg.default_argument = "new Aabb(new Vector3(" + + _get_vector3_cs_ctor_args(aabb.position) + "), new Vector3(" + + _get_vector3_cs_ctor_args(aabb.size) + "))"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; case Variant::RECT2: { Rect2 rect = p_val.operator Rect2(); - r_iarg.default_argument = "new Rect2(new Vector2" + rect.position.operator String() + ", new Vector2" + rect.size.operator String() + ")"; + r_iarg.default_argument = "new Rect2(new Vector2(" + + _get_vector2_cs_ctor_args(rect.position) + "), new Vector2(" + + _get_vector2_cs_ctor_args(rect.size) + "))"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; case Variant::RECT2I: { Rect2i rect = p_val.operator Rect2i(); - r_iarg.default_argument = "new Rect2I(new Vector2I" + rect.position.operator String() + ", new Vector2I" + rect.size.operator String() + ")"; + r_iarg.default_argument = "new Rect2I(new Vector2I(" + + _get_vector2i_cs_ctor_args(rect.position) + "), new Vector2I(" + + _get_vector2i_cs_ctor_args(rect.size) + "))"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; case Variant::COLOR: + r_iarg.default_argument = "new Color(" + _get_color_cs_ctor_args(p_val.operator Color()) + ")"; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::VECTOR2: + r_iarg.default_argument = "new Vector2(" + _get_vector2_cs_ctor_args(p_val.operator Vector2()) + ")"; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::VECTOR2I: + r_iarg.default_argument = "new Vector2I(" + _get_vector2i_cs_ctor_args(p_val.operator Vector2i()) + ")"; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::VECTOR3: + r_iarg.default_argument = "new Vector3(" + _get_vector3_cs_ctor_args(p_val.operator Vector3()) + ")"; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::VECTOR3I: - r_iarg.default_argument = "new %s" + r_iarg.default_argument; + r_iarg.default_argument = "new Vector3I(" + _get_vector3i_cs_ctor_args(p_val.operator Vector3i()) + ")"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; case Variant::VECTOR4: + r_iarg.default_argument = "new Vector4(" + _get_vector4_cs_ctor_args(p_val.operator Vector4()) + ")"; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::VECTOR4I: - r_iarg.default_argument = "new %s" + r_iarg.default_argument; + r_iarg.default_argument = "new Vector4I(" + _get_vector4i_cs_ctor_args(p_val.operator Vector4i()) + ")"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; case Variant::OBJECT: @@ -4491,7 +4553,10 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar if (transform == Transform2D()) { r_iarg.default_argument = "Transform2D.Identity"; } else { - r_iarg.default_argument = "new Transform2D(new Vector2" + transform.columns[0].operator String() + ", new Vector2" + transform.columns[1].operator String() + ", new Vector2" + transform.columns[2].operator String() + ")"; + r_iarg.default_argument = "new Transform2D(new Vector2(" + + _get_vector2_cs_ctor_args(transform.columns[0]) + "), new Vector2(" + + _get_vector2_cs_ctor_args(transform.columns[1]) + "), new Vector2(" + + _get_vector2_cs_ctor_args(transform.columns[2]) + "))"; } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; @@ -4501,7 +4566,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = "Transform3D.Identity"; } else { Basis basis = transform.basis; - r_iarg.default_argument = "new Transform3D(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")"; + r_iarg.default_argument = "new Transform3D(new Vector3(" + + _get_vector3_cs_ctor_args(basis.get_column(0)) + "), new Vector3(" + + _get_vector3_cs_ctor_args(basis.get_column(1)) + "), new Vector3(" + + _get_vector3_cs_ctor_args(basis.get_column(2)) + "), new Vector3(" + + _get_vector3_cs_ctor_args(transform.origin) + "))"; } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; @@ -4510,7 +4579,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar if (projection == Projection()) { r_iarg.default_argument = "Projection.Identity"; } else { - r_iarg.default_argument = "new Projection(new Vector4" + projection.columns[0].operator String() + ", new Vector4" + projection.columns[1].operator String() + ", new Vector4" + projection.columns[2].operator String() + ", new Vector4" + projection.columns[3].operator String() + ")"; + r_iarg.default_argument = "new Projection(new Vector4(" + + _get_vector4_cs_ctor_args(projection.columns[0]) + "), new Vector4(" + + _get_vector4_cs_ctor_args(projection.columns[1]) + "), new Vector4(" + + _get_vector4_cs_ctor_args(projection.columns[2]) + "), new Vector4(" + + _get_vector4_cs_ctor_args(projection.columns[3]) + "))"; } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; @@ -4519,7 +4592,10 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar if (basis == Basis()) { r_iarg.default_argument = "Basis.Identity"; } else { - r_iarg.default_argument = "new Basis(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ")"; + r_iarg.default_argument = "new Basis(new Vector3(" + + _get_vector3_cs_ctor_args(basis.get_column(0)) + "), new Vector3(" + + _get_vector3_cs_ctor_args(basis.get_column(1)) + "), new Vector3(" + + _get_vector3_cs_ctor_args(basis.get_column(2)) + "))"; } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; @@ -4528,7 +4604,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar if (quaternion == Quaternion()) { r_iarg.default_argument = "Quaternion.Identity"; } else { - r_iarg.default_argument = "new Quaternion" + quaternion.operator String(); + r_iarg.default_argument = "new Quaternion(" + + String::num_real(quaternion.x, false) + "f, " + + String::num_real(quaternion.y, false) + "f, " + + String::num_real(quaternion.z, false) + "f, " + + String::num_real(quaternion.w, false) + "f)"; } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; @@ -4960,22 +5040,25 @@ void BindingsGenerator::_populate_global_constants() { } } - // HARDCODED - List<StringName> hardcoded_enums; - hardcoded_enums.push_back("Vector2.Axis"); - hardcoded_enums.push_back("Vector2I.Axis"); - hardcoded_enums.push_back("Vector3.Axis"); - hardcoded_enums.push_back("Vector3I.Axis"); - for (const StringName &enum_cname : hardcoded_enums) { - // These enums are not generated and must be written manually (e.g.: Vector3.Axis) - // Here, we assume core types do not begin with underscore - TypeInterface enum_itype; - enum_itype.is_enum = true; - enum_itype.name = enum_cname.operator String(); - enum_itype.cname = enum_cname; - enum_itype.proxy_name = pascal_to_pascal_case(enum_itype.name); - TypeInterface::postsetup_enum_type(enum_itype); - enum_types.insert(enum_itype.cname, enum_itype); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + if (i == Variant::OBJECT) { + continue; + } + + const Variant::Type type = Variant::Type(i); + + List<StringName> enum_names; + Variant::get_enums_for_type(type, &enum_names); + + for (const StringName &enum_name : enum_names) { + TypeInterface enum_itype; + enum_itype.is_enum = true; + enum_itype.name = Variant::get_type_name(type) + "." + enum_name; + enum_itype.cname = enum_itype.name; + enum_itype.proxy_name = pascal_to_pascal_case(enum_itype.name); + TypeInterface::postsetup_enum_type(enum_itype); + enum_types.insert(enum_itype.cname, enum_itype); + } } } diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp index ae914e71ef..94222f3d67 100644 --- a/modules/mono/editor/code_completion.cpp +++ b/modules/mono/editor/code_completion.cpp @@ -116,7 +116,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr continue; } - String name = prop.name.substr(prop.name.find("/") + 1, prop.name.length()); + String name = prop.name.substr(prop.name.find_char('/') + 1, prop.name.length()); suggestions.push_back(quoted(name)); } } break; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportToolButtonAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportToolButtonAttribute.cs new file mode 100644 index 0000000000..87a9e628f9 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportToolButtonAttribute.cs @@ -0,0 +1,33 @@ +using System; + +#nullable enable + +namespace Godot +{ + /// <summary> + /// Exports the annotated <see cref="Callable"/> as a clickable button. + /// </summary> + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] + public sealed class ExportToolButtonAttribute : Attribute + { + /// <summary> + /// The label of the button. + /// </summary> + public string Text { get; } + + /// <summary> + /// If defined, used to fetch an icon for the button via <see cref="Control.GetThemeIcon"/>, + /// from the <code>EditorIcons</code> theme type. + /// </summary> + public string? Icon { get; init; } + + /// <summary> + /// Exports the annotated <see cref="Callable"/> as a clickable button. + /// </summary> + /// <param name="text">The label of the button.</param> + public ExportToolButtonAttribute(string text) + { + Text = text; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs index dc151e2c3e..222ded6895 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs @@ -534,7 +534,10 @@ namespace Godot.NativeInterop [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Callable ConvertToCallable(in godot_variant p_var) - => Marshaling.ConvertCallableToManaged(ConvertToNativeCallable(p_var)); + { + using var callable = ConvertToNativeCallable(p_var); + return Marshaling.ConvertCallableToManaged(callable); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static godot_signal ConvertToNativeSignal(in godot_variant p_var) @@ -542,7 +545,10 @@ namespace Godot.NativeInterop [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Signal ConvertToSignal(in godot_variant p_var) - => Marshaling.ConvertSignalToManaged(ConvertToNativeSignal(p_var)); + { + using var signal = ConvertToNativeSignal(p_var); + return Marshaling.ConvertSignalToManaged(signal); + } public static godot_array ConvertToNativeArray(in godot_variant p_var) => p_var.Type == Variant.Type.Array ? diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 3a3134d160..5aa68559d8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -48,6 +48,7 @@ <!-- Sources --> <ItemGroup> <Compile Include="Core\Aabb.cs" /> + <Compile Include="Core\Attributes\ExportToolButtonAttribute.cs" /> <Compile Include="Core\Bridge\GodotSerializationInfo.cs" /> <Compile Include="Core\Bridge\MethodInfo.cs" /> <Compile Include="Core\Callable.generics.cs" /> diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index ee17a668d7..068ac8b4e1 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -212,7 +212,7 @@ String relative_to_impl(const String &p_path, const String &p_relative_to) { #ifdef WINDOWS_ENABLED String get_drive_letter(const String &p_norm_path) { int idx = p_norm_path.find(":/"); - if (idx != -1 && idx < p_norm_path.find("/")) { + if (idx != -1 && idx < p_norm_path.find_char('/')) { return p_norm_path.substr(0, idx + 1); } return String(); diff --git a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml index c2d879962c..edcaa3baef 100644 --- a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml +++ b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml @@ -53,7 +53,7 @@ </methods> <members> <member name="delta_interval" type="float" setter="set_delta_interval" getter="get_delta_interval" default="0.0"> - Time interval between delta synchronizations. When set to [code]0.0[/code] (the default), delta synchronizations happen every network process frame. + Time interval between delta synchronizations. Used when the replication is set to [constant SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE]. If set to [code]0.0[/code] (the default), delta synchronizations happen every network process frame. </member> <member name="public_visibility" type="bool" setter="set_visibility_public" getter="is_visibility_public" default="true"> Whether synchronization should be visible to all peers by default. See [method set_visibility_for] and [method add_visibility_filter] for ways of configuring fine-grained visibility options. @@ -62,7 +62,7 @@ Resource containing which properties to synchronize. </member> <member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0"> - Time interval between synchronizations. When set to [code]0.0[/code] (the default), synchronizations happen every network process frame. + Time interval between synchronizations. Used when the replication is set to [constant SceneReplicationConfig.REPLICATION_MODE_ALWAYS]. If set to [code]0.0[/code] (the default), synchronizations happen every network process frame. </member> <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("..")"> Node path that replicated properties are relative to. diff --git a/modules/multiplayer/editor/editor_network_profiler.cpp b/modules/multiplayer/editor/editor_network_profiler.cpp index f5f20d6931..dc3a3e3be7 100644 --- a/modules/multiplayer/editor/editor_network_profiler.cpp +++ b/modules/multiplayer/editor/editor_network_profiler.cpp @@ -45,11 +45,11 @@ void EditorNetworkProfiler::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { if (activate->is_pressed()) { - activate->set_icon(theme_cache.stop_icon); + activate->set_button_icon(theme_cache.stop_icon); } else { - activate->set_icon(theme_cache.play_icon); + activate->set_button_icon(theme_cache.play_icon); } - clear_button->set_icon(theme_cache.clear_icon); + clear_button->set_button_icon(theme_cache.clear_icon); incoming_bandwidth_text->set_right_icon(theme_cache.incoming_bandwidth_icon); outgoing_bandwidth_text->set_right_icon(theme_cache.outgoing_bandwidth_icon); @@ -184,10 +184,10 @@ void EditorNetworkProfiler::_activate_pressed() { void EditorNetworkProfiler::_update_button_text() { if (activate->is_pressed()) { - activate->set_icon(theme_cache.stop_icon); + activate->set_button_icon(theme_cache.stop_icon); activate->set_text(TTR("Stop")); } else { - activate->set_icon(theme_cache.play_icon); + activate->set_button_icon(theme_cache.play_icon); activate->set_text(TTR("Start")); } } diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp index 386feae4f9..4d5480eebf 100644 --- a/modules/multiplayer/editor/replication_editor.cpp +++ b/modules/multiplayer/editor/replication_editor.cpp @@ -353,8 +353,8 @@ void ReplicationEditor::_notification(int p_what) { } case NOTIFICATION_ENTER_TREE: { add_theme_style_override(SceneStringName(panel), EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SceneStringName(panel), SNAME("Panel"))); - add_pick_button->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); - pin->set_icon(get_theme_icon(SNAME("Pin"), EditorStringName(EditorIcons))); + add_pick_button->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); + pin->set_button_icon(get_theme_icon(SNAME("Pin"), EditorStringName(EditorIcons))); } break; } } @@ -375,7 +375,7 @@ void ReplicationEditor::_add_pressed() { return; } - int idx = np_text.find(":"); + int idx = np_text.find_char(':'); if (idx == -1) { np_text = ".:" + np_text; } else if (idx == 0) { @@ -554,7 +554,7 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, Node *root_node = current && !current->get_root_path().is_empty() ? current->get_node(current->get_root_path()) : nullptr; Ref<Texture2D> icon = _get_class_icon(root_node); if (root_node) { - String path = prop.substr(0, prop.find(":")); + String path = prop.substr(0, prop.find_char(':')); String subpath = prop.substr(path.size()); Node *node = root_node->get_node_or_null(path); if (!node) { diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp index 682d20022f..69a7545e51 100644 --- a/modules/multiplayer/multiplayer_spawner.cpp +++ b/modules/multiplayer/multiplayer_spawner.cpp @@ -97,7 +97,13 @@ PackedStringArray MultiplayerSpawner::get_configuration_warnings() const { void MultiplayerSpawner::add_spawnable_scene(const String &p_path) { SpawnableScene sc; - sc.path = p_path; + if (p_path.begins_with("uid://")) { + sc.uid = p_path; + sc.path = ResourceUID::uid_to_path(p_path); + } else { + sc.uid = ResourceUID::path_to_uid(p_path); + sc.path = p_path; + } if (Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_COND(!ResourceLoader::exists(p_path)); } @@ -139,7 +145,7 @@ Vector<String> MultiplayerSpawner::_get_spawnable_scenes() const { Vector<String> ss; ss.resize(spawnable_scenes.size()); for (int i = 0; i < ss.size(); i++) { - ss.write[i] = spawnable_scenes[i].path; + ss.write[i] = spawnable_scenes[i].uid; } return ss; } diff --git a/modules/multiplayer/multiplayer_spawner.h b/modules/multiplayer/multiplayer_spawner.h index 0e94b781ea..868efb9e0b 100644 --- a/modules/multiplayer/multiplayer_spawner.h +++ b/modules/multiplayer/multiplayer_spawner.h @@ -49,6 +49,7 @@ public: private: struct SpawnableScene { String path; + String uid; Ref<PackedScene> cache; }; diff --git a/modules/multiplayer/scene_multiplayer.cpp b/modules/multiplayer/scene_multiplayer.cpp index e245101eeb..dde14034e6 100644 --- a/modules/multiplayer/scene_multiplayer.cpp +++ b/modules/multiplayer/scene_multiplayer.cpp @@ -684,9 +684,9 @@ void SceneMultiplayer::_bind_methods() { SceneMultiplayer::SceneMultiplayer() { relay_buffer.instantiate(); - cache = Ref<SceneCacheInterface>(memnew(SceneCacheInterface(this))); - replicator = Ref<SceneReplicationInterface>(memnew(SceneReplicationInterface(this, cache.ptr()))); - rpc = Ref<SceneRPCInterface>(memnew(SceneRPCInterface(this, cache.ptr(), replicator.ptr()))); + cache.instantiate(this); + replicator.instantiate(this, cache.ptr()); + rpc.instantiate(this, cache.ptr(), replicator.ptr()); set_multiplayer_peer(Ref<OfflineMultiplayerPeer>(memnew(OfflineMultiplayerPeer))); } diff --git a/modules/multiplayer/scene_multiplayer.h b/modules/multiplayer/scene_multiplayer.h index 725cb9dbb6..5b668e1651 100644 --- a/modules/multiplayer/scene_multiplayer.h +++ b/modules/multiplayer/scene_multiplayer.h @@ -52,14 +52,14 @@ public: virtual void set_target_peer(int p_peer_id) override {} virtual int get_packet_peer() const override { return 0; } - virtual TransferMode get_packet_mode() const override { return TRANSFER_MODE_RELIABLE; }; + virtual TransferMode get_packet_mode() const override { return TRANSFER_MODE_RELIABLE; } virtual int get_packet_channel() const override { return 0; } virtual void disconnect_peer(int p_peer, bool p_force = false) override {} virtual bool is_server() const override { return true; } virtual void poll() override {} virtual void close() override {} virtual int get_unique_id() const override { return TARGET_PEER_SERVER; } - virtual ConnectionStatus get_connection_status() const override { return CONNECTION_CONNECTED; }; + virtual ConnectionStatus get_connection_status() const override { return CONNECTION_CONNECTED; } }; class SceneMultiplayer : public MultiplayerAPI { diff --git a/modules/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp index 0938d7ef99..b5f3889268 100644 --- a/modules/multiplayer/scene_rpc_interface.cpp +++ b/modules/multiplayer/scene_rpc_interface.cpp @@ -73,16 +73,6 @@ int get_packet_len(uint32_t p_node_target, int p_packet_len) { } } -bool SceneRPCInterface::_sort_rpc_names(const Variant &p_l, const Variant &p_r) { - if (likely(p_l.is_string() && p_r.is_string())) { - return p_l.operator String() < p_r.operator String(); - } - bool valid = false; - Variant res; - Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid); - return valid ? res.operator bool() : false; -} - void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache) { if (p_config.get_type() == Variant::NIL) { return; @@ -90,7 +80,7 @@ void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_no ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY); const Dictionary config = p_config; Array names = config.keys(); - names.sort_custom(callable_mp_static(&SceneRPCInterface::_sort_rpc_names)); // Ensure ID order + names.sort_custom(callable_mp_static(&StringLikeVariantOrder::compare)); // Ensure ID order for (int i = 0; i < names.size(); i++) { ERR_CONTINUE(!names[i].is_string()); String name = names[i].operator String(); diff --git a/modules/multiplayer/scene_rpc_interface.h b/modules/multiplayer/scene_rpc_interface.h index 852cef7830..5c9b66d5f5 100644 --- a/modules/multiplayer/scene_rpc_interface.h +++ b/modules/multiplayer/scene_rpc_interface.h @@ -91,8 +91,6 @@ private: #endif protected: - static bool _sort_rpc_names(const Variant &p_l, const Variant &p_r); - void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount); diff --git a/modules/navigation/2d/nav_mesh_generator_2d.cpp b/modules/navigation/2d/nav_mesh_generator_2d.cpp index 78983187c7..a8eb07147c 100644 --- a/modules/navigation/2d/nav_mesh_generator_2d.cpp +++ b/modules/navigation/2d/nav_mesh_generator_2d.cpp @@ -691,11 +691,15 @@ void NavMeshGenerator2D::generator_parse_navigationobstacle_node(const Ref<Navig return; } - const Transform2D node_xform = p_source_geometry_data->root_node_transform * Transform2D(0.0, obstacle->get_global_position()); - + const Vector2 safe_scale = obstacle->get_global_scale().abs().maxf(0.001); const float obstacle_radius = obstacle->get_radius(); if (obstacle_radius > 0.0) { + // Radius defined obstacle should be uniformly scaled from obstacle basis max scale axis. + const float scaling_max_value = safe_scale[safe_scale.max_axis_index()]; + const Vector2 uniform_max_scale = Vector2(scaling_max_value, scaling_max_value); + const Transform2D obstacle_circle_transform = p_source_geometry_data->root_node_transform * Transform2D(obstacle->get_global_rotation(), uniform_max_scale, 0.0, obstacle->get_global_position()); + Vector<Vector2> obstruction_circle_vertices; // The point of this is that the moving obstacle can make a simple hole in the navigation mesh and affect the pathfinding. @@ -709,12 +713,15 @@ void NavMeshGenerator2D::generator_parse_navigationobstacle_node(const Ref<Navig for (int i = 0; i < circle_points; i++) { const float angle = i * circle_point_step; - circle_vertices_ptrw[i] = node_xform.xform(Vector2(Math::cos(angle) * obstacle_radius, Math::sin(angle) * obstacle_radius)); + circle_vertices_ptrw[i] = obstacle_circle_transform.xform(Vector2(Math::cos(angle) * obstacle_radius, Math::sin(angle) * obstacle_radius)); } p_source_geometry_data->add_projected_obstruction(obstruction_circle_vertices, obstacle->get_carve_navigation_mesh()); } + // Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account. + const Transform2D node_xform = p_source_geometry_data->root_node_transform * obstacle->get_global_transform(); + const Vector<Vector2> &obstacle_vertices = obstacle->get_vertices(); if (obstacle_vertices.is_empty()) { @@ -755,21 +762,19 @@ void NavMeshGenerator2D::generator_parse_source_geometry_data(Ref<NavigationPoly for (Node *E : parse_nodes) { generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, E, recurse_children); } -}; +} static void generator_recursive_process_polytree_items(List<TPPLPoly> &p_tppl_in_polygon, const Clipper2Lib::PolyPathD *p_polypath_item) { using namespace Clipper2Lib; - Vector<Vector2> polygon_vertices; + TPPLPoly tp; + int size = p_polypath_item->Polygon().size(); + tp.Init(size); + int j = 0; for (const PointD &polypath_point : p_polypath_item->Polygon()) { - polygon_vertices.push_back(Vector2(static_cast<real_t>(polypath_point.x), static_cast<real_t>(polypath_point.y))); - } - - TPPLPoly tp; - tp.Init(polygon_vertices.size()); - for (int j = 0; j < polygon_vertices.size(); j++) { - tp[j] = polygon_vertices[j]; + tp[j] = Vector2(static_cast<real_t>(polypath_point.x), static_cast<real_t>(polypath_point.y)); + ++j; } if (p_polypath_item->IsHole()) { @@ -842,83 +847,74 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation return; } - if (p_navigation_mesh->get_outline_count() == 0 && !p_source_geometry_data->has_data()) { - return; - } - - int outline_count = p_navigation_mesh->get_outline_count(); - - Vector<Vector<Vector2>> traversable_outlines; - Vector<Vector<Vector2>> obstruction_outlines; - Vector<NavigationMeshSourceGeometryData2D::ProjectedObstruction> projected_obstructions; - - p_source_geometry_data->get_data( - traversable_outlines, - obstruction_outlines, - projected_obstructions); - - if (outline_count == 0 && traversable_outlines.size() == 0) { - return; - } - using namespace Clipper2Lib; - PathsD traversable_polygon_paths; PathsD obstruction_polygon_paths; + bool empty_projected_obstructions = true; + { + RWLockRead read_lock(p_source_geometry_data->geometry_rwlock); - traversable_polygon_paths.reserve(outline_count + traversable_outlines.size()); - obstruction_polygon_paths.reserve(obstruction_outlines.size()); + const Vector<Vector<Vector2>> &traversable_outlines = p_source_geometry_data->traversable_outlines; + int outline_count = p_navigation_mesh->get_outline_count(); - for (int i = 0; i < outline_count; i++) { - const Vector<Vector2> &traversable_outline = p_navigation_mesh->get_outline(i); - PathD subject_path; - subject_path.reserve(traversable_outline.size()); - for (const Vector2 &traversable_point : traversable_outline) { - const PointD &point = PointD(traversable_point.x, traversable_point.y); - subject_path.push_back(point); + if (outline_count == 0 && (!p_source_geometry_data->has_data() || (traversable_outlines.is_empty()))) { + return; } - traversable_polygon_paths.push_back(subject_path); - } - for (const Vector<Vector2> &traversable_outline : traversable_outlines) { - PathD subject_path; - subject_path.reserve(traversable_outline.size()); - for (const Vector2 &traversable_point : traversable_outline) { - const PointD &point = PointD(traversable_point.x, traversable_point.y); - subject_path.push_back(point); - } - traversable_polygon_paths.push_back(subject_path); - } + const Vector<Vector<Vector2>> &obstruction_outlines = p_source_geometry_data->obstruction_outlines; + const Vector<NavigationMeshSourceGeometryData2D::ProjectedObstruction> &projected_obstructions = p_source_geometry_data->_projected_obstructions; - for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) { - PathD clip_path; - clip_path.reserve(obstruction_outline.size()); - for (const Vector2 &obstruction_point : obstruction_outline) { - const PointD &point = PointD(obstruction_point.x, obstruction_point.y); - clip_path.push_back(point); + traversable_polygon_paths.reserve(outline_count + traversable_outlines.size()); + obstruction_polygon_paths.reserve(obstruction_outlines.size()); + + for (int i = 0; i < outline_count; i++) { + const Vector<Vector2> &traversable_outline = p_navigation_mesh->get_outline(i); + PathD subject_path; + subject_path.reserve(traversable_outline.size()); + for (const Vector2 &traversable_point : traversable_outline) { + subject_path.emplace_back(traversable_point.x, traversable_point.y); + } + traversable_polygon_paths.push_back(std::move(subject_path)); } - obstruction_polygon_paths.push_back(clip_path); - } - if (!projected_obstructions.is_empty()) { - for (const NavigationMeshSourceGeometryData2D::ProjectedObstruction &projected_obstruction : projected_obstructions) { - if (projected_obstruction.carve) { - continue; + for (const Vector<Vector2> &traversable_outline : traversable_outlines) { + PathD subject_path; + subject_path.reserve(traversable_outline.size()); + for (const Vector2 &traversable_point : traversable_outline) { + subject_path.emplace_back(traversable_point.x, traversable_point.y); } - if (projected_obstruction.vertices.is_empty() || projected_obstruction.vertices.size() % 2 != 0) { - continue; + traversable_polygon_paths.push_back(std::move(subject_path)); + } + + empty_projected_obstructions = projected_obstructions.is_empty(); + if (!empty_projected_obstructions) { + for (const NavigationMeshSourceGeometryData2D::ProjectedObstruction &projected_obstruction : projected_obstructions) { + if (projected_obstruction.carve) { + continue; + } + if (projected_obstruction.vertices.is_empty() || projected_obstruction.vertices.size() % 2 != 0) { + continue; + } + + PathD clip_path; + clip_path.reserve(projected_obstruction.vertices.size() / 2); + for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) { + clip_path.emplace_back(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]); + } + if (!IsPositive(clip_path)) { + std::reverse(clip_path.begin(), clip_path.end()); + } + obstruction_polygon_paths.push_back(std::move(clip_path)); } + } + for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) { PathD clip_path; - clip_path.reserve(projected_obstruction.vertices.size() / 2); - for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) { - const PointD &point = PointD(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]); - clip_path.push_back(point); + clip_path.reserve(obstruction_outline.size()); + for (const Vector2 &obstruction_point : obstruction_outline) { + clip_path.emplace_back(obstruction_point.x, obstruction_point.y); } - if (!IsPositive(clip_path)) { - std::reverse(clip_path.begin(), clip_path.end()); - } - obstruction_polygon_paths.push_back(clip_path); + obstruction_polygon_paths.push_back(std::move(clip_path)); } } @@ -937,22 +933,23 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation obstruction_polygon_paths = RectClip(clipper_rect, obstruction_polygon_paths); } - PathsD path_solution; - // first merge all traversable polygons according to user specified fill rule PathsD dummy_clip_path; traversable_polygon_paths = Union(traversable_polygon_paths, dummy_clip_path, FillRule::NonZero); // merge all obstruction polygons, don't allow holes for what is considered "solid" 2D geometry obstruction_polygon_paths = Union(obstruction_polygon_paths, dummy_clip_path, FillRule::NonZero); - path_solution = Difference(traversable_polygon_paths, obstruction_polygon_paths, FillRule::NonZero); + PathsD path_solution = Difference(traversable_polygon_paths, obstruction_polygon_paths, FillRule::NonZero); real_t agent_radius_offset = p_navigation_mesh->get_agent_radius(); if (agent_radius_offset > 0.0) { path_solution = InflatePaths(path_solution, -agent_radius_offset, JoinType::Miter, EndType::Polygon); } - if (!projected_obstructions.is_empty()) { + // Apply obstructions that are not affected by agent radius, the ones with carve enabled. + if (!empty_projected_obstructions) { + RWLockRead read_lock(p_source_geometry_data->geometry_rwlock); + const Vector<NavigationMeshSourceGeometryData2D::ProjectedObstruction> &projected_obstructions = p_source_geometry_data->_projected_obstructions; obstruction_polygon_paths.resize(0); for (const NavigationMeshSourceGeometryData2D::ProjectedObstruction &projected_obstruction : projected_obstructions) { if (!projected_obstruction.carve) { @@ -965,13 +962,12 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation PathD clip_path; clip_path.reserve(projected_obstruction.vertices.size() / 2); for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) { - const PointD &point = PointD(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]); - clip_path.push_back(point); + clip_path.emplace_back(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]); } if (!IsPositive(clip_path)) { std::reverse(clip_path.begin(), clip_path.end()); } - obstruction_polygon_paths.push_back(clip_path); + obstruction_polygon_paths.push_back(std::move(clip_path)); } if (obstruction_polygon_paths.size() > 0) { path_solution = Difference(path_solution, obstruction_polygon_paths, FillRule::NonZero); @@ -994,33 +990,11 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation path_solution = RectClip(clipper_rect, path_solution); } - Vector<Vector<Vector2>> new_baked_outlines; - - for (const PathD &scaled_path : path_solution) { - Vector<Vector2> polypath; - for (const PointD &scaled_point : scaled_path) { - polypath.push_back(Vector2(static_cast<real_t>(scaled_point.x), static_cast<real_t>(scaled_point.y))); - } - new_baked_outlines.push_back(polypath); - } - - if (new_baked_outlines.size() == 0) { + if (path_solution.size() == 0) { p_navigation_mesh->clear(); return; } - PathsD polygon_paths; - polygon_paths.reserve(new_baked_outlines.size()); - - for (const Vector<Vector2> &baked_outline : new_baked_outlines) { - PathD polygon_path; - for (const Vector2 &baked_outline_point : baked_outline) { - const PointD &point = PointD(baked_outline_point.x, baked_outline_point.y); - polygon_path.push_back(point); - } - polygon_paths.push_back(polygon_path); - } - ClipType clipper_cliptype = ClipType::Union; List<TPPLPoly> tppl_in_polygon, tppl_out_polygon; @@ -1028,7 +1002,7 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation PolyTreeD polytree; ClipperD clipper_D; - clipper_D.AddSubject(polygon_paths); + clipper_D.AddSubject(path_solution); clipper_D.Execute(clipper_cliptype, FillRule::NonZero, polytree); for (size_t i = 0; i < polytree.Count(); i++) { diff --git a/modules/navigation/3d/nav_mesh_generator_3d.cpp b/modules/navigation/3d/nav_mesh_generator_3d.cpp index e92a9d304b..3d0697a7cf 100644 --- a/modules/navigation/3d/nav_mesh_generator_3d.cpp +++ b/modules/navigation/3d/nav_mesh_generator_3d.cpp @@ -595,11 +595,17 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig return; } - const Transform3D node_xform = p_source_geometry_data->root_node_transform * Transform3D(Basis(), obstacle->get_global_position()); - + const float elevation = obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y; + // Prevent non-positive scaling. + const Vector3 safe_scale = obstacle->get_global_basis().get_scale().abs().maxf(0.001); const float obstacle_radius = obstacle->get_radius(); if (obstacle_radius > 0.0) { + // Radius defined obstacle should be uniformly scaled from obstacle basis max scale axis. + const float scaling_max_value = safe_scale[safe_scale.max_axis_index()]; + const Vector3 uniform_max_scale = Vector3(scaling_max_value, scaling_max_value, scaling_max_value); + const Transform3D obstacle_circle_transform = p_source_geometry_data->root_node_transform * Transform3D(Basis().scaled(uniform_max_scale), obstacle->get_global_position()); + Vector<Vector3> obstruction_circle_vertices; // The point of this is that the moving obstacle can make a simple hole in the navigation mesh and affect the pathfinding. @@ -613,12 +619,15 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig for (int i = 0; i < circle_points; i++) { const float angle = i * circle_point_step; - circle_vertices_ptrw[i] = node_xform.xform(Vector3(Math::cos(angle) * obstacle_radius, 0.0, Math::sin(angle) * obstacle_radius)); + circle_vertices_ptrw[i] = obstacle_circle_transform.xform(Vector3(Math::cos(angle) * obstacle_radius, 0.0, Math::sin(angle) * obstacle_radius)); } - p_source_geometry_data->add_projected_obstruction(obstruction_circle_vertices, obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y - obstacle_radius, obstacle_radius, obstacle->get_carve_navigation_mesh()); + p_source_geometry_data->add_projected_obstruction(obstruction_circle_vertices, elevation - obstacle_radius, scaling_max_value * obstacle_radius, obstacle->get_carve_navigation_mesh()); } + // Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account. + const Transform3D node_xform = p_source_geometry_data->root_node_transform * Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), obstacle->get_global_rotation().y), obstacle->get_global_position()); + const Vector<Vector3> &obstacle_vertices = obstacle->get_vertices(); if (obstacle_vertices.is_empty()) { @@ -635,7 +644,7 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig obstruction_shape_vertices_ptrw[i] = node_xform.xform(obstacle_vertices_ptr[i]); obstruction_shape_vertices_ptrw[i].y = 0.0; } - p_source_geometry_data->add_projected_obstruction(obstruction_shape_vertices, obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y, obstacle->get_height(), obstacle->get_carve_navigation_mesh()); + p_source_geometry_data->add_projected_obstruction(obstruction_shape_vertices, elevation, safe_scale.y * obstacle->get_height(), obstacle->get_carve_navigation_mesh()); } void NavMeshGenerator3D::generator_parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_root_node) { @@ -660,7 +669,7 @@ void NavMeshGenerator3D::generator_parse_source_geometry_data(const Ref<Navigati for (Node *parse_node : parse_nodes) { generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, parse_node, recurse_children); } -}; +} void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data) { if (p_navigation_mesh.is_null() || p_source_geometry_data.is_null()) { diff --git a/modules/navigation/3d/nav_mesh_queries_3d.cpp b/modules/navigation/3d/nav_mesh_queries_3d.cpp index 70207f86ce..5acc598d43 100644 --- a/modules/navigation/3d/nav_mesh_queries_3d.cpp +++ b/modules/navigation/3d/nav_mesh_queries_3d.cpp @@ -234,7 +234,7 @@ Vector<Vector3> NavMeshQueries3D::polygons_get_path(const LocalVector<gd::Polygo // Takes the current least_cost_poly neighbors (iterating over its edges) and compute the traveled_distance. for (const gd::Edge &edge : navigation_polys[least_cost_id].poly->edges) { // Iterate over connections in this edge, then compute the new optimized travel distance assigned to this polygon. - for (int connection_index = 0; connection_index < edge.connections.size(); connection_index++) { + for (uint32_t connection_index = 0; connection_index < edge.connections.size(); connection_index++) { const gd::Edge::Connection &connection = edge.connections[connection_index]; // Only consider the connection to another polygon if this polygon is in a region with compatible layers. diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp index 7f0cbc7b5e..ed0cdeb287 100644 --- a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp +++ b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp @@ -54,8 +54,8 @@ void NavigationMeshEditor::_node_removed(Node *p_node) { void NavigationMeshEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - button_bake->set_icon(get_theme_icon(SNAME("Bake"), EditorStringName(EditorIcons))); - button_reset->set_icon(get_theme_icon(SNAME("Reload"), EditorStringName(EditorIcons))); + button_bake->set_button_icon(get_theme_icon(SNAME("Bake"), EditorStringName(EditorIcons))); + button_reset->set_button_icon(get_theme_icon(SNAME("Reload"), EditorStringName(EditorIcons))); } break; } } diff --git a/modules/navigation/nav_agent.cpp b/modules/navigation/nav_agent.cpp index 2dbe57eb4a..037b237328 100644 --- a/modules/navigation/nav_agent.cpp +++ b/modules/navigation/nav_agent.cpp @@ -308,7 +308,7 @@ void NavAgent::set_avoidance_priority(real_t p_priority) { rvo_agent_2d.avoidance_priority_ = avoidance_priority; } agent_dirty = true; -}; +} bool NavAgent::check_dirty() { const bool was_dirty = agent_dirty; diff --git a/modules/navigation/nav_agent.h b/modules/navigation/nav_agent.h index 18997803f2..d56e053ac4 100644 --- a/modules/navigation/nav_agent.h +++ b/modules/navigation/nav_agent.h @@ -67,7 +67,7 @@ class NavAgent : public NavRid { uint32_t avoidance_mask = 1; real_t avoidance_priority = 1.0; - Callable avoidance_callback = Callable(); + Callable avoidance_callback; bool agent_dirty = true; @@ -130,13 +130,13 @@ public: const Vector3 &get_velocity_forced() const { return velocity_forced; } void set_avoidance_layers(uint32_t p_layers); - uint32_t get_avoidance_layers() const { return avoidance_layers; }; + uint32_t get_avoidance_layers() const { return avoidance_layers; } void set_avoidance_mask(uint32_t p_mask); - uint32_t get_avoidance_mask() const { return avoidance_mask; }; + uint32_t get_avoidance_mask() const { return avoidance_mask; } void set_avoidance_priority(real_t p_priority); - real_t get_avoidance_priority() const { return avoidance_priority; }; + real_t get_avoidance_priority() const { return avoidance_priority; } void set_paused(bool p_paused); bool get_paused() const; diff --git a/modules/navigation/nav_link.cpp b/modules/navigation/nav_link.cpp index c693cc91c8..61c3b59fab 100644 --- a/modules/navigation/nav_link.cpp +++ b/modules/navigation/nav_link.cpp @@ -57,7 +57,7 @@ void NavLink::set_enabled(bool p_enabled) { // TODO: This should not require a full rebuild as the link has not really changed. link_dirty = true; -}; +} void NavLink::set_bidirectional(bool p_bidirectional) { if (bidirectional == p_bidirectional) { diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 8df1db533d..8055dd4bc8 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -427,25 +427,36 @@ void NavMap::sync() { _new_pm_polygon_count = polygon_count; // Group all edges per key. - HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections; + connection_pairs_map.clear(); + connection_pairs_map.reserve(polygons.size()); + int free_edges_count = 0; // How many ConnectionPairs have only one Connection. + for (gd::Polygon &poly : polygons) { for (uint32_t p = 0; p < poly.points.size(); p++) { - int next_point = (p + 1) % poly.points.size(); - gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key); + const int next_point = (p + 1) % poly.points.size(); + const gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key); - HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey>::Iterator connection = connections.find(ek); - if (!connection) { - connections[ek] = Vector<gd::Edge::Connection>(); + HashMap<gd::EdgeKey, ConnectionPair, gd::EdgeKey>::Iterator pair_it = connection_pairs_map.find(ek); + if (!pair_it) { + pair_it = connection_pairs_map.insert(ek, ConnectionPair()); _new_pm_edge_count += 1; + ++free_edges_count; } - if (connections[ek].size() <= 1) { + ConnectionPair &pair = pair_it->value; + if (pair.size < 2) { // Add the polygon/edge tuple to this key. gd::Edge::Connection new_connection; new_connection.polygon = &poly; new_connection.edge = p; new_connection.pathway_start = poly.points[p].pos; new_connection.pathway_end = poly.points[next_point].pos; - connections[ek].push_back(new_connection); + + pair.connections[pair.size] = new_connection; + ++pair.size; + if (pair.size == 2) { + --free_edges_count; + } + } else { // The edge is already connected with another edge, skip. ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to merge a navigation mesh polygon edge with another already-merged edge. This is usually caused by crossing edges, overlapping polygons, or a mismatch of the NavigationMesh / NavigationPolygon baked 'cell_size' and navigation map 'cell_size'. If you're certain none of above is the case, change 'navigation/3d/merge_rasterizer_cell_scale' to 0.001."); @@ -453,20 +464,23 @@ void NavMap::sync() { } } - Vector<gd::Edge::Connection> free_edges; - for (KeyValue<gd::EdgeKey, Vector<gd::Edge::Connection>> &E : connections) { - if (E.value.size() == 2) { + free_edges.clear(); + free_edges.reserve(free_edges_count); + + for (const KeyValue<gd::EdgeKey, ConnectionPair> &pair_it : connection_pairs_map) { + const ConnectionPair &pair = pair_it.value; + if (pair.size == 2) { // Connect edge that are shared in different polygons. - gd::Edge::Connection &c1 = E.value.write[0]; - gd::Edge::Connection &c2 = E.value.write[1]; + const gd::Edge::Connection &c1 = pair.connections[0]; + const gd::Edge::Connection &c2 = pair.connections[1]; c1.polygon->edges[c1.edge].connections.push_back(c2); c2.polygon->edges[c2.edge].connections.push_back(c1); // Note: The pathway_start/end are full for those connection and do not need to be modified. _new_pm_edge_merge_count += 1; } else { - CRASH_COND_MSG(E.value.size() != 1, vformat("Number of connection != 1. Found: %d", E.value.size())); - if (use_edge_connections && E.value[0].polygon->owner->get_use_edge_connections()) { - free_edges.push_back(E.value[0]); + CRASH_COND_MSG(pair.size != 1, vformat("Number of connection != 1. Found: %d", pair.size)); + if (use_edge_connections && pair.connections[0].polygon->owner->get_use_edge_connections()) { + free_edges.push_back(pair.connections[0]); } } } @@ -480,14 +494,14 @@ void NavMap::sync() { // connection, integration and path finding. _new_pm_edge_free_count = free_edges.size(); - real_t sqr_edge_connection_margin = edge_connection_margin * edge_connection_margin; + const real_t edge_connection_margin_squared = edge_connection_margin * edge_connection_margin; - for (int i = 0; i < free_edges.size(); i++) { + for (uint32_t i = 0; i < free_edges.size(); i++) { const gd::Edge::Connection &free_edge = free_edges[i]; Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos; Vector3 edge_p2 = free_edge.polygon->points[(free_edge.edge + 1) % free_edge.polygon->points.size()].pos; - for (int j = 0; j < free_edges.size(); j++) { + for (uint32_t j = 0; j < free_edges.size(); j++) { const gd::Edge::Connection &other_edge = free_edges[j]; if (i == j || free_edge.polygon->owner == other_edge.polygon->owner) { continue; @@ -512,7 +526,7 @@ void NavMap::sync() { } else { other1 = other_edge_p1.lerp(other_edge_p2, (1.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio)); } - if (other1.distance_squared_to(self1) > sqr_edge_connection_margin) { + if (other1.distance_squared_to(self1) > edge_connection_margin_squared) { continue; } @@ -523,7 +537,7 @@ void NavMap::sync() { } else { other2 = other_edge_p1.lerp(other_edge_p2, (0.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio)); } - if (other2.distance_squared_to(self2) > sqr_edge_connection_margin) { + if (other2.distance_squared_to(self2) > edge_connection_margin_squared) { continue; } diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index b9120c04d9..3442b78497 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -128,6 +128,14 @@ class NavMap : public NavRid { HashMap<NavRegion *, LocalVector<gd::Edge::Connection>> region_external_connections; + struct ConnectionPair { + gd::Edge::Connection connections[2]; + int size = 0; + }; + + HashMap<gd::EdgeKey, ConnectionPair, gd::EdgeKey> connection_pairs_map; + LocalVector<gd::Edge::Connection> free_edges; + public: NavMap(); ~NavMap(); diff --git a/modules/navigation/nav_obstacle.h b/modules/navigation/nav_obstacle.h index e231e83836..a6aca9d637 100644 --- a/modules/navigation/nav_obstacle.h +++ b/modules/navigation/nav_obstacle.h @@ -92,7 +92,7 @@ public: bool is_map_changed(); void set_avoidance_layers(uint32_t p_layers); - uint32_t get_avoidance_layers() const { return avoidance_layers; }; + uint32_t get_avoidance_layers() const { return avoidance_layers; } void set_paused(bool p_paused); bool get_paused() const; diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp index 2c91b80af2..679997b8e1 100644 --- a/modules/navigation/nav_region.cpp +++ b/modules/navigation/nav_region.cpp @@ -59,7 +59,7 @@ void NavRegion::set_enabled(bool p_enabled) { // TODO: This should not require a full rebuild as the region has not really changed. polygons_dirty = true; -}; +} void NavRegion::set_use_edge_connections(bool p_enabled) { if (use_edge_connections != p_enabled) { diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h index c015802b92..d13f666e9a 100644 --- a/modules/navigation/nav_region.h +++ b/modules/navigation/nav_region.h @@ -94,7 +94,7 @@ public: gd::ClosestPointQueryResult get_closest_point_info(const Vector3 &p_point) const; Vector3 get_random_point(uint32_t p_navigation_layers, bool p_uniformly) const; - real_t get_surface_area() const { return surface_area; }; + real_t get_surface_area() const { return surface_area; } bool sync(); diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h index ba4c44b748..c466c82fc7 100644 --- a/modules/navigation/nav_utils.h +++ b/modules/navigation/nav_utils.h @@ -94,7 +94,7 @@ struct Edge { }; /// Connections from this edge to other polygons. - Vector<Connection> connections; + LocalVector<Connection> connections; }; struct Polygon { diff --git a/modules/noise/doc_classes/FastNoiseLite.xml b/modules/noise/doc_classes/FastNoiseLite.xml index 6f6a637893..e29581693b 100644 --- a/modules/noise/doc_classes/FastNoiseLite.xml +++ b/modules/noise/doc_classes/FastNoiseLite.xml @@ -118,7 +118,7 @@ Manhattan distance (taxicab metric) to the nearest point. </constant> <constant name="DISTANCE_HYBRID" value="3" enum="CellularDistanceFunction"> - Blend of [constant DISTANCE_EUCLIDEAN] and [constant DISTANCE_MANHATTAN] to give curved cell boundaries + Blend of [constant DISTANCE_EUCLIDEAN] and [constant DISTANCE_MANHATTAN] to give curved cell boundaries. </constant> <constant name="RETURN_CELL_VALUE" value="0" enum="CellularReturnType"> The cellular distance function will return the same value for all points within a cell. diff --git a/modules/noise/tests/test_noise_texture_2d.h b/modules/noise/tests/test_noise_texture_2d.h index 0d18d66e74..0cccb678ec 100644 --- a/modules/noise/tests/test_noise_texture_2d.h +++ b/modules/noise/tests/test_noise_texture_2d.h @@ -44,7 +44,7 @@ class NoiseTextureTester : public RefCounted { public: NoiseTextureTester(const NoiseTexture2D *const p_texture) : - texture{ p_texture } {}; + texture{ p_texture } {} Color compute_average_color(const Ref<Image> &p_noise_image) { Color r_avg_color{}; diff --git a/modules/noise/tests/test_noise_texture_3d.h b/modules/noise/tests/test_noise_texture_3d.h index 434cd20a08..78616d478e 100644 --- a/modules/noise/tests/test_noise_texture_3d.h +++ b/modules/noise/tests/test_noise_texture_3d.h @@ -44,7 +44,7 @@ class NoiseTexture3DTester : public RefCounted { public: NoiseTexture3DTester(const NoiseTexture3D *const p_texture) : - texture{ p_texture } {}; + texture{ p_texture } {} Color compute_average_color(const Ref<Image> &p_noise_image) { Color r_avg_color{}; diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index dd6a921440..48c87bcd59 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -26,7 +26,7 @@ elif env["platform"] == "linuxbsd": env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"]) if env["wayland"]: - env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_WAYLAND"]) + env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_EGL"]) # FIXME: Review what needs to be set for Android and macOS. env_openxr.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"]) diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp index 5430a41d6d..f924386ecf 100644 --- a/modules/openxr/action_map/openxr_action_map.cpp +++ b/modules/openxr/action_map/openxr_action_map.cpp @@ -576,20 +576,15 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p const OpenXRInteractionProfileMetadata::InteractionProfile *profile = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(ip->get_interaction_profile_path()); if (profile != nullptr) { - for (int j = 0; j < ip->get_binding_count(); j++) { - Ref<OpenXRIPBinding> binding = ip->get_binding(j); - if (binding->get_action() == p_action) { - PackedStringArray paths = binding->get_paths(); - - for (int k = 0; k < paths.size(); k++) { - const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(paths[k]); - if (io_path != nullptr) { - String top_path = io_path->top_level_path; - - if (!arr.has(top_path)) { - arr.push_back(top_path); - } - } + Vector<Ref<OpenXRIPBinding>> bindings = ip->get_bindings_for_action(p_action); + for (const Ref<OpenXRIPBinding> &binding : bindings) { + String binding_path = binding->get_binding_path(); + const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(binding_path); + if (io_path != nullptr) { + String top_path = io_path->top_level_path; + + if (!arr.has(top_path)) { + arr.push_back(top_path); } } } diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp index 1266457113..2aab55f6ec 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile.cpp @@ -35,23 +35,30 @@ void OpenXRIPBinding::_bind_methods() { ClassDB::bind_method(D_METHOD("get_action"), &OpenXRIPBinding::get_action); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "action", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRAction"), "set_action", "get_action"); - ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count); + ClassDB::bind_method(D_METHOD("set_binding_path", "binding_path"), &OpenXRIPBinding::set_binding_path); + ClassDB::bind_method(D_METHOD("get_binding_path"), &OpenXRIPBinding::get_binding_path); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "binding_path"), "set_binding_path", "get_binding_path"); + + // Deprecated +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_paths", "paths"), &OpenXRIPBinding::set_paths); ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"), "set_paths", "get_paths"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_paths", "get_paths"); + ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count); ClassDB::bind_method(D_METHOD("has_path", "path"), &OpenXRIPBinding::has_path); ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path); ClassDB::bind_method(D_METHOD("remove_path", "path"), &OpenXRIPBinding::remove_path); +#endif // DISABLE_DEPRECATED } -Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) { +Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path) { // This is a helper function to help build our default action sets Ref<OpenXRIPBinding> binding; binding.instantiate(); binding->set_action(p_action); - binding->parse_paths(String(p_paths)); + binding->set_binding_path(p_binding_path); return binding; } @@ -65,42 +72,68 @@ Ref<OpenXRAction> OpenXRIPBinding::get_action() const { return action; } -int OpenXRIPBinding::get_path_count() const { - return paths.size(); +void OpenXRIPBinding::set_binding_path(const String &path) { + binding_path = path; + emit_changed(); } -void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) { - paths = p_paths; - emit_changed(); +String OpenXRIPBinding::get_binding_path() const { + return binding_path; } -PackedStringArray OpenXRIPBinding::get_paths() const { +#ifndef DISABLE_DEPRECATED + +void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) { // Deprecated, but needed for loading old action maps. + // Fallback logic, this should ONLY be called when loading older action maps. + // We'll parse this momentarily and extract individual bindings. + binding_path = ""; + for (const String &path : p_paths) { + if (!binding_path.is_empty()) { + binding_path += ","; + } + binding_path += path; + } +} + +PackedStringArray OpenXRIPBinding::get_paths() const { // Deprecated, but needed for converting old action maps. + // Fallback logic, return an array. + // If we just loaded an old action map from disc, this will be a comma separated list of actions. + // Once parsed there should be only one path in our array. + PackedStringArray paths = binding_path.split(",", false); + return paths; } -void OpenXRIPBinding::parse_paths(const String p_paths) { - paths = p_paths.split(",", false); - emit_changed(); +int OpenXRIPBinding::get_path_count() const { // Deprecated. + // Fallback logic, we only have one entry. + return binding_path.is_empty() ? 0 : 1; } -bool OpenXRIPBinding::has_path(const String p_path) const { - return paths.has(p_path); +bool OpenXRIPBinding::has_path(const String p_path) const { // Deprecated. + // Fallback logic, return true if this is our path. + return binding_path == p_path; } -void OpenXRIPBinding::add_path(const String p_path) { - if (!paths.has(p_path)) { - paths.push_back(p_path); +void OpenXRIPBinding::add_path(const String p_path) { // Deprecated. + // Fallback logic, only assign first time this is called. + if (binding_path != p_path) { + ERR_FAIL_COND_MSG(!binding_path.is_empty(), "Method add_path has been deprecated. A binding path was already set, create separate binding resources for each path and use set_binding_path instead."); + + binding_path = p_path; emit_changed(); } } -void OpenXRIPBinding::remove_path(const String p_path) { - if (paths.has(p_path)) { - paths.erase(p_path); - emit_changed(); - } +void OpenXRIPBinding::remove_path(const String p_path) { // Deprecated. + ERR_FAIL_COND_MSG(binding_path != p_path, "Method remove_path has been deprecated. Attempt at removing a different binding path, remove the correct binding record from the interaction profile instead."); + + // Fallback logic, clear if this is our path. + binding_path = p_path; + emit_changed(); } +#endif // DISABLE_DEPRECATED + OpenXRIPBinding::~OpenXRIPBinding() { action.unref(); } @@ -151,9 +184,18 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding(int p_index) const { } void OpenXRInteractionProfile::set_bindings(Array p_bindings) { - // TODO add check here that our bindings don't contain duplicate actions + bindings.clear(); + + for (Ref<OpenXRIPBinding> binding : p_bindings) { + String binding_path = binding->get_binding_path(); + if (binding_path.find_char(',') >= 0) { + // Convert old binding approach to new... + add_new_binding(binding->get_action(), binding_path); + } else { + add_binding(binding); + } + } - bindings = p_bindings; emit_changed(); } @@ -161,10 +203,9 @@ Array OpenXRInteractionProfile::get_bindings() const { return bindings; } -Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref<OpenXRAction> p_action) const { - for (int i = 0; i < bindings.size(); i++) { - Ref<OpenXRIPBinding> binding = bindings[i]; - if (binding->get_action() == p_action) { +Ref<OpenXRIPBinding> OpenXRInteractionProfile::find_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path) const { + for (Ref<OpenXRIPBinding> binding : bindings) { + if (binding->get_action() == p_action && binding->get_binding_path() == p_binding_path) { return binding; } } @@ -172,11 +213,23 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref< return Ref<OpenXRIPBinding>(); } +Vector<Ref<OpenXRIPBinding>> OpenXRInteractionProfile::get_bindings_for_action(const Ref<OpenXRAction> p_action) const { + Vector<Ref<OpenXRIPBinding>> ret_bindings; + + for (Ref<OpenXRIPBinding> binding : bindings) { + if (binding->get_action() == p_action) { + ret_bindings.push_back(binding); + } + } + + return ret_bindings; +} + void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) { ERR_FAIL_COND(p_binding.is_null()); if (!bindings.has(p_binding)) { - ERR_FAIL_COND_MSG(get_binding_for_action(p_binding->get_action()).is_valid(), "There is already a binding for this action in this interaction profile"); + ERR_FAIL_COND_MSG(find_binding(p_binding->get_action(), p_binding->get_binding_path()).is_valid(), "There is already a binding for this action and binding path in this interaction profile."); bindings.push_back(p_binding); emit_changed(); @@ -191,11 +244,15 @@ void OpenXRInteractionProfile::remove_binding(Ref<OpenXRIPBinding> p_binding) { } } -void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) { +void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> p_action, const String &p_paths) { // This is a helper function to help build our default action sets - Ref<OpenXRIPBinding> binding = OpenXRIPBinding::new_binding(p_action, p_paths); - add_binding(binding); + PackedStringArray paths = p_paths.split(",", false); + + for (const String &path : paths) { + Ref<OpenXRIPBinding> binding = OpenXRIPBinding::new_binding(p_action, path); + add_binding(binding); + } } void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction> p_action) { diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h index 479cc3c527..952f87a09d 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.h +++ b/modules/openxr/action_map/openxr_interaction_profile.h @@ -41,26 +41,29 @@ class OpenXRIPBinding : public Resource { private: Ref<OpenXRAction> action; - PackedStringArray paths; + String binding_path; protected: static void _bind_methods(); public: - static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Helper function for adding a new binding + static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path); // Helper function for adding a new binding. - void set_action(const Ref<OpenXRAction> p_action); // Set the action for this binding - Ref<OpenXRAction> get_action() const; // Get the action for this binding + void set_action(const Ref<OpenXRAction> p_action); // Set the action for this binding. + Ref<OpenXRAction> get_action() const; // Get the action for this binding. - int get_path_count() const; // Get the number of io paths - void set_paths(const PackedStringArray p_paths); // Set our paths (for loading from resource) - PackedStringArray get_paths() const; // Get our paths (for saving to resource) + void set_binding_path(const String &path); + String get_binding_path() const; - void parse_paths(const String p_paths); // Parse a comma separated string of io paths. - - bool has_path(const String p_path) const; // Has this io path - void add_path(const String p_path); // Add an io path - void remove_path(const String p_path); // Remove an io path + // Deprecated. +#ifndef DISABLE_DEPRECATED + void set_paths(const PackedStringArray p_paths); // Set our paths (for loading from resource), needed for loading old action maps. + PackedStringArray get_paths() const; // Get our paths (for saving to resource), needed for converted old action maps. + int get_path_count() const; // Get the number of io paths. + bool has_path(const String p_path) const; // Has this io path. + void add_path(const String p_path); // Add an io path. + void remove_path(const String p_path); // Remove an io path. +#endif // DISABLE_DEPRECATED // TODO add validation that we can display in the interface that checks if no two paths belong to the same top level path @@ -88,11 +91,12 @@ public: void set_bindings(Array p_bindings); // Set the bindings (for loading from a resource) Array get_bindings() const; // Get the bindings (for saving to a resource) - Ref<OpenXRIPBinding> get_binding_for_action(const Ref<OpenXRAction> p_action) const; // Get our binding record for a given action + Ref<OpenXRIPBinding> find_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path) const; // Get our binding record + Vector<Ref<OpenXRIPBinding>> get_bindings_for_action(const Ref<OpenXRAction> p_action) const; // Get our binding record for a given action void add_binding(Ref<OpenXRIPBinding> p_binding); // Add a binding object void remove_binding(Ref<OpenXRIPBinding> p_binding); // Remove a binding object - void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Create a new binding for this profile + void add_new_binding(const Ref<OpenXRAction> p_action, const String &p_paths); // Create a new binding for this profile void remove_binding_for_action(const Ref<OpenXRAction> p_action); // Remove all bindings for this action bool has_binding_for_action(const Ref<OpenXRAction> p_action); // Returns true if we have a binding for this action diff --git a/modules/openxr/doc_classes/OpenXRCompositionLayer.xml b/modules/openxr/doc_classes/OpenXRCompositionLayer.xml index 341b50065c..cfc7cd4d97 100644 --- a/modules/openxr/doc_classes/OpenXRCompositionLayer.xml +++ b/modules/openxr/doc_classes/OpenXRCompositionLayer.xml @@ -29,7 +29,7 @@ <method name="is_natively_supported" qualifiers="const"> <return type="bool" /> <description> - Returns true if the OpenXR runtime natively supports this composition layer type. + Returns [code]true[/code] if the OpenXR runtime natively supports this composition layer type. [b]Note:[/b] This will only return an accurate result after the OpenXR session has started. </description> </method> diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml index 813c9d582e..c174ee4d69 100644 --- a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml +++ b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml @@ -90,6 +90,21 @@ Called right after the main swapchains are (re)created. </description> </method> + <method name="_on_post_draw_viewport" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="viewport" type="RID" /> + <description> + Called right after the given viewport is rendered. + [b]Note:[/b] The draw commands might only be queued at this point, not executed. + </description> + </method> + <method name="_on_pre_draw_viewport" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="viewport" type="RID" /> + <description> + Called right before the given viewport is rendered. + </description> + </method> <method name="_on_pre_render" qualifiers="virtual"> <return type="void" /> <description> @@ -220,7 +235,7 @@ <return type="int" /> <param index="0" name="next_pointer" type="void*" /> <description> - Adds additional data structures when interogating OpenXR system abilities. + Adds additional data structures when querying OpenXR system abilities. </description> </method> <method name="_set_viewport_composition_layer_and_get_next_pointer" qualifiers="virtual"> diff --git a/modules/openxr/doc_classes/OpenXRIPBinding.xml b/modules/openxr/doc_classes/OpenXRIPBinding.xml index f274f0868e..ddd6fbe268 100644 --- a/modules/openxr/doc_classes/OpenXRIPBinding.xml +++ b/modules/openxr/doc_classes/OpenXRIPBinding.xml @@ -4,32 +4,32 @@ Defines a binding between an [OpenXRAction] and an XR input or output. </brief_description> <description> - This binding resource binds an [OpenXRAction] to inputs or outputs. As most controllers have left hand and right versions that are handled by the same interaction profile we can specify multiple bindings. For instance an action "Fire" could be bound to both "/user/hand/left/input/trigger" and "/user/hand/right/input/trigger". + This binding resource binds an [OpenXRAction] to an input or output. As most controllers have left hand and right versions that are handled by the same interaction profile we can specify multiple bindings. For instance an action "Fire" could be bound to both "/user/hand/left/input/trigger" and "/user/hand/right/input/trigger". This would require two binding entries. </description> <tutorials> </tutorials> <methods> - <method name="add_path"> + <method name="add_path" deprecated="Binding is for a single path."> <return type="void" /> <param index="0" name="path" type="String" /> <description> Add an input/output path to this binding. </description> </method> - <method name="get_path_count" qualifiers="const"> + <method name="get_path_count" qualifiers="const" deprecated="Binding is for a single path."> <return type="int" /> <description> Get the number of input/output paths in this binding. </description> </method> - <method name="has_path" qualifiers="const"> + <method name="has_path" qualifiers="const" deprecated="Binding is for a single path."> <return type="bool" /> <param index="0" name="path" type="String" /> <description> Returns [code]true[/code] if this input/output path is part of this binding. </description> </method> - <method name="remove_path"> + <method name="remove_path" deprecated="Binding is for a single path."> <return type="void" /> <param index="0" name="path" type="String" /> <description> @@ -39,9 +39,13 @@ </methods> <members> <member name="action" type="OpenXRAction" setter="set_action" getter="get_action"> - [OpenXRAction] that is bound to these paths. + [OpenXRAction] that is bound to [member binding_path]. </member> - <member name="paths" type="PackedStringArray" setter="set_paths" getter="get_paths" default="PackedStringArray()"> + <member name="binding_path" type="String" setter="set_binding_path" getter="get_binding_path" default=""""> + Binding path that defines the input or output bound to [member action]. + [b]Note:[/b] Binding paths are suggestions, an XR runtime may choose to bind the action to a different input or output emulating this input or output. + </member> + <member name="paths" type="PackedStringArray" setter="set_paths" getter="get_paths" deprecated="Use [member binding_path] instead."> Paths that define the inputs or outputs bound on the device. </member> </members> diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp index 63162ba3dc..dd5f6378f4 100644 --- a/modules/openxr/editor/openxr_action_editor.cpp +++ b/modules/openxr/editor/openxr_action_editor.cpp @@ -41,7 +41,7 @@ void OpenXRActionEditor::_bind_methods() { } void OpenXRActionEditor::_theme_changed() { - rem_action->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + rem_action->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); } void OpenXRActionEditor::_notification(int p_what) { diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h index 11d1fd657a..b672fe7340 100644 --- a/modules/openxr/editor/openxr_action_editor.h +++ b/modules/openxr/editor/openxr_action_editor.h @@ -68,7 +68,7 @@ protected: void _do_set_action_type(OpenXRAction::ActionType p_action_type); public: - Ref<OpenXRAction> get_action() { return action; }; + Ref<OpenXRAction> get_action() { return action; } OpenXRActionEditor(Ref<OpenXRAction> p_action); }; diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp index 0c55592707..e5e034ef08 100644 --- a/modules/openxr/editor/openxr_action_set_editor.cpp +++ b/modules/openxr/editor/openxr_action_set_editor.cpp @@ -46,16 +46,16 @@ void OpenXRActionSetEditor::_bind_methods() { void OpenXRActionSetEditor::_set_fold_icon() { if (is_expanded) { - fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); + fold_btn->set_button_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); } else { - fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); + fold_btn->set_button_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); } } void OpenXRActionSetEditor::_theme_changed() { _set_fold_icon(); - add_action->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); - rem_action_set->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + add_action->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); + rem_action_set->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); } void OpenXRActionSetEditor::_notification(int p_what) { diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h index 3261f3a29e..21437aa631 100644 --- a/modules/openxr/editor/openxr_action_set_editor.h +++ b/modules/openxr/editor/openxr_action_set_editor.h @@ -87,7 +87,7 @@ protected: void _do_remove_action_editor(OpenXRActionEditor *p_action_editor); public: - Ref<OpenXRActionSet> get_action_set() { return action_set; }; + Ref<OpenXRActionSet> get_action_set() { return action_set; } void set_focus_on_entry(); void remove_all_actions(); diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp index 651171358c..a390919856 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp +++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp @@ -73,17 +73,19 @@ void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, con Ref<OpenXRAction> action = action_map->get_action(p_action); ERR_FAIL_COND(action.is_null()); - Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action); + Ref<OpenXRIPBinding> binding = interaction_profile->find_binding(action, p_path); if (binding.is_null()) { // create a new binding binding.instantiate(); binding->set_action(action); + binding->set_binding_path(p_path); + + // add it to our interaction profile interaction_profile->add_binding(binding); interaction_profile->set_edited(true); - } - binding->add_path(p_path); - binding->set_edited(true); + binding->set_edited(true); + } // Update our toplevel paths action->set_toplevel_paths(action_map->get_top_level_paths(action)); @@ -98,15 +100,10 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, Ref<OpenXRAction> action = action_map->get_action(p_action); ERR_FAIL_COND(action.is_null()); - Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action); + Ref<OpenXRIPBinding> binding = interaction_profile->find_binding(action, p_path); if (binding.is_valid()) { - binding->remove_path(p_path); - binding->set_edited(true); - - if (binding->get_path_count() == 0) { - interaction_profile->remove_binding(binding); - interaction_profile->set_edited(true); - } + interaction_profile->remove_binding(binding); + interaction_profile->set_edited(true); // Update our toplevel paths action->set_toplevel_paths(action_map->get_top_level_paths(action)); @@ -116,21 +113,22 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, } void OpenXRInteractionProfileEditorBase::remove_all_bindings_for_action(Ref<OpenXRAction> p_action) { - Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(p_action); - if (binding.is_valid()) { + Vector<Ref<OpenXRIPBinding>> bindings = interaction_profile->get_bindings_for_action(p_action); + if (bindings.size() > 0) { String action_name = p_action->get_name_with_set(); // for our undo/redo we process all paths undo_redo->create_action(TTR("Remove action from interaction profile")); - PackedStringArray paths = binding->get_paths(); - for (const String &path : paths) { - undo_redo->add_do_method(this, "_remove_binding", action_name, path); - undo_redo->add_undo_method(this, "_add_binding", action_name, path); + for (const Ref<OpenXRIPBinding> &binding : bindings) { + undo_redo->add_do_method(this, "_remove_binding", action_name, binding->get_binding_path()); + undo_redo->add_undo_method(this, "_add_binding", action_name, binding->get_binding_path()); } undo_redo->commit_action(false); // but we take a shortcut here :) - interaction_profile->remove_binding(binding); + for (const Ref<OpenXRIPBinding> &binding : bindings) { + interaction_profile->remove_binding(binding); + } interaction_profile->set_edited(true); // Update our toplevel paths @@ -220,7 +218,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co path_hb->add_child(type_label); Button *path_add = memnew(Button); - path_add->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); + path_add->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); path_add->set_flat(true); path_add->connect(SceneStringName(pressed), callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for).bind(String(p_io_path->openxr_path))); path_hb->add_child(path_add); @@ -228,9 +226,8 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co if (interaction_profile.is_valid()) { String io_path = String(p_io_path->openxr_path); Array bindings = interaction_profile->get_bindings(); - for (int i = 0; i < bindings.size(); i++) { - Ref<OpenXRIPBinding> binding = bindings[i]; - if (binding->has_path(io_path)) { + for (Ref<OpenXRIPBinding> binding : bindings) { + if (binding->get_binding_path() == io_path) { Ref<OpenXRAction> action = binding->get_action(); HBoxContainer *action_hb = memnew(HBoxContainer); @@ -248,7 +245,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co Button *action_rem = memnew(Button); action_rem->set_flat(true); - action_rem->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + action_rem->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); action_rem->connect(SceneStringName(pressed), callable_mp((OpenXRInteractionProfileEditor *)this, &OpenXRInteractionProfileEditor::_on_remove_pressed).bind(action->get_name_with_set(), String(p_io_path->openxr_path))); action_hb->add_child(action_rem); } diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp index dc30b95b27..1e3490d1ed 100644 --- a/modules/openxr/extensions/openxr_composition_layer_extension.cpp +++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp @@ -281,7 +281,7 @@ void OpenXRViewportCompositionLayerProvider::create_android_surface() { composition_layer_extension->create_android_surface_swapchain(&info, &android_surface.swapchain, &surface); if (surface) { - android_surface.surface = Ref<JavaObject>(memnew(JavaObject(JavaClassWrapper::get_singleton()->wrap("android.view.Surface"), surface))); + android_surface.surface.instantiate(JavaClassWrapper::get_singleton()->wrap("android.view.Surface"), surface); } } #endif @@ -341,7 +341,7 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos } XrSwapchainSubImage subimage = { - 0, // swapchain + 0, // swapchain // NOLINT(modernize-use-nullptr) - 32-bit uses non-pointer uint64 { { 0, 0 }, { 0, 0 } }, // imageRect 0, // imageArrayIndex }; diff --git a/modules/openxr/extensions/openxr_debug_utils_extension.cpp b/modules/openxr/extensions/openxr_debug_utils_extension.cpp index 10dbe629f7..cb7f72d02d 100644 --- a/modules/openxr/extensions/openxr_debug_utils_extension.cpp +++ b/modules/openxr/extensions/openxr_debug_utils_extension.cpp @@ -173,7 +173,7 @@ void OpenXRDebugUtilsExtension::begin_debug_label_region(const char *p_label_nam const XrDebugUtilsLabelEXT session_active_region_label = { XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type - NULL, // next + nullptr, // next p_label_name, // labelName }; @@ -199,7 +199,7 @@ void OpenXRDebugUtilsExtension::insert_debug_label(const char *p_label_name) { const XrDebugUtilsLabelEXT session_active_region_label = { XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type - NULL, // next + nullptr, // next p_label_name, // labelName }; diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp index 07ca476421..fb8d1b9d69 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp +++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp @@ -51,6 +51,8 @@ void OpenXRExtensionWrapperExtension::_bind_methods() { GDVIRTUAL_BIND(_on_process); GDVIRTUAL_BIND(_on_pre_render); GDVIRTUAL_BIND(_on_main_swapchains_created); + GDVIRTUAL_BIND(_on_pre_draw_viewport, "viewport"); + GDVIRTUAL_BIND(_on_post_draw_viewport, "viewport"); GDVIRTUAL_BIND(_on_session_destroyed); GDVIRTUAL_BIND(_on_state_idle); GDVIRTUAL_BIND(_on_state_ready); @@ -208,6 +210,14 @@ void OpenXRExtensionWrapperExtension::on_session_destroyed() { GDVIRTUAL_CALL(_on_session_destroyed); } +void OpenXRExtensionWrapperExtension::on_pre_draw_viewport(RID p_render_target) { + GDVIRTUAL_CALL(_on_pre_draw_viewport, p_render_target); +} + +void OpenXRExtensionWrapperExtension::on_post_draw_viewport(RID p_render_target) { + GDVIRTUAL_CALL(_on_post_draw_viewport, p_render_target); +} + void OpenXRExtensionWrapperExtension::on_state_idle() { GDVIRTUAL_CALL(_on_state_idle); } @@ -298,8 +308,7 @@ void OpenXRExtensionWrapperExtension::register_extension_wrapper() { OpenXRAPI::register_extension_wrapper(this); } -OpenXRExtensionWrapperExtension::OpenXRExtensionWrapperExtension() : - Object(), OpenXRExtensionWrapper() { +OpenXRExtensionWrapperExtension::OpenXRExtensionWrapperExtension() { openxr_api.instantiate(); } diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h index 5cdf288c93..8fc6511277 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h +++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h @@ -88,6 +88,8 @@ public: virtual void on_pre_render() override; virtual void on_main_swapchains_created() override; virtual void on_session_destroyed() override; + virtual void on_pre_draw_viewport(RID p_render_target) override; + virtual void on_post_draw_viewport(RID p_render_target) override; GDVIRTUAL0(_on_register_metadata); GDVIRTUAL0(_on_before_instance_created); @@ -98,6 +100,8 @@ public: GDVIRTUAL0(_on_pre_render); GDVIRTUAL0(_on_main_swapchains_created); GDVIRTUAL0(_on_session_destroyed); + GDVIRTUAL1(_on_pre_draw_viewport, RID); + GDVIRTUAL1(_on_post_draw_viewport, RID); virtual void on_state_idle() override; virtual void on_state_ready() override; diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp index caded14ca7..4fcb3f7b75 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp @@ -64,6 +64,9 @@ HashMap<String, bool *> OpenXROpenGLExtension::get_requested_extensions() { #else request_extensions[XR_KHR_OPENGL_ENABLE_EXTENSION_NAME] = nullptr; #endif +#if defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) + request_extensions[XR_MNDX_EGL_ENABLE_EXTENSION_NAME] = &egl_extension_enabled; +#endif return request_extensions; } @@ -128,9 +131,14 @@ bool OpenXROpenGLExtension::check_graphics_api_support(XrVersion p_desired_versi XrGraphicsBindingOpenGLWin32KHR OpenXROpenGLExtension::graphics_binding_gl; #elif defined(ANDROID_ENABLED) XrGraphicsBindingOpenGLESAndroidKHR OpenXROpenGLExtension::graphics_binding_gl; -#elif defined(X11_ENABLED) +#elif defined(LINUXBSD_ENABLED) +#ifdef X11_ENABLED XrGraphicsBindingOpenGLXlibKHR OpenXROpenGLExtension::graphics_binding_gl; #endif +#if defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) +XrGraphicsBindingEGLMNDX OpenXROpenGLExtension::graphics_binding_egl; +#endif +#endif void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) { XrVersion desired_version = XR_MAKE_VERSION(3, 3, 0); @@ -142,10 +150,6 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex DisplayServer *display_server = DisplayServer::get_singleton(); -#ifdef WAYLAND_ENABLED - ERR_FAIL_COND_V_MSG(display_server->get_name() == "Wayland", p_next_pointer, "OpenXR is not yet supported on OpenGL Wayland."); -#endif - #ifdef WIN32 graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, graphics_binding_gl.next = p_next_pointer; @@ -159,7 +163,23 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex graphics_binding_gl.display = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE); graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122 graphics_binding_gl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT); -#elif defined(X11_ENABLED) +#else +#if defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) + if (display_server->get_name() == "Wayland") { + ERR_FAIL_COND_V_MSG(!egl_extension_enabled, p_next_pointer, "OpenXR cannot initialize on Wayland without the XR_MNDX_egl_enable extension."); + + graphics_binding_egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX; + graphics_binding_egl.next = p_next_pointer; + + graphics_binding_egl.getProcAddress = eglGetProcAddress; + graphics_binding_egl.display = (void *)display_server->window_get_native_handle(DisplayServer::EGL_DISPLAY); + graphics_binding_egl.config = (void *)display_server->window_get_native_handle(DisplayServer::EGL_CONFIG); + graphics_binding_egl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT); + + return &graphics_binding_egl; + } +#endif +#if defined(X11_ENABLED) graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR; graphics_binding_gl.next = p_next_pointer; @@ -173,10 +193,15 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex // spec says to use proper values but runtimes don't care graphics_binding_gl.visualid = 0; - graphics_binding_gl.glxFBConfig = 0; + graphics_binding_gl.glxFBConfig = nullptr; +#endif #endif +#if defined(WIN32) || defined(ANDROID_ENABLED) || defined(X11_ENABLED) return &graphics_binding_gl; +#else + return p_next_pointer; +#endif } void OpenXROpenGLExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) { diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.h b/modules/openxr/extensions/platform/openxr_opengl_extension.h index 8da3ca48f4..f4a73c667b 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.h +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.h @@ -64,9 +64,18 @@ private: static XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl; #elif defined(ANDROID_ENABLED) static XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl; -#else // Linux/X11 +#elif defined(LINUXBSD_ENABLED) +#ifdef X11_ENABLED static XrGraphicsBindingOpenGLXlibKHR graphics_binding_gl; #endif +#if defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) + static XrGraphicsBindingEGLMNDX graphics_binding_egl; + + bool egl_extension_enabled = false; +#endif +#else +#error "OpenXR with OpenGL isn't supported on this platform" +#endif struct SwapchainGraphicsData { bool is_multiview; diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index c67be5a2b3..1775541757 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -1294,7 +1294,7 @@ bool OpenXRAPI::create_main_swapchains(Size2i p_size) { } return true; -}; +} void OpenXRAPI::destroy_session() { // TODO need to figure out if we're still rendering our current frame @@ -2036,8 +2036,9 @@ bool OpenXRAPI::poll_events() { if (local_floor_emulation.enabled) { local_floor_emulation.should_reset_floor_height = true; } - if (event->poseValid && xr_interface) { - xr_interface->on_pose_recentered(); + + if (xr_interface) { + xr_interface->on_reference_space_change_pending(); } } break; case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: { @@ -2353,7 +2354,7 @@ void OpenXRAPI::post_draw_viewport(RID p_render_target) { for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { wrapper->on_post_draw_viewport(p_render_target); } -}; +} void OpenXRAPI::end_frame() { XrResult result; @@ -2752,8 +2753,9 @@ void OpenXRAPI::parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_l } bool OpenXRAPI::xr_result(XrResult result, const char *format, Array args) const { - if (XR_SUCCEEDED(result)) + if (XR_SUCCEEDED(result)) { return true; + } char resultString[XR_MAX_RESULT_STRING_SIZE]; xrResultToString(instance, result, resultString); diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index 0d1e4eb414..ecffce1816 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -396,12 +396,12 @@ private: } public: - XrInstance get_instance() const { return instance; }; - XrSystemId get_system_id() const { return system_id; }; - XrSession get_session() const { return session; }; - OpenXRGraphicsExtensionWrapper *get_graphics_extension() const { return graphics_extension; }; - String get_runtime_name() const { return runtime_name; }; - String get_runtime_version() const { return runtime_version; }; + XrInstance get_instance() const { return instance; } + XrSystemId get_system_id() const { return system_id; } + XrSession get_session() const { return session; } + OpenXRGraphicsExtensionWrapper *get_graphics_extension() const { return graphics_extension; } + String get_runtime_name() const { return runtime_name; } + String get_runtime_version() const { return runtime_version; } // helper method to convert an XrPosef to a Transform3D Transform3D transform_from_pose(const XrPosef &p_pose); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 73ac529537..68e04694e3 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -160,11 +160,11 @@ void OpenXRInterface::_bind_methods() { StringName OpenXRInterface::get_name() const { return StringName("OpenXR"); -}; +} uint32_t OpenXRInterface::get_capabilities() const { return XRInterface::XR_VR + XRInterface::XR_STEREO; -}; +} PackedStringArray OpenXRInterface::get_suggested_tracker_names() const { // These are hardcoded in OpenXR, note that they will only be available if added to our action map @@ -300,10 +300,7 @@ void OpenXRInterface::_load_action_map() { continue; } - PackedStringArray paths = xr_binding->get_paths(); - for (int k = 0; k < paths.size(); k++) { - openxr_api->interaction_profile_add_binding(ip, action->action_rid, paths[k]); - } + openxr_api->interaction_profile_add_binding(ip, action->action_rid, xr_binding->get_binding_path()); } // Now submit our suggestions @@ -614,7 +611,7 @@ bool OpenXRInterface::initialize_on_startup() const { bool OpenXRInterface::is_initialized() const { return initialized; -}; +} bool OpenXRInterface::initialize() { XRServer *xr_server = XRServer::get_singleton(); @@ -1137,6 +1134,12 @@ void OpenXRInterface::process() { if (head.is_valid()) { head->set_pose("default", head_transform, head_linear_velocity, head_angular_velocity, head_confidence); } + + if (reference_stage_changing) { + // Now that we have updated tracking information in our updated reference space, trigger our pose recentered signal. + emit_signal(SNAME("pose_recentered")); + reference_stage_changing = false; + } } void OpenXRInterface::pre_render() { @@ -1318,8 +1321,8 @@ void OpenXRInterface::on_state_exiting() { emit_signal(SNAME("instance_exiting")); } -void OpenXRInterface::on_pose_recentered() { - emit_signal(SNAME("pose_recentered")); +void OpenXRInterface::on_reference_space_change_pending() { + reference_stage_changing = true; } void OpenXRInterface::on_refresh_rate_changes(float p_new_rate) { diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index f0ee0dc3c4..d1bf2aaf78 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -70,6 +70,7 @@ class OpenXRInterface : public XRInterface { private: OpenXRAPI *openxr_api = nullptr; bool initialized = false; + bool reference_stage_changing = false; XRInterface::TrackingStatus tracking_state; // At a minimum we need a tracker for our head @@ -207,7 +208,7 @@ public: void on_state_stopping(); void on_state_loss_pending(); void on_state_exiting(); - void on_pose_recentered(); + void on_reference_space_change_pending(); void on_refresh_rate_changes(float p_new_rate); void tracker_profile_changed(RID p_tracker, RID p_interaction_profile); diff --git a/modules/openxr/openxr_platform_inc.h b/modules/openxr/openxr_platform_inc.h index 957a87cbb2..09bc0c89a2 100644 --- a/modules/openxr/openxr_platform_inc.h +++ b/modules/openxr/openxr_platform_inc.h @@ -49,6 +49,13 @@ #else #define XR_USE_GRAPHICS_API_OPENGL #endif // ANDROID_ENABLED +#if defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED) +#ifdef GLAD_ENABLED +#include "thirdparty/glad/glad/egl.h" +#else +#include <EGL/egl.h> +#endif // GLAD_ENABLED +#endif // defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED) #ifdef X11_ENABLED #define GL_GLEXT_PROTOTYPES 1 #define GL3_PROTOTYPES 1 diff --git a/modules/openxr/scene/openxr_composition_layer.cpp b/modules/openxr/scene/openxr_composition_layer.cpp index 697369d516..bc429e4632 100644 --- a/modules/openxr/scene/openxr_composition_layer.cpp +++ b/modules/openxr/scene/openxr_composition_layer.cpp @@ -56,6 +56,10 @@ OpenXRCompositionLayer::OpenXRCompositionLayer(XrCompositionLayerBaseHeader *p_c openxr_api = OpenXRAPI::get_singleton(); composition_layer_extension = OpenXRCompositionLayerExtension::get_singleton(); + if (openxr_api) { + openxr_session_running = openxr_api->is_running(); + } + Ref<OpenXRInterface> openxr_interface = XRServer::get_singleton()->find_interface("OpenXR"); if (openxr_interface.is_valid()) { openxr_interface->connect("session_begun", callable_mp(this, &OpenXRCompositionLayer::_on_openxr_session_begun)); diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index 94d8b267d1..3609f5a554 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -90,18 +90,11 @@ void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D td.camera_dir = -p_cam_transform.basis.get_column(2); td.camera_orthogonal = p_cam_orthogonal; - Projection inv_camera_matrix = p_cam_projection.inverse(); - Vector3 camera_corner_proj = Vector3(-1.0f, -1.0f, -1.0f); - Vector3 camera_corner_view = inv_camera_matrix.xform(camera_corner_proj); - td.pixel_corner = p_cam_transform.xform(camera_corner_view); - - Vector3 top_corner_proj = Vector3(-1.0f, 1.0f, -1.0f); - Vector3 top_corner_view = inv_camera_matrix.xform(top_corner_proj); - Vector3 top_corner_world = p_cam_transform.xform(top_corner_view); - - Vector3 left_corner_proj = Vector3(1.0f, -1.0f, -1.0f); - Vector3 left_corner_view = inv_camera_matrix.xform(left_corner_proj); - Vector3 left_corner_world = p_cam_transform.xform(left_corner_view); + // Calculate the world coordinates of the viewport. + Vector2 viewport_half = p_cam_projection.get_viewport_half_extents(); + td.pixel_corner = p_cam_transform.xform(Vector3(-viewport_half.x, -viewport_half.y, -p_cam_projection.get_z_near())); + Vector3 top_corner_world = p_cam_transform.xform(Vector3(-viewport_half.x, viewport_half.y, -p_cam_projection.get_z_near())); + Vector3 left_corner_world = p_cam_transform.xform(Vector3(viewport_half.x, -viewport_half.y, -p_cam_projection.get_z_near())); td.pixel_u_interp = left_corner_world - td.pixel_corner; td.pixel_v_interp = top_corner_world - td.pixel_corner; @@ -140,7 +133,7 @@ void RaycastOcclusionCull::RaycastHZBuffer::_generate_camera_rays(const CameraRa Vector3 dir; if (p_data->camera_orthogonal) { - dir = -p_data->camera_dir; + dir = p_data->camera_dir; tile.ray.org_x[j] = pixel_pos.x - dir.x * p_data->z_near; tile.ray.org_y[j] = pixel_pos.y - dir.y * p_data->z_near; tile.ray.org_z[j] = pixel_pos.z - dir.z * p_data->z_near; @@ -181,17 +174,7 @@ void RaycastOcclusionCull::RaycastHZBuffer::sort_rays(const Vector3 &p_camera_di } int k = tile_i * TILE_SIZE + tile_j; int tile_index = i * tile_grid_size.x + j; - float d = camera_rays[tile_index].ray.tfar[k]; - - if (!p_orthogonal) { - const float &dir_x = camera_rays[tile_index].ray.dir_x[k]; - const float &dir_y = camera_rays[tile_index].ray.dir_y[k]; - const float &dir_z = camera_rays[tile_index].ray.dir_z[k]; - float cos_theta = p_camera_dir.x * dir_x + p_camera_dir.y * dir_y + p_camera_dir.z * dir_z; - d *= cos_theta; - } - - mips[0][y * buffer_size.x + x] = d; + mips[0][y * buffer_size.x + x] = camera_rays[tile_index].ray.tfar[k]; } } } diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml index e12dc43b6f..66e7cd5a0b 100644 --- a/modules/regex/doc_classes/RegEx.xml +++ b/modules/regex/doc_classes/RegEx.xml @@ -34,14 +34,14 @@ print(result.get_string("digit")) # Would print 01 03 0 3f 42 [/codeblock] - [b]Example of splitting a string using a RegEx:[/b] + [b]Example:[/b] Split a string using a RegEx: [codeblock] var regex = RegEx.new() regex.compile("\\S+") # Negated whitespace character class. var results = [] for result in regex.search_all("One Two \n\tThree"): results.push_back(result.get_string()) - # The `results` array now contains "One", "Two", "Three". + # The `results` array now contains "One", "Two", and "Three". [/codeblock] [b]Note:[/b] Godot's regex implementation is based on the [url=https://www.pcre.org/]PCRE2[/url] library. You can view the full pattern reference [url=https://www.pcre.org/current/doc/html/pcre2pattern.html]here[/url]. [b]Tip:[/b] You can use [url=https://regexr.com/]Regexr[/url] to test regular expressions online. diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index d903137195..1f7d5504b6 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -53,7 +53,7 @@ void ImageLoaderSVG::_replace_color_property(const HashMap<Color, Color> &p_colo int pos = r_string.find(p_prefix); while (pos != -1) { pos += prefix_len; // Skip prefix. - int end_pos = r_string.find("\"", pos); + int end_pos = r_string.find_char('"', pos); ERR_FAIL_COND_MSG(end_pos == -1, vformat("Malformed SVG string after property \"%s\".", p_prefix)); const String color_code = r_string.substr(pos, end_pos - pos); if (color_code != "none" && !color_code.begins_with("url(")) { @@ -104,51 +104,33 @@ Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref<Image> p_image, const ui picture->size(width, height); std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen(); - // Note: memalloc here, be sure to memfree before any return. - uint32_t *buffer = (uint32_t *)memalloc(sizeof(uint32_t) * width * height); + Vector<uint8_t> buffer; + buffer.resize(sizeof(uint32_t) * width * height); - tvg::Result res = sw_canvas->target(buffer, width, width, height, tvg::SwCanvas::ARGB8888S); + tvg::Result res = sw_canvas->target((uint32_t *)buffer.ptrw(), width, width, height, tvg::SwCanvas::ABGR8888S); if (res != tvg::Result::Success) { - memfree(buffer); ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't set target on ThorVG canvas."); } res = sw_canvas->push(std::move(picture)); if (res != tvg::Result::Success) { - memfree(buffer); ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't insert ThorVG picture on canvas."); } res = sw_canvas->draw(); if (res != tvg::Result::Success) { - memfree(buffer); ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't draw ThorVG pictures on canvas."); } res = sw_canvas->sync(); if (res != tvg::Result::Success) { - memfree(buffer); ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't sync ThorVG canvas."); } - Vector<uint8_t> image; - image.resize(width * height * sizeof(uint32_t)); - - for (uint32_t y = 0; y < height; y++) { - for (uint32_t x = 0; x < width; x++) { - uint32_t n = buffer[y * width + x]; - const size_t offset = sizeof(uint32_t) * width * y + sizeof(uint32_t) * x; - image.write[offset + 0] = (n >> 16) & 0xff; - image.write[offset + 1] = (n >> 8) & 0xff; - image.write[offset + 2] = n & 0xff; - image.write[offset + 3] = (n >> 24) & 0xff; - } - } + p_image->set_data(width, height, false, Image::FORMAT_RGBA8, buffer); res = sw_canvas->clear(true); - memfree(buffer); - p_image->set_data(width, height, false, Image::FORMAT_RGBA8, image); return OK; } diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index f1dcef6667..f6aa242698 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -477,7 +477,7 @@ if env["builtin_icu4c"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - icu_data_name = "icudt75l.dat" + icu_data_name = "icudt76l.dat" if env.editor_build: env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name) diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct index 4c305f3b3f..fb705eaa50 100644 --- a/modules/text_server_adv/gdextension_build/SConstruct +++ b/modules/text_server_adv/gdextension_build/SConstruct @@ -717,7 +717,7 @@ thirdparty_icu_sources = [ ] thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources] -icu_data_name = "icudt75l.dat" +icu_data_name = "icudt76l.dat" if env["static_icu_data"]: env_icu.Depends("../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/" + icu_data_name) diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 1c6e62650a..8d557aae2a 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -5264,42 +5264,44 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ // Find usable fonts, if fonts from the last glyph do not have required chars. RID dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; - if (!_font_has_char(dot_gl_font_rid, sd->el_char)) { - const Array &fonts = spans[spans.size() - 1].fonts; - for (int i = 0; i < fonts.size(); i++) { - if (_font_has_char(fonts[i], sd->el_char)) { - dot_gl_font_rid = fonts[i]; - found_el_char = true; - break; - } - } - if (!found_el_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { - const char32_t u32str[] = { sd->el_char, 0 }; - RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, u32str); - if (rid.is_valid()) { - dot_gl_font_rid = rid; - found_el_char = true; - } - } - } else { - found_el_char = true; - } - if (!found_el_char) { - bool found_dot_char = false; - dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; - if (!_font_has_char(dot_gl_font_rid, '.')) { + if (add_ellipsis || enforce_ellipsis) { + if (!_font_has_char(dot_gl_font_rid, sd->el_char)) { const Array &fonts = spans[spans.size() - 1].fonts; for (int i = 0; i < fonts.size(); i++) { - if (_font_has_char(fonts[i], '.')) { + if (_font_has_char(fonts[i], sd->el_char)) { dot_gl_font_rid = fonts[i]; - found_dot_char = true; + found_el_char = true; break; } } - if (!found_dot_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { - RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, "."); + if (!found_el_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { + const char32_t u32str[] = { sd->el_char, 0 }; + RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, u32str); if (rid.is_valid()) { dot_gl_font_rid = rid; + found_el_char = true; + } + } + } else { + found_el_char = true; + } + if (!found_el_char) { + bool found_dot_char = false; + dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; + if (!_font_has_char(dot_gl_font_rid, '.')) { + const Array &fonts = spans[spans.size() - 1].fonts; + for (int i = 0; i < fonts.size(); i++) { + if (_font_has_char(fonts[i], '.')) { + dot_gl_font_rid = fonts[i]; + found_dot_char = true; + break; + } + } + if (!found_dot_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { + RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, "."); + if (rid.is_valid()) { + dot_gl_font_rid = rid; + } } } } @@ -5315,8 +5317,8 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ } } - int32_t dot_gl_idx = dot_gl_font_rid.is_valid() ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; - Vector2 dot_adv = dot_gl_font_rid.is_valid() ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); + int32_t dot_gl_idx = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; + Vector2 dot_adv = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); int32_t whitespace_gl_idx = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_index(whitespace_gl_font_rid, last_gl_font_size, ' ', 0) : -1; Vector2 whitespace_adv = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_advance(whitespace_gl_font_rid, last_gl_font_size, whitespace_gl_idx) : Vector2(); diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 9c8d75b358..def57b9372 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -96,6 +96,11 @@ using namespace godot; // Thirdparty headers. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#endif + #include <unicode/ubidi.h> #include <unicode/ubrk.h> #include <unicode/uchar.h> @@ -109,6 +114,10 @@ using namespace godot; #include <unicode/ustring.h> #include <unicode/utypes.h> +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + #ifdef MODULE_FREETYPE_ENABLED #include <ft2build.h> #include FT_FREETYPE_H diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index ce95622f09..ae636a3151 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -156,11 +156,11 @@ bool TextServerFallback::_has(const RID &p_rid) { String TextServerFallback::_get_support_data_filename() const { return ""; -}; +} String TextServerFallback::_get_support_data_info() const { return "Not supported"; -}; +} bool TextServerFallback::_load_support_data(const String &p_filename) { return false; // No extra data used. @@ -4077,42 +4077,44 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ // Find usable fonts, if fonts from the last glyph do not have required chars. RID dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; - if (!_font_has_char(dot_gl_font_rid, sd->el_char)) { - const Array &fonts = spans[spans.size() - 1].fonts; - for (int i = 0; i < fonts.size(); i++) { - if (_font_has_char(fonts[i], sd->el_char)) { - dot_gl_font_rid = fonts[i]; - found_el_char = true; - break; - } - } - if (!found_el_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { - const char32_t u32str[] = { sd->el_char, 0 }; - RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, u32str); - if (rid.is_valid()) { - dot_gl_font_rid = rid; - found_el_char = true; - } - } - } else { - found_el_char = true; - } - if (!found_el_char) { - bool found_dot_char = false; - dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; - if (!_font_has_char(dot_gl_font_rid, '.')) { + if (add_ellipsis || enforce_ellipsis) { + if (!_font_has_char(dot_gl_font_rid, sd->el_char)) { const Array &fonts = spans[spans.size() - 1].fonts; for (int i = 0; i < fonts.size(); i++) { - if (_font_has_char(fonts[i], '.')) { + if (_font_has_char(fonts[i], sd->el_char)) { dot_gl_font_rid = fonts[i]; - found_dot_char = true; + found_el_char = true; break; } } - if (!found_dot_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { - RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, "."); + if (!found_el_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { + const char32_t u32str[] = { sd->el_char, 0 }; + RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, u32str); if (rid.is_valid()) { dot_gl_font_rid = rid; + found_el_char = true; + } + } + } else { + found_el_char = true; + } + if (!found_el_char) { + bool found_dot_char = false; + dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; + if (!_font_has_char(dot_gl_font_rid, '.')) { + const Array &fonts = spans[spans.size() - 1].fonts; + for (int i = 0; i < fonts.size(); i++) { + if (_font_has_char(fonts[i], '.')) { + dot_gl_font_rid = fonts[i]; + found_dot_char = true; + break; + } + } + if (!found_dot_char && OS::get_singleton()->has_feature("system_fonts") && fonts.size() > 0 && _font_is_allow_system_fallback(fonts[0])) { + RID rid = _find_sys_font_for_text(fonts[0], String(), spans[spans.size() - 1].language, "."); + if (rid.is_valid()) { + dot_gl_font_rid = rid; + } } } } @@ -4128,8 +4130,8 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ } } - int32_t dot_gl_idx = dot_gl_font_rid.is_valid() ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; - Vector2 dot_adv = dot_gl_font_rid.is_valid() ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); + int32_t dot_gl_idx = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; + Vector2 dot_adv = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); int32_t whitespace_gl_idx = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_index(whitespace_gl_font_rid, last_gl_font_size, ' ', 0) : -1; Vector2 whitespace_adv = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_advance(whitespace_gl_font_rid, last_gl_font_size, whitespace_gl_idx) : Vector2(); @@ -4728,7 +4730,7 @@ void TextServerFallback::_update_settings() { TextServerFallback::TextServerFallback() { _insert_feature_sets(); ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &TextServerFallback::_update_settings)); -}; +} void TextServerFallback::_cleanup() { for (const KeyValue<SystemFontKey, SystemFontCache> &E : system_fonts) { @@ -4747,4 +4749,4 @@ TextServerFallback::~TextServerFallback() { FT_Done_FreeType(ft_library); } #endif -}; +} diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index e2bb89811c..b205dbbbf2 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/io/file_access_memory.h" +#include "core/io/image.h" #include "core/os/os.h" #include "core/string/print_string.h" diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index d964fd7627..372885b0b4 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -31,6 +31,7 @@ #include "video_stream_theora.h" #include "core/config/project_settings.h" +#include "core/io/image.h" #include "core/os/os.h" #include "scene/resources/image_texture.h" @@ -114,7 +115,7 @@ void VideoStreamPlaybackTheora::video_write() { format = Image::FORMAT_RGBA8; } - Ref<Image> img = memnew(Image(size.x, size.y, 0, Image::FORMAT_RGBA8, frame_data)); //zero copy image creation + Ref<Image> img = memnew(Image(size.x, size.y, false, Image::FORMAT_RGBA8, frame_data)); //zero copy image creation texture->update(img); //zero copy send to rendering server @@ -628,7 +629,7 @@ void VideoStreamPlaybackTheora::_streaming_thread(void *ud) { #endif VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { - texture = Ref<ImageTexture>(memnew(ImageTexture)); + texture.instantiate(); #ifdef THEORA_USE_THREAD_STREAMING int rb_power = nearest_shift(RB_SIZE_KB * 1024); @@ -644,7 +645,7 @@ VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() { memdelete(thread_sem); #endif clear(); -}; +} void VideoStreamTheora::_bind_methods() {} diff --git a/modules/tinyexr/image_saver_tinyexr.cpp b/modules/tinyexr/image_saver_tinyexr.cpp index 31c1e06dee..b0a977f647 100644 --- a/modules/tinyexr/image_saver_tinyexr.cpp +++ b/modules/tinyexr/image_saver_tinyexr.cpp @@ -31,6 +31,7 @@ #include "image_saver_tinyexr.h" #include "core/math/math_funcs.h" +#include "core/os/os.h" #include <zlib.h> // Should come before including tinyexr. diff --git a/modules/tinyexr/image_saver_tinyexr.h b/modules/tinyexr/image_saver_tinyexr.h index 058eeae58e..014c2f2e19 100644 --- a/modules/tinyexr/image_saver_tinyexr.h +++ b/modules/tinyexr/image_saver_tinyexr.h @@ -31,7 +31,7 @@ #ifndef IMAGE_SAVER_TINYEXR_H #define IMAGE_SAVER_TINYEXR_H -#include "core/os/os.h" +#include "core/io/image.h" Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale); Vector<uint8_t> save_exr_buffer(const Ref<Image> &p_img, bool p_grayscale); diff --git a/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml b/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml index 8ae63140f5..cede03c73a 100644 --- a/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml +++ b/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml @@ -29,15 +29,15 @@ </methods> <members> <member name="bar_beats" type="int" setter="" getter="" default="4"> - The number of bars within a single beat in the audio track. This is only relevant for music that wishes to make use of interactive music functionality (not implemented yet), not sound effects. + The number of bars within a single beat in the audio track. This is only relevant for music that wishes to make use of interactive music functionality, not sound effects. A more convenient editor for [member bar_beats] is provided in the [b]Advanced Import Settings[/b] dialog, as it lets you preview your changes without having to reimport the audio. </member> <member name="beat_count" type="int" setter="" getter="" default="0"> - The beat count of the audio track. This is only relevant for music that wishes to make use of interactive music functionality (not implemented yet), not sound effects. + The beat count of the audio track. This is only relevant for music that wishes to make use of interactive music functionality, not sound effects. A more convenient editor for [member beat_count] is provided in the [b]Advanced Import Settings[/b] dialog, as it lets you preview your changes without having to reimport the audio. </member> <member name="bpm" type="float" setter="" getter="" default="0"> - The Beats Per Minute of the audio track. This should match the BPM measure that was used to compose the track. This is only relevant for music that wishes to make use of interactive music functionality (not implemented yet), not sound effects. + The beats per minute of the audio track. This should match the BPM measure that was used to compose the track. This is only relevant for music that wishes to make use of interactive music functionality, not sound effects. A more convenient editor for [member bpm] is provided in the [b]Advanced Import Settings[/b] dialog, as it lets you preview your changes without having to reimport the audio. </member> <member name="loop" type="bool" setter="" getter="" default="false"> diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp index 729a6f5561..a7423e2d7b 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp @@ -95,7 +95,7 @@ void ResourceImporterOggVorbis::show_advanced_options(const String &p_path) { } #endif -Error ResourceImporterOggVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterOggVorbis::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { bool loop = p_options["loop"]; double loop_offset = p_options["loop_offset"]; double bpm = p_options["bpm"]; diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h index 59ae3378a0..a4e4441d82 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.h +++ b/modules/vorbis/resource_importer_ogg_vorbis.h @@ -63,7 +63,9 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + + virtual bool can_import_threaded() const override { return true; } ResourceImporterOggVorbis(); }; diff --git a/modules/webp/webp_common.cpp b/modules/webp/webp_common.cpp index 3a2ac5a90e..0284eec574 100644 --- a/modules/webp/webp_common.cpp +++ b/modules/webp/webp_common.cpp @@ -149,7 +149,7 @@ Ref<Image> _webp_unpack(const Vector<uint8_t> &p_buffer) { ERR_FAIL_COND_V_MSG(errdec, Ref<Image>(), "Failed decoding WebP image."); - Ref<Image> img = memnew(Image(features.width, features.height, 0, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image)); + Ref<Image> img = memnew(Image(features.width, features.height, false, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image)); return img; } diff --git a/modules/webrtc/webrtc_peer_connection_js.cpp b/modules/webrtc/webrtc_peer_connection_js.cpp index 26256a4e30..19df397002 100644 --- a/modules/webrtc/webrtc_peer_connection_js.cpp +++ b/modules/webrtc/webrtc_peer_connection_js.cpp @@ -150,5 +150,5 @@ WebRTCPeerConnectionJS::~WebRTCPeerConnectionJS() { godot_js_rtc_pc_destroy(_js_id); _js_id = 0; } -}; +} #endif diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml index 0978e1fcee..b2e1cb345b 100644 --- a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml +++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml @@ -60,7 +60,7 @@ <member name="inbound_buffer_size" type="int" setter="set_inbound_buffer_size" getter="get_inbound_buffer_size" default="65535"> The inbound buffer size for connected peers. See [member WebSocketPeer.inbound_buffer_size] for more details. </member> - <member name="max_queued_packets" type="int" setter="set_max_queued_packets" getter="get_max_queued_packets" default="2048"> + <member name="max_queued_packets" type="int" setter="set_max_queued_packets" getter="get_max_queued_packets" default="4096"> The maximum number of queued packets for connected peers. See [member WebSocketPeer.max_queued_packets] for more details. </member> <member name="outbound_buffer_size" type="int" setter="set_outbound_buffer_size" getter="get_outbound_buffer_size" default="65535"> diff --git a/modules/websocket/doc_classes/WebSocketPeer.xml b/modules/websocket/doc_classes/WebSocketPeer.xml index 238dd30536..d329e21b88 100644 --- a/modules/websocket/doc_classes/WebSocketPeer.xml +++ b/modules/websocket/doc_classes/WebSocketPeer.xml @@ -155,10 +155,14 @@ The extra HTTP headers to be sent during the WebSocket handshake. [b]Note:[/b] Not supported in Web exports due to browsers' restrictions. </member> + <member name="heartbeat_interval" type="float" setter="set_heartbeat_interval" getter="get_heartbeat_interval" default="0.0"> + The interval (in seconds) at which the peer will automatically send WebSocket "ping" control frames. When set to [code]0[/code], no "ping" control frames will be sent. + [b]Note:[/b] Has no effect in Web exports due to browser restrictions. + </member> <member name="inbound_buffer_size" type="int" setter="set_inbound_buffer_size" getter="get_inbound_buffer_size" default="65535"> The size of the input buffer in bytes (roughly the maximum amount of memory that will be allocated for the inbound packets). </member> - <member name="max_queued_packets" type="int" setter="set_max_queued_packets" getter="get_max_queued_packets" default="2048"> + <member name="max_queued_packets" type="int" setter="set_max_queued_packets" getter="get_max_queued_packets" default="4096"> The maximum amount of packets that will be allowed in the queues (both inbound and outbound). </member> <member name="outbound_buffer_size" type="int" setter="set_outbound_buffer_size" getter="get_outbound_buffer_size" default="65535"> diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index fe0bc594e6..89dc4fa36e 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -84,7 +84,7 @@ public: virtual int get_available_packet_count() const override; virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override; - virtual int get_max_packet_size() const override { return packet_buffer.size(); }; + virtual int get_max_packet_size() const override { return packet_buffer.size(); } // WebSocketPeer virtual Error send(const uint8_t *p_buffer, int p_buffer_size, WriteMode p_mode) override; diff --git a/modules/websocket/packet_buffer.h b/modules/websocket/packet_buffer.h index f98ee12ef9..4ab0579912 100644 --- a/modules/websocket/packet_buffer.h +++ b/modules/websocket/packet_buffer.h @@ -104,6 +104,14 @@ public: return _queued; } + int payload_space_left() const { + return _payload.space_left(); + } + + int packets_space_left() const { + return _packets.size() - _queued; + } + void clear() { _payload.resize(0); _packets.resize(0); diff --git a/modules/websocket/websocket_peer.cpp b/modules/websocket/websocket_peer.cpp index 95a1a238e9..5c24b5d082 100644 --- a/modules/websocket/websocket_peer.cpp +++ b/modules/websocket/websocket_peer.cpp @@ -70,6 +70,9 @@ void WebSocketPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_max_queued_packets", "buffer_size"), &WebSocketPeer::set_max_queued_packets); ClassDB::bind_method(D_METHOD("get_max_queued_packets"), &WebSocketPeer::get_max_queued_packets); + ClassDB::bind_method(D_METHOD("set_heartbeat_interval", "interval"), &WebSocketPeer::set_heartbeat_interval); + ClassDB::bind_method(D_METHOD("get_heartbeat_interval"), &WebSocketPeer::get_heartbeat_interval); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "supported_protocols"), "set_supported_protocols", "get_supported_protocols"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "handshake_headers"), "set_handshake_headers", "get_handshake_headers"); @@ -78,6 +81,8 @@ void WebSocketPeer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "max_queued_packets"), "set_max_queued_packets", "get_max_queued_packets"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "heartbeat_interval"), "set_heartbeat_interval", "get_heartbeat_interval"); + BIND_ENUM_CONSTANT(WRITE_MODE_TEXT); BIND_ENUM_CONSTANT(WRITE_MODE_BINARY); @@ -151,3 +156,12 @@ void WebSocketPeer::set_max_queued_packets(int p_max_queued_packets) { int WebSocketPeer::get_max_queued_packets() const { return max_queued_packets; } + +double WebSocketPeer::get_heartbeat_interval() const { + return heartbeat_interval_msec / 1000.0; +} + +void WebSocketPeer::set_heartbeat_interval(double p_interval) { + ERR_FAIL_COND(p_interval < 0); + heartbeat_interval_msec = p_interval * 1000.0; +} diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index ef0197cf6c..4854122471 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -71,7 +71,8 @@ protected: int outbound_buffer_size = DEFAULT_BUFFER_SIZE; int inbound_buffer_size = DEFAULT_BUFFER_SIZE; - int max_queued_packets = 2048; + int max_queued_packets = 4096; + uint64_t heartbeat_interval_msec = 0; public: static WebSocketPeer *create(bool p_notify_postinitialize = true) { @@ -117,6 +118,9 @@ public: void set_max_queued_packets(int p_max_queued_packets); int get_max_queued_packets() const; + double get_heartbeat_interval() const; + void set_heartbeat_interval(double p_interval); + WebSocketPeer(); ~WebSocketPeer(); }; diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp index 0c0a046805..81e5673583 100644 --- a/modules/websocket/wsl_peer.cpp +++ b/modules/websocket/wsl_peer.cpp @@ -295,6 +295,7 @@ Error WSLPeer::_do_server_handshake() { resolver.stop(); // Response sent, initialize wslay context. wslay_event_context_server_init(&wsl_ctx, &_wsl_callbacks, this); + wslay_event_config_set_no_buffering(wsl_ctx, 1); wslay_event_config_set_max_recv_msg_length(wsl_ctx, inbound_buffer_size); in_buffer.resize(nearest_shift(inbound_buffer_size), max_queued_packets); packet_buffer.resize(inbound_buffer_size); @@ -403,6 +404,7 @@ void WSLPeer::_do_client_handshake() { ERR_FAIL_MSG("Invalid response headers."); } wslay_event_context_client_init(&wsl_ctx, &_wsl_callbacks, this); + wslay_event_config_set_no_buffering(wsl_ctx, 1); wslay_event_config_set_max_recv_msg_length(wsl_ctx, inbound_buffer_size); in_buffer.resize(nearest_shift(inbound_buffer_size), max_queued_packets); packet_buffer.resize(inbound_buffer_size); @@ -568,8 +570,15 @@ ssize_t WSLPeer::_wsl_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); return -1; } + // Make sure we don't read more than what our buffer can hold. + size_t buffer_limit = MIN(peer->in_buffer.payload_space_left(), peer->in_buffer.packets_space_left() * 2); // The minimum size of a websocket message is 2 bytes. + size_t to_read = MIN(len, buffer_limit); + if (to_read == 0) { + wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); + return -1; + } int read = 0; - Error err = conn->get_partial_data(data, len, read); + Error err = conn->get_partial_data(data, to_read, read); if (err != OK) { print_verbose("Websocket get data error: " + itos(err) + ", read (should be 0!): " + itos(read)); wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); @@ -582,6 +591,37 @@ ssize_t WSLPeer::_wsl_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, return read; } +void WSLPeer::_wsl_recv_start_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data) { + WSLPeer *peer = (WSLPeer *)user_data; + uint8_t op = arg->opcode; + if (op == WSLAY_TEXT_FRAME || op == WSLAY_BINARY_FRAME) { + // Get ready to process a data package. + PendingMessage &pm = peer->pending_message; + pm.opcode = op; + pm.payload_size = arg->payload_length; + } +} + +void WSLPeer::_wsl_frame_recv_chunk_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data) { + WSLPeer *peer = (WSLPeer *)user_data; + PendingMessage &pm = peer->pending_message; + if (pm.opcode != 0) { + // Only write the payload. + peer->in_buffer.write_packet(arg->data, arg->data_length, nullptr); + } +} + +void WSLPeer::_wsl_frame_recv_end_callback(wslay_event_context_ptr ctx, void *user_data) { + WSLPeer *peer = (WSLPeer *)user_data; + PendingMessage &pm = peer->pending_message; + if (pm.opcode != 0) { + // Only write the packet (since it's now completed). + uint8_t is_string = pm.opcode == WSLAY_TEXT_FRAME ? 1 : 0; + peer->in_buffer.write_packet(nullptr, pm.payload_size, &is_string); + pm.clear(); + } +} + ssize_t WSLPeer::_wsl_send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data) { WSLPeer *peer = (WSLPeer *)user_data; Ref<StreamPeer> conn = peer->connection; @@ -627,25 +667,19 @@ void WSLPeer::_wsl_msg_recv_callback(wslay_event_context_ptr ctx, const struct w return; } - if (peer->ready_state == STATE_CLOSING) { - return; - } - - if (op == WSLAY_TEXT_FRAME || op == WSLAY_BINARY_FRAME) { - // Message. - uint8_t is_string = arg->opcode == WSLAY_TEXT_FRAME ? 1 : 0; - peer->in_buffer.write_packet(arg->msg, arg->msg_length, &is_string); + if (op == WSLAY_PONG) { + peer->heartbeat_waiting = false; } - // Ping or pong. + // Ping, or message (already parsed in chunks). } wslay_event_callbacks WSLPeer::_wsl_callbacks = { _wsl_recv_callback, _wsl_send_callback, _wsl_genmask_callback, - nullptr, /* on_frame_recv_start_callback */ - nullptr, /* on_frame_recv_callback */ - nullptr, /* on_frame_recv_end_callback */ + _wsl_recv_start_callback, + _wsl_frame_recv_chunk_callback, + _wsl_frame_recv_end_callback, _wsl_msg_recv_callback }; @@ -680,7 +714,31 @@ void WSLPeer::poll() { if (ready_state == STATE_OPEN || ready_state == STATE_CLOSING) { ERR_FAIL_NULL(wsl_ctx); + uint64_t ticks = OS::get_singleton()->get_ticks_msec(); int err = 0; + if (heartbeat_interval_msec != 0 && ticks - last_heartbeat > heartbeat_interval_msec && ready_state == STATE_OPEN) { + if (heartbeat_waiting) { + wslay_event_context_free(wsl_ctx); + wsl_ctx = nullptr; + close(-1); + return; + } + heartbeat_waiting = true; + struct wslay_event_msg msg; + msg.opcode = WSLAY_PING; + msg.msg = nullptr; + msg.msg_length = 0; + err = wslay_event_queue_msg(wsl_ctx, &msg); + if (err == 0) { + last_heartbeat = ticks; + } else { + print_verbose("Websocket (wslay) failed to send ping: " + itos(err)); + wslay_event_context_free(wsl_ctx); + wsl_ctx = nullptr; + close(-1); + return; + } + } if ((err = wslay_event_recv(wsl_ctx)) != 0 || (err = wslay_event_send(wsl_ctx)) != 0) { // Error close. print_verbose("Websocket (wslay) poll error: " + itos(err)); @@ -689,12 +747,37 @@ void WSLPeer::poll() { close(-1); return; } - if (wslay_event_get_close_sent(wsl_ctx) && wslay_event_get_close_received(wsl_ctx)) { - // Clean close. - wslay_event_context_free(wsl_ctx); - wsl_ctx = nullptr; - close(-1); - return; + if (wslay_event_get_close_sent(wsl_ctx)) { + if (wslay_event_get_close_received(wsl_ctx)) { + // Clean close. + wslay_event_context_free(wsl_ctx); + wsl_ctx = nullptr; + close(-1); + return; + } else if (!wslay_event_get_read_enabled(wsl_ctx)) { + // Some protocol error caused wslay to stop processing incoming events, we'll never receive a close from the other peer. + close_code = wslay_event_get_status_code_sent(wsl_ctx); + switch (close_code) { + case WSLAY_CODE_MESSAGE_TOO_BIG: + close_reason = "Message too big"; + break; + case WSLAY_CODE_PROTOCOL_ERROR: + close_reason = "Protocol error"; + break; + case WSLAY_CODE_ABNORMAL_CLOSURE: + close_reason = "Abnormal closure"; + break; + case WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA: + close_reason = "Invalid frame payload data"; + break; + default: + close_reason = "Unknown"; + } + wslay_event_context_free(wsl_ctx); + wsl_ctx = nullptr; + close(-1); + return; + } } } } @@ -781,8 +864,10 @@ void WSLPeer::close(int p_code, String p_reason) { } } + heartbeat_waiting = false; in_buffer.clear(); packet_buffer.resize(0); + pending_message.clear(); } IPAddress WSLPeer::get_connected_host() const { diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index fb01da7ce2..45cca48224 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -53,6 +53,10 @@ private: // Callbacks. static ssize_t _wsl_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, int flags, void *user_data); + static void _wsl_recv_start_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data); + static void _wsl_frame_recv_chunk_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data); + static void _wsl_frame_recv_end_callback(wslay_event_context_ptr ctx, void *user_data); + static ssize_t _wsl_send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data); static int _wsl_genmask_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, void *user_data); static void _wsl_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *user_data); @@ -80,6 +84,16 @@ private: Resolver() {} }; + struct PendingMessage { + size_t payload_size = 0; + uint8_t opcode = 0; + + void clear() { + payload_size = 0; + opcode = 0; + } + }; + Resolver resolver; // WebSocket connection state. @@ -99,6 +113,9 @@ private: int close_code = -1; String close_reason; uint8_t was_string = 0; + uint64_t last_heartbeat = 0; + bool heartbeat_waiting = false; + PendingMessage pending_message; // WebSocket configuration. bool use_tls = true; @@ -127,7 +144,7 @@ public: virtual int get_available_packet_count() const override; virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override; - virtual int get_max_packet_size() const override { return packet_buffer.size(); }; + virtual int get_max_packet_size() const override { return packet_buffer.size(); } // WebSocketPeer virtual Error send(const uint8_t *p_buffer, int p_buffer_size, WriteMode p_mode) override; diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp index 352d495dd4..f45135a611 100644 --- a/modules/webxr/webxr_interface_js.cpp +++ b/modules/webxr/webxr_interface_js.cpp @@ -271,19 +271,19 @@ void WebXRInterfaceJS::_set_environment_blend_mode(String p_blend_mode_string) { StringName WebXRInterfaceJS::get_name() const { return "WebXR"; -}; +} uint32_t WebXRInterfaceJS::get_capabilities() const { return XRInterface::XR_STEREO | XRInterface::XR_MONO | XRInterface::XR_VR | XRInterface::XR_AR; -}; +} uint32_t WebXRInterfaceJS::get_view_count() { return godot_webxr_get_view_count(); -}; +} bool WebXRInterfaceJS::is_initialized() const { return (initialized); -}; +} bool WebXRInterfaceJS::initialize() { XRServer *xr_server = XRServer::get_singleton(); @@ -333,7 +333,7 @@ bool WebXRInterfaceJS::initialize() { }; return true; -}; +} void WebXRInterfaceJS::uninitialize() { if (initialized) { @@ -378,7 +378,7 @@ void WebXRInterfaceJS::uninitialize() { environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_OPAQUE; initialized = false; }; -}; +} Dictionary WebXRInterfaceJS::get_system_info() { Dictionary dict; @@ -427,7 +427,7 @@ Size2 WebXRInterfaceJS::get_render_target_size() { render_targetsize.height = (float)js_size[1]; return render_targetsize; -}; +} Transform3D WebXRInterfaceJS::get_camera_transform() { Transform3D camera_transform; @@ -445,7 +445,7 @@ Transform3D WebXRInterfaceJS::get_camera_transform() { } return camera_transform; -}; +} Transform3D WebXRInterfaceJS::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) { XRServer *xr_server = XRServer::get_singleton(); @@ -464,7 +464,7 @@ Transform3D WebXRInterfaceJS::get_transform_for_view(uint32_t p_view, const Tran transform_for_view.origin *= world_scale; return p_cam_transform * xr_server->get_reference_frame() * transform_for_view; -}; +} Projection WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { Projection view; @@ -527,7 +527,7 @@ Vector<BlitToScreen> WebXRInterfaceJS::post_draw_viewport(RID p_render_target, c texture_storage->render_target_set_reattach_textures(p_render_target, false); return blit_to_screen; -}; +} RID WebXRInterfaceJS::_get_color_texture() { unsigned int texture_id = godot_webxr_get_color_texture(); @@ -608,7 +608,7 @@ void WebXRInterfaceJS::process() { _update_input_source(i); } }; -}; +} void WebXRInterfaceJS::_update_input_source(int p_input_source_id) { XRServer *xr_server = XRServer::get_singleton(); @@ -871,13 +871,13 @@ WebXRInterfaceJS::WebXRInterfaceJS() { initialized = false; session_mode = "inline"; requested_reference_space_types = "local"; -}; +} WebXRInterfaceJS::~WebXRInterfaceJS() { // and make sure we cleanup if we haven't already if (initialized) { uninitialize(); }; -}; +} #endif // WEB_ENABLED diff --git a/platform/SCsub b/platform/SCsub index 7c9d07f6ef..248b4b88dd 100644 --- a/platform/SCsub +++ b/platform/SCsub @@ -60,7 +60,7 @@ register_platform_apis = env.CommandNoCache( ) env.add_source_files(env.platform_sources, register_platform_apis) for platform in env.platform_apis: - env.add_source_files(env.platform_sources, f"{platform}/api/api.cpp") + env.add_source_files(env.platform_sources, f"{platform}/api/*.cpp") lib = env.add_library("platform", env.platform_sources) env.Prepend(LIBS=[lib]) diff --git a/platform/android/detect.py b/platform/android/detect.py index 0a10754e24..03a208391c 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -5,6 +5,7 @@ import sys from typing import TYPE_CHECKING from methods import print_error, print_warning +from platform_methods import validate_arch if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -30,6 +31,7 @@ def get_opts(): ), BoolVariable("store_release", "Editor build for Google Play Store (for official builds only)", False), BoolVariable("generate_apk", "Generate an APK/AAB after building Android library by calling Gradle", False), + BoolVariable("swappy", "Use Swappy Frame Pacing library", False), ] @@ -95,15 +97,19 @@ def install_ndk_if_needed(env: "SConsEnvironment"): env["ANDROID_NDK_ROOT"] = get_android_ndk_root(env) +def detect_swappy(): + archs = ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"] + has_swappy = True + for arch in archs: + if not os.path.isfile(f"thirdparty/swappy-frame-pacing/{arch}/libswappy_static.a"): + has_swappy = False + return has_swappy + + def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["x86_32", "x86_64", "arm32", "arm64"] - if env["arch"] not in supported_arches: - print_error( - 'Unsupported CPU architecture "%s" for Android. Supported architectures are: %s.' - % (env["arch"], ", ".join(supported_arches)) - ) - sys.exit(255) + validate_arch(env["arch"], get_name(), supported_arches) if get_min_sdk_version(env["ndk_platform"]) < get_min_target_api(): print_warning( @@ -171,31 +177,52 @@ def configure(env: "SConsEnvironment"): env["AS"] = compiler_path + "/clang" env.Append( - CCFLAGS=( - "-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing".split() - ) + CCFLAGS=(["-fpic", "-ffunction-sections", "-funwind-tables", "-fstack-protector-strong", "-fvisibility=hidden"]) ) + has_swappy = detect_swappy() + if not has_swappy: + print_warning( + "Swappy Frame Pacing not detected! It is strongly recommended you download it from https://github.com/darksylinc/godot-swappy/releases and extract it so that the following files can be found:\n" + + " thirdparty/swappy-frame-pacing/arm64-v8a/libswappy_static.a\n" + + " thirdparty/swappy-frame-pacing/armeabi-v7a/libswappy_static.a\n" + + " thirdparty/swappy-frame-pacing/x86/libswappy_static.a\n" + + " thirdparty/swappy-frame-pacing/x86_64/libswappy_static.a\n" + + "Without Swappy, Godot apps on Android will inevitable suffer stutter and struggle to keep consistent 30/60/90/120 fps. Though Swappy cannot guarantee your app will be stutter-free, not having Swappy will guarantee there will be stutter even on the best phones and the most simple of scenes." + ) + if env["swappy"]: + print_error("Use build option `swappy=no` to ignore missing Swappy dependency and build without it.") + sys.exit(255) + if get_min_sdk_version(env["ndk_platform"]) >= 24: env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)]) if env["arch"] == "x86_32": # The NDK adds this if targeting API < 24, so we can drop it when Godot targets it at least env.Append(CCFLAGS=["-mstackrealign"]) + if has_swappy: + env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/x86"]) + elif env["arch"] == "x86_64": + if has_swappy: + env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/x86_64"]) elif env["arch"] == "arm32": - env.Append(CCFLAGS="-march=armv7-a -mfloat-abi=softfp".split()) + env.Append(CCFLAGS=["-march=armv7-a", "-mfloat-abi=softfp"]) env.Append(CPPDEFINES=["__ARM_ARCH_7__", "__ARM_ARCH_7A__"]) env.Append(CPPDEFINES=["__ARM_NEON__"]) + if has_swappy: + env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/armeabi-v7a"]) elif env["arch"] == "arm64": env.Append(CCFLAGS=["-mfix-cortex-a53-835769"]) env.Append(CPPDEFINES=["__ARM_ARCH_8A__"]) + if has_swappy: + env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/arm64-v8a"]) env.Append(CCFLAGS=["-ffp-contract=off"]) # Link flags - env.Append(LINKFLAGS="-Wl,--gc-sections -Wl,--no-undefined -Wl,-z,now".split()) - env.Append(LINKFLAGS="-Wl,-soname,libgodot_android.so") + env.Append(LINKFLAGS=["-Wl,--gc-sections", "-Wl,--no-undefined", "-Wl,-z,now"]) + env.Append(LINKFLAGS=["-Wl,-soname,libgodot_android.so"]) env.Prepend(CPPPATH=["#platform/android"]) env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"]) @@ -203,6 +230,9 @@ def configure(env: "SConsEnvironment"): if env["vulkan"]: env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) + if has_swappy: + env.Append(CPPDEFINES=["SWAPPY_FRAME_PACING_ENABLED"]) + env.Append(LIBS=["swappy_static"]) if not env["use_volk"]: env.Append(LIBS=["vulkan"]) diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index fa5b970a96..38f6931c8a 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -71,8 +71,9 @@ bool DisplayServerAndroid::has_feature(Feature p_feature) const { case FEATURE_MOUSE: //case FEATURE_MOUSE_WARP: //case FEATURE_NATIVE_DIALOG: - //case FEATURE_NATIVE_DIALOG_INPUT: - //case FEATURE_NATIVE_DIALOG_FILE: + case FEATURE_NATIVE_DIALOG_INPUT: + case FEATURE_NATIVE_DIALOG_FILE: + //case FEATURE_NATIVE_DIALOG_FILE_EXTRA: //case FEATURE_NATIVE_ICON: //case FEATURE_WINDOW_TRANSPARENCY: case FEATURE_CLIPBOARD: @@ -176,6 +177,38 @@ bool DisplayServerAndroid::clipboard_has() const { } } +Error DisplayServerAndroid::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) { + GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); + ERR_FAIL_NULL_V(godot_java, FAILED); + input_dialog_callback = p_callback; + return godot_java->show_input_dialog(p_title, p_description, p_partial); +} + +void DisplayServerAndroid::emit_input_dialog_callback(String p_text) { + if (input_dialog_callback.is_valid()) { + input_dialog_callback.call_deferred(p_text); + } +} + +Error DisplayServerAndroid::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) { + GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); + ERR_FAIL_NULL_V(godot_java, FAILED); + file_picker_callback = p_callback; + return godot_java->show_file_picker(p_current_directory, p_filename, p_mode, p_filters); +} + +void DisplayServerAndroid::emit_file_picker_callback(bool p_ok, const Vector<String> &p_selected_paths) { + if (file_picker_callback.is_valid()) { + file_picker_callback.call_deferred(p_ok, p_selected_paths, 0); + } +} + +Color DisplayServerAndroid::get_accent_color() const { + GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); + ERR_FAIL_NULL_V(godot_java, Color(0, 0, 0, 0)); + return godot_java->get_accent_color(); +} + TypedArray<Rect2> DisplayServerAndroid::get_display_cutouts() const { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); ERR_FAIL_NULL_V(godot_io_java, Array()); @@ -389,6 +422,14 @@ int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type, } return 0; } + case EGL_DISPLAY: { + // @todo Find a way to get this from the Java side. + return 0; + } + case EGL_CONFIG: { + // @todo Find a way to get this from the Java side. + return 0; + } #endif default: { return 0; @@ -596,12 +637,6 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis native_menu = memnew(NativeMenu); -#if defined(GLES3_ENABLED) - if (rendering_driver == "opengl3") { - RasterizerGLES3::make_current(false); - } -#endif - #if defined(RD_ENABLED) rendering_context = nullptr; rendering_device = nullptr; @@ -616,19 +651,24 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis if (rendering_context->initialize() != OK) { memdelete(rendering_context); rendering_context = nullptr; +#if defined(GLES3_ENABLED) bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); if (fallback_to_opengl3 && rendering_driver != "opengl3") { WARN_PRINT("Your device seem not to support Vulkan, switching to OpenGL 3."); rendering_driver = "opengl3"; OS::get_singleton()->set_current_rendering_method("gl_compatibility"); OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); - } else { + } else +#endif + { ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver)); r_error = ERR_UNAVAILABLE; return; } } + } + if (rendering_context) { union { #ifdef VULKAN_ENABLED RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan; @@ -668,6 +708,12 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis } #endif +#if defined(GLES3_ENABLED) + if (rendering_driver == "opengl3") { + RasterizerGLES3::make_current(false); + } +#endif + Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); r_error = OK; diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 65c6a53446..1744ad3069 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -87,6 +87,9 @@ class DisplayServerAndroid : public DisplayServer { Callable system_theme_changed; + Callable input_dialog_callback; + Callable file_picker_callback; + void _window_callback(const Callable &p_callable, const Variant &p_arg, bool p_deferred = false) const; static void _dispatch_input_events(const Ref<InputEvent> &p_event); @@ -116,6 +119,14 @@ public: virtual String clipboard_get() const override; virtual bool clipboard_has() const override; + virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override; + void emit_input_dialog_callback(String p_text); + + virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, const FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override; + void emit_file_picker_callback(bool p_ok, const Vector<String> &p_selected_paths); + + virtual Color get_accent_color() const override; + virtual TypedArray<Rect2> get_display_cutouts() const override; virtual Rect2i get_display_safe_area() const override; diff --git a/platform/android/doc_classes/EditorExportPlatformAndroid.xml b/platform/android/doc_classes/EditorExportPlatformAndroid.xml index 2fe5539e56..983683fd78 100644 --- a/platform/android/doc_classes/EditorExportPlatformAndroid.xml +++ b/platform/android/doc_classes/EditorExportPlatformAndroid.xml @@ -151,6 +151,9 @@ <member name="permissions/access_location_extra_commands" type="bool" setter="" getter=""> Allows access to the extra location provider commands. See [url=https://developer.android.com/reference/android/Manifest.permission#ACCESS_LOCATION_EXTRA_COMMANDS]ACCESS_LOCATION_EXTRA_COMMANDS[/url]. </member> + <member name="permissions/access_media_location" type="bool" setter="" getter=""> + Allows an application to access any geographic locations persisted in the user's shared collection. See [url=https://developer.android.com/reference/android/Manifest.permission#ACCESS_MEDIA_LOCATION]ACCESS_MEDIA_LOCATION[/url]. + </member> <member name="permissions/access_mock_location" type="bool" setter="" getter=""> Allows an application to create mock location providers for testing. </member> @@ -412,6 +415,18 @@ <member name="permissions/read_logs" type="bool" setter="" getter=""> Allows an application to read the low-level system log files. See [url=https://developer.android.com/reference/android/Manifest.permission#READ_LOGS]READ_LOGS[/url]. </member> + <member name="permissions/read_media_audio" type="bool" setter="" getter=""> + Allows an application to read audio files from external storage. See [url=https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_AUDIO]READ_MEDIA_AUDIO[/url]. + </member> + <member name="permissions/read_media_images" type="bool" setter="" getter=""> + Allows an application to read image files from external storage. See [url=https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_IMAGES]READ_MEDIA_IMAGES[/url]. + </member> + <member name="permissions/read_media_video" type="bool" setter="" getter=""> + Allows an application to read video files from external storage. See [url=https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_VIDEO]READ_MEDIA_VIDEO[/url]. + </member> + <member name="permissions/read_media_visual_user_selected" type="bool" setter="" getter=""> + Allows an application to read image or video files from external storage that a user has selected via the permission prompt photo picker. See [url=https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_VISUAL_USER_SELECTED]READ_MEDIA_VISUAL_USER_SELECTED[/url]. + </member> <member name="permissions/read_phone_state" type="bool" setter="" getter=""> Allows read only access to phone state. See [url=https://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE]READ_PHONE_STATE[/url]. </member> @@ -577,7 +592,7 @@ Allows an application to write to the user dictionary. </member> <member name="screen/immersive_mode" type="bool" setter="" getter=""> - If [code]true[/code], hides navigation and status bar. + If [code]true[/code], hides navigation and status bar. See [method DisplayServer.window_set_mode] to toggle it at runtime. </member> <member name="screen/support_large" type="bool" setter="" getter=""> Indicates whether the application supports larger screen form-factors. diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 93ac498ab3..dc7a287a91 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -37,6 +37,8 @@ #include "editor/editor_settings.h" #include "editor/export/editor_export.h" +String get_default_android_sdk_path(); + void register_android_exporter_types() { GDREGISTER_VIRTUAL_CLASS(EditorExportPlatformAndroid); } @@ -49,11 +51,15 @@ void register_android_exporter() { EDITOR_DEF_BASIC("export/android/debug_keystore_pass", DEFAULT_ANDROID_KEYSTORE_DEBUG_PASSWORD); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore_pass", PROPERTY_HINT_PASSWORD)); -#ifndef ANDROID_ENABLED +#ifdef ANDROID_ENABLED + EDITOR_DEF_BASIC("export/android/install_exported_apk", true); +#else EDITOR_DEF_BASIC("export/android/java_sdk_path", OS::get_singleton()->get_environment("JAVA_HOME")); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/java_sdk_path", PROPERTY_HINT_GLOBAL_DIR)); - EDITOR_DEF_BASIC("export/android/android_sdk_path", OS::get_singleton()->get_environment("ANDROID_HOME")); + + EDITOR_DEF_BASIC("export/android/android_sdk_path", OS::get_singleton()->has_environment("ANDROID_HOME") ? OS::get_singleton()->get_environment("ANDROID_HOME") : get_default_android_sdk_path()); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR)); + EDITOR_DEF("export/android/force_system_user", false); EDITOR_DEF("export/android/shutdown_adb_on_exit", true); @@ -67,3 +73,15 @@ void register_android_exporter() { Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>(memnew(EditorExportPlatformAndroid)); EditorExport::get_singleton()->add_export_platform(exporter); } + +inline String get_default_android_sdk_path() { +#ifdef WINDOWS_ENABLED + return OS::get_singleton()->get_environment("LOCALAPPDATA").path_join("Android/Sdk"); +#elif LINUXBSD_ENABLED + return OS::get_singleton()->get_environment("HOME").path_join("Android/Sdk"); +#elif MACOS_ENABLED + return OS::get_singleton()->get_environment("HOME").path_join("Library/Android/sdk"); +#else + return String(); +#endif +} diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 41f460ca8f..e20de99c2d 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -68,6 +68,7 @@ static const char *android_perms[] = { "ACCESS_COARSE_LOCATION", "ACCESS_FINE_LOCATION", "ACCESS_LOCATION_EXTRA_COMMANDS", + "ACCESS_MEDIA_LOCATION", "ACCESS_MOCK_LOCATION", "ACCESS_NETWORK_STATE", "ACCESS_SURFACE_FLINGER", @@ -155,6 +156,10 @@ static const char *android_perms[] = { "READ_HISTORY_BOOKMARKS", "READ_INPUT_STATE", "READ_LOGS", + "READ_MEDIA_AUDIO", + "READ_MEDIA_IMAGES", + "READ_MEDIA_VIDEO", + "READ_MEDIA_VISUAL_USER_SELECTED", "READ_PHONE_STATE", "READ_PROFILE", "READ_SMS", @@ -783,15 +788,16 @@ Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObj return OK; } -Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { APKExportData *ed = static_cast<APKExportData *>(p_userdata); - String dst_path = p_path.replace_first("res://", "assets/"); + const String path = ResourceUID::ensure_path(p_path); + const String dst_path = path.replace_first("res://", "assets/"); - store_in_apk(ed, dst_path, p_data, _should_compress_asset(p_path, p_data) ? Z_DEFLATED : 0); + store_in_apk(ed, dst_path, p_data, _should_compress_asset(path, p_data) ? Z_DEFLATED : 0); return OK; } -Error EditorExportPlatformAndroid::ignore_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error EditorExportPlatformAndroid::ignore_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { return OK; } @@ -1559,7 +1565,7 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> & str = get_project_name(package_name); } else { - String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_"); + String lang = str.substr(str.rfind_char('-') + 1, str.length()).replace("-", "_"); if (appnames.has(lang)) { str = appnames[lang]; } else { @@ -1693,7 +1699,7 @@ void EditorExportPlatformAndroid::load_icon_refs(const Ref<EditorExportPreset> & path = static_cast<String>(p_preset->get(launcher_adaptive_icon_monochrome_option)).strip_edges(); if (!path.is_empty()) { print_verbose("Loading adaptive monochrome icon from " + path); - ImageLoader::load_image(path, background); + ImageLoader::load_image(path, monochrome); } } @@ -1778,6 +1784,12 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport if (!is_package_name_valid(pn, &pn_err)) { return TTR("Invalid package name:") + " " + pn_err; } + } else if (p_name == launcher_adaptive_icon_monochrome_option) { + String monochrome_icon_path = p_preset->get(launcher_adaptive_icon_monochrome_option); + + if (monochrome_icon_path.is_empty()) { + return TTR("No adaptive monochrome icon specified; default Godot monochrome icon will be used."); + } } else if (p_name == "gradle_build/use_gradle_build") { bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); String enabled_plugins_names = _get_plugins_names(Ref<EditorExportPreset>(p_preset)); @@ -1892,7 +1904,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "com.example.$genname", false, true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "package/app_category", PROPERTY_HINT_ENUM, "Accessibility,Audio,Game,Image,Maps,News,Productivity,Social,Video"), APP_CATEGORY_GAME)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "package/app_category", PROPERTY_HINT_ENUM, "Accessibility,Audio,Game,Image,Maps,News,Productivity,Social,Video,Undefined"), APP_CATEGORY_GAME)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/retain_data_on_uninstall"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/exclude_from_recents"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/show_in_android_tv"), false)); @@ -2887,6 +2899,14 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre #endif print_verbose("Successfully completed signing build."); + +#ifdef ANDROID_ENABLED + bool prompt_apk_install = EDITOR_GET("export/android/install_exported_apk"); + if (prompt_apk_install) { + OS_Android::get_singleton()->shell_open(apk_path); + } +#endif + return OK; } @@ -3151,9 +3171,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP user_data.libs_directory = gradle_build_directory.path_join("libs"); user_data.debug = p_debug; if (p_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) { - err = export_project_files(p_preset, p_debug, ignore_apk_file, &user_data, copy_gradle_so); + err = export_project_files(p_preset, p_debug, ignore_apk_file, nullptr, &user_data, copy_gradle_so); } else { - err = export_project_files(p_preset, p_debug, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); + err = export_project_files(p_preset, p_debug, rename_and_store_file_in_gradle_project, nullptr, &user_data, copy_gradle_so); } if (err != OK) { add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not export project files to gradle project.")); @@ -3544,7 +3564,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP APKExportData ed; ed.ep = &ep; ed.apk = unaligned_apk; - err = export_project_files(p_preset, p_debug, ignore_apk_file, &ed, save_apk_so); + err = export_project_files(p_preset, p_debug, ignore_apk_file, nullptr, &ed, save_apk_so); } else { if (apk_expansion) { err = save_apk_expansion_file(p_preset, p_debug, p_path); @@ -3556,7 +3576,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP APKExportData ed; ed.ep = &ep; ed.apk = unaligned_apk; - err = export_project_files(p_preset, p_debug, save_apk_file, &ed, save_apk_so); + err = export_project_files(p_preset, p_debug, save_apk_file, nullptr, &ed, save_apk_so); } } diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 7e1d626486..23b6f9b193 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -35,6 +35,7 @@ #include "godot_plugin_config.h" #endif // DISABLE_DEPRECATED +#include "core/io/image.h" #include "core/io/zip_io.h" #include "core/os/os.h" #include "editor/export/editor_export_platform.h" @@ -141,9 +142,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { static Error save_apk_so(void *p_userdata, const SharedObject &p_so); - static Error save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); - static Error ignore_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error ignore_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so); @@ -185,7 +186,7 @@ protected: void _notification(int p_what); public: - typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp index 9eddef6a4c..433888581f 100644 --- a/platform/android/export/gradle_export_util.cpp +++ b/platform/android/export/gradle_export_util.cpp @@ -88,6 +88,8 @@ int _get_app_category_value(int category_index) { return 7; case APP_CATEGORY_SOCIAL: return 4; + case APP_CATEGORY_UNDEFINED: + return -1; case APP_CATEGORY_VIDEO: return 2; case APP_CATEGORY_GAME: @@ -167,10 +169,11 @@ Error store_string_at_path(const String &p_path, const String &p_data) { // It is used by the export_project_files method to save all the asset files into the gradle project. // It's functionality mirrors that of the method save_apk_file. // This method will be called ONLY when gradle build is enabled. -Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { +Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed) { CustomExportData *export_data = static_cast<CustomExportData *>(p_userdata); - String dst_path = p_path.replace_first("res://", export_data->assets_directory + "/"); - print_verbose("Saving project files from " + p_path + " into " + dst_path); + const String path = ResourceUID::ensure_path(p_path); + const String dst_path = path.replace_first("res://", export_data->assets_directory + "/"); + print_verbose("Saving project files from " + path + " into " + dst_path); Error err = store_file_at_path(dst_path, p_data); return err; } @@ -311,17 +314,21 @@ String _get_application_tag(const Ref<EditorExportPlatform> &p_export_platform, " <application android:label=\"@string/godot_project_name_string\"\n" " android:allowBackup=\"%s\"\n" " android:icon=\"@mipmap/icon\"\n" - " android:appCategory=\"%s\"\n" " android:isGame=\"%s\"\n" " android:hasFragileUserData=\"%s\"\n" - " android:requestLegacyExternalStorage=\"%s\"\n" - " tools:replace=\"android:allowBackup,android:appCategory,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n" - " tools:ignore=\"GoogleAppIndexingWarning\">\n\n", + " android:requestLegacyExternalStorage=\"%s\"\n", bool_to_string(p_preset->get("user_data_backup/allow")), - _get_app_category_label(app_category_index), bool_to_string(is_game), bool_to_string(p_preset->get("package/retain_data_on_uninstall")), bool_to_string(p_has_read_write_storage_permission)); + if (app_category_index != APP_CATEGORY_UNDEFINED) { + manifest_application_text += vformat(" android:appCategory=\"%s\"\n", _get_app_category_label(app_category_index)); + manifest_application_text += " tools:replace=\"android:allowBackup,android:appCategory,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n"; + } else { + manifest_application_text += " tools:remove=\"android:appCategory\"\n"; + manifest_application_text += " tools:replace=\"android:allowBackup,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n"; + } + manifest_application_text += " tools:ignore=\"GoogleAppIndexingWarning\">\n\n"; Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); for (int i = 0; i < export_plugins.size(); i++) { diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 9f8e476f73..a528fd5211 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -55,6 +55,7 @@ static const int APP_CATEGORY_NEWS = 5; static const int APP_CATEGORY_PRODUCTIVITY = 6; static const int APP_CATEGORY_SOCIAL = 7; static const int APP_CATEGORY_VIDEO = 8; +static const int APP_CATEGORY_UNDEFINED = 9; // Supported XR modes. // This should match the entries in 'platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java' @@ -92,7 +93,7 @@ Error store_string_at_path(const String &p_path, const String &p_data); // It is used by the export_project_files method to save all the asset files into the gradle project. // It's functionality mirrors that of the method save_apk_file. // This method will be called ONLY when gradle build is enabled. -Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); +Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed); // Creates strings.xml files inside the gradle project for different locales. Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset, const String &project_name, const String &p_gradle_build_dir); diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml index 3ab8401928..3c86e54df5 100644 --- a/platform/android/java/app/res/values/themes.xml +++ b/platform/android/java/app/res/values/themes.xml @@ -1,7 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="GodotAppMainTheme" parent="@android:style/Theme.Black.NoTitleBar"/> + <style name="GodotAppMainTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar"> + <item name ="android:windowDrawsSystemBarBackgrounds">false</item> + </style> <style name="GodotAppSplashTheme" parent="Theme.SplashScreen"> <!-- Set the splash screen background, animated icon, and animation diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle index 45222ca3b0..276d74b75b 100644 --- a/platform/android/java/editor/build.gradle +++ b/platform/android/java/editor/build.gradle @@ -173,7 +173,7 @@ dependencies { implementation "androidx.window:window:1.3.0" implementation "androidx.core:core-splashscreen:$versions.splashscreenVersion" implementation "androidx.constraintlayout:constraintlayout:2.1.4" - implementation "org.bouncycastle:bcprov-jdk15to18:1.77" + implementation "org.bouncycastle:bcprov-jdk15to18:1.78" // Meta dependencies horizonosImplementation "org.godotengine:godot-openxr-vendors-meta:3.0.0-stable" diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml index a875745860..c1eb03b31f 100644 --- a/platform/android/java/editor/src/main/AndroidManifest.xml +++ b/platform/android/java/editor/src/main/AndroidManifest.xml @@ -25,6 +25,7 @@ <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.VIBRATE" /> + <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <application android:allowBackup="false" diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt index 7b6d1f6bd1..6aa2ba7195 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt @@ -390,7 +390,7 @@ abstract class BaseGodotEditor : GodotActivity() { * If the launch policy is [LaunchPolicy.AUTO], resolve it into a specific policy based on the * editor setting or device and screen metrics. * - * If the launch policy is [LaunchPolicy.PIP] but PIP is not supported, fallback to the default + * If the launch policy is [LaunchPolicy.SAME_AND_LAUNCH_IN_PIP_MODE] but PIP is not supported, fallback to the default * launch policy. */ private fun resolveLaunchPolicyIfNeeded(policy: LaunchPolicy): LaunchPolicy { @@ -453,9 +453,9 @@ abstract class BaseGodotEditor : GodotActivity() { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) // Check if we got the MANAGE_EXTERNAL_STORAGE permission - if (requestCode == PermissionsUtil.REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (!Environment.isExternalStorageManager()) { + when (requestCode) { + PermissionsUtil.REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) { Toast.makeText( this, R.string.denied_storage_permission_error_msg, @@ -463,6 +463,16 @@ abstract class BaseGodotEditor : GodotActivity() { ).show() } } + + PermissionsUtil.REQUEST_INSTALL_PACKAGES_REQ_CODE -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !packageManager.canRequestPackageInstalls()) { + Toast.makeText( + this, + R.string.denied_install_packages_permission_error_msg, + Toast.LENGTH_LONG + ).show() + } + } } } @@ -514,7 +524,7 @@ abstract class BaseGodotEditor : GodotActivity() { override fun supportsFeature(featureTag: String): Boolean { if (featureTag == "xr_editor") { - return isNativeXRDevice(); + return isNativeXRDevice() } if (featureTag == "horizonos") { diff --git a/platform/android/java/editor/src/main/res/values/strings.xml b/platform/android/java/editor/src/main/res/values/strings.xml index 0ad54ac3a1..a25b6c0a2d 100644 --- a/platform/android/java/editor/src/main/res/values/strings.xml +++ b/platform/android/java/editor/src/main/res/values/strings.xml @@ -2,5 +2,6 @@ <resources> <string name="godot_game_activity_name">Godot Play window</string> <string name="denied_storage_permission_error_msg">Missing storage access permission!</string> + <string name="denied_install_packages_permission_error_msg">Missing install packages permission!</string> <string name="pip_button_description">Button used to toggle picture-in-picture mode for the Play window</string> </resources> diff --git a/platform/android/java/editor/src/main/res/values/themes.xml b/platform/android/java/editor/src/main/res/values/themes.xml index 2b352247db..8de2c6e288 100644 --- a/platform/android/java/editor/src/main/res/values/themes.xml +++ b/platform/android/java/editor/src/main/res/values/themes.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="GodotEditorTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen"> + <style name="GodotEditorTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"> + <item name ="android:windowDrawsSystemBarBackgrounds">false</item> </style> <style name="GodotEditorSplashScreenTheme" parent="Theme.SplashScreen.IconBackground"> diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle index f6aee434e5..f273105efc 100644 --- a/platform/android/java/lib/build.gradle +++ b/platform/android/java/lib/build.gradle @@ -106,8 +106,8 @@ android { boolean devBuild = buildType == "dev" boolean debugSymbols = devBuild boolean runTests = devBuild - boolean productionBuild = !devBuild boolean storeRelease = buildType == "release" + boolean productionBuild = storeRelease def sconsTarget = flavorName if (sconsTarget == "template") { diff --git a/platform/android/java/lib/res/values/dimens.xml b/platform/android/java/lib/res/values/dimens.xml index 9034dbbcc1..287d1c8920 100644 --- a/platform/android/java/lib/res/values/dimens.xml +++ b/platform/android/java/lib/res/values/dimens.xml @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="text_edit_height">48dp</dimen> + <dimen name="input_dialog_padding_horizontal">10dp</dimen> + <dimen name="input_dialog_padding_vertical">5dp</dimen> </resources> diff --git a/platform/android/java/lib/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml index 03752e092e..e44addadd0 100644 --- a/platform/android/java/lib/res/values/strings.xml +++ b/platform/android/java/lib/res/values/strings.xml @@ -55,4 +55,7 @@ <string name="kilobytes_per_second">%1$s KB/s</string> <string name="time_remaining">Time remaining: %1$s</string> <string name="time_remaining_notification">%1$s left</string> + + <!-- Labels for the dialog action buttons --> + <string name="dialog_ok">OK</string> </resources> diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt index 567b134234..3ad8e6bc9e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt @@ -44,6 +44,7 @@ import android.os.* import android.util.Log import android.util.TypedValue import android.view.* +import android.widget.EditText import android.widget.FrameLayout import androidx.annotation.Keep import androidx.annotation.StringRes @@ -56,6 +57,7 @@ import com.google.android.vending.expansion.downloader.* import org.godotengine.godot.error.Error import org.godotengine.godot.input.GodotEditText import org.godotengine.godot.input.GodotInputHandler +import org.godotengine.godot.io.FilePicker import org.godotengine.godot.io.directory.DirectoryAccessHandler import org.godotengine.godot.io.file.FileAccessHandler import org.godotengine.godot.plugin.AndroidRuntimePlugin @@ -81,6 +83,7 @@ import java.util.* import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference + /** * Core component used to interface with the native layer of the engine. * @@ -477,12 +480,17 @@ class Godot(private val context: Context) { // ...add to FrameLayout containerLayout?.addView(editText) renderView = if (usesVulkan()) { - if (!meetsVulkanRequirements(activity.packageManager)) { + if (meetsVulkanRequirements(activity.packageManager)) { + GodotVulkanRenderView(host, this, godotInputHandler) + } else if (canFallbackToOpenGL()) { + // Fallback to OpenGl. + GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl) + } else { throw IllegalStateException(activity.getString(R.string.error_missing_vulkan_requirements_message)) } - GodotVulkanRenderView(host, this, godotInputHandler) + } else { - // Fallback to openGl + // Fallback to OpenGl. GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl) } @@ -670,6 +678,9 @@ class Godot(private val context: Context) { for (plugin in pluginRegistry.allPlugins) { plugin.onMainActivityResult(requestCode, resultCode, data) } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + FilePicker.handleActivityResult(context, requestCode, resultCode, data) + } } /** @@ -772,7 +783,7 @@ class Godot(private val context: Context) { val builder = AlertDialog.Builder(activity) builder.setMessage(message).setTitle(title) builder.setPositiveButton( - "OK" + R.string.dialog_ok ) { dialog: DialogInterface, id: Int -> okCallback?.run() dialog.cancel() @@ -817,6 +828,13 @@ class Godot(private val context: Context) { } /** + * Returns true if can fallback to OpenGL. + */ + private fun canFallbackToOpenGL(): Boolean { + return java.lang.Boolean.parseBoolean(GodotLib.getGlobal("rendering/rendering_device/fallback_to_opengl3")) + } + + /** * Returns true if the device meets the base requirements for Vulkan support, false otherwise. */ private fun meetsVulkanRequirements(packageManager: PackageManager?): Boolean { @@ -876,6 +894,44 @@ class Godot(private val context: Context) { mClipboard.setPrimaryClip(clip) } + @Keep + private fun showFilePicker(currentDirectory: String, filename: String, fileMode: Int, filters: Array<String>) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + FilePicker.showFilePicker(context, getActivity(), currentDirectory, filename, fileMode, filters) + } + } + + /** + * Popup a dialog to input text. + */ + @Keep + private fun showInputDialog(title: String, message: String, existingText: String) { + val activity: Activity = getActivity() ?: return + val inputField = EditText(activity) + val paddingHorizontal = activity.resources.getDimensionPixelSize(R.dimen.input_dialog_padding_horizontal) + val paddingVertical = activity.resources.getDimensionPixelSize(R.dimen.input_dialog_padding_vertical) + inputField.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical) + inputField.setText(existingText) + runOnUiThread { + val builder = AlertDialog.Builder(activity) + builder.setMessage(message).setTitle(title).setView(inputField) + builder.setPositiveButton(R.string.dialog_ok) { + dialog: DialogInterface, id: Int -> + GodotLib.inputDialogCallback(inputField.text.toString()) + dialog.dismiss() + } + val dialog = builder.create() + dialog.show() + } + } + + @Keep + private fun getAccentColor(): Int { + val value = TypedValue() + context.theme.resolveAttribute(android.R.attr.colorAccent, value, true) + return value.data + } + /** * Destroys the Godot Engine and kill the process it's running in. */ diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index f060c7aaff..79751dd58f 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -47,6 +47,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.DisplayCutout; +import android.view.Surface; import android.view.WindowInsets; import androidx.core.content.FileProvider; diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index 295a4a6340..13ae2150d7 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -225,6 +225,16 @@ public class GodotLib { public static native void onNightModeChanged(); /** + * Invoked on the input dialog submitted. + */ + public static native void inputDialogCallback(String p_text); + + /** + * Invoked on the file picker closed. + */ + public static native void filePickerCallback(boolean p_ok, String[] p_selected_paths); + + /** * Invoked on the GL thread to configure the height of the virtual keyboard. */ public static native void setVirtualKeyboardHeight(int p_height); diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/FilePicker.kt b/platform/android/java/lib/src/org/godotengine/godot/io/FilePicker.kt new file mode 100644 index 0000000000..2befe0583b --- /dev/null +++ b/platform/android/java/lib/src/org/godotengine/godot/io/FilePicker.kt @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* FilePicker.kt */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + +package org.godotengine.godot.io + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.provider.DocumentsContract +import android.util.Log +import androidx.annotation.RequiresApi +import org.godotengine.godot.GodotLib +import org.godotengine.godot.io.file.MediaStoreData + +/** + * Utility class for managing file selection and file picker activities. + * + * It provides methods to launch a file picker and handle the result, supporting various file modes, + * including opening files, directories, and saving files. + */ +internal class FilePicker { + companion object { + private const val FILE_PICKER_REQUEST = 1000 + private val TAG = FilePicker::class.java.simpleName + + // Constants for fileMode values + private const val FILE_MODE_OPEN_FILE = 0 + private const val FILE_MODE_OPEN_FILES = 1 + private const val FILE_MODE_OPEN_DIR = 2 + private const val FILE_MODE_OPEN_ANY = 3 + private const val FILE_MODE_SAVE_FILE = 4 + + /** + * Handles the result from a file picker activity and processes the selected file(s) or directory. + * + * @param context The context from which the file picker was launched. + * @param requestCode The request code used when starting the file picker activity. + * @param resultCode The result code returned by the activity. + * @param data The intent data containing the selected file(s) or directory. + */ + @RequiresApi(Build.VERSION_CODES.Q) + fun handleActivityResult(context: Context, requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == FILE_PICKER_REQUEST) { + if (resultCode == Activity.RESULT_CANCELED) { + Log.d(TAG, "File picker canceled") + GodotLib.filePickerCallback(false, emptyArray()) + return + } + if (resultCode == Activity.RESULT_OK) { + val selectedPaths: MutableList<String> = mutableListOf() + // Handle multiple file selection. + val clipData = data?.clipData + if (clipData != null) { + for (i in 0 until clipData.itemCount) { + val uri = clipData.getItemAt(i).uri + uri?.let { + val filepath = MediaStoreData.getFilePathFromUri(context, uri) + if (filepath != null) { + selectedPaths.add(filepath) + } else { + Log.d(TAG, "null filepath URI: $it") + } + } + } + } else { + val uri: Uri? = data?.data + uri?.let { + val filepath = MediaStoreData.getFilePathFromUri(context, uri) + if (filepath != null) { + selectedPaths.add(filepath) + } else { + Log.d(TAG, "null filepath URI: $it") + } + } + } + + if (selectedPaths.isNotEmpty()) { + GodotLib.filePickerCallback(true, selectedPaths.toTypedArray()) + } else { + GodotLib.filePickerCallback(false, emptyArray()) + } + } + } + } + + /** + * Launches a file picker activity with specified settings based on the mode, initial directory, + * file type filters, and other parameters. + * + * @param context The context from which to start the file picker. + * @param activity The activity instance used to initiate the picker. Required for activity results. + * @param currentDirectory The directory path to start the file picker in. + * @param filename The name of the file when using save mode. + * @param fileMode The mode to operate in, specifying open, save, or directory select. + * @param filters Array of MIME types to filter file selection. + */ + @RequiresApi(Build.VERSION_CODES.Q) + fun showFilePicker(context: Context, activity: Activity?, currentDirectory: String, filename: String, fileMode: Int, filters: Array<String>) { + val intent = when (fileMode) { + FILE_MODE_OPEN_DIR -> Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + FILE_MODE_SAVE_FILE -> Intent(Intent.ACTION_CREATE_DOCUMENT) + else -> Intent(Intent.ACTION_OPEN_DOCUMENT) + } + val initialDirectory = MediaStoreData.getUriFromDirectoryPath(context, currentDirectory) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && initialDirectory != null) { + intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialDirectory) + } else { + Log.d(TAG, "Error cannot set initial directory") + } + if (fileMode == FILE_MODE_OPEN_FILES) { + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) // Set multi select for FILE_MODE_OPEN_FILES + } else if (fileMode == FILE_MODE_SAVE_FILE) { + intent.putExtra(Intent.EXTRA_TITLE, filename) // Set filename for FILE_MODE_SAVE_FILE + } + // ACTION_OPEN_DOCUMENT_TREE does not support intent type + if (fileMode != FILE_MODE_OPEN_DIR) { + intent.type = "*/*" + if (filters.isNotEmpty()) { + if (filters.size == 1) { + intent.type = filters[0] + } else { + intent.putExtra(Intent.EXTRA_MIME_TYPES, filters) + } + } + intent.addCategory(Intent.CATEGORY_OPENABLE) + } + intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true) + activity?.startActivityForResult(intent, FILE_PICKER_REQUEST) + } + } +} diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt index 97362e2542..46bd465e90 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt @@ -38,6 +38,7 @@ import android.net.Uri import android.os.Build import android.os.Environment import android.provider.MediaStore +import android.util.Log import androidx.annotation.RequiresApi import java.io.File @@ -46,6 +47,7 @@ import java.io.FileNotFoundException import java.io.FileOutputStream import java.nio.channels.FileChannel + /** * Implementation of [DataAccess] which handles access and interactions with file and data * under scoped storage via the MediaStore API. @@ -81,6 +83,10 @@ internal class MediaStoreData(context: Context, filePath: String, accessFlag: Fi private const val SELECTION_BY_PATH = "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ? " + " AND ${MediaStore.Files.FileColumns.RELATIVE_PATH} = ?" + private const val AUTHORITY_MEDIA_DOCUMENTS = "com.android.providers.media.documents" + private const val AUTHORITY_EXTERNAL_STORAGE_DOCUMENTS = "com.android.externalstorage.documents" + private const val AUTHORITY_DOWNLOADS_DOCUMENTS = "com.android.providers.downloads.documents" + private fun getSelectionByPathArguments(path: String): Array<String> { return arrayOf(getMediaStoreDisplayName(path), getMediaStoreRelativePath(path)) } @@ -230,6 +236,72 @@ internal class MediaStoreData(context: Context, filePath: String, accessFlag: Fi ) return updated > 0 } + + fun getUriFromDirectoryPath(context: Context, directoryPath: String): Uri? { + if (!directoryExists(directoryPath)) { + return null + } + // Check if the path is under external storage. + val externalStorageRoot = Environment.getExternalStorageDirectory().absolutePath + if (directoryPath.startsWith(externalStorageRoot)) { + val relativePath = directoryPath.replaceFirst(externalStorageRoot, "").trim('/') + val uri = Uri.Builder() + .scheme("content") + .authority(AUTHORITY_EXTERNAL_STORAGE_DOCUMENTS) + .appendPath("document") + .appendPath("primary:$relativePath") + .build() + return uri + } + return null + } + + fun getFilePathFromUri(context: Context, uri: Uri): String? { + // Converts content uri to filepath. + val id = getIdFromUri(uri) ?: return null + + if (uri.authority == AUTHORITY_EXTERNAL_STORAGE_DOCUMENTS) { + val split = id.split(":") + val fileName = split.last() + val relativePath = split.dropLast(1).joinToString("/") + val fullPath = File(Environment.getExternalStorageDirectory(), "$relativePath/$fileName").absolutePath + return fullPath + } else { + val id = id.toLongOrNull() ?: return null + val dataItems = queryById(context, id) + return if (dataItems.isNotEmpty()) { + val dataItem = dataItems[0] + File(Environment.getExternalStorageDirectory(), File(dataItem.relativePath, dataItem.displayName).toString()).absolutePath + } else { + null + } + } + } + + private fun getIdFromUri(uri: Uri): String? { + return try { + if (uri.authority == AUTHORITY_EXTERNAL_STORAGE_DOCUMENTS || uri.authority == AUTHORITY_MEDIA_DOCUMENTS || uri.authority == AUTHORITY_DOWNLOADS_DOCUMENTS) { + val documentId = uri.lastPathSegment ?: throw IllegalArgumentException("Invalid URI: $uri") + documentId.substringAfter(":") + } else { + throw IllegalArgumentException("Unsupported URI format: $uri") + } + } catch (e: Exception) { + Log.d(TAG, "Failed to parse ID from URI: $uri", e) + null + } + } + + private fun directoryExists(path: String): Boolean { + return try { + val file = File(path) + file.isDirectory && file.exists() + } catch (e: SecurityException) { + Log.d(TAG, "Failed to check directoryExists: $path", e) + false + } + } + } private val id: Long diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java index c44a6dd472..885873e46d 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java @@ -49,7 +49,6 @@ import androidx.core.content.ContextCompat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -66,6 +65,7 @@ public final class PermissionsUtil { public static final int REQUEST_ALL_PERMISSION_REQ_CODE = 1001; public static final int REQUEST_SINGLE_PERMISSION_REQ_CODE = 1002; public static final int REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE = 2002; + public static final int REQUEST_INSTALL_PACKAGES_REQ_CODE = 3002; private PermissionsUtil() { } @@ -105,6 +105,16 @@ public final class PermissionsUtil { activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE); } } + } else if (permission.equals(Manifest.permission.REQUEST_INSTALL_PACKAGES)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !activity.getPackageManager().canRequestPackageInstalls()) { + try { + Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES); + intent.setData(Uri.parse(String.format("package:%s", activity.getPackageName()))); + activity.startActivityForResult(intent, REQUEST_INSTALL_PACKAGES_REQ_CODE); + } catch (Exception e) { + Log.e(TAG, "Unable to request permission " + Manifest.permission.REQUEST_INSTALL_PACKAGES); + } + } } else { PermissionInfo permissionInfo = getPermissionInfo(activity, permission); int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel; @@ -215,7 +225,7 @@ public final class PermissionsUtil { try { manifestPermissions = getManifestPermissions(activity); } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); + Log.e(TAG, "Unable to retrieve manifest permissions", e); return false; } @@ -242,7 +252,7 @@ public final class PermissionsUtil { try { manifestPermissions = getManifestPermissions(context); } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); + Log.e(TAG, "Unable to retrieve manifest permissions", e); return new String[0]; } if (manifestPermissions.isEmpty()) { diff --git a/platform/android/java/nativeSrcsConfigs/CMakeLists.txt b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt index a7d2774db5..a5ecafeb09 100644 --- a/platform/android/java/nativeSrcsConfigs/CMakeLists.txt +++ b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt @@ -21,4 +21,4 @@ target_include_directories(${PROJECT_NAME} ${ANDROID_ROOT_DIR} ${OPENXR_INCLUDE_DIR}) -add_definitions(-DUNIX_ENABLED -DVULKAN_ENABLED -DANDROID_ENABLED -DGLES3_ENABLED -DTOOLS_ENABLED) +add_definitions(-DUNIX_ENABLED -DVULKAN_ENABLED -DANDROID_ENABLED -DGLES3_ENABLED -DTOOLS_ENABLED -DDEBUG_ENABLED) diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 1a256959cd..5c1e78dcc4 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -540,6 +540,30 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onNightModeChanged(JN } } +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_inputDialogCallback(JNIEnv *env, jclass clazz, jstring p_text) { + DisplayServerAndroid *ds = (DisplayServerAndroid *)DisplayServer::get_singleton(); + if (ds) { + String text = jstring_to_string(p_text, env); + ds->emit_input_dialog_callback(text); + } +} + +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_filePickerCallback(JNIEnv *env, jclass clazz, jboolean p_ok, jobjectArray p_selected_paths) { + DisplayServerAndroid *ds = (DisplayServerAndroid *)DisplayServer::get_singleton(); + if (ds) { + Vector<String> selected_paths; + + jint length = env->GetArrayLength(p_selected_paths); + for (jint i = 0; i < length; ++i) { + jstring java_string = (jstring)env->GetObjectArrayElement(p_selected_paths, i); + String path = jstring_to_string(java_string, env); + selected_paths.push_back(path); + env->DeleteLocalRef(java_string); + } + ds->emit_file_picker_callback(p_ok, selected_paths); + } +} + JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result) { String permission = jstring_to_string(p_permission, env); if (permission == "android.permission.RECORD_AUDIO" && p_result) { diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 2165ce264b..31a7598a7b 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -67,6 +67,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onNightModeChanged(JNIEnv *env, jclass clazz); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_inputDialogCallback(JNIEnv *env, jclass clazz, jstring p_text); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_filePickerCallback(JNIEnv *env, jclass clazz, jboolean p_ok, jobjectArray p_selected_paths); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz); JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_shouldDispatchInputToRenderThread(JNIEnv *env, jclass clazz); diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index d3b30e4589..5ecd789d43 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -64,9 +64,12 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_ _alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); _is_dark_mode_supported = p_env->GetMethodID(godot_class, "isDarkModeSupported", "()Z"); _is_dark_mode = p_env->GetMethodID(godot_class, "isDarkMode", "()Z"); + _get_accent_color = p_env->GetMethodID(godot_class, "getAccentColor", "()I"); _get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;"); _set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V"); _has_clipboard = p_env->GetMethodID(godot_class, "hasClipboard", "()Z"); + _show_input_dialog = p_env->GetMethodID(godot_class, "showInputDialog", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + _show_file_picker = p_env->GetMethodID(godot_class, "showFilePicker", "(Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)V"); _request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z"); _request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z"); _get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;"); @@ -212,6 +215,23 @@ bool GodotJavaWrapper::is_dark_mode() { } } +Color GodotJavaWrapper::get_accent_color() { + if (_get_accent_color) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_NULL_V(env, Color(0, 0, 0, 0)); + int accent_color = env->CallIntMethod(godot_instance, _get_accent_color); + + // Convert ARGB to RGBA. + int alpha = (accent_color >> 24) & 0xFF; + int red = (accent_color >> 16) & 0xFF; + int green = (accent_color >> 8) & 0xFF; + int blue = accent_color & 0xFF; + return Color(red / 255.0f, green / 255.0f, blue / 255.0f, alpha / 255.0f); + } else { + return Color(0, 0, 0, 0); + } +} + bool GodotJavaWrapper::has_get_clipboard() { return _get_clipboard != nullptr; } @@ -268,6 +288,46 @@ bool GodotJavaWrapper::has_clipboard() { } } +Error GodotJavaWrapper::show_input_dialog(const String &p_title, const String &p_message, const String &p_existing_text) { + if (_show_input_dialog) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED); + jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data()); + jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data()); + jstring jStrExistingText = env->NewStringUTF(p_existing_text.utf8().get_data()); + env->CallVoidMethod(godot_instance, _show_input_dialog, jStrTitle, jStrMessage, jStrExistingText); + env->DeleteLocalRef(jStrTitle); + env->DeleteLocalRef(jStrMessage); + env->DeleteLocalRef(jStrExistingText); + return OK; + } else { + return ERR_UNCONFIGURED; + } +} + +Error GodotJavaWrapper::show_file_picker(const String &p_current_directory, const String &p_filename, int p_mode, const Vector<String> &p_filters) { + if (_show_file_picker) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED); + jstring j_current_directory = env->NewStringUTF(p_current_directory.utf8().get_data()); + jstring j_filename = env->NewStringUTF(p_filename.utf8().get_data()); + jint j_mode = p_mode; + jobjectArray j_filters = env->NewObjectArray(p_filters.size(), env->FindClass("java/lang/String"), nullptr); + for (int i = 0; i < p_filters.size(); ++i) { + jstring j_filter = env->NewStringUTF(p_filters[i].utf8().get_data()); + env->SetObjectArrayElement(j_filters, i, j_filter); + env->DeleteLocalRef(j_filter); + } + env->CallVoidMethod(godot_instance, _show_file_picker, j_current_directory, j_filename, j_mode, j_filters); + env->DeleteLocalRef(j_current_directory); + env->DeleteLocalRef(j_filename); + env->DeleteLocalRef(j_filters); + return OK; + } else { + return ERR_UNCONFIGURED; + } +} + bool GodotJavaWrapper::request_permission(const String &p_name) { if (_request_permission) { JNIEnv *env = get_jni_env(); diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index 51d7f98541..512779169a 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -34,6 +34,7 @@ #include "java_godot_view_wrapper.h" #include "string_android.h" +#include "core/math/color.h" #include "core/templates/list.h" #include <android/log.h> @@ -55,9 +56,12 @@ private: jmethodID _alert = nullptr; jmethodID _is_dark_mode_supported = nullptr; jmethodID _is_dark_mode = nullptr; + jmethodID _get_accent_color = nullptr; jmethodID _get_clipboard = nullptr; jmethodID _set_clipboard = nullptr; jmethodID _has_clipboard = nullptr; + jmethodID _show_input_dialog = nullptr; + jmethodID _show_file_picker = nullptr; jmethodID _request_permission = nullptr; jmethodID _request_permissions = nullptr; jmethodID _get_granted_permissions = nullptr; @@ -97,12 +101,15 @@ public: void alert(const String &p_message, const String &p_title); bool is_dark_mode_supported(); bool is_dark_mode(); + Color get_accent_color(); bool has_get_clipboard(); String get_clipboard(); bool has_set_clipboard(); void set_clipboard(const String &p_text); bool has_has_clipboard(); bool has_clipboard(); + Error show_input_dialog(const String &p_title, const String &p_message, const String &p_existing_text); + Error show_file_picker(const String &p_current_directory, const String &p_filename, int p_mode, const Vector<String> &p_filters); bool request_permission(const String &p_name); bool request_permissions(); Vector<String> get_granted_permissions() const; diff --git a/platform/android/net_socket_android.cpp b/platform/android/net_socket_android.cpp index 8f0ee51fac..9ab7d6a04f 100644 --- a/platform/android/net_socket_android.cpp +++ b/platform/android/net_socket_android.cpp @@ -84,7 +84,7 @@ NetSocketAndroid::~NetSocketAndroid() { } void NetSocketAndroid::close() { - NetSocketPosix::close(); + NetSocketUnix::close(); if (wants_broadcast) { multicast_lock_release(); } @@ -96,7 +96,7 @@ void NetSocketAndroid::close() { } Error NetSocketAndroid::set_broadcasting_enabled(bool p_enabled) { - Error err = NetSocketPosix::set_broadcasting_enabled(p_enabled); + Error err = NetSocketUnix::set_broadcasting_enabled(p_enabled); if (err != OK) { return err; } @@ -115,7 +115,7 @@ Error NetSocketAndroid::set_broadcasting_enabled(bool p_enabled) { } Error NetSocketAndroid::join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { - Error err = NetSocketPosix::join_multicast_group(p_multi_address, p_if_name); + Error err = NetSocketUnix::join_multicast_group(p_multi_address, p_if_name); if (err != OK) { return err; } @@ -129,7 +129,7 @@ Error NetSocketAndroid::join_multicast_group(const IPAddress &p_multi_address, c } Error NetSocketAndroid::leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { - Error err = NetSocketPosix::leave_multicast_group(p_multi_address, p_if_name); + Error err = NetSocketUnix::leave_multicast_group(p_multi_address, p_if_name); if (err != OK) { return err; } diff --git a/platform/android/net_socket_android.h b/platform/android/net_socket_android.h index 26cb2d4e3d..c33146d2d8 100644 --- a/platform/android/net_socket_android.h +++ b/platform/android/net_socket_android.h @@ -31,7 +31,7 @@ #ifndef NET_SOCKET_ANDROID_H #define NET_SOCKET_ANDROID_H -#include "drivers/unix/net_socket_posix.h" +#include "drivers/unix/net_socket_unix.h" #include <jni.h> @@ -44,7 +44,7 @@ * the lock when broadcasting is enabled/disabled on a socket, or that socket * joins/leaves a multicast group. */ -class NetSocketAndroid : public NetSocketPosix { +class NetSocketAndroid : public NetSocketUnix { private: static jobject net_utils; static jclass cls; diff --git a/platform/ios/detect.py b/platform/ios/detect.py index 20a3a996bc..0f7f938852 100644 --- a/platform/ios/detect.py +++ b/platform/ios/detect.py @@ -3,6 +3,7 @@ import sys from typing import TYPE_CHECKING from methods import detect_darwin_sdk_path, print_error, print_warning +from platform_methods import validate_arch if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -60,12 +61,7 @@ def get_flags(): def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["x86_64", "arm64"] - if env["arch"] not in supported_arches: - print_error( - 'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.' - % (env["arch"], ", ".join(supported_arches)) - ) - sys.exit(255) + validate_arch(env["arch"], get_name(), supported_arches) ## LTO @@ -134,7 +130,7 @@ def configure(env: "SConsEnvironment"): elif env["arch"] == "arm64": env.Append( CCFLAGS=( - "-fobjc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing" + "-fobjc-arc -arch arm64 -fmessage-length=0" " -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits" " -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies" " -isysroot $IOS_SDK_PATH".split() diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index dcc6ce9218..5d9179bd9a 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -111,19 +111,24 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode if (rendering_context->initialize() != OK) { memdelete(rendering_context); rendering_context = nullptr; +#if defined(GLES3_ENABLED) bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); if (fallback_to_opengl3 && rendering_driver != "opengl3") { WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3."); rendering_driver = "opengl3"; OS::get_singleton()->set_current_rendering_method("gl_compatibility"); OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); - } else { + } else +#endif + { ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver)); r_error = ERR_UNAVAILABLE; return; } } + } + if (rendering_context) { if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) { ERR_PRINT(vformat("Failed to create %s window.", rendering_driver)); memdelete(rendering_context); @@ -365,6 +370,7 @@ bool DisplayServerIOS::has_feature(Feature p_feature) const { // case FEATURE_NATIVE_DIALOG: // case FEATURE_NATIVE_DIALOG_INPUT: // case FEATURE_NATIVE_DIALOG_FILE: + // case FEATURE_NATIVE_DIALOG_FILE_EXTRA: // case FEATURE_NATIVE_ICON: // case FEATURE_WINDOW_TRANSPARENCY: case FEATURE_CLIPBOARD: diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index d6cd2e0f3c..3c5a930bab 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -1082,7 +1082,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor } if (splash.is_null()) { - splash = Ref<Image>(memnew(Image(boot_splash_png))); + splash.instantiate(boot_splash_png); } // Using same image for both @2x and @3x diff --git a/platform/ios/ios.mm b/platform/ios/ios.mm index 6943de5ac8..26067b94bb 100644 --- a/platform/ios/ios.mm +++ b/platform/ios/ios.mm @@ -42,7 +42,7 @@ void iOS::_bind_methods() { ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine); ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine); ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine); -}; +} bool iOS::supports_haptic_engine() { if (@available(iOS 13, *)) { diff --git a/platform/linuxbsd/crash_handler_linuxbsd.h b/platform/linuxbsd/crash_handler_linuxbsd.h index 684f62b249..a14b93e11b 100644 --- a/platform/linuxbsd/crash_handler_linuxbsd.h +++ b/platform/linuxbsd/crash_handler_linuxbsd.h @@ -38,7 +38,7 @@ public: void initialize(); void disable(); - bool is_disabled() const { return disabled; }; + bool is_disabled() const { return disabled; } CrashHandler(); ~CrashHandler(); diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index a67434527c..c8202b147d 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -4,7 +4,7 @@ import sys from typing import TYPE_CHECKING from methods import get_compiler_version, print_error, print_warning, using_gcc -from platform_methods import detect_arch +from platform_methods import detect_arch, validate_arch if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -74,12 +74,7 @@ def get_flags(): def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"] - if env["arch"] not in supported_arches: - print_error( - 'Unsupported CPU architecture "%s" for Linux / *BSD. Supported architectures are: %s.' - % (env["arch"], ", ".join(supported_arches)) - ) - sys.exit(255) + validate_arch(env["arch"], get_name(), supported_arches) ## Build type @@ -284,16 +279,18 @@ def configure(env: "SConsEnvironment"): env.ParseConfig("pkg-config libwebp --cflags --libs") if not env["builtin_mbedtls"]: - # mbedTLS does not provide a pkgconfig config yet. See https://github.com/ARMmbed/mbedtls/issues/228 - env.Append(LIBS=["mbedtls", "mbedcrypto", "mbedx509"]) + # mbedTLS only provides a pkgconfig file since 3.6.0, but we still support 2.28.x, + # so fallback to manually specifying LIBS if it fails. + if os.system("pkg-config --exists mbedtls") == 0: # 0 means found + env.ParseConfig("pkg-config mbedtls mbedcrypto mbedx509 --cflags --libs") + else: + env.Append(LIBS=["mbedtls", "mbedcrypto", "mbedx509"]) if not env["builtin_wslay"]: env.ParseConfig("pkg-config libwslay --cflags --libs") if not env["builtin_miniupnpc"]: - # No pkgconfig file so far, hardcode default paths. - env.Prepend(CPPPATH=["/usr/include/miniupnpc"]) - env.Append(LIBS=["miniupnpc"]) + env.ParseConfig("pkg-config miniupnpc --cflags --libs") # On Linux wchar_t should be 32-bits # 16-bit library shouldn't be required due to compiler optimizations diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h index 9e016bd4c3..c8842b3a17 100644 --- a/platform/linuxbsd/export/export_plugin.h +++ b/platform/linuxbsd/export/export_plugin.h @@ -55,7 +55,7 @@ class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC { ssh_args = p_ssh_arg; cmd_args = p_cmd_args; wait = p_wait; - }; + } }; Ref<ImageTexture> run_icon; diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index 94a748e414..63eed41cd3 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -394,7 +394,7 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo } else { if (flt == "*.*") { filter_exts.push_back("*"); - filter_names.push_back(RTR("All Files")); + filter_names.push_back(RTR("All Files") + " (*)"); } else { filter_exts.push_back(flt); filter_names.push_back(flt); @@ -405,7 +405,7 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo } if (filter_names.is_empty()) { filter_exts.push_back("*"); - filter_names.push_back(RTR("All Files")); + filter_names.push_back(RTR("All Files") + " (*)"); } DBusError err; diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 6355562feb..b309e8d8eb 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -771,11 +771,11 @@ Vector<String> OS_LinuxBSD::get_system_font_path_for_text(const String &p_font_n FcLangSetAdd(lang_set, reinterpret_cast<const FcChar8 *>(p_locale.utf8().get_data())); FcPatternAddLangSet(pattern, FC_LANG, lang_set); - FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result; - FcPattern *match = FcFontMatch(0, pattern, &result); + FcPattern *match = FcFontMatch(nullptr, pattern, &result); if (match) { char *file_name = nullptr; if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) { @@ -816,11 +816,11 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, int p_weight FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch)); FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN); - FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result; - FcPattern *match = FcFontMatch(0, pattern, &result); + FcPattern *match = FcFontMatch(nullptr, pattern, &result); if (match) { if (!allow_substitutes) { char *family_name = nullptr; diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 71c721ca1d..fe359532bb 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -216,7 +216,8 @@ bool DisplayServerWayland::has_feature(Feature p_feature) const { //case FEATURE_NATIVE_DIALOG: //case FEATURE_NATIVE_DIALOG_INPUT: #ifdef DBUS_ENABLED - case FEATURE_NATIVE_DIALOG_FILE: { + case FEATURE_NATIVE_DIALOG_FILE: + case FEATURE_NATIVE_DIALOG_FILE_EXTRA: { return true; } break; #endif @@ -627,6 +628,18 @@ int64_t DisplayServerWayland::window_get_native_handle(HandleType p_handle_type, } return 0; } break; + case EGL_DISPLAY: { + if (egl_manager) { + return (int64_t)egl_manager->get_display(p_window); + } + return 0; + } + case EGL_CONFIG: { + if (egl_manager) { + return (int64_t)egl_manager->get_config(p_window); + } + return 0; + } #endif // GLES3_ENABLED default: { @@ -1344,13 +1357,16 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win if (rendering_context->initialize() != OK) { memdelete(rendering_context); rendering_context = nullptr; +#if defined(GLES3_ENABLED) bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); if (fallback_to_opengl3 && rendering_driver != "opengl3") { WARN_PRINT("Your video card drivers seem not to support the required Vulkan version, switching to OpenGL 3."); rendering_driver = "opengl3"; OS::get_singleton()->set_current_rendering_method("gl_compatibility"); OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); - } else { + } else +#endif // GLES3_ENABLED + { r_error = ERR_CANT_CREATE; if (p_rendering_driver == "vulkan") { diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp index e066e78e5b..d8d58ba54b 100644 --- a/platform/linuxbsd/wayland/wayland_thread.cpp +++ b/platform/linuxbsd/wayland/wayland_thread.cpp @@ -3988,10 +3988,10 @@ void WaylandThread::selection_set_text(const String &p_text) { wl_data_source_add_listener(ss->wl_data_source_selection, &wl_data_source_listener, ss); wl_data_source_offer(ss->wl_data_source_selection, "text/plain;charset=utf-8"); wl_data_source_offer(ss->wl_data_source_selection, "text/plain"); - } - // TODO: Implement a good way of getting the latest serial from the user. - wl_data_device_set_selection(ss->wl_data_device, ss->wl_data_source_selection, MAX(ss->pointer_data.button_serial, ss->last_key_pressed_serial)); + // TODO: Implement a good way of getting the latest serial from the user. + wl_data_device_set_selection(ss->wl_data_device, ss->wl_data_source_selection, MAX(ss->pointer_data.button_serial, ss->last_key_pressed_serial)); + } // Wait for the message to get to the server before continuing, otherwise the // clipboard update might come with a delay. diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 293623e594..a9c94bd823 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -129,6 +129,7 @@ bool DisplayServerX11::has_feature(Feature p_feature) const { case FEATURE_ICON: #ifdef DBUS_ENABLED case FEATURE_NATIVE_DIALOG_FILE: + case FEATURE_NATIVE_DIALOG_FILE_EXTRA: #endif //case FEATURE_NATIVE_DIALOG: //case FEATURE_NATIVE_DIALOG_INPUT: @@ -1861,6 +1862,18 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win } return 0; } + case EGL_DISPLAY: { + if (gl_manager_egl) { + return (int64_t)gl_manager_egl->get_display(p_window); + } + return 0; + } + case EGL_CONFIG: { + if (gl_manager_egl) { + return (int64_t)gl_manager_egl->get_config(p_window); + } + return 0; + } #endif default: { return 0; @@ -6156,13 +6169,16 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode if (rendering_context->initialize() != OK) { memdelete(rendering_context); rendering_context = nullptr; +#if defined(GLES3_ENABLED) bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); if (fallback_to_opengl3 && rendering_driver != "opengl3") { WARN_PRINT("Your video card drivers seem not to support the required Vulkan version, switching to OpenGL 3."); rendering_driver = "opengl3"; OS::get_singleton()->set_current_rendering_method("gl_compatibility"); OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); - } else { + } else +#endif // GLES3_ENABLED + { r_error = ERR_CANT_CREATE; if (p_rendering_driver == "vulkan") { diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c index bba21b9cb7..7e1f3b8072 100644 --- a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c +++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c @@ -1,12 +1,8 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:09:53 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include "thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h" --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c --ignore-other // -// NOTE: Generated from Xcursor 1.2.0. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXcursor.so.1, were removed. #include <stdint.h> #define XcursorImageCreate XcursorImageCreate_dylibloader_orig_xcursor @@ -130,65 +126,65 @@ #undef XcursorSetThemeCore #include <dlfcn.h> #include <stdio.h> -XcursorImage* (*XcursorImageCreate_dylibloader_wrapper_xcursor)( int, int); -void (*XcursorImageDestroy_dylibloader_wrapper_xcursor)( XcursorImage*); -XcursorImages* (*XcursorImagesCreate_dylibloader_wrapper_xcursor)( int); -void (*XcursorImagesDestroy_dylibloader_wrapper_xcursor)( XcursorImages*); -void (*XcursorImagesSetName_dylibloader_wrapper_xcursor)( XcursorImages*,const char*); -XcursorCursors* (*XcursorCursorsCreate_dylibloader_wrapper_xcursor)( Display*, int); -void (*XcursorCursorsDestroy_dylibloader_wrapper_xcursor)( XcursorCursors*); -XcursorAnimate* (*XcursorAnimateCreate_dylibloader_wrapper_xcursor)( XcursorCursors*); -void (*XcursorAnimateDestroy_dylibloader_wrapper_xcursor)( XcursorAnimate*); -Cursor (*XcursorAnimateNext_dylibloader_wrapper_xcursor)( XcursorAnimate*); -XcursorComment* (*XcursorCommentCreate_dylibloader_wrapper_xcursor)( XcursorUInt, int); -void (*XcursorCommentDestroy_dylibloader_wrapper_xcursor)( XcursorComment*); -XcursorComments* (*XcursorCommentsCreate_dylibloader_wrapper_xcursor)( int); -void (*XcursorCommentsDestroy_dylibloader_wrapper_xcursor)( XcursorComments*); -XcursorImage* (*XcursorXcFileLoadImage_dylibloader_wrapper_xcursor)( XcursorFile*, int); -XcursorImages* (*XcursorXcFileLoadImages_dylibloader_wrapper_xcursor)( XcursorFile*, int); -XcursorImages* (*XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor)( XcursorFile*); -XcursorBool (*XcursorXcFileLoad_dylibloader_wrapper_xcursor)( XcursorFile*, XcursorComments**, XcursorImages**); -XcursorBool (*XcursorXcFileSave_dylibloader_wrapper_xcursor)( XcursorFile*,const XcursorComments*,const XcursorImages*); -XcursorImage* (*XcursorFileLoadImage_dylibloader_wrapper_xcursor)( FILE*, int); -XcursorImages* (*XcursorFileLoadImages_dylibloader_wrapper_xcursor)( FILE*, int); -XcursorImages* (*XcursorFileLoadAllImages_dylibloader_wrapper_xcursor)( FILE*); -XcursorBool (*XcursorFileLoad_dylibloader_wrapper_xcursor)( FILE*, XcursorComments**, XcursorImages**); -XcursorBool (*XcursorFileSaveImages_dylibloader_wrapper_xcursor)( FILE*,const XcursorImages*); -XcursorBool (*XcursorFileSave_dylibloader_wrapper_xcursor)( FILE*,const XcursorComments*,const XcursorImages*); -XcursorImage* (*XcursorFilenameLoadImage_dylibloader_wrapper_xcursor)(const char*, int); -XcursorImages* (*XcursorFilenameLoadImages_dylibloader_wrapper_xcursor)(const char*, int); -XcursorImages* (*XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor)(const char*); -XcursorBool (*XcursorFilenameLoad_dylibloader_wrapper_xcursor)(const char*, XcursorComments**, XcursorImages**); -XcursorBool (*XcursorFilenameSaveImages_dylibloader_wrapper_xcursor)(const char*,const XcursorImages*); -XcursorBool (*XcursorFilenameSave_dylibloader_wrapper_xcursor)(const char*,const XcursorComments*,const XcursorImages*); -XcursorImage* (*XcursorLibraryLoadImage_dylibloader_wrapper_xcursor)(const char*,const char*, int); -XcursorImages* (*XcursorLibraryLoadImages_dylibloader_wrapper_xcursor)(const char*,const char*, int); -const char* (*XcursorLibraryPath_dylibloader_wrapper_xcursor)( void); -int (*XcursorLibraryShape_dylibloader_wrapper_xcursor)(const char*); -Cursor (*XcursorImageLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImage*); -XcursorCursors* (*XcursorImagesLoadCursors_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*); -Cursor (*XcursorImagesLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*); -Cursor (*XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*); -XcursorCursors* (*XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*); -Cursor (*XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*); -XcursorCursors* (*XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*); -XcursorImage* (*XcursorShapeLoadImage_dylibloader_wrapper_xcursor)( unsigned int,const char*, int); -XcursorImages* (*XcursorShapeLoadImages_dylibloader_wrapper_xcursor)( unsigned int,const char*, int); -Cursor (*XcursorShapeLoadCursor_dylibloader_wrapper_xcursor)( Display*, unsigned int); -XcursorCursors* (*XcursorShapeLoadCursors_dylibloader_wrapper_xcursor)( Display*, unsigned int); -Cursor (*XcursorTryShapeCursor_dylibloader_wrapper_xcursor)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*); -void (*XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor)( Display*, Pixmap, unsigned int, unsigned int); -void (*XcursorNoticePutBitmap_dylibloader_wrapper_xcursor)( Display*, Drawable, XImage*); -Cursor (*XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int); -void (*XcursorImageHash_dylibloader_wrapper_xcursor)( XImage*, unsigned char [16]); -XcursorBool (*XcursorSupportsARGB_dylibloader_wrapper_xcursor)( Display*); -XcursorBool (*XcursorSupportsAnim_dylibloader_wrapper_xcursor)( Display*); -XcursorBool (*XcursorSetDefaultSize_dylibloader_wrapper_xcursor)( Display*, int); -int (*XcursorGetDefaultSize_dylibloader_wrapper_xcursor)( Display*); -XcursorBool (*XcursorSetTheme_dylibloader_wrapper_xcursor)( Display*,const char*); -char* (*XcursorGetTheme_dylibloader_wrapper_xcursor)( Display*); -XcursorBool (*XcursorGetThemeCore_dylibloader_wrapper_xcursor)( Display*); -XcursorBool (*XcursorSetThemeCore_dylibloader_wrapper_xcursor)( Display*, XcursorBool); +XcursorImage *(*XcursorImageCreate_dylibloader_wrapper_xcursor)(int, int); +void (*XcursorImageDestroy_dylibloader_wrapper_xcursor)(XcursorImage *); +XcursorImages *(*XcursorImagesCreate_dylibloader_wrapper_xcursor)(int); +void (*XcursorImagesDestroy_dylibloader_wrapper_xcursor)(XcursorImages *); +void (*XcursorImagesSetName_dylibloader_wrapper_xcursor)(XcursorImages *, const char *); +XcursorCursors *(*XcursorCursorsCreate_dylibloader_wrapper_xcursor)(Display *, int); +void (*XcursorCursorsDestroy_dylibloader_wrapper_xcursor)(XcursorCursors *); +XcursorAnimate *(*XcursorAnimateCreate_dylibloader_wrapper_xcursor)(XcursorCursors *); +void (*XcursorAnimateDestroy_dylibloader_wrapper_xcursor)(XcursorAnimate *); +Cursor (*XcursorAnimateNext_dylibloader_wrapper_xcursor)(XcursorAnimate *); +XcursorComment *(*XcursorCommentCreate_dylibloader_wrapper_xcursor)(XcursorUInt, int); +void (*XcursorCommentDestroy_dylibloader_wrapper_xcursor)(XcursorComment *); +XcursorComments *(*XcursorCommentsCreate_dylibloader_wrapper_xcursor)(int); +void (*XcursorCommentsDestroy_dylibloader_wrapper_xcursor)(XcursorComments *); +XcursorImage *(*XcursorXcFileLoadImage_dylibloader_wrapper_xcursor)(XcursorFile *, int); +XcursorImages *(*XcursorXcFileLoadImages_dylibloader_wrapper_xcursor)(XcursorFile *, int); +XcursorImages *(*XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor)(XcursorFile *); +XcursorBool (*XcursorXcFileLoad_dylibloader_wrapper_xcursor)(XcursorFile *, XcursorComments **, XcursorImages **); +XcursorBool (*XcursorXcFileSave_dylibloader_wrapper_xcursor)(XcursorFile *, const XcursorComments *, const XcursorImages *); +XcursorImage *(*XcursorFileLoadImage_dylibloader_wrapper_xcursor)(FILE *, int); +XcursorImages *(*XcursorFileLoadImages_dylibloader_wrapper_xcursor)(FILE *, int); +XcursorImages *(*XcursorFileLoadAllImages_dylibloader_wrapper_xcursor)(FILE *); +XcursorBool (*XcursorFileLoad_dylibloader_wrapper_xcursor)(FILE *, XcursorComments **, XcursorImages **); +XcursorBool (*XcursorFileSaveImages_dylibloader_wrapper_xcursor)(FILE *, const XcursorImages *); +XcursorBool (*XcursorFileSave_dylibloader_wrapper_xcursor)(FILE *, const XcursorComments *, const XcursorImages *); +XcursorImage *(*XcursorFilenameLoadImage_dylibloader_wrapper_xcursor)(const char *, int); +XcursorImages *(*XcursorFilenameLoadImages_dylibloader_wrapper_xcursor)(const char *, int); +XcursorImages *(*XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor)(const char *); +XcursorBool (*XcursorFilenameLoad_dylibloader_wrapper_xcursor)(const char *, XcursorComments **, XcursorImages **); +XcursorBool (*XcursorFilenameSaveImages_dylibloader_wrapper_xcursor)(const char *, const XcursorImages *); +XcursorBool (*XcursorFilenameSave_dylibloader_wrapper_xcursor)(const char *, const XcursorComments *, const XcursorImages *); +XcursorImage *(*XcursorLibraryLoadImage_dylibloader_wrapper_xcursor)(const char *, const char *, int); +XcursorImages *(*XcursorLibraryLoadImages_dylibloader_wrapper_xcursor)(const char *, const char *, int); +const char *(*XcursorLibraryPath_dylibloader_wrapper_xcursor)(void); +int (*XcursorLibraryShape_dylibloader_wrapper_xcursor)(const char *); +Cursor (*XcursorImageLoadCursor_dylibloader_wrapper_xcursor)(Display *, const XcursorImage *); +XcursorCursors *(*XcursorImagesLoadCursors_dylibloader_wrapper_xcursor)(Display *, const XcursorImages *); +Cursor (*XcursorImagesLoadCursor_dylibloader_wrapper_xcursor)(Display *, const XcursorImages *); +Cursor (*XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor)(Display *, const char *); +XcursorCursors *(*XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor)(Display *, const char *); +Cursor (*XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor)(Display *, const char *); +XcursorCursors *(*XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor)(Display *, const char *); +XcursorImage *(*XcursorShapeLoadImage_dylibloader_wrapper_xcursor)(unsigned int, const char *, int); +XcursorImages *(*XcursorShapeLoadImages_dylibloader_wrapper_xcursor)(unsigned int, const char *, int); +Cursor (*XcursorShapeLoadCursor_dylibloader_wrapper_xcursor)(Display *, unsigned int); +XcursorCursors *(*XcursorShapeLoadCursors_dylibloader_wrapper_xcursor)(Display *, unsigned int); +Cursor (*XcursorTryShapeCursor_dylibloader_wrapper_xcursor)(Display *, Font, Font, unsigned int, unsigned int, const XColor *, const XColor *); +void (*XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor)(Display *, Pixmap, unsigned int, unsigned int); +void (*XcursorNoticePutBitmap_dylibloader_wrapper_xcursor)(Display *, Drawable, XImage *); +Cursor (*XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor)(Display *, Pixmap, Pixmap, XColor *, XColor *, unsigned int, unsigned int); +void (*XcursorImageHash_dylibloader_wrapper_xcursor)(XImage *, unsigned char [16]); +XcursorBool (*XcursorSupportsARGB_dylibloader_wrapper_xcursor)(Display *); +XcursorBool (*XcursorSupportsAnim_dylibloader_wrapper_xcursor)(Display *); +XcursorBool (*XcursorSetDefaultSize_dylibloader_wrapper_xcursor)(Display *, int); +int (*XcursorGetDefaultSize_dylibloader_wrapper_xcursor)(Display *); +XcursorBool (*XcursorSetTheme_dylibloader_wrapper_xcursor)(Display *, const char *); +char *(*XcursorGetTheme_dylibloader_wrapper_xcursor)(Display *); +XcursorBool (*XcursorGetThemeCore_dylibloader_wrapper_xcursor)(Display *); +XcursorBool (*XcursorSetThemeCore_dylibloader_wrapper_xcursor)(Display *, XcursorBool); int initialize_xcursor(int verbose) { void *handle; char *error; diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h index 9f8d8bbca2..7266cfe609 100644 --- a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h +++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h @@ -2,13 +2,9 @@ #define DYLIBLOAD_WRAPPER_XCURSOR // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:09:53 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include "thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h" --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c --ignore-other // -// NOTE: Generated from Xcursor 1.2.0. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXcursor.so.1, were removed. #include <stdint.h> #define XcursorImageCreate XcursorImageCreate_dylibloader_orig_xcursor @@ -192,65 +188,65 @@ extern "C" { #define XcursorGetTheme XcursorGetTheme_dylibloader_wrapper_xcursor #define XcursorGetThemeCore XcursorGetThemeCore_dylibloader_wrapper_xcursor #define XcursorSetThemeCore XcursorSetThemeCore_dylibloader_wrapper_xcursor -extern XcursorImage* (*XcursorImageCreate_dylibloader_wrapper_xcursor)( int, int); -extern void (*XcursorImageDestroy_dylibloader_wrapper_xcursor)( XcursorImage*); -extern XcursorImages* (*XcursorImagesCreate_dylibloader_wrapper_xcursor)( int); -extern void (*XcursorImagesDestroy_dylibloader_wrapper_xcursor)( XcursorImages*); -extern void (*XcursorImagesSetName_dylibloader_wrapper_xcursor)( XcursorImages*,const char*); -extern XcursorCursors* (*XcursorCursorsCreate_dylibloader_wrapper_xcursor)( Display*, int); -extern void (*XcursorCursorsDestroy_dylibloader_wrapper_xcursor)( XcursorCursors*); -extern XcursorAnimate* (*XcursorAnimateCreate_dylibloader_wrapper_xcursor)( XcursorCursors*); -extern void (*XcursorAnimateDestroy_dylibloader_wrapper_xcursor)( XcursorAnimate*); -extern Cursor (*XcursorAnimateNext_dylibloader_wrapper_xcursor)( XcursorAnimate*); -extern XcursorComment* (*XcursorCommentCreate_dylibloader_wrapper_xcursor)( XcursorUInt, int); -extern void (*XcursorCommentDestroy_dylibloader_wrapper_xcursor)( XcursorComment*); -extern XcursorComments* (*XcursorCommentsCreate_dylibloader_wrapper_xcursor)( int); -extern void (*XcursorCommentsDestroy_dylibloader_wrapper_xcursor)( XcursorComments*); -extern XcursorImage* (*XcursorXcFileLoadImage_dylibloader_wrapper_xcursor)( XcursorFile*, int); -extern XcursorImages* (*XcursorXcFileLoadImages_dylibloader_wrapper_xcursor)( XcursorFile*, int); -extern XcursorImages* (*XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor)( XcursorFile*); -extern XcursorBool (*XcursorXcFileLoad_dylibloader_wrapper_xcursor)( XcursorFile*, XcursorComments**, XcursorImages**); -extern XcursorBool (*XcursorXcFileSave_dylibloader_wrapper_xcursor)( XcursorFile*,const XcursorComments*,const XcursorImages*); -extern XcursorImage* (*XcursorFileLoadImage_dylibloader_wrapper_xcursor)( FILE*, int); -extern XcursorImages* (*XcursorFileLoadImages_dylibloader_wrapper_xcursor)( FILE*, int); -extern XcursorImages* (*XcursorFileLoadAllImages_dylibloader_wrapper_xcursor)( FILE*); -extern XcursorBool (*XcursorFileLoad_dylibloader_wrapper_xcursor)( FILE*, XcursorComments**, XcursorImages**); -extern XcursorBool (*XcursorFileSaveImages_dylibloader_wrapper_xcursor)( FILE*,const XcursorImages*); -extern XcursorBool (*XcursorFileSave_dylibloader_wrapper_xcursor)( FILE*,const XcursorComments*,const XcursorImages*); -extern XcursorImage* (*XcursorFilenameLoadImage_dylibloader_wrapper_xcursor)(const char*, int); -extern XcursorImages* (*XcursorFilenameLoadImages_dylibloader_wrapper_xcursor)(const char*, int); -extern XcursorImages* (*XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor)(const char*); -extern XcursorBool (*XcursorFilenameLoad_dylibloader_wrapper_xcursor)(const char*, XcursorComments**, XcursorImages**); -extern XcursorBool (*XcursorFilenameSaveImages_dylibloader_wrapper_xcursor)(const char*,const XcursorImages*); -extern XcursorBool (*XcursorFilenameSave_dylibloader_wrapper_xcursor)(const char*,const XcursorComments*,const XcursorImages*); -extern XcursorImage* (*XcursorLibraryLoadImage_dylibloader_wrapper_xcursor)(const char*,const char*, int); -extern XcursorImages* (*XcursorLibraryLoadImages_dylibloader_wrapper_xcursor)(const char*,const char*, int); -extern const char* (*XcursorLibraryPath_dylibloader_wrapper_xcursor)( void); -extern int (*XcursorLibraryShape_dylibloader_wrapper_xcursor)(const char*); -extern Cursor (*XcursorImageLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImage*); -extern XcursorCursors* (*XcursorImagesLoadCursors_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*); -extern Cursor (*XcursorImagesLoadCursor_dylibloader_wrapper_xcursor)( Display*,const XcursorImages*); -extern Cursor (*XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*); -extern XcursorCursors* (*XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*); -extern Cursor (*XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor)( Display*,const char*); -extern XcursorCursors* (*XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor)( Display*,const char*); -extern XcursorImage* (*XcursorShapeLoadImage_dylibloader_wrapper_xcursor)( unsigned int,const char*, int); -extern XcursorImages* (*XcursorShapeLoadImages_dylibloader_wrapper_xcursor)( unsigned int,const char*, int); -extern Cursor (*XcursorShapeLoadCursor_dylibloader_wrapper_xcursor)( Display*, unsigned int); -extern XcursorCursors* (*XcursorShapeLoadCursors_dylibloader_wrapper_xcursor)( Display*, unsigned int); -extern Cursor (*XcursorTryShapeCursor_dylibloader_wrapper_xcursor)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*); -extern void (*XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor)( Display*, Pixmap, unsigned int, unsigned int); -extern void (*XcursorNoticePutBitmap_dylibloader_wrapper_xcursor)( Display*, Drawable, XImage*); -extern Cursor (*XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int); -extern void (*XcursorImageHash_dylibloader_wrapper_xcursor)( XImage*, unsigned char [16]); -extern XcursorBool (*XcursorSupportsARGB_dylibloader_wrapper_xcursor)( Display*); -extern XcursorBool (*XcursorSupportsAnim_dylibloader_wrapper_xcursor)( Display*); -extern XcursorBool (*XcursorSetDefaultSize_dylibloader_wrapper_xcursor)( Display*, int); -extern int (*XcursorGetDefaultSize_dylibloader_wrapper_xcursor)( Display*); -extern XcursorBool (*XcursorSetTheme_dylibloader_wrapper_xcursor)( Display*,const char*); -extern char* (*XcursorGetTheme_dylibloader_wrapper_xcursor)( Display*); -extern XcursorBool (*XcursorGetThemeCore_dylibloader_wrapper_xcursor)( Display*); -extern XcursorBool (*XcursorSetThemeCore_dylibloader_wrapper_xcursor)( Display*, XcursorBool); +extern XcursorImage *(*XcursorImageCreate_dylibloader_wrapper_xcursor)(int, int); +extern void (*XcursorImageDestroy_dylibloader_wrapper_xcursor)(XcursorImage *); +extern XcursorImages *(*XcursorImagesCreate_dylibloader_wrapper_xcursor)(int); +extern void (*XcursorImagesDestroy_dylibloader_wrapper_xcursor)(XcursorImages *); +extern void (*XcursorImagesSetName_dylibloader_wrapper_xcursor)(XcursorImages *, const char *); +extern XcursorCursors *(*XcursorCursorsCreate_dylibloader_wrapper_xcursor)(Display *, int); +extern void (*XcursorCursorsDestroy_dylibloader_wrapper_xcursor)(XcursorCursors *); +extern XcursorAnimate *(*XcursorAnimateCreate_dylibloader_wrapper_xcursor)(XcursorCursors *); +extern void (*XcursorAnimateDestroy_dylibloader_wrapper_xcursor)(XcursorAnimate *); +extern Cursor (*XcursorAnimateNext_dylibloader_wrapper_xcursor)(XcursorAnimate *); +extern XcursorComment *(*XcursorCommentCreate_dylibloader_wrapper_xcursor)(XcursorUInt, int); +extern void (*XcursorCommentDestroy_dylibloader_wrapper_xcursor)(XcursorComment *); +extern XcursorComments *(*XcursorCommentsCreate_dylibloader_wrapper_xcursor)(int); +extern void (*XcursorCommentsDestroy_dylibloader_wrapper_xcursor)(XcursorComments *); +extern XcursorImage *(*XcursorXcFileLoadImage_dylibloader_wrapper_xcursor)(XcursorFile *, int); +extern XcursorImages *(*XcursorXcFileLoadImages_dylibloader_wrapper_xcursor)(XcursorFile *, int); +extern XcursorImages *(*XcursorXcFileLoadAllImages_dylibloader_wrapper_xcursor)(XcursorFile *); +extern XcursorBool (*XcursorXcFileLoad_dylibloader_wrapper_xcursor)(XcursorFile *, XcursorComments **, XcursorImages **); +extern XcursorBool (*XcursorXcFileSave_dylibloader_wrapper_xcursor)(XcursorFile *, const XcursorComments *, const XcursorImages *); +extern XcursorImage *(*XcursorFileLoadImage_dylibloader_wrapper_xcursor)(FILE *, int); +extern XcursorImages *(*XcursorFileLoadImages_dylibloader_wrapper_xcursor)(FILE *, int); +extern XcursorImages *(*XcursorFileLoadAllImages_dylibloader_wrapper_xcursor)(FILE *); +extern XcursorBool (*XcursorFileLoad_dylibloader_wrapper_xcursor)(FILE *, XcursorComments **, XcursorImages **); +extern XcursorBool (*XcursorFileSaveImages_dylibloader_wrapper_xcursor)(FILE *, const XcursorImages *); +extern XcursorBool (*XcursorFileSave_dylibloader_wrapper_xcursor)(FILE *, const XcursorComments *, const XcursorImages *); +extern XcursorImage *(*XcursorFilenameLoadImage_dylibloader_wrapper_xcursor)(const char *, int); +extern XcursorImages *(*XcursorFilenameLoadImages_dylibloader_wrapper_xcursor)(const char *, int); +extern XcursorImages *(*XcursorFilenameLoadAllImages_dylibloader_wrapper_xcursor)(const char *); +extern XcursorBool (*XcursorFilenameLoad_dylibloader_wrapper_xcursor)(const char *, XcursorComments **, XcursorImages **); +extern XcursorBool (*XcursorFilenameSaveImages_dylibloader_wrapper_xcursor)(const char *, const XcursorImages *); +extern XcursorBool (*XcursorFilenameSave_dylibloader_wrapper_xcursor)(const char *, const XcursorComments *, const XcursorImages *); +extern XcursorImage *(*XcursorLibraryLoadImage_dylibloader_wrapper_xcursor)(const char *, const char *, int); +extern XcursorImages *(*XcursorLibraryLoadImages_dylibloader_wrapper_xcursor)(const char *, const char *, int); +extern const char *(*XcursorLibraryPath_dylibloader_wrapper_xcursor)(void); +extern int (*XcursorLibraryShape_dylibloader_wrapper_xcursor)(const char *); +extern Cursor (*XcursorImageLoadCursor_dylibloader_wrapper_xcursor)(Display *, const XcursorImage *); +extern XcursorCursors *(*XcursorImagesLoadCursors_dylibloader_wrapper_xcursor)(Display *, const XcursorImages *); +extern Cursor (*XcursorImagesLoadCursor_dylibloader_wrapper_xcursor)(Display *, const XcursorImages *); +extern Cursor (*XcursorFilenameLoadCursor_dylibloader_wrapper_xcursor)(Display *, const char *); +extern XcursorCursors *(*XcursorFilenameLoadCursors_dylibloader_wrapper_xcursor)(Display *, const char *); +extern Cursor (*XcursorLibraryLoadCursor_dylibloader_wrapper_xcursor)(Display *, const char *); +extern XcursorCursors *(*XcursorLibraryLoadCursors_dylibloader_wrapper_xcursor)(Display *, const char *); +extern XcursorImage *(*XcursorShapeLoadImage_dylibloader_wrapper_xcursor)(unsigned int, const char *, int); +extern XcursorImages *(*XcursorShapeLoadImages_dylibloader_wrapper_xcursor)(unsigned int, const char *, int); +extern Cursor (*XcursorShapeLoadCursor_dylibloader_wrapper_xcursor)(Display *, unsigned int); +extern XcursorCursors *(*XcursorShapeLoadCursors_dylibloader_wrapper_xcursor)(Display *, unsigned int); +extern Cursor (*XcursorTryShapeCursor_dylibloader_wrapper_xcursor)(Display *, Font, Font, unsigned int, unsigned int, const XColor *, const XColor *); +extern void (*XcursorNoticeCreateBitmap_dylibloader_wrapper_xcursor)(Display *, Pixmap, unsigned int, unsigned int); +extern void (*XcursorNoticePutBitmap_dylibloader_wrapper_xcursor)(Display *, Drawable, XImage *); +extern Cursor (*XcursorTryShapeBitmapCursor_dylibloader_wrapper_xcursor)(Display *, Pixmap, Pixmap, XColor *, XColor *, unsigned int, unsigned int); +extern void (*XcursorImageHash_dylibloader_wrapper_xcursor)(XImage *, unsigned char [16]); +extern XcursorBool (*XcursorSupportsARGB_dylibloader_wrapper_xcursor)(Display *); +extern XcursorBool (*XcursorSupportsAnim_dylibloader_wrapper_xcursor)(Display *); +extern XcursorBool (*XcursorSetDefaultSize_dylibloader_wrapper_xcursor)(Display *, int); +extern int (*XcursorGetDefaultSize_dylibloader_wrapper_xcursor)(Display *); +extern XcursorBool (*XcursorSetTheme_dylibloader_wrapper_xcursor)(Display *, const char *); +extern char *(*XcursorGetTheme_dylibloader_wrapper_xcursor)(Display *); +extern XcursorBool (*XcursorGetThemeCore_dylibloader_wrapper_xcursor)(Display *); +extern XcursorBool (*XcursorSetThemeCore_dylibloader_wrapper_xcursor)(Display *, XcursorBool); int initialize_xcursor(int verbose); #ifdef __cplusplus } diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c index 4e3349c574..56ae854686 100644 --- a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c +++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c @@ -1,19 +1,11 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:29 -// flags: generate-wrapper.py --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xext.h" --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/shape.h" --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xext.h --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/shape.h --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c --ignore-other --implementation-header thirdparty/linuxbsd_headers/X11/Xlib.h // -// NOTE: Generated from Xext 1.3.5. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXext.so.6, were removed and an include needed for -// proper parsing was added (this had also to be temporarily added to the -// original header, as dynload-wrapper would complain otherwise) #include <stdint.h> -// HANDPATCH: Needed for a successful compilation. #include "thirdparty/linuxbsd_headers/X11/Xlib.h" - #define XShapeQueryExtension XShapeQueryExtension_dylibloader_orig_xext #define XShapeQueryVersion XShapeQueryVersion_dylibloader_orig_xext #define XShapeCombineRegion XShapeCombineRegion_dylibloader_orig_xext @@ -40,17 +32,17 @@ #undef XShapeGetRectangles #include <dlfcn.h> #include <stdio.h> -int (*XShapeQueryExtension_dylibloader_wrapper_xext)( Display*, int*, int*); -int (*XShapeQueryVersion_dylibloader_wrapper_xext)( Display*, int*, int*); -void (*XShapeCombineRegion_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Region, int); -void (*XShapeCombineRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int, int, XRectangle*, int, int, int); -void (*XShapeCombineMask_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Pixmap, int); -void (*XShapeCombineShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Window, int, int); -void (*XShapeOffsetShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int); -int (*XShapeQueryExtents_dylibloader_wrapper_xext)( Display*, Window, int*, int*, int*, unsigned int*, unsigned int*, int*, int*, int*, unsigned int*, unsigned int*); -void (*XShapeSelectInput_dylibloader_wrapper_xext)( Display*, Window, unsigned long); -unsigned long (*XShapeInputSelected_dylibloader_wrapper_xext)( Display*, Window); -XRectangle* (*XShapeGetRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int*, int*); +int (*XShapeQueryExtension_dylibloader_wrapper_xext)(Display *, int *, int *); +int (*XShapeQueryVersion_dylibloader_wrapper_xext)(Display *, int *, int *); +void (*XShapeCombineRegion_dylibloader_wrapper_xext)(Display *, Window, int, int, int, Region, int); +void (*XShapeCombineRectangles_dylibloader_wrapper_xext)(Display *, Window, int, int, int, XRectangle *, int, int, int); +void (*XShapeCombineMask_dylibloader_wrapper_xext)(Display *, Window, int, int, int, Pixmap, int); +void (*XShapeCombineShape_dylibloader_wrapper_xext)(Display *, Window, int, int, int, Window, int, int); +void (*XShapeOffsetShape_dylibloader_wrapper_xext)(Display *, Window, int, int, int); +int (*XShapeQueryExtents_dylibloader_wrapper_xext)(Display *, Window, int *, int *, int *, unsigned int *, unsigned int *, int *, int *, int *, unsigned int *, unsigned int *); +void (*XShapeSelectInput_dylibloader_wrapper_xext)(Display *, Window, unsigned long); +unsigned long (*XShapeInputSelected_dylibloader_wrapper_xext)(Display *, Window); +XRectangle *(*XShapeGetRectangles_dylibloader_wrapper_xext)(Display *, Window, int, int *, int *); int initialize_xext(int verbose) { void *handle; char *error; diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h index e535756d82..ecce399d09 100644 --- a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h +++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h @@ -2,20 +2,11 @@ #define DYLIBLOAD_WRAPPER_XEXT // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:29 -// flags: generate-wrapper.py --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xext.h" --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/shape.h" --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xext.h --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/shape.h --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c --ignore-other --implementation-header thirdparty/linuxbsd_headers/X11/Xlib.h // -// NOTE: Generated from Xext 1.3.5. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXext.so.6, were removed and an include needed for -// proper parsing was added (this had also to be temporarily added to the -// original header, as dynload-wrapper would complain otherwise) #include <stdint.h> -// HANDPATCH: Needed for a successful compilation. -#include "thirdparty/linuxbsd_headers/X11/Xlib.h" - #define XShapeQueryExtension XShapeQueryExtension_dylibloader_orig_xext #define XShapeQueryVersion XShapeQueryVersion_dylibloader_orig_xext #define XShapeCombineRegion XShapeCombineRegion_dylibloader_orig_xext @@ -54,17 +45,17 @@ extern "C" { #define XShapeSelectInput XShapeSelectInput_dylibloader_wrapper_xext #define XShapeInputSelected XShapeInputSelected_dylibloader_wrapper_xext #define XShapeGetRectangles XShapeGetRectangles_dylibloader_wrapper_xext -extern int (*XShapeQueryExtension_dylibloader_wrapper_xext)( Display*, int*, int*); -extern int (*XShapeQueryVersion_dylibloader_wrapper_xext)( Display*, int*, int*); -extern void (*XShapeCombineRegion_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Region, int); -extern void (*XShapeCombineRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int, int, XRectangle*, int, int, int); -extern void (*XShapeCombineMask_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Pixmap, int); -extern void (*XShapeCombineShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int, Window, int, int); -extern void (*XShapeOffsetShape_dylibloader_wrapper_xext)( Display*, Window, int, int, int); -extern int (*XShapeQueryExtents_dylibloader_wrapper_xext)( Display*, Window, int*, int*, int*, unsigned int*, unsigned int*, int*, int*, int*, unsigned int*, unsigned int*); -extern void (*XShapeSelectInput_dylibloader_wrapper_xext)( Display*, Window, unsigned long); -extern unsigned long (*XShapeInputSelected_dylibloader_wrapper_xext)( Display*, Window); -extern XRectangle* (*XShapeGetRectangles_dylibloader_wrapper_xext)( Display*, Window, int, int*, int*); +extern int (*XShapeQueryExtension_dylibloader_wrapper_xext)(Display *, int *, int *); +extern int (*XShapeQueryVersion_dylibloader_wrapper_xext)(Display *, int *, int *); +extern void (*XShapeCombineRegion_dylibloader_wrapper_xext)(Display *, Window, int, int, int, Region, int); +extern void (*XShapeCombineRectangles_dylibloader_wrapper_xext)(Display *, Window, int, int, int, XRectangle *, int, int, int); +extern void (*XShapeCombineMask_dylibloader_wrapper_xext)(Display *, Window, int, int, int, Pixmap, int); +extern void (*XShapeCombineShape_dylibloader_wrapper_xext)(Display *, Window, int, int, int, Window, int, int); +extern void (*XShapeOffsetShape_dylibloader_wrapper_xext)(Display *, Window, int, int, int); +extern int (*XShapeQueryExtents_dylibloader_wrapper_xext)(Display *, Window, int *, int *, int *, unsigned int *, unsigned int *, int *, int *, int *, unsigned int *, unsigned int *); +extern void (*XShapeSelectInput_dylibloader_wrapper_xext)(Display *, Window, unsigned long); +extern unsigned long (*XShapeInputSelected_dylibloader_wrapper_xext)(Display *, Window); +extern XRectangle *(*XShapeGetRectangles_dylibloader_wrapper_xext)(Display *, Window, int, int *, int *); int initialize_xext(int verbose); #ifdef __cplusplus } diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c index 850ed1fc6b..eeb6bf7a8f 100644 --- a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c +++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c @@ -1,12 +1,8 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:35 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h" --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c --ignore-other // -// NOTE: Generated from Xinerama 1.1.4. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXinerama.so.1, were removed. #include <stdint.h> #define XineramaQueryExtension XineramaQueryExtension_dylibloader_orig_xinerama @@ -20,10 +16,10 @@ #undef XineramaQueryScreens #include <dlfcn.h> #include <stdio.h> -int (*XineramaQueryExtension_dylibloader_wrapper_xinerama)( Display*, int*, int*); -int (*XineramaQueryVersion_dylibloader_wrapper_xinerama)( Display*, int*, int*); -int (*XineramaIsActive_dylibloader_wrapper_xinerama)( Display*); -XineramaScreenInfo* (*XineramaQueryScreens_dylibloader_wrapper_xinerama)( Display*, int*); +int (*XineramaQueryExtension_dylibloader_wrapper_xinerama)(Display *, int *, int *); +int (*XineramaQueryVersion_dylibloader_wrapper_xinerama)(Display *, int *, int *); +int (*XineramaIsActive_dylibloader_wrapper_xinerama)(Display *); +XineramaScreenInfo *(*XineramaQueryScreens_dylibloader_wrapper_xinerama)(Display *, int *); int initialize_xinerama(int verbose) { void *handle; char *error; diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h index e3cedfc8ad..b421a0ecf5 100644 --- a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h +++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h @@ -2,13 +2,9 @@ #define DYLIBLOAD_WRAPPER_XINERAMA // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:35 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h" --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c --ignore-other // -// NOTE: Generated from Xinerama 1.1.4. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXinerama.so.1, were removed. #include <stdint.h> #define XineramaQueryExtension XineramaQueryExtension_dylibloader_orig_xinerama @@ -27,10 +23,10 @@ extern "C" { #define XineramaQueryVersion XineramaQueryVersion_dylibloader_wrapper_xinerama #define XineramaIsActive XineramaIsActive_dylibloader_wrapper_xinerama #define XineramaQueryScreens XineramaQueryScreens_dylibloader_wrapper_xinerama -extern int (*XineramaQueryExtension_dylibloader_wrapper_xinerama)( Display*, int*, int*); -extern int (*XineramaQueryVersion_dylibloader_wrapper_xinerama)( Display*, int*, int*); -extern int (*XineramaIsActive_dylibloader_wrapper_xinerama)( Display*); -extern XineramaScreenInfo* (*XineramaQueryScreens_dylibloader_wrapper_xinerama)( Display*, int*); +extern int (*XineramaQueryExtension_dylibloader_wrapper_xinerama)(Display *, int *, int *); +extern int (*XineramaQueryVersion_dylibloader_wrapper_xinerama)(Display *, int *, int *); +extern int (*XineramaIsActive_dylibloader_wrapper_xinerama)(Display *); +extern XineramaScreenInfo *(*XineramaQueryScreens_dylibloader_wrapper_xinerama)(Display *, int *); int initialize_xinerama(int verbose); #ifdef __cplusplus } diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c index fc08b97e3c..8f031acb20 100644 --- a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c +++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c @@ -1,12 +1,8 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:12:16 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/XInput2.h" --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c --ignore-other // -// NOTE: Generated from Xi 1.7.10. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, liXext and libXfixes, but absent in libXi.so.6, were removed. #include <stdint.h> #define XIQueryPointer XIQueryPointer_dylibloader_orig_xinput2 @@ -80,40 +76,40 @@ #undef XIFreeDeviceInfo #include <dlfcn.h> #include <stdio.h> -int (*XIQueryPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window*, Window*, double*, double*, double*, double*, XIButtonState*, XIModifierState*, XIGroupState*); -int (*XIWarpPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window, double, double, unsigned int, unsigned int, double, double); -int (*XIDefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor); -int (*XIUndefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window); -int (*XIChangeHierarchy_dylibloader_wrapper_xinput2)( Display*, XIAnyHierarchyChangeInfo*, int); -int (*XISetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int); -int (*XIGetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int*); -int (*XISelectEvents_dylibloader_wrapper_xinput2)( Display*, Window, XIEventMask*, int); -XIEventMask* (*XIGetSelectedEvents_dylibloader_wrapper_xinput2)( Display*, Window, int*); -int (*XIQueryVersion_dylibloader_wrapper_xinput2)( Display*, int*, int*); -XIDeviceInfo* (*XIQueryDevice_dylibloader_wrapper_xinput2)( Display*, int, int*); -int (*XISetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window, Time); -int (*XIGetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window*); -int (*XIGrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Window, Time, Cursor, int, int, int, XIEventMask*); -int (*XIUngrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Time); -int (*XIAllowEvents_dylibloader_wrapper_xinput2)( Display*, int, int, Time); -int (*XIAllowTouchEvents_dylibloader_wrapper_xinput2)( Display*, int, unsigned int, Window, int); -int (*XIGrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*); -int (*XIGrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*); -int (*XIGrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*); -int (*XIGrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*); -int (*XIGrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIEventMask*, int, XIGrabModifiers*); -int (*XIUngrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*); -int (*XIUngrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*); -int (*XIUngrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*); -int (*XIUngrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*); -int (*XIUngrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*); -Atom* (*XIListProperties_dylibloader_wrapper_xinput2)( Display*, int, int*); -void (*XIChangeProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, Atom, int, int, unsigned char*, int); -void (*XIDeleteProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom); -int (*XIGetProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -void (*XIBarrierReleasePointers_dylibloader_wrapper_xinput2)( Display*, XIBarrierReleasePointerInfo*, int); -void (*XIBarrierReleasePointer_dylibloader_wrapper_xinput2)( Display*, int, PointerBarrier, BarrierEventID); -void (*XIFreeDeviceInfo_dylibloader_wrapper_xinput2)( XIDeviceInfo*); +int (*XIQueryPointer_dylibloader_wrapper_xinput2)(Display *, int, Window, Window *, Window *, double *, double *, double *, double *, XIButtonState *, XIModifierState *, XIGroupState *); +int (*XIWarpPointer_dylibloader_wrapper_xinput2)(Display *, int, Window, Window, double, double, unsigned int, unsigned int, double, double); +int (*XIDefineCursor_dylibloader_wrapper_xinput2)(Display *, int, Window, Cursor); +int (*XIUndefineCursor_dylibloader_wrapper_xinput2)(Display *, int, Window); +int (*XIChangeHierarchy_dylibloader_wrapper_xinput2)(Display *, XIAnyHierarchyChangeInfo *, int); +int (*XISetClientPointer_dylibloader_wrapper_xinput2)(Display *, Window, int); +int (*XIGetClientPointer_dylibloader_wrapper_xinput2)(Display *, Window, int *); +int (*XISelectEvents_dylibloader_wrapper_xinput2)(Display *, Window, XIEventMask *, int); +XIEventMask *(*XIGetSelectedEvents_dylibloader_wrapper_xinput2)(Display *, Window, int *); +int (*XIQueryVersion_dylibloader_wrapper_xinput2)(Display *, int *, int *); +XIDeviceInfo *(*XIQueryDevice_dylibloader_wrapper_xinput2)(Display *, int, int *); +int (*XISetFocus_dylibloader_wrapper_xinput2)(Display *, int, Window, Time); +int (*XIGetFocus_dylibloader_wrapper_xinput2)(Display *, int, Window *); +int (*XIGrabDevice_dylibloader_wrapper_xinput2)(Display *, int, Window, Time, Cursor, int, int, int, XIEventMask *); +int (*XIUngrabDevice_dylibloader_wrapper_xinput2)(Display *, int, Time); +int (*XIAllowEvents_dylibloader_wrapper_xinput2)(Display *, int, int, Time); +int (*XIAllowTouchEvents_dylibloader_wrapper_xinput2)(Display *, int, unsigned int, Window, int); +int (*XIGrabButton_dylibloader_wrapper_xinput2)(Display *, int, int, Window, Cursor, int, int, int, XIEventMask *, int, XIGrabModifiers *); +int (*XIGrabKeycode_dylibloader_wrapper_xinput2)(Display *, int, int, Window, int, int, int, XIEventMask *, int, XIGrabModifiers *); +int (*XIGrabEnter_dylibloader_wrapper_xinput2)(Display *, int, Window, Cursor, int, int, int, XIEventMask *, int, XIGrabModifiers *); +int (*XIGrabFocusIn_dylibloader_wrapper_xinput2)(Display *, int, Window, int, int, int, XIEventMask *, int, XIGrabModifiers *); +int (*XIGrabTouchBegin_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIEventMask *, int, XIGrabModifiers *); +int (*XIUngrabButton_dylibloader_wrapper_xinput2)(Display *, int, int, Window, int, XIGrabModifiers *); +int (*XIUngrabKeycode_dylibloader_wrapper_xinput2)(Display *, int, int, Window, int, XIGrabModifiers *); +int (*XIUngrabEnter_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIGrabModifiers *); +int (*XIUngrabFocusIn_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIGrabModifiers *); +int (*XIUngrabTouchBegin_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIGrabModifiers *); +Atom *(*XIListProperties_dylibloader_wrapper_xinput2)(Display *, int, int *); +void (*XIChangeProperty_dylibloader_wrapper_xinput2)(Display *, int, Atom, Atom, int, int, unsigned char *, int); +void (*XIDeleteProperty_dylibloader_wrapper_xinput2)(Display *, int, Atom); +int (*XIGetProperty_dylibloader_wrapper_xinput2)(Display *, int, Atom, long, long, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +void (*XIBarrierReleasePointers_dylibloader_wrapper_xinput2)(Display *, XIBarrierReleasePointerInfo *, int); +void (*XIBarrierReleasePointer_dylibloader_wrapper_xinput2)(Display *, int, PointerBarrier, BarrierEventID); +void (*XIFreeDeviceInfo_dylibloader_wrapper_xinput2)(XIDeviceInfo *); int initialize_xinput2(int verbose) { void *handle; char *error; diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h index 571072c3cd..7c54dc080a 100644 --- a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h +++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h @@ -2,13 +2,9 @@ #define DYLIBLOAD_WRAPPER_XINPUT2 // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:12:16 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/XInput2.h" --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c --ignore-other // -// NOTE: Generated from Xi 1.7.10. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, liXext and libXfixes, but absent in libXi.so.6, were removed. #include <stdint.h> #define XIQueryPointer XIQueryPointer_dylibloader_orig_xinput2 @@ -117,40 +113,40 @@ extern "C" { #define XIBarrierReleasePointers XIBarrierReleasePointers_dylibloader_wrapper_xinput2 #define XIBarrierReleasePointer XIBarrierReleasePointer_dylibloader_wrapper_xinput2 #define XIFreeDeviceInfo XIFreeDeviceInfo_dylibloader_wrapper_xinput2 -extern int (*XIQueryPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window*, Window*, double*, double*, double*, double*, XIButtonState*, XIModifierState*, XIGroupState*); -extern int (*XIWarpPointer_dylibloader_wrapper_xinput2)( Display*, int, Window, Window, double, double, unsigned int, unsigned int, double, double); -extern int (*XIDefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor); -extern int (*XIUndefineCursor_dylibloader_wrapper_xinput2)( Display*, int, Window); -extern int (*XIChangeHierarchy_dylibloader_wrapper_xinput2)( Display*, XIAnyHierarchyChangeInfo*, int); -extern int (*XISetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int); -extern int (*XIGetClientPointer_dylibloader_wrapper_xinput2)( Display*, Window, int*); -extern int (*XISelectEvents_dylibloader_wrapper_xinput2)( Display*, Window, XIEventMask*, int); -extern XIEventMask* (*XIGetSelectedEvents_dylibloader_wrapper_xinput2)( Display*, Window, int*); -extern int (*XIQueryVersion_dylibloader_wrapper_xinput2)( Display*, int*, int*); -extern XIDeviceInfo* (*XIQueryDevice_dylibloader_wrapper_xinput2)( Display*, int, int*); -extern int (*XISetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window, Time); -extern int (*XIGetFocus_dylibloader_wrapper_xinput2)( Display*, int, Window*); -extern int (*XIGrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Window, Time, Cursor, int, int, int, XIEventMask*); -extern int (*XIUngrabDevice_dylibloader_wrapper_xinput2)( Display*, int, Time); -extern int (*XIAllowEvents_dylibloader_wrapper_xinput2)( Display*, int, int, Time); -extern int (*XIAllowTouchEvents_dylibloader_wrapper_xinput2)( Display*, int, unsigned int, Window, int); -extern int (*XIGrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*); -extern int (*XIGrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*); -extern int (*XIGrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, Cursor, int, int, int, XIEventMask*, int, XIGrabModifiers*); -extern int (*XIGrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, int, int, XIEventMask*, int, XIGrabModifiers*); -extern int (*XIGrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIEventMask*, int, XIGrabModifiers*); -extern int (*XIUngrabButton_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*); -extern int (*XIUngrabKeycode_dylibloader_wrapper_xinput2)( Display*, int, int, Window, int, XIGrabModifiers*); -extern int (*XIUngrabEnter_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*); -extern int (*XIUngrabFocusIn_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*); -extern int (*XIUngrabTouchBegin_dylibloader_wrapper_xinput2)( Display*, int, Window, int, XIGrabModifiers*); -extern Atom* (*XIListProperties_dylibloader_wrapper_xinput2)( Display*, int, int*); -extern void (*XIChangeProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, Atom, int, int, unsigned char*, int); -extern void (*XIDeleteProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom); -extern int (*XIGetProperty_dylibloader_wrapper_xinput2)( Display*, int, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -extern void (*XIBarrierReleasePointers_dylibloader_wrapper_xinput2)( Display*, XIBarrierReleasePointerInfo*, int); -extern void (*XIBarrierReleasePointer_dylibloader_wrapper_xinput2)( Display*, int, PointerBarrier, BarrierEventID); -extern void (*XIFreeDeviceInfo_dylibloader_wrapper_xinput2)( XIDeviceInfo*); +extern int (*XIQueryPointer_dylibloader_wrapper_xinput2)(Display *, int, Window, Window *, Window *, double *, double *, double *, double *, XIButtonState *, XIModifierState *, XIGroupState *); +extern int (*XIWarpPointer_dylibloader_wrapper_xinput2)(Display *, int, Window, Window, double, double, unsigned int, unsigned int, double, double); +extern int (*XIDefineCursor_dylibloader_wrapper_xinput2)(Display *, int, Window, Cursor); +extern int (*XIUndefineCursor_dylibloader_wrapper_xinput2)(Display *, int, Window); +extern int (*XIChangeHierarchy_dylibloader_wrapper_xinput2)(Display *, XIAnyHierarchyChangeInfo *, int); +extern int (*XISetClientPointer_dylibloader_wrapper_xinput2)(Display *, Window, int); +extern int (*XIGetClientPointer_dylibloader_wrapper_xinput2)(Display *, Window, int *); +extern int (*XISelectEvents_dylibloader_wrapper_xinput2)(Display *, Window, XIEventMask *, int); +extern XIEventMask *(*XIGetSelectedEvents_dylibloader_wrapper_xinput2)(Display *, Window, int *); +extern int (*XIQueryVersion_dylibloader_wrapper_xinput2)(Display *, int *, int *); +extern XIDeviceInfo *(*XIQueryDevice_dylibloader_wrapper_xinput2)(Display *, int, int *); +extern int (*XISetFocus_dylibloader_wrapper_xinput2)(Display *, int, Window, Time); +extern int (*XIGetFocus_dylibloader_wrapper_xinput2)(Display *, int, Window *); +extern int (*XIGrabDevice_dylibloader_wrapper_xinput2)(Display *, int, Window, Time, Cursor, int, int, int, XIEventMask *); +extern int (*XIUngrabDevice_dylibloader_wrapper_xinput2)(Display *, int, Time); +extern int (*XIAllowEvents_dylibloader_wrapper_xinput2)(Display *, int, int, Time); +extern int (*XIAllowTouchEvents_dylibloader_wrapper_xinput2)(Display *, int, unsigned int, Window, int); +extern int (*XIGrabButton_dylibloader_wrapper_xinput2)(Display *, int, int, Window, Cursor, int, int, int, XIEventMask *, int, XIGrabModifiers *); +extern int (*XIGrabKeycode_dylibloader_wrapper_xinput2)(Display *, int, int, Window, int, int, int, XIEventMask *, int, XIGrabModifiers *); +extern int (*XIGrabEnter_dylibloader_wrapper_xinput2)(Display *, int, Window, Cursor, int, int, int, XIEventMask *, int, XIGrabModifiers *); +extern int (*XIGrabFocusIn_dylibloader_wrapper_xinput2)(Display *, int, Window, int, int, int, XIEventMask *, int, XIGrabModifiers *); +extern int (*XIGrabTouchBegin_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIEventMask *, int, XIGrabModifiers *); +extern int (*XIUngrabButton_dylibloader_wrapper_xinput2)(Display *, int, int, Window, int, XIGrabModifiers *); +extern int (*XIUngrabKeycode_dylibloader_wrapper_xinput2)(Display *, int, int, Window, int, XIGrabModifiers *); +extern int (*XIUngrabEnter_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIGrabModifiers *); +extern int (*XIUngrabFocusIn_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIGrabModifiers *); +extern int (*XIUngrabTouchBegin_dylibloader_wrapper_xinput2)(Display *, int, Window, int, XIGrabModifiers *); +extern Atom *(*XIListProperties_dylibloader_wrapper_xinput2)(Display *, int, int *); +extern void (*XIChangeProperty_dylibloader_wrapper_xinput2)(Display *, int, Atom, Atom, int, int, unsigned char *, int); +extern void (*XIDeleteProperty_dylibloader_wrapper_xinput2)(Display *, int, Atom); +extern int (*XIGetProperty_dylibloader_wrapper_xinput2)(Display *, int, Atom, long, long, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +extern void (*XIBarrierReleasePointers_dylibloader_wrapper_xinput2)(Display *, XIBarrierReleasePointerInfo *, int); +extern void (*XIBarrierReleasePointer_dylibloader_wrapper_xinput2)(Display *, int, PointerBarrier, BarrierEventID); +extern void (*XIFreeDeviceInfo_dylibloader_wrapper_xinput2)(XIDeviceInfo *); int initialize_xinput2(int verbose); #ifdef __cplusplus } diff --git a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c index d2838569b0..8500f20198 100644 --- a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c +++ b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c @@ -1,14 +1,8 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:26 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include "thirdparty/linuxbsd_headers/X11/Xlib.h" --sys-include "thirdparty/linuxbsd_headers/X11/Xutil.h" --sys-include "thirdparty/linuxbsd_headers/X11/XKBlib.h" --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c~ +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include thirdparty/linuxbsd_headers/X11/Xlib.h --sys-include thirdparty/linuxbsd_headers/X11/Xutil.h --sys-include thirdparty/linuxbsd_headers/X11/XKBlib.h --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c // -// NOTE: Generated from Xlib 1.6.9. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, the type of the third argument of -// XIfEvent, XPeekIfEvent and XCheckIfEvent had to be fixed as it wasn't parsed -// fully (it's a Bool function pointer, but it was just being parsed as an int -// pointer). #include <stdint.h> #define _Xmblen _Xmblen_dylibloader_orig_xlib @@ -100,6 +94,7 @@ #define XScreenNumberOfScreen XScreenNumberOfScreen_dylibloader_orig_xlib #define XSetErrorHandler XSetErrorHandler_dylibloader_orig_xlib #define XSetIOErrorHandler XSetIOErrorHandler_dylibloader_orig_xlib +#define XSetIOErrorExitHandler XSetIOErrorExitHandler_dylibloader_orig_xlib #define XListPixmapFormats XListPixmapFormats_dylibloader_orig_xlib #define XListDepths XListDepths_dylibloader_orig_xlib #define XReconfigureWMWindow XReconfigureWMWindow_dylibloader_orig_xlib @@ -423,6 +418,7 @@ #define _Xwctomb _Xwctomb_dylibloader_orig_xlib #define XGetEventData XGetEventData_dylibloader_orig_xlib #define XFreeEventData XFreeEventData_dylibloader_orig_xlib +#define XFreeThreads XFreeThreads_dylibloader_orig_xlib #define XAllocClassHint XAllocClassHint_dylibloader_orig_xlib #define XAllocIconSize XAllocIconSize_dylibloader_orig_xlib #define XAllocSizeHints XAllocSizeHints_dylibloader_orig_xlib @@ -706,6 +702,7 @@ #undef XScreenNumberOfScreen #undef XSetErrorHandler #undef XSetIOErrorHandler +#undef XSetIOErrorExitHandler #undef XListPixmapFormats #undef XListDepths #undef XReconfigureWMWindow @@ -1029,6 +1026,7 @@ #undef _Xwctomb #undef XGetEventData #undef XFreeEventData +#undef XFreeThreads #undef XAllocClassHint #undef XAllocIconSize #undef XAllocSizeHints @@ -1222,609 +1220,611 @@ #undef XkbUpdateKeyTypeVirtualMods #include <dlfcn.h> #include <stdio.h> -int (*_Xmblen_dylibloader_wrapper_xlib)( char*, int); -XFontStruct* (*XLoadQueryFont_dylibloader_wrapper_xlib)( Display*,const char*); -XFontStruct* (*XQueryFont_dylibloader_wrapper_xlib)( Display*, XID); -XTimeCoord* (*XGetMotionEvents_dylibloader_wrapper_xlib)( Display*, Window, Time, Time, int*); -XModifierKeymap* (*XDeleteModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int); -XModifierKeymap* (*XGetModifierMapping_dylibloader_wrapper_xlib)( Display*); -XModifierKeymap* (*XInsertModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int); -XModifierKeymap* (*XNewModifiermap_dylibloader_wrapper_xlib)( int); -XImage* (*XCreateImage_dylibloader_wrapper_xlib)( Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int); -int (*XInitImage_dylibloader_wrapper_xlib)( XImage*); -XImage* (*XGetImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int); -XImage* (*XGetSubImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int, XImage*, int, int); -Display* (*XOpenDisplay_dylibloader_wrapper_xlib)(const char*); -void (*XrmInitialize_dylibloader_wrapper_xlib)( void); -char* (*XFetchBytes_dylibloader_wrapper_xlib)( Display*, int*); -char* (*XFetchBuffer_dylibloader_wrapper_xlib)( Display*, int*, int); -char* (*XGetAtomName_dylibloader_wrapper_xlib)( Display*, Atom); -int (*XGetAtomNames_dylibloader_wrapper_xlib)( Display*, Atom*, int, char**); -char* (*XGetDefault_dylibloader_wrapper_xlib)( Display*,const char*,const char*); -char* (*XDisplayName_dylibloader_wrapper_xlib)(const char*); -char* (*XKeysymToString_dylibloader_wrapper_xlib)( KeySym); -int* (*XSynchronize_dylibloader_wrapper_xlib)( Display*, int); -int* (*XSetAfterFunction_dylibloader_wrapper_xlib)( Display*, int*); -Atom (*XInternAtom_dylibloader_wrapper_xlib)( Display*,const char*, int); -int (*XInternAtoms_dylibloader_wrapper_xlib)( Display*, char**, int, int, Atom*); -Colormap (*XCopyColormapAndFree_dylibloader_wrapper_xlib)( Display*, Colormap); -Colormap (*XCreateColormap_dylibloader_wrapper_xlib)( Display*, Window, Visual*, int); -Cursor (*XCreatePixmapCursor_dylibloader_wrapper_xlib)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int); -Cursor (*XCreateGlyphCursor_dylibloader_wrapper_xlib)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*); -Cursor (*XCreateFontCursor_dylibloader_wrapper_xlib)( Display*, unsigned int); -Font (*XLoadFont_dylibloader_wrapper_xlib)( Display*,const char*); -GC (*XCreateGC_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned long, XGCValues*); -GContext (*XGContextFromGC_dylibloader_wrapper_xlib)( GC); -void (*XFlushGC_dylibloader_wrapper_xlib)( Display*, GC); -Pixmap (*XCreatePixmap_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int); -Pixmap (*XCreateBitmapFromData_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int, unsigned int); -Pixmap (*XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib)( Display*, Drawable, char*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int); -Window (*XCreateSimpleWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); -Window (*XGetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom); -Window (*XCreateWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*); -Colormap* (*XListInstalledColormaps_dylibloader_wrapper_xlib)( Display*, Window, int*); -char** (*XListFonts_dylibloader_wrapper_xlib)( Display*,const char*, int, int*); -char** (*XListFontsWithInfo_dylibloader_wrapper_xlib)( Display*,const char*, int, int*, XFontStruct**); -char** (*XGetFontPath_dylibloader_wrapper_xlib)( Display*, int*); -char** (*XListExtensions_dylibloader_wrapper_xlib)( Display*, int*); -Atom* (*XListProperties_dylibloader_wrapper_xlib)( Display*, Window, int*); -XHostAddress* (*XListHosts_dylibloader_wrapper_xlib)( Display*, int*, int*); -KeySym (*XKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int); -KeySym (*XLookupKeysym_dylibloader_wrapper_xlib)( XKeyEvent*, int); -KeySym* (*XGetKeyboardMapping_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int*); -KeySym (*XStringToKeysym_dylibloader_wrapper_xlib)(const char*); -long (*XMaxRequestSize_dylibloader_wrapper_xlib)( Display*); -long (*XExtendedMaxRequestSize_dylibloader_wrapper_xlib)( Display*); -char* (*XResourceManagerString_dylibloader_wrapper_xlib)( Display*); -char* (*XScreenResourceString_dylibloader_wrapper_xlib)( Screen*); -unsigned long (*XDisplayMotionBufferSize_dylibloader_wrapper_xlib)( Display*); -VisualID (*XVisualIDFromVisual_dylibloader_wrapper_xlib)( Visual*); -int (*XInitThreads_dylibloader_wrapper_xlib)( void); -void (*XLockDisplay_dylibloader_wrapper_xlib)( Display*); -void (*XUnlockDisplay_dylibloader_wrapper_xlib)( Display*); -XExtCodes* (*XInitExtension_dylibloader_wrapper_xlib)( Display*,const char*); -XExtCodes* (*XAddExtension_dylibloader_wrapper_xlib)( Display*); -XExtData* (*XFindOnExtensionList_dylibloader_wrapper_xlib)( XExtData**, int); -XExtData** (*XEHeadOfExtensionList_dylibloader_wrapper_xlib)( XEDataObject); -Window (*XRootWindow_dylibloader_wrapper_xlib)( Display*, int); -Window (*XDefaultRootWindow_dylibloader_wrapper_xlib)( Display*); -Window (*XRootWindowOfScreen_dylibloader_wrapper_xlib)( Screen*); -Visual* (*XDefaultVisual_dylibloader_wrapper_xlib)( Display*, int); -Visual* (*XDefaultVisualOfScreen_dylibloader_wrapper_xlib)( Screen*); -GC (*XDefaultGC_dylibloader_wrapper_xlib)( Display*, int); -GC (*XDefaultGCOfScreen_dylibloader_wrapper_xlib)( Screen*); -unsigned long (*XBlackPixel_dylibloader_wrapper_xlib)( Display*, int); -unsigned long (*XWhitePixel_dylibloader_wrapper_xlib)( Display*, int); -unsigned long (*XAllPlanes_dylibloader_wrapper_xlib)( void); -unsigned long (*XBlackPixelOfScreen_dylibloader_wrapper_xlib)( Screen*); -unsigned long (*XWhitePixelOfScreen_dylibloader_wrapper_xlib)( Screen*); -unsigned long (*XNextRequest_dylibloader_wrapper_xlib)( Display*); -unsigned long (*XLastKnownRequestProcessed_dylibloader_wrapper_xlib)( Display*); -char* (*XServerVendor_dylibloader_wrapper_xlib)( Display*); -char* (*XDisplayString_dylibloader_wrapper_xlib)( Display*); -Colormap (*XDefaultColormap_dylibloader_wrapper_xlib)( Display*, int); -Colormap (*XDefaultColormapOfScreen_dylibloader_wrapper_xlib)( Screen*); -Display* (*XDisplayOfScreen_dylibloader_wrapper_xlib)( Screen*); -Screen* (*XScreenOfDisplay_dylibloader_wrapper_xlib)( Display*, int); -Screen* (*XDefaultScreenOfDisplay_dylibloader_wrapper_xlib)( Display*); -long (*XEventMaskOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XScreenNumberOfScreen_dylibloader_wrapper_xlib)( Screen*); -XErrorHandler (*XSetErrorHandler_dylibloader_wrapper_xlib)( XErrorHandler); -XIOErrorHandler (*XSetIOErrorHandler_dylibloader_wrapper_xlib)( XIOErrorHandler); -XPixmapFormatValues* (*XListPixmapFormats_dylibloader_wrapper_xlib)( Display*, int*); -int* (*XListDepths_dylibloader_wrapper_xlib)( Display*, int, int*); -int (*XReconfigureWMWindow_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, XWindowChanges*); -int (*XGetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom**, int*); -int (*XSetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int); -int (*XIconifyWindow_dylibloader_wrapper_xlib)( Display*, Window, int); -int (*XWithdrawWindow_dylibloader_wrapper_xlib)( Display*, Window, int); -int (*XGetCommand_dylibloader_wrapper_xlib)( Display*, Window, char***, int*); -int (*XGetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window**, int*); -int (*XSetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window*, int); -void (*XFreeStringList_dylibloader_wrapper_xlib)( char**); -int (*XSetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window); -int (*XActivateScreenSaver_dylibloader_wrapper_xlib)( Display*); -int (*XAddHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*); -int (*XAddHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int); -int (*XAddToExtensionList_dylibloader_wrapper_xlib)(struct _XExtData**, XExtData*); -int (*XAddToSaveSet_dylibloader_wrapper_xlib)( Display*, Window); -int (*XAllocColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*); -int (*XAllocColorCells_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, unsigned int, unsigned long*, unsigned int); -int (*XAllocColorPlanes_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, int, int, int, int, unsigned long*, unsigned long*, unsigned long*); -int (*XAllocNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*); -int (*XAllowEvents_dylibloader_wrapper_xlib)( Display*, int, Time); -int (*XAutoRepeatOff_dylibloader_wrapper_xlib)( Display*); -int (*XAutoRepeatOn_dylibloader_wrapper_xlib)( Display*); -int (*XBell_dylibloader_wrapper_xlib)( Display*, int); -int (*XBitmapBitOrder_dylibloader_wrapper_xlib)( Display*); -int (*XBitmapPad_dylibloader_wrapper_xlib)( Display*); -int (*XBitmapUnit_dylibloader_wrapper_xlib)( Display*); -int (*XCellsOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XChangeActivePointerGrab_dylibloader_wrapper_xlib)( Display*, unsigned int, Cursor, Time); -int (*XChangeGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*); -int (*XChangeKeyboardControl_dylibloader_wrapper_xlib)( Display*, unsigned long, XKeyboardControl*); -int (*XChangeKeyboardMapping_dylibloader_wrapper_xlib)( Display*, int, int, KeySym*, int); -int (*XChangePointerControl_dylibloader_wrapper_xlib)( Display*, int, int, int, int, int); -int (*XChangeProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, Atom, int, int,const unsigned char*, int); -int (*XChangeSaveSet_dylibloader_wrapper_xlib)( Display*, Window, int); -int (*XChangeWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, unsigned long, XSetWindowAttributes*); -int (*XCheckIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer); -int (*XCheckMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*); -int (*XCheckTypedEvent_dylibloader_wrapper_xlib)( Display*, int, XEvent*); -int (*XCheckTypedWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, int, XEvent*); -int (*XCheckWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*); -int (*XCirculateSubwindows_dylibloader_wrapper_xlib)( Display*, Window, int); -int (*XCirculateSubwindowsDown_dylibloader_wrapper_xlib)( Display*, Window); -int (*XCirculateSubwindowsUp_dylibloader_wrapper_xlib)( Display*, Window); -int (*XClearArea_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, int); -int (*XClearWindow_dylibloader_wrapper_xlib)( Display*, Window); -int (*XCloseDisplay_dylibloader_wrapper_xlib)( Display*); -int (*XConfigureWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, XWindowChanges*); -int (*XConnectionNumber_dylibloader_wrapper_xlib)( Display*); -int (*XConvertSelection_dylibloader_wrapper_xlib)( Display*, Atom, Atom, Atom, Window, Time); -int (*XCopyArea_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int); -int (*XCopyGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, GC); -int (*XCopyPlane_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long); -int (*XDefaultDepth_dylibloader_wrapper_xlib)( Display*, int); -int (*XDefaultDepthOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XDefaultScreen_dylibloader_wrapper_xlib)( Display*); -int (*XDefineCursor_dylibloader_wrapper_xlib)( Display*, Window, Cursor); -int (*XDeleteProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom); -int (*XDestroyWindow_dylibloader_wrapper_xlib)( Display*, Window); -int (*XDestroySubwindows_dylibloader_wrapper_xlib)( Display*, Window); -int (*XDoesBackingStore_dylibloader_wrapper_xlib)( Screen*); -int (*XDoesSaveUnders_dylibloader_wrapper_xlib)( Screen*); -int (*XDisableAccessControl_dylibloader_wrapper_xlib)( Display*); -int (*XDisplayCells_dylibloader_wrapper_xlib)( Display*, int); -int (*XDisplayHeight_dylibloader_wrapper_xlib)( Display*, int); -int (*XDisplayHeightMM_dylibloader_wrapper_xlib)( Display*, int); -int (*XDisplayKeycodes_dylibloader_wrapper_xlib)( Display*, int*, int*); -int (*XDisplayPlanes_dylibloader_wrapper_xlib)( Display*, int); -int (*XDisplayWidth_dylibloader_wrapper_xlib)( Display*, int); -int (*XDisplayWidthMM_dylibloader_wrapper_xlib)( Display*, int); -int (*XDrawArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int); -int (*XDrawArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int); -int (*XDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int); -int (*XDrawImageString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int); -int (*XDrawLine_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, int, int); -int (*XDrawLines_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int); -int (*XDrawPoint_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int); -int (*XDrawPoints_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int); -int (*XDrawRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int); -int (*XDrawRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int); -int (*XDrawSegments_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XSegment*, int); -int (*XDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int); -int (*XDrawString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int); -int (*XDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem*, int); -int (*XDrawText16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem16*, int); -int (*XEnableAccessControl_dylibloader_wrapper_xlib)( Display*); -int (*XEventsQueued_dylibloader_wrapper_xlib)( Display*, int); -int (*XFetchName_dylibloader_wrapper_xlib)( Display*, Window, char**); -int (*XFillArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int); -int (*XFillArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int); -int (*XFillPolygon_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int, int); -int (*XFillRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int); -int (*XFillRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int); -int (*XFlush_dylibloader_wrapper_xlib)( Display*); -int (*XForceScreenSaver_dylibloader_wrapper_xlib)( Display*, int); -int (*XFree_dylibloader_wrapper_xlib)( void*); -int (*XFreeColormap_dylibloader_wrapper_xlib)( Display*, Colormap); -int (*XFreeColors_dylibloader_wrapper_xlib)( Display*, Colormap, unsigned long*, int, unsigned long); -int (*XFreeCursor_dylibloader_wrapper_xlib)( Display*, Cursor); -int (*XFreeExtensionList_dylibloader_wrapper_xlib)( char**); -int (*XFreeFont_dylibloader_wrapper_xlib)( Display*, XFontStruct*); -int (*XFreeFontInfo_dylibloader_wrapper_xlib)( char**, XFontStruct*, int); -int (*XFreeFontNames_dylibloader_wrapper_xlib)( char**); -int (*XFreeFontPath_dylibloader_wrapper_xlib)( char**); -int (*XFreeGC_dylibloader_wrapper_xlib)( Display*, GC); -int (*XFreeModifiermap_dylibloader_wrapper_xlib)( XModifierKeymap*); -int (*XFreePixmap_dylibloader_wrapper_xlib)( Display*, Pixmap); -int (*XGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, unsigned int, unsigned int, int, int, int*, int*, int*, int*); -int (*XGetErrorDatabaseText_dylibloader_wrapper_xlib)( Display*,const char*,const char*,const char*, char*, int); -int (*XGetErrorText_dylibloader_wrapper_xlib)( Display*, int, char*, int); -int (*XGetFontProperty_dylibloader_wrapper_xlib)( XFontStruct*, Atom, unsigned long*); -int (*XGetGCValues_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*); -int (*XGetGeometry_dylibloader_wrapper_xlib)( Display*, Drawable, Window*, int*, int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*); -int (*XGetIconName_dylibloader_wrapper_xlib)( Display*, Window, char**); -int (*XGetInputFocus_dylibloader_wrapper_xlib)( Display*, Window*, int*); -int (*XGetKeyboardControl_dylibloader_wrapper_xlib)( Display*, XKeyboardState*); -int (*XGetPointerControl_dylibloader_wrapper_xlib)( Display*, int*, int*, int*); -int (*XGetPointerMapping_dylibloader_wrapper_xlib)( Display*, unsigned char*, int); -int (*XGetScreenSaver_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*); -int (*XGetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window*); -int (*XGetWindowProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -int (*XGetWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, XWindowAttributes*); -int (*XGrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window, int, unsigned int, int, int, Window, Cursor); -int (*XGrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window, int, int, int); -int (*XGrabKeyboard_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, Time); -int (*XGrabPointer_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, int, int, Window, Cursor, Time); -int (*XGrabServer_dylibloader_wrapper_xlib)( Display*); -int (*XHeightMMOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XHeightOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer); -int (*XImageByteOrder_dylibloader_wrapper_xlib)( Display*); -int (*XInstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap); -KeyCode (*XKeysymToKeycode_dylibloader_wrapper_xlib)( Display*, KeySym); -int (*XKillClient_dylibloader_wrapper_xlib)( Display*, XID); -int (*XLookupColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*); -int (*XLowerWindow_dylibloader_wrapper_xlib)( Display*, Window); -int (*XMapRaised_dylibloader_wrapper_xlib)( Display*, Window); -int (*XMapSubwindows_dylibloader_wrapper_xlib)( Display*, Window); -int (*XMapWindow_dylibloader_wrapper_xlib)( Display*, Window); -int (*XMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*); -int (*XMaxCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XMinCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XMoveResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int); -int (*XMoveWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int); -int (*XNextEvent_dylibloader_wrapper_xlib)( Display*, XEvent*); -int (*XNoOp_dylibloader_wrapper_xlib)( Display*); -int (*XParseColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*); -int (*XParseGeometry_dylibloader_wrapper_xlib)(const char*, int*, int*, unsigned int*, unsigned int*); -int (*XPeekEvent_dylibloader_wrapper_xlib)( Display*, XEvent*); -int (*XPeekIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer); -int (*XPending_dylibloader_wrapper_xlib)( Display*); -int (*XPlanesOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XProtocolRevision_dylibloader_wrapper_xlib)( Display*); -int (*XProtocolVersion_dylibloader_wrapper_xlib)( Display*); -int (*XPutBackEvent_dylibloader_wrapper_xlib)( Display*, XEvent*); -int (*XPutImage_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int); -int (*XQLength_dylibloader_wrapper_xlib)( Display*); -int (*XQueryBestCursor_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -int (*XQueryBestSize_dylibloader_wrapper_xlib)( Display*, int, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -int (*XQueryBestStipple_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -int (*XQueryBestTile_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -int (*XQueryColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*); -int (*XQueryColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int); -int (*XQueryExtension_dylibloader_wrapper_xlib)( Display*,const char*, int*, int*, int*); -int (*XQueryKeymap_dylibloader_wrapper_xlib)( Display*, char [32]); -int (*XQueryPointer_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, int*, int*, int*, int*, unsigned int*); -int (*XQueryTextExtents_dylibloader_wrapper_xlib)( Display*, XID,const char*, int, int*, int*, int*, XCharStruct*); -int (*XQueryTextExtents16_dylibloader_wrapper_xlib)( Display*, XID,const XChar2b*, int, int*, int*, int*, XCharStruct*); -int (*XQueryTree_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, Window**, unsigned int*); -int (*XRaiseWindow_dylibloader_wrapper_xlib)( Display*, Window); -int (*XReadBitmapFile_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int*, unsigned int*, Pixmap*, int*, int*); -int (*XReadBitmapFileData_dylibloader_wrapper_xlib)(const char*, unsigned int*, unsigned int*, unsigned char**, int*, int*); -int (*XRebindKeysym_dylibloader_wrapper_xlib)( Display*, KeySym, KeySym*, int,const unsigned char*, int); -int (*XRecolorCursor_dylibloader_wrapper_xlib)( Display*, Cursor, XColor*, XColor*); -int (*XRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XMappingEvent*); -int (*XRemoveFromSaveSet_dylibloader_wrapper_xlib)( Display*, Window); -int (*XRemoveHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*); -int (*XRemoveHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int); -int (*XReparentWindow_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int); -int (*XResetScreenSaver_dylibloader_wrapper_xlib)( Display*); -int (*XResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, unsigned int); -int (*XRestackWindows_dylibloader_wrapper_xlib)( Display*, Window*, int); -int (*XRotateBuffers_dylibloader_wrapper_xlib)( Display*, int); -int (*XRotateWindowProperties_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int, int); -int (*XScreenCount_dylibloader_wrapper_xlib)( Display*); -int (*XSelectInput_dylibloader_wrapper_xlib)( Display*, Window, long); -int (*XSendEvent_dylibloader_wrapper_xlib)( Display*, Window, int, long, XEvent*); -int (*XSetAccessControl_dylibloader_wrapper_xlib)( Display*, int); -int (*XSetArcMode_dylibloader_wrapper_xlib)( Display*, GC, int); -int (*XSetBackground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long); -int (*XSetClipMask_dylibloader_wrapper_xlib)( Display*, GC, Pixmap); -int (*XSetClipOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int); -int (*XSetClipRectangles_dylibloader_wrapper_xlib)( Display*, GC, int, int, XRectangle*, int, int); -int (*XSetCloseDownMode_dylibloader_wrapper_xlib)( Display*, int); -int (*XSetCommand_dylibloader_wrapper_xlib)( Display*, Window, char**, int); -int (*XSetDashes_dylibloader_wrapper_xlib)( Display*, GC, int,const char*, int); -int (*XSetFillRule_dylibloader_wrapper_xlib)( Display*, GC, int); -int (*XSetFillStyle_dylibloader_wrapper_xlib)( Display*, GC, int); -int (*XSetFont_dylibloader_wrapper_xlib)( Display*, GC, Font); -int (*XSetFontPath_dylibloader_wrapper_xlib)( Display*, char**, int); -int (*XSetForeground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long); -int (*XSetFunction_dylibloader_wrapper_xlib)( Display*, GC, int); -int (*XSetGraphicsExposures_dylibloader_wrapper_xlib)( Display*, GC, int); -int (*XSetIconName_dylibloader_wrapper_xlib)( Display*, Window,const char*); -int (*XSetInputFocus_dylibloader_wrapper_xlib)( Display*, Window, int, Time); -int (*XSetLineAttributes_dylibloader_wrapper_xlib)( Display*, GC, unsigned int, int, int, int); -int (*XSetModifierMapping_dylibloader_wrapper_xlib)( Display*, XModifierKeymap*); -int (*XSetPlaneMask_dylibloader_wrapper_xlib)( Display*, GC, unsigned long); -int (*XSetPointerMapping_dylibloader_wrapper_xlib)( Display*,const unsigned char*, int); -int (*XSetScreenSaver_dylibloader_wrapper_xlib)( Display*, int, int, int, int); -int (*XSetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom, Window, Time); -int (*XSetState_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, unsigned long, int, unsigned long); -int (*XSetStipple_dylibloader_wrapper_xlib)( Display*, GC, Pixmap); -int (*XSetSubwindowMode_dylibloader_wrapper_xlib)( Display*, GC, int); -int (*XSetTSOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int); -int (*XSetTile_dylibloader_wrapper_xlib)( Display*, GC, Pixmap); -int (*XSetWindowBackground_dylibloader_wrapper_xlib)( Display*, Window, unsigned long); -int (*XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap); -int (*XSetWindowBorder_dylibloader_wrapper_xlib)( Display*, Window, unsigned long); -int (*XSetWindowBorderPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap); -int (*XSetWindowBorderWidth_dylibloader_wrapper_xlib)( Display*, Window, unsigned int); -int (*XSetWindowColormap_dylibloader_wrapper_xlib)( Display*, Window, Colormap); -int (*XStoreBuffer_dylibloader_wrapper_xlib)( Display*,const char*, int, int); -int (*XStoreBytes_dylibloader_wrapper_xlib)( Display*,const char*, int); -int (*XStoreColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*); -int (*XStoreColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int); -int (*XStoreName_dylibloader_wrapper_xlib)( Display*, Window,const char*); -int (*XStoreNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, unsigned long, int); -int (*XSync_dylibloader_wrapper_xlib)( Display*, int); -int (*XTextExtents_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int, int*, int*, int*, XCharStruct*); -int (*XTextExtents16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int, int*, int*, int*, XCharStruct*); -int (*XTextWidth_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int); -int (*XTextWidth16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int); -int (*XTranslateCoordinates_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, int*, int*, Window*); -int (*XUndefineCursor_dylibloader_wrapper_xlib)( Display*, Window); -int (*XUngrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window); -int (*XUngrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window); -int (*XUngrabKeyboard_dylibloader_wrapper_xlib)( Display*, Time); -int (*XUngrabPointer_dylibloader_wrapper_xlib)( Display*, Time); -int (*XUngrabServer_dylibloader_wrapper_xlib)( Display*); -int (*XUninstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap); -int (*XUnloadFont_dylibloader_wrapper_xlib)( Display*, Font); -int (*XUnmapSubwindows_dylibloader_wrapper_xlib)( Display*, Window); -int (*XUnmapWindow_dylibloader_wrapper_xlib)( Display*, Window); -int (*XVendorRelease_dylibloader_wrapper_xlib)( Display*); -int (*XWarpPointer_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, unsigned int, unsigned int, int, int); -int (*XWidthMMOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XWidthOfScreen_dylibloader_wrapper_xlib)( Screen*); -int (*XWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*); -int (*XWriteBitmapFile_dylibloader_wrapper_xlib)( Display*,const char*, Pixmap, unsigned int, unsigned int, int, int); -int (*XSupportsLocale_dylibloader_wrapper_xlib)( void); -char* (*XSetLocaleModifiers_dylibloader_wrapper_xlib)(const char*); -XOM (*XOpenOM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*,const char*,const char*); -int (*XCloseOM_dylibloader_wrapper_xlib)( XOM); -char* (*XSetOMValues_dylibloader_wrapper_xlib)( XOM,...); -char* (*XGetOMValues_dylibloader_wrapper_xlib)( XOM,...); -Display* (*XDisplayOfOM_dylibloader_wrapper_xlib)( XOM); -char* (*XLocaleOfOM_dylibloader_wrapper_xlib)( XOM); -XOC (*XCreateOC_dylibloader_wrapper_xlib)( XOM,...); -void (*XDestroyOC_dylibloader_wrapper_xlib)( XOC); -XOM (*XOMOfOC_dylibloader_wrapper_xlib)( XOC); -char* (*XSetOCValues_dylibloader_wrapper_xlib)( XOC,...); -char* (*XGetOCValues_dylibloader_wrapper_xlib)( XOC,...); -XFontSet (*XCreateFontSet_dylibloader_wrapper_xlib)( Display*,const char*, char***, int*, char**); -void (*XFreeFontSet_dylibloader_wrapper_xlib)( Display*, XFontSet); -int (*XFontsOfFontSet_dylibloader_wrapper_xlib)( XFontSet, XFontStruct***, char***); -char* (*XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib)( XFontSet); -char* (*XLocaleOfFontSet_dylibloader_wrapper_xlib)( XFontSet); -int (*XContextDependentDrawing_dylibloader_wrapper_xlib)( XFontSet); -int (*XDirectionalDependentDrawing_dylibloader_wrapper_xlib)( XFontSet); -int (*XContextualDrawing_dylibloader_wrapper_xlib)( XFontSet); -XFontSetExtents* (*XExtentsOfFontSet_dylibloader_wrapper_xlib)( XFontSet); -int (*XmbTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int); -int (*XwcTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int); -int (*Xutf8TextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int); -int (*XmbTextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*); -int (*XwcTextExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*); -int (*Xutf8TextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*); -int (*XmbTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*); -int (*XwcTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*); -int (*Xutf8TextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*); -void (*XmbDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int); -void (*XwcDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XwcTextItem*, int); -void (*Xutf8DrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int); -void (*XmbDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -void (*XwcDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int); -void (*Xutf8DrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -void (*XmbDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -void (*XwcDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int); -void (*Xutf8DrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -XIM (*XOpenIM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*); -int (*XCloseIM_dylibloader_wrapper_xlib)( XIM); -char* (*XGetIMValues_dylibloader_wrapper_xlib)( XIM,...); -char* (*XSetIMValues_dylibloader_wrapper_xlib)( XIM,...); -Display* (*XDisplayOfIM_dylibloader_wrapper_xlib)( XIM); -char* (*XLocaleOfIM_dylibloader_wrapper_xlib)( XIM); -XIC (*XCreateIC_dylibloader_wrapper_xlib)( XIM,...); -void (*XDestroyIC_dylibloader_wrapper_xlib)( XIC); -void (*XSetICFocus_dylibloader_wrapper_xlib)( XIC); -void (*XUnsetICFocus_dylibloader_wrapper_xlib)( XIC); -wchar_t* (*XwcResetIC_dylibloader_wrapper_xlib)( XIC); -char* (*XmbResetIC_dylibloader_wrapper_xlib)( XIC); -char* (*Xutf8ResetIC_dylibloader_wrapper_xlib)( XIC); -char* (*XSetICValues_dylibloader_wrapper_xlib)( XIC,...); -char* (*XGetICValues_dylibloader_wrapper_xlib)( XIC,...); -XIM (*XIMOfIC_dylibloader_wrapper_xlib)( XIC); -int (*XFilterEvent_dylibloader_wrapper_xlib)( XEvent*, Window); -int (*XmbLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*); -int (*XwcLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, wchar_t*, int, KeySym*, int*); -int (*Xutf8LookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*); -XVaNestedList (*XVaCreateNestedList_dylibloader_wrapper_xlib)( int,...); -int (*XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer); -int (*XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer); -int (*XInternalConnectionNumbers_dylibloader_wrapper_xlib)( Display*, int**, int*); -void (*XProcessInternalConnection_dylibloader_wrapper_xlib)( Display*, int); -int (*XAddConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer); -void (*XRemoveConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer); -void (*XSetAuthorization_dylibloader_wrapper_xlib)( char*, int, char*, int); -int (*_Xmbtowc_dylibloader_wrapper_xlib)( wchar_t*, char*, int); -int (*_Xwctomb_dylibloader_wrapper_xlib)( char*, wchar_t); -int (*XGetEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*); -void (*XFreeEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*); -XClassHint* (*XAllocClassHint_dylibloader_wrapper_xlib)( void); -XIconSize* (*XAllocIconSize_dylibloader_wrapper_xlib)( void); -XSizeHints* (*XAllocSizeHints_dylibloader_wrapper_xlib)( void); -XStandardColormap* (*XAllocStandardColormap_dylibloader_wrapper_xlib)( void); -XWMHints* (*XAllocWMHints_dylibloader_wrapper_xlib)( void); -int (*XClipBox_dylibloader_wrapper_xlib)( Region, XRectangle*); -Region (*XCreateRegion_dylibloader_wrapper_xlib)( void); -const char* (*XDefaultString_dylibloader_wrapper_xlib)( void); -int (*XDeleteContext_dylibloader_wrapper_xlib)( Display*, XID, XContext); -int (*XDestroyRegion_dylibloader_wrapper_xlib)( Region); -int (*XEmptyRegion_dylibloader_wrapper_xlib)( Region); -int (*XEqualRegion_dylibloader_wrapper_xlib)( Region, Region); -int (*XFindContext_dylibloader_wrapper_xlib)( Display*, XID, XContext, XPointer*); -int (*XGetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*); -int (*XGetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize**, int*); -int (*XGetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -int (*XGetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap**, int*, Atom); -int (*XGetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom); -int (*XGetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom); -int (*XGetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom); -XVisualInfo* (*XGetVisualInfo_dylibloader_wrapper_xlib)( Display*, long, XVisualInfo*, int*); -int (*XGetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -XWMHints* (*XGetWMHints_dylibloader_wrapper_xlib)( Display*, Window); -int (*XGetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -int (*XGetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -int (*XGetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*); -int (*XGetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*, Atom); -int (*XGetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -int (*XIntersectRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -void (*XConvertCase_dylibloader_wrapper_xlib)( KeySym, KeySym*, KeySym*); -int (*XLookupString_dylibloader_wrapper_xlib)( XKeyEvent*, char*, int, KeySym*, XComposeStatus*); -int (*XMatchVisualInfo_dylibloader_wrapper_xlib)( Display*, int, int, int, XVisualInfo*); -int (*XOffsetRegion_dylibloader_wrapper_xlib)( Region, int, int); -int (*XPointInRegion_dylibloader_wrapper_xlib)( Region, int, int); -Region (*XPolygonRegion_dylibloader_wrapper_xlib)( XPoint*, int, int); -int (*XRectInRegion_dylibloader_wrapper_xlib)( Region, int, int, unsigned int, unsigned int); -int (*XSaveContext_dylibloader_wrapper_xlib)( Display*, XID, XContext,const char*); -int (*XSetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*); -int (*XSetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize*, int); -int (*XSetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -void (*XSetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, int, Atom); -int (*XSetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom); -int (*XSetStandardProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, Pixmap, char**, int, XSizeHints*); -void (*XSetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom); -void (*XSetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -int (*XSetWMHints_dylibloader_wrapper_xlib)( Display*, Window, XWMHints*); -void (*XSetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -void (*XSetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -void (*XSetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -void (*XSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*); -void (*XmbSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*); -void (*Xutf8SetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*); -void (*XSetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom); -int (*XSetRegion_dylibloader_wrapper_xlib)( Display*, GC, Region); -void (*XSetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom); -int (*XSetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -int (*XShrinkRegion_dylibloader_wrapper_xlib)( Region, int, int); -int (*XStringListToTextProperty_dylibloader_wrapper_xlib)( char**, int, XTextProperty*); -int (*XSubtractRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -int (*XmbTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*); -int (*XwcTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, wchar_t**, int, XICCEncodingStyle, XTextProperty*); -int (*Xutf8TextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*); -void (*XwcFreeStringList_dylibloader_wrapper_xlib)( wchar_t**); -int (*XTextPropertyToStringList_dylibloader_wrapper_xlib)( XTextProperty*, char***, int*); -int (*XmbTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*); -int (*XwcTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, wchar_t***, int*); -int (*Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*); -int (*XUnionRectWithRegion_dylibloader_wrapper_xlib)( XRectangle*, Region, Region); -int (*XUnionRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -int (*XWMGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, XSizeHints*, int*, int*, int*, int*, int*); -int (*XXorRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -int (*XkbIgnoreExtension_dylibloader_wrapper_xlib)( int); -Display* (*XkbOpenDisplay_dylibloader_wrapper_xlib)( char*, int*, int*, int*, int*, int*); -int (*XkbQueryExtension_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*, int*); -int (*XkbUseExtension_dylibloader_wrapper_xlib)( Display*, int*, int*); -int (*XkbLibraryVersion_dylibloader_wrapper_xlib)( int*, int*); -unsigned int (*XkbSetXlibControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -unsigned int (*XkbGetXlibControls_dylibloader_wrapper_xlib)( Display*); -unsigned int (*XkbXlibControlsImplemented_dylibloader_wrapper_xlib)( void); -void (*XkbSetAtomFuncs_dylibloader_wrapper_xlib)( XkbInternAtomFunc, XkbGetAtomNameFunc); -KeySym (*XkbKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int); -unsigned int (*XkbKeysymToModifiers_dylibloader_wrapper_xlib)( Display*, KeySym); -int (*XkbLookupKeySym_dylibloader_wrapper_xlib)( Display*, KeyCode, unsigned int, unsigned int*, KeySym*); -int (*XkbLookupKeyBinding_dylibloader_wrapper_xlib)( Display*, KeySym, unsigned int, char*, int, int*); -int (*XkbTranslateKeyCode_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, unsigned int, unsigned int*, KeySym*); -int (*XkbTranslateKeySym_dylibloader_wrapper_xlib)( Display*, KeySym*, unsigned int, char*, int, int*); -int (*XkbSetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -int (*XkbGetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*); -int (*XkbChangeEnabledControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -int (*XkbDeviceBell_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom); -int (*XkbForceDeviceBell_dylibloader_wrapper_xlib)( Display*, int, int, int, int); -int (*XkbDeviceBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom); -int (*XkbBell_dylibloader_wrapper_xlib)( Display*, Window, int, Atom); -int (*XkbForceBell_dylibloader_wrapper_xlib)( Display*, int); -int (*XkbBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, Atom); -int (*XkbSelectEvents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -int (*XkbSelectEventDetails_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned long, unsigned long); -void (*XkbNoteMapChanges_dylibloader_wrapper_xlib)( XkbMapChangesPtr, XkbMapNotifyEvent*, unsigned int); -void (*XkbNoteNameChanges_dylibloader_wrapper_xlib)( XkbNameChangesPtr, XkbNamesNotifyEvent*, unsigned int); -int (*XkbGetIndicatorState_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*); -int (*XkbGetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -int (*XkbSetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -int (*XkbGetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int*, int*, XkbIndicatorMapPtr, int*); -int (*XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int*, int*, XkbIndicatorMapPtr, int*); -int (*XkbSetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int, int, int, XkbIndicatorMapPtr); -int (*XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int, int, int, XkbIndicatorMapPtr); -int (*XkbLockModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -int (*XkbLatchModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -int (*XkbLockGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -int (*XkbLatchGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -int (*XkbSetServerInternalMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -int (*XkbSetIgnoreLockMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -int (*XkbVirtualModsToReal_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int*); -int (*XkbComputeEffectiveMap_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned char*); -int (*XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -XkbDescPtr (*XkbAllocKeyboard_dylibloader_wrapper_xlib)( void); -void (*XkbFreeKeyboard_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -int (*XkbAllocClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int); -int (*XkbAllocServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int); -void (*XkbFreeClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -void (*XkbFreeServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -XkbKeyTypePtr (*XkbAddKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, Atom, int, int, int); -int (*XkbAllocIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr); -void (*XkbFreeIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr); -XkbDescPtr (*XkbGetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -int (*XkbGetUpdatedMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -int (*XkbGetMapChanges_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr); -int (*XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XkbMapNotifyEvent*); -int (*XkbGetKeyTypes_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -int (*XkbGetKeySyms_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -int (*XkbGetKeyActions_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -int (*XkbGetKeyBehaviors_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -int (*XkbGetVirtualMods_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -int (*XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -int (*XkbGetKeyModifierMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -int (*XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -int (*XkbAllocControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int); -void (*XkbFreeControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -int (*XkbGetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -int (*XkbSetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -void (*XkbNoteControlsChanges_dylibloader_wrapper_xlib)( XkbControlsChangesPtr, XkbControlsNotifyEvent*, unsigned int); -int (*XkbAllocCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int); -void (*XkbFreeCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -int (*XkbGetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -int (*XkbSetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr, int); -int (*XkbAllocNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int, int); -int (*XkbGetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -int (*XkbSetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, XkbDescPtr); -int (*XkbChangeNames_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbNameChangesPtr); -void (*XkbFreeNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -int (*XkbGetState_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbStatePtr); -int (*XkbSetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -int (*XkbChangeMap_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr); -int (*XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int, int*); -int (*XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int*); -int (*XkbSetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*); -int (*XkbGetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int*, unsigned int*); -int (*XkbSetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*); -int (*XkbGetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int*); -int (*XkbCopyKeyType_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr); -int (*XkbCopyKeyTypes_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr, int); -int (*XkbResizeKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, int, int); -KeySym* (*XkbResizeKeySyms_dylibloader_wrapper_xlib)( XkbDescPtr, int, int); -XkbAction* (*XkbResizeKeyActions_dylibloader_wrapper_xlib)( XkbDescPtr, int, int); -int (*XkbChangeTypesOfKey_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, unsigned int, int*, XkbMapChangesPtr); -int (*XkbChangeKeycodeRange_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, XkbChangesPtr); -XkbComponentListPtr (*XkbListComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, int*); -void (*XkbFreeComponentList_dylibloader_wrapper_xlib)( XkbComponentListPtr); -XkbDescPtr (*XkbGetKeyboard_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -XkbDescPtr (*XkbGetKeyboardByName_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, unsigned int, unsigned int, int); -int (*XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib)( XkbDescPtr, int, KeySym*, unsigned int, int*, KeySym*); -int (*XkbApplyCompatMapToKey_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, XkbChangesPtr); -int (*XkbUpdateMapFromCore_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, int, int, KeySym*, XkbChangesPtr); -XkbDeviceLedInfoPtr (*XkbAddDeviceLedInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, unsigned int); -int (*XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int); -XkbDeviceInfoPtr (*XkbAllocDeviceInfo_dylibloader_wrapper_xlib)( unsigned int, unsigned int, unsigned int); -void (*XkbFreeDeviceInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, int); -void (*XkbNoteDeviceChanges_dylibloader_wrapper_xlib)( XkbDeviceChangesPtr, XkbExtensionDeviceNotifyEvent*, unsigned int); -XkbDeviceInfoPtr (*XkbGetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int); -int (*XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr); -int (*XkbGetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, int, unsigned int, unsigned int); -int (*XkbGetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); -int (*XkbSetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDeviceInfoPtr); -int (*XkbChangeDeviceInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr); -int (*XkbSetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); -int (*XkbSetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int); -char (*XkbToControl_dylibloader_wrapper_xlib)( char); -int (*XkbSetDebuggingFlags_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, char*, unsigned int, unsigned int, unsigned int*, unsigned int*); -int (*XkbApplyVirtualModChanges_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, XkbChangesPtr); -int (*XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbAction*, unsigned int); -void (*XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned int, XkbChangesPtr); +int (*_Xmblen_dylibloader_wrapper_xlib)(char *, int); +XFontStruct *(*XLoadQueryFont_dylibloader_wrapper_xlib)(Display *, const char *); +XFontStruct *(*XQueryFont_dylibloader_wrapper_xlib)(Display *, XID); +XTimeCoord *(*XGetMotionEvents_dylibloader_wrapper_xlib)(Display *, Window, Time, Time, int *); +XModifierKeymap *(*XDeleteModifiermapEntry_dylibloader_wrapper_xlib)(XModifierKeymap *, KeyCode, int); +XModifierKeymap *(*XGetModifierMapping_dylibloader_wrapper_xlib)(Display *); +XModifierKeymap *(*XInsertModifiermapEntry_dylibloader_wrapper_xlib)(XModifierKeymap *, KeyCode, int); +XModifierKeymap *(*XNewModifiermap_dylibloader_wrapper_xlib)(int); +XImage *(*XCreateImage_dylibloader_wrapper_xlib)(Display *, Visual *, unsigned int, int, int, char *, unsigned int, unsigned int, int, int); +int (*XInitImage_dylibloader_wrapper_xlib)(XImage *); +XImage *(*XGetImage_dylibloader_wrapper_xlib)(Display *, Drawable, int, int, unsigned int, unsigned int, unsigned long, int); +XImage *(*XGetSubImage_dylibloader_wrapper_xlib)(Display *, Drawable, int, int, unsigned int, unsigned int, unsigned long, int, XImage *, int, int); +Display *(*XOpenDisplay_dylibloader_wrapper_xlib)(const char *); +void (*XrmInitialize_dylibloader_wrapper_xlib)(void); +char *(*XFetchBytes_dylibloader_wrapper_xlib)(Display *, int *); +char *(*XFetchBuffer_dylibloader_wrapper_xlib)(Display *, int *, int); +char *(*XGetAtomName_dylibloader_wrapper_xlib)(Display *, Atom); +int (*XGetAtomNames_dylibloader_wrapper_xlib)(Display *, Atom *, int, char **); +char *(*XGetDefault_dylibloader_wrapper_xlib)(Display *, const char *, const char *); +char *(*XDisplayName_dylibloader_wrapper_xlib)(const char *); +char *(*XKeysymToString_dylibloader_wrapper_xlib)(KeySym); +int (*(*XSynchronize_dylibloader_wrapper_xlib)(Display *, int))(Display *); +int (*(*XSetAfterFunction_dylibloader_wrapper_xlib)(Display *, int (*)(Display *)))(Display *); +Atom (*XInternAtom_dylibloader_wrapper_xlib)(Display *, const char *, int); +int (*XInternAtoms_dylibloader_wrapper_xlib)(Display *, char **, int, int, Atom *); +Colormap (*XCopyColormapAndFree_dylibloader_wrapper_xlib)(Display *, Colormap); +Colormap (*XCreateColormap_dylibloader_wrapper_xlib)(Display *, Window, Visual *, int); +Cursor (*XCreatePixmapCursor_dylibloader_wrapper_xlib)(Display *, Pixmap, Pixmap, XColor *, XColor *, unsigned int, unsigned int); +Cursor (*XCreateGlyphCursor_dylibloader_wrapper_xlib)(Display *, Font, Font, unsigned int, unsigned int, const XColor *, const XColor *); +Cursor (*XCreateFontCursor_dylibloader_wrapper_xlib)(Display *, unsigned int); +Font (*XLoadFont_dylibloader_wrapper_xlib)(Display *, const char *); +GC (*XCreateGC_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned long, XGCValues *); +GContext (*XGContextFromGC_dylibloader_wrapper_xlib)(GC); +void (*XFlushGC_dylibloader_wrapper_xlib)(Display *, GC); +Pixmap (*XCreatePixmap_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int); +Pixmap (*XCreateBitmapFromData_dylibloader_wrapper_xlib)(Display *, Drawable, const char *, unsigned int, unsigned int); +Pixmap (*XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib)(Display *, Drawable, char *, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int); +Window (*XCreateSimpleWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); +Window (*XGetSelectionOwner_dylibloader_wrapper_xlib)(Display *, Atom); +Window (*XCreateWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *); +Colormap *(*XListInstalledColormaps_dylibloader_wrapper_xlib)(Display *, Window, int *); +char **(*XListFonts_dylibloader_wrapper_xlib)(Display *, const char *, int, int *); +char **(*XListFontsWithInfo_dylibloader_wrapper_xlib)(Display *, const char *, int, int *, XFontStruct **); +char **(*XGetFontPath_dylibloader_wrapper_xlib)(Display *, int *); +char **(*XListExtensions_dylibloader_wrapper_xlib)(Display *, int *); +Atom *(*XListProperties_dylibloader_wrapper_xlib)(Display *, Window, int *); +XHostAddress *(*XListHosts_dylibloader_wrapper_xlib)(Display *, int *, int *); +KeySym (*XKeycodeToKeysym_dylibloader_wrapper_xlib)(Display *, KeyCode, int); +KeySym (*XLookupKeysym_dylibloader_wrapper_xlib)(XKeyEvent *, int); +KeySym *(*XGetKeyboardMapping_dylibloader_wrapper_xlib)(Display *, KeyCode, int, int *); +KeySym (*XStringToKeysym_dylibloader_wrapper_xlib)(const char *); +long (*XMaxRequestSize_dylibloader_wrapper_xlib)(Display *); +long (*XExtendedMaxRequestSize_dylibloader_wrapper_xlib)(Display *); +char *(*XResourceManagerString_dylibloader_wrapper_xlib)(Display *); +char *(*XScreenResourceString_dylibloader_wrapper_xlib)(Screen *); +unsigned long (*XDisplayMotionBufferSize_dylibloader_wrapper_xlib)(Display *); +VisualID (*XVisualIDFromVisual_dylibloader_wrapper_xlib)(Visual *); +int (*XInitThreads_dylibloader_wrapper_xlib)(void); +void (*XLockDisplay_dylibloader_wrapper_xlib)(Display *); +void (*XUnlockDisplay_dylibloader_wrapper_xlib)(Display *); +XExtCodes *(*XInitExtension_dylibloader_wrapper_xlib)(Display *, const char *); +XExtCodes *(*XAddExtension_dylibloader_wrapper_xlib)(Display *); +XExtData *(*XFindOnExtensionList_dylibloader_wrapper_xlib)(XExtData **, int); +XExtData **(*XEHeadOfExtensionList_dylibloader_wrapper_xlib)(XEDataObject); +Window (*XRootWindow_dylibloader_wrapper_xlib)(Display *, int); +Window (*XDefaultRootWindow_dylibloader_wrapper_xlib)(Display *); +Window (*XRootWindowOfScreen_dylibloader_wrapper_xlib)(Screen *); +Visual *(*XDefaultVisual_dylibloader_wrapper_xlib)(Display *, int); +Visual *(*XDefaultVisualOfScreen_dylibloader_wrapper_xlib)(Screen *); +GC (*XDefaultGC_dylibloader_wrapper_xlib)(Display *, int); +GC (*XDefaultGCOfScreen_dylibloader_wrapper_xlib)(Screen *); +unsigned long (*XBlackPixel_dylibloader_wrapper_xlib)(Display *, int); +unsigned long (*XWhitePixel_dylibloader_wrapper_xlib)(Display *, int); +unsigned long (*XAllPlanes_dylibloader_wrapper_xlib)(void); +unsigned long (*XBlackPixelOfScreen_dylibloader_wrapper_xlib)(Screen *); +unsigned long (*XWhitePixelOfScreen_dylibloader_wrapper_xlib)(Screen *); +unsigned long (*XNextRequest_dylibloader_wrapper_xlib)(Display *); +unsigned long (*XLastKnownRequestProcessed_dylibloader_wrapper_xlib)(Display *); +char *(*XServerVendor_dylibloader_wrapper_xlib)(Display *); +char *(*XDisplayString_dylibloader_wrapper_xlib)(Display *); +Colormap (*XDefaultColormap_dylibloader_wrapper_xlib)(Display *, int); +Colormap (*XDefaultColormapOfScreen_dylibloader_wrapper_xlib)(Screen *); +Display *(*XDisplayOfScreen_dylibloader_wrapper_xlib)(Screen *); +Screen *(*XScreenOfDisplay_dylibloader_wrapper_xlib)(Display *, int); +Screen *(*XDefaultScreenOfDisplay_dylibloader_wrapper_xlib)(Display *); +long (*XEventMaskOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XScreenNumberOfScreen_dylibloader_wrapper_xlib)(Screen *); +XErrorHandler (*XSetErrorHandler_dylibloader_wrapper_xlib)(XErrorHandler); +XIOErrorHandler (*XSetIOErrorHandler_dylibloader_wrapper_xlib)(XIOErrorHandler); +void (*XSetIOErrorExitHandler_dylibloader_wrapper_xlib)(Display *, XIOErrorExitHandler, void *); +XPixmapFormatValues *(*XListPixmapFormats_dylibloader_wrapper_xlib)(Display *, int *); +int *(*XListDepths_dylibloader_wrapper_xlib)(Display *, int, int *); +int (*XReconfigureWMWindow_dylibloader_wrapper_xlib)(Display *, Window, int, unsigned int, XWindowChanges *); +int (*XGetWMProtocols_dylibloader_wrapper_xlib)(Display *, Window, Atom **, int *); +int (*XSetWMProtocols_dylibloader_wrapper_xlib)(Display *, Window, Atom *, int); +int (*XIconifyWindow_dylibloader_wrapper_xlib)(Display *, Window, int); +int (*XWithdrawWindow_dylibloader_wrapper_xlib)(Display *, Window, int); +int (*XGetCommand_dylibloader_wrapper_xlib)(Display *, Window, char ***, int *); +int (*XGetWMColormapWindows_dylibloader_wrapper_xlib)(Display *, Window, Window **, int *); +int (*XSetWMColormapWindows_dylibloader_wrapper_xlib)(Display *, Window, Window *, int); +void (*XFreeStringList_dylibloader_wrapper_xlib)(char **); +int (*XSetTransientForHint_dylibloader_wrapper_xlib)(Display *, Window, Window); +int (*XActivateScreenSaver_dylibloader_wrapper_xlib)(Display *); +int (*XAddHost_dylibloader_wrapper_xlib)(Display *, XHostAddress *); +int (*XAddHosts_dylibloader_wrapper_xlib)(Display *, XHostAddress *, int); +int (*XAddToExtensionList_dylibloader_wrapper_xlib)(struct _XExtData **, XExtData *); +int (*XAddToSaveSet_dylibloader_wrapper_xlib)(Display *, Window); +int (*XAllocColor_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *); +int (*XAllocColorCells_dylibloader_wrapper_xlib)(Display *, Colormap, int, unsigned long *, unsigned int, unsigned long *, unsigned int); +int (*XAllocColorPlanes_dylibloader_wrapper_xlib)(Display *, Colormap, int, unsigned long *, int, int, int, int, unsigned long *, unsigned long *, unsigned long *); +int (*XAllocNamedColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, XColor *, XColor *); +int (*XAllowEvents_dylibloader_wrapper_xlib)(Display *, int, Time); +int (*XAutoRepeatOff_dylibloader_wrapper_xlib)(Display *); +int (*XAutoRepeatOn_dylibloader_wrapper_xlib)(Display *); +int (*XBell_dylibloader_wrapper_xlib)(Display *, int); +int (*XBitmapBitOrder_dylibloader_wrapper_xlib)(Display *); +int (*XBitmapPad_dylibloader_wrapper_xlib)(Display *); +int (*XBitmapUnit_dylibloader_wrapper_xlib)(Display *); +int (*XCellsOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XChangeActivePointerGrab_dylibloader_wrapper_xlib)(Display *, unsigned int, Cursor, Time); +int (*XChangeGC_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, XGCValues *); +int (*XChangeKeyboardControl_dylibloader_wrapper_xlib)(Display *, unsigned long, XKeyboardControl *); +int (*XChangeKeyboardMapping_dylibloader_wrapper_xlib)(Display *, int, int, KeySym *, int); +int (*XChangePointerControl_dylibloader_wrapper_xlib)(Display *, int, int, int, int, int); +int (*XChangeProperty_dylibloader_wrapper_xlib)(Display *, Window, Atom, Atom, int, int, const unsigned char *, int); +int (*XChangeSaveSet_dylibloader_wrapper_xlib)(Display *, Window, int); +int (*XChangeWindowAttributes_dylibloader_wrapper_xlib)(Display *, Window, unsigned long, XSetWindowAttributes *); +int (*XCheckIfEvent_dylibloader_wrapper_xlib)(Display *, XEvent *, int (*)(Display *, XEvent *, XPointer), XPointer); +int (*XCheckMaskEvent_dylibloader_wrapper_xlib)(Display *, long, XEvent *); +int (*XCheckTypedEvent_dylibloader_wrapper_xlib)(Display *, int, XEvent *); +int (*XCheckTypedWindowEvent_dylibloader_wrapper_xlib)(Display *, Window, int, XEvent *); +int (*XCheckWindowEvent_dylibloader_wrapper_xlib)(Display *, Window, long, XEvent *); +int (*XCirculateSubwindows_dylibloader_wrapper_xlib)(Display *, Window, int); +int (*XCirculateSubwindowsDown_dylibloader_wrapper_xlib)(Display *, Window); +int (*XCirculateSubwindowsUp_dylibloader_wrapper_xlib)(Display *, Window); +int (*XClearArea_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int, int); +int (*XClearWindow_dylibloader_wrapper_xlib)(Display *, Window); +int (*XCloseDisplay_dylibloader_wrapper_xlib)(Display *); +int (*XConfigureWindow_dylibloader_wrapper_xlib)(Display *, Window, unsigned int, XWindowChanges *); +int (*XConnectionNumber_dylibloader_wrapper_xlib)(Display *); +int (*XConvertSelection_dylibloader_wrapper_xlib)(Display *, Atom, Atom, Atom, Window, Time); +int (*XCopyArea_dylibloader_wrapper_xlib)(Display *, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int); +int (*XCopyGC_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, GC); +int (*XCopyPlane_dylibloader_wrapper_xlib)(Display *, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long); +int (*XDefaultDepth_dylibloader_wrapper_xlib)(Display *, int); +int (*XDefaultDepthOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XDefaultScreen_dylibloader_wrapper_xlib)(Display *); +int (*XDefineCursor_dylibloader_wrapper_xlib)(Display *, Window, Cursor); +int (*XDeleteProperty_dylibloader_wrapper_xlib)(Display *, Window, Atom); +int (*XDestroyWindow_dylibloader_wrapper_xlib)(Display *, Window); +int (*XDestroySubwindows_dylibloader_wrapper_xlib)(Display *, Window); +int (*XDoesBackingStore_dylibloader_wrapper_xlib)(Screen *); +int (*XDoesSaveUnders_dylibloader_wrapper_xlib)(Screen *); +int (*XDisableAccessControl_dylibloader_wrapper_xlib)(Display *); +int (*XDisplayCells_dylibloader_wrapper_xlib)(Display *, int); +int (*XDisplayHeight_dylibloader_wrapper_xlib)(Display *, int); +int (*XDisplayHeightMM_dylibloader_wrapper_xlib)(Display *, int); +int (*XDisplayKeycodes_dylibloader_wrapper_xlib)(Display *, int *, int *); +int (*XDisplayPlanes_dylibloader_wrapper_xlib)(Display *, int); +int (*XDisplayWidth_dylibloader_wrapper_xlib)(Display *, int); +int (*XDisplayWidthMM_dylibloader_wrapper_xlib)(Display *, int); +int (*XDrawArc_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int, int, int); +int (*XDrawArcs_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XArc *, int); +int (*XDrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const char *, int); +int (*XDrawImageString16_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const XChar2b *, int); +int (*XDrawLine_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, int, int); +int (*XDrawLines_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XPoint *, int, int); +int (*XDrawPoint_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int); +int (*XDrawPoints_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XPoint *, int, int); +int (*XDrawRectangle_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int); +int (*XDrawRectangles_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XRectangle *, int); +int (*XDrawSegments_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XSegment *, int); +int (*XDrawString_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const char *, int); +int (*XDrawString16_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const XChar2b *, int); +int (*XDrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XTextItem *, int); +int (*XDrawText16_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XTextItem16 *, int); +int (*XEnableAccessControl_dylibloader_wrapper_xlib)(Display *); +int (*XEventsQueued_dylibloader_wrapper_xlib)(Display *, int); +int (*XFetchName_dylibloader_wrapper_xlib)(Display *, Window, char **); +int (*XFillArc_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int, int, int); +int (*XFillArcs_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XArc *, int); +int (*XFillPolygon_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XPoint *, int, int, int); +int (*XFillRectangle_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int); +int (*XFillRectangles_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XRectangle *, int); +int (*XFlush_dylibloader_wrapper_xlib)(Display *); +int (*XForceScreenSaver_dylibloader_wrapper_xlib)(Display *, int); +int (*XFree_dylibloader_wrapper_xlib)(void *); +int (*XFreeColormap_dylibloader_wrapper_xlib)(Display *, Colormap); +int (*XFreeColors_dylibloader_wrapper_xlib)(Display *, Colormap, unsigned long *, int, unsigned long); +int (*XFreeCursor_dylibloader_wrapper_xlib)(Display *, Cursor); +int (*XFreeExtensionList_dylibloader_wrapper_xlib)(char **); +int (*XFreeFont_dylibloader_wrapper_xlib)(Display *, XFontStruct *); +int (*XFreeFontInfo_dylibloader_wrapper_xlib)(char **, XFontStruct *, int); +int (*XFreeFontNames_dylibloader_wrapper_xlib)(char **); +int (*XFreeFontPath_dylibloader_wrapper_xlib)(char **); +int (*XFreeGC_dylibloader_wrapper_xlib)(Display *, GC); +int (*XFreeModifiermap_dylibloader_wrapper_xlib)(XModifierKeymap *); +int (*XFreePixmap_dylibloader_wrapper_xlib)(Display *, Pixmap); +int (*XGeometry_dylibloader_wrapper_xlib)(Display *, int, const char *, const char *, unsigned int, unsigned int, unsigned int, int, int, int *, int *, int *, int *); +int (*XGetErrorDatabaseText_dylibloader_wrapper_xlib)(Display *, const char *, const char *, const char *, char *, int); +int (*XGetErrorText_dylibloader_wrapper_xlib)(Display *, int, char *, int); +int (*XGetFontProperty_dylibloader_wrapper_xlib)(XFontStruct *, Atom, unsigned long *); +int (*XGetGCValues_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, XGCValues *); +int (*XGetGeometry_dylibloader_wrapper_xlib)(Display *, Drawable, Window *, int *, int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *); +int (*XGetIconName_dylibloader_wrapper_xlib)(Display *, Window, char **); +int (*XGetInputFocus_dylibloader_wrapper_xlib)(Display *, Window *, int *); +int (*XGetKeyboardControl_dylibloader_wrapper_xlib)(Display *, XKeyboardState *); +int (*XGetPointerControl_dylibloader_wrapper_xlib)(Display *, int *, int *, int *); +int (*XGetPointerMapping_dylibloader_wrapper_xlib)(Display *, unsigned char *, int); +int (*XGetScreenSaver_dylibloader_wrapper_xlib)(Display *, int *, int *, int *, int *); +int (*XGetTransientForHint_dylibloader_wrapper_xlib)(Display *, Window, Window *); +int (*XGetWindowProperty_dylibloader_wrapper_xlib)(Display *, Window, Atom, long, long, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +int (*XGetWindowAttributes_dylibloader_wrapper_xlib)(Display *, Window, XWindowAttributes *); +int (*XGrabButton_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, Window, int, unsigned int, int, int, Window, Cursor); +int (*XGrabKey_dylibloader_wrapper_xlib)(Display *, int, unsigned int, Window, int, int, int); +int (*XGrabKeyboard_dylibloader_wrapper_xlib)(Display *, Window, int, int, int, Time); +int (*XGrabPointer_dylibloader_wrapper_xlib)(Display *, Window, int, unsigned int, int, int, Window, Cursor, Time); +int (*XGrabServer_dylibloader_wrapper_xlib)(Display *); +int (*XHeightMMOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XHeightOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XIfEvent_dylibloader_wrapper_xlib)(Display *, XEvent *, int (*)(Display *, XEvent *, XPointer), XPointer); +int (*XImageByteOrder_dylibloader_wrapper_xlib)(Display *); +int (*XInstallColormap_dylibloader_wrapper_xlib)(Display *, Colormap); +KeyCode (*XKeysymToKeycode_dylibloader_wrapper_xlib)(Display *, KeySym); +int (*XKillClient_dylibloader_wrapper_xlib)(Display *, XID); +int (*XLookupColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, XColor *, XColor *); +int (*XLowerWindow_dylibloader_wrapper_xlib)(Display *, Window); +int (*XMapRaised_dylibloader_wrapper_xlib)(Display *, Window); +int (*XMapSubwindows_dylibloader_wrapper_xlib)(Display *, Window); +int (*XMapWindow_dylibloader_wrapper_xlib)(Display *, Window); +int (*XMaskEvent_dylibloader_wrapper_xlib)(Display *, long, XEvent *); +int (*XMaxCmapsOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XMinCmapsOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XMoveResizeWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int); +int (*XMoveWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int); +int (*XNextEvent_dylibloader_wrapper_xlib)(Display *, XEvent *); +int (*XNoOp_dylibloader_wrapper_xlib)(Display *); +int (*XParseColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, XColor *); +int (*XParseGeometry_dylibloader_wrapper_xlib)(const char *, int *, int *, unsigned int *, unsigned int *); +int (*XPeekEvent_dylibloader_wrapper_xlib)(Display *, XEvent *); +int (*XPeekIfEvent_dylibloader_wrapper_xlib)(Display *, XEvent *, int (*)(Display *, XEvent *, XPointer), XPointer); +int (*XPending_dylibloader_wrapper_xlib)(Display *); +int (*XPlanesOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XProtocolRevision_dylibloader_wrapper_xlib)(Display *); +int (*XProtocolVersion_dylibloader_wrapper_xlib)(Display *); +int (*XPutBackEvent_dylibloader_wrapper_xlib)(Display *, XEvent *); +int (*XPutImage_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XImage *, int, int, int, int, unsigned int, unsigned int); +int (*XQLength_dylibloader_wrapper_xlib)(Display *); +int (*XQueryBestCursor_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +int (*XQueryBestSize_dylibloader_wrapper_xlib)(Display *, int, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +int (*XQueryBestStipple_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +int (*XQueryBestTile_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +int (*XQueryColor_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *); +int (*XQueryColors_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *, int); +int (*XQueryExtension_dylibloader_wrapper_xlib)(Display *, const char *, int *, int *, int *); +int (*XQueryKeymap_dylibloader_wrapper_xlib)(Display *, char [32]); +int (*XQueryPointer_dylibloader_wrapper_xlib)(Display *, Window, Window *, Window *, int *, int *, int *, int *, unsigned int *); +int (*XQueryTextExtents_dylibloader_wrapper_xlib)(Display *, XID, const char *, int, int *, int *, int *, XCharStruct *); +int (*XQueryTextExtents16_dylibloader_wrapper_xlib)(Display *, XID, const XChar2b *, int, int *, int *, int *, XCharStruct *); +int (*XQueryTree_dylibloader_wrapper_xlib)(Display *, Window, Window *, Window *, Window **, unsigned int *); +int (*XRaiseWindow_dylibloader_wrapper_xlib)(Display *, Window); +int (*XReadBitmapFile_dylibloader_wrapper_xlib)(Display *, Drawable, const char *, unsigned int *, unsigned int *, Pixmap *, int *, int *); +int (*XReadBitmapFileData_dylibloader_wrapper_xlib)(const char *, unsigned int *, unsigned int *, unsigned char **, int *, int *); +int (*XRebindKeysym_dylibloader_wrapper_xlib)(Display *, KeySym, KeySym *, int, const unsigned char *, int); +int (*XRecolorCursor_dylibloader_wrapper_xlib)(Display *, Cursor, XColor *, XColor *); +int (*XRefreshKeyboardMapping_dylibloader_wrapper_xlib)(XMappingEvent *); +int (*XRemoveFromSaveSet_dylibloader_wrapper_xlib)(Display *, Window); +int (*XRemoveHost_dylibloader_wrapper_xlib)(Display *, XHostAddress *); +int (*XRemoveHosts_dylibloader_wrapper_xlib)(Display *, XHostAddress *, int); +int (*XReparentWindow_dylibloader_wrapper_xlib)(Display *, Window, Window, int, int); +int (*XResetScreenSaver_dylibloader_wrapper_xlib)(Display *); +int (*XResizeWindow_dylibloader_wrapper_xlib)(Display *, Window, unsigned int, unsigned int); +int (*XRestackWindows_dylibloader_wrapper_xlib)(Display *, Window *, int); +int (*XRotateBuffers_dylibloader_wrapper_xlib)(Display *, int); +int (*XRotateWindowProperties_dylibloader_wrapper_xlib)(Display *, Window, Atom *, int, int); +int (*XScreenCount_dylibloader_wrapper_xlib)(Display *); +int (*XSelectInput_dylibloader_wrapper_xlib)(Display *, Window, long); +int (*XSendEvent_dylibloader_wrapper_xlib)(Display *, Window, int, long, XEvent *); +int (*XSetAccessControl_dylibloader_wrapper_xlib)(Display *, int); +int (*XSetArcMode_dylibloader_wrapper_xlib)(Display *, GC, int); +int (*XSetBackground_dylibloader_wrapper_xlib)(Display *, GC, unsigned long); +int (*XSetClipMask_dylibloader_wrapper_xlib)(Display *, GC, Pixmap); +int (*XSetClipOrigin_dylibloader_wrapper_xlib)(Display *, GC, int, int); +int (*XSetClipRectangles_dylibloader_wrapper_xlib)(Display *, GC, int, int, XRectangle *, int, int); +int (*XSetCloseDownMode_dylibloader_wrapper_xlib)(Display *, int); +int (*XSetCommand_dylibloader_wrapper_xlib)(Display *, Window, char **, int); +int (*XSetDashes_dylibloader_wrapper_xlib)(Display *, GC, int, const char *, int); +int (*XSetFillRule_dylibloader_wrapper_xlib)(Display *, GC, int); +int (*XSetFillStyle_dylibloader_wrapper_xlib)(Display *, GC, int); +int (*XSetFont_dylibloader_wrapper_xlib)(Display *, GC, Font); +int (*XSetFontPath_dylibloader_wrapper_xlib)(Display *, char **, int); +int (*XSetForeground_dylibloader_wrapper_xlib)(Display *, GC, unsigned long); +int (*XSetFunction_dylibloader_wrapper_xlib)(Display *, GC, int); +int (*XSetGraphicsExposures_dylibloader_wrapper_xlib)(Display *, GC, int); +int (*XSetIconName_dylibloader_wrapper_xlib)(Display *, Window, const char *); +int (*XSetInputFocus_dylibloader_wrapper_xlib)(Display *, Window, int, Time); +int (*XSetLineAttributes_dylibloader_wrapper_xlib)(Display *, GC, unsigned int, int, int, int); +int (*XSetModifierMapping_dylibloader_wrapper_xlib)(Display *, XModifierKeymap *); +int (*XSetPlaneMask_dylibloader_wrapper_xlib)(Display *, GC, unsigned long); +int (*XSetPointerMapping_dylibloader_wrapper_xlib)(Display *, const unsigned char *, int); +int (*XSetScreenSaver_dylibloader_wrapper_xlib)(Display *, int, int, int, int); +int (*XSetSelectionOwner_dylibloader_wrapper_xlib)(Display *, Atom, Window, Time); +int (*XSetState_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, unsigned long, int, unsigned long); +int (*XSetStipple_dylibloader_wrapper_xlib)(Display *, GC, Pixmap); +int (*XSetSubwindowMode_dylibloader_wrapper_xlib)(Display *, GC, int); +int (*XSetTSOrigin_dylibloader_wrapper_xlib)(Display *, GC, int, int); +int (*XSetTile_dylibloader_wrapper_xlib)(Display *, GC, Pixmap); +int (*XSetWindowBackground_dylibloader_wrapper_xlib)(Display *, Window, unsigned long); +int (*XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib)(Display *, Window, Pixmap); +int (*XSetWindowBorder_dylibloader_wrapper_xlib)(Display *, Window, unsigned long); +int (*XSetWindowBorderPixmap_dylibloader_wrapper_xlib)(Display *, Window, Pixmap); +int (*XSetWindowBorderWidth_dylibloader_wrapper_xlib)(Display *, Window, unsigned int); +int (*XSetWindowColormap_dylibloader_wrapper_xlib)(Display *, Window, Colormap); +int (*XStoreBuffer_dylibloader_wrapper_xlib)(Display *, const char *, int, int); +int (*XStoreBytes_dylibloader_wrapper_xlib)(Display *, const char *, int); +int (*XStoreColor_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *); +int (*XStoreColors_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *, int); +int (*XStoreName_dylibloader_wrapper_xlib)(Display *, Window, const char *); +int (*XStoreNamedColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, unsigned long, int); +int (*XSync_dylibloader_wrapper_xlib)(Display *, int); +int (*XTextExtents_dylibloader_wrapper_xlib)(XFontStruct *, const char *, int, int *, int *, int *, XCharStruct *); +int (*XTextExtents16_dylibloader_wrapper_xlib)(XFontStruct *, const XChar2b *, int, int *, int *, int *, XCharStruct *); +int (*XTextWidth_dylibloader_wrapper_xlib)(XFontStruct *, const char *, int); +int (*XTextWidth16_dylibloader_wrapper_xlib)(XFontStruct *, const XChar2b *, int); +int (*XTranslateCoordinates_dylibloader_wrapper_xlib)(Display *, Window, Window, int, int, int *, int *, Window *); +int (*XUndefineCursor_dylibloader_wrapper_xlib)(Display *, Window); +int (*XUngrabButton_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, Window); +int (*XUngrabKey_dylibloader_wrapper_xlib)(Display *, int, unsigned int, Window); +int (*XUngrabKeyboard_dylibloader_wrapper_xlib)(Display *, Time); +int (*XUngrabPointer_dylibloader_wrapper_xlib)(Display *, Time); +int (*XUngrabServer_dylibloader_wrapper_xlib)(Display *); +int (*XUninstallColormap_dylibloader_wrapper_xlib)(Display *, Colormap); +int (*XUnloadFont_dylibloader_wrapper_xlib)(Display *, Font); +int (*XUnmapSubwindows_dylibloader_wrapper_xlib)(Display *, Window); +int (*XUnmapWindow_dylibloader_wrapper_xlib)(Display *, Window); +int (*XVendorRelease_dylibloader_wrapper_xlib)(Display *); +int (*XWarpPointer_dylibloader_wrapper_xlib)(Display *, Window, Window, int, int, unsigned int, unsigned int, int, int); +int (*XWidthMMOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XWidthOfScreen_dylibloader_wrapper_xlib)(Screen *); +int (*XWindowEvent_dylibloader_wrapper_xlib)(Display *, Window, long, XEvent *); +int (*XWriteBitmapFile_dylibloader_wrapper_xlib)(Display *, const char *, Pixmap, unsigned int, unsigned int, int, int); +int (*XSupportsLocale_dylibloader_wrapper_xlib)(void); +char *(*XSetLocaleModifiers_dylibloader_wrapper_xlib)(const char *); +XOM (*XOpenOM_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, const char *, const char *); +int (*XCloseOM_dylibloader_wrapper_xlib)(XOM); +char *(*XSetOMValues_dylibloader_wrapper_xlib)(XOM, ...); +char *(*XGetOMValues_dylibloader_wrapper_xlib)(XOM, ...); +Display *(*XDisplayOfOM_dylibloader_wrapper_xlib)(XOM); +char *(*XLocaleOfOM_dylibloader_wrapper_xlib)(XOM); +XOC (*XCreateOC_dylibloader_wrapper_xlib)(XOM, ...); +void (*XDestroyOC_dylibloader_wrapper_xlib)(XOC); +XOM (*XOMOfOC_dylibloader_wrapper_xlib)(XOC); +char *(*XSetOCValues_dylibloader_wrapper_xlib)(XOC, ...); +char *(*XGetOCValues_dylibloader_wrapper_xlib)(XOC, ...); +XFontSet (*XCreateFontSet_dylibloader_wrapper_xlib)(Display *, const char *, char ***, int *, char **); +void (*XFreeFontSet_dylibloader_wrapper_xlib)(Display *, XFontSet); +int (*XFontsOfFontSet_dylibloader_wrapper_xlib)(XFontSet, XFontStruct ***, char ***); +char *(*XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib)(XFontSet); +char *(*XLocaleOfFontSet_dylibloader_wrapper_xlib)(XFontSet); +int (*XContextDependentDrawing_dylibloader_wrapper_xlib)(XFontSet); +int (*XDirectionalDependentDrawing_dylibloader_wrapper_xlib)(XFontSet); +int (*XContextualDrawing_dylibloader_wrapper_xlib)(XFontSet); +XFontSetExtents *(*XExtentsOfFontSet_dylibloader_wrapper_xlib)(XFontSet); +int (*XmbTextEscapement_dylibloader_wrapper_xlib)(XFontSet, const char *, int); +int (*XwcTextEscapement_dylibloader_wrapper_xlib)(XFontSet, const wchar_t *, int); +int (*Xutf8TextEscapement_dylibloader_wrapper_xlib)(XFontSet, const char *, int); +int (*XmbTextExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *); +int (*XwcTextExtents_dylibloader_wrapper_xlib)(XFontSet, const wchar_t *, int, XRectangle *, XRectangle *); +int (*Xutf8TextExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *); +int (*XmbTextPerCharExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *, int, int *, XRectangle *, XRectangle *); +int (*XwcTextPerCharExtents_dylibloader_wrapper_xlib)(XFontSet, const wchar_t *, int, XRectangle *, XRectangle *, int, int *, XRectangle *, XRectangle *); +int (*Xutf8TextPerCharExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *, int, int *, XRectangle *, XRectangle *); +void (*XmbDrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XmbTextItem *, int); +void (*XwcDrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XwcTextItem *, int); +void (*Xutf8DrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XmbTextItem *, int); +void (*XmbDrawString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +void (*XwcDrawString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const wchar_t *, int); +void (*Xutf8DrawString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +void (*XmbDrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +void (*XwcDrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const wchar_t *, int); +void (*Xutf8DrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +XIM (*XOpenIM_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, char *, char *); +int (*XCloseIM_dylibloader_wrapper_xlib)(XIM); +char *(*XGetIMValues_dylibloader_wrapper_xlib)(XIM, ...); +char *(*XSetIMValues_dylibloader_wrapper_xlib)(XIM, ...); +Display *(*XDisplayOfIM_dylibloader_wrapper_xlib)(XIM); +char *(*XLocaleOfIM_dylibloader_wrapper_xlib)(XIM); +XIC (*XCreateIC_dylibloader_wrapper_xlib)(XIM, ...); +void (*XDestroyIC_dylibloader_wrapper_xlib)(XIC); +void (*XSetICFocus_dylibloader_wrapper_xlib)(XIC); +void (*XUnsetICFocus_dylibloader_wrapper_xlib)(XIC); +wchar_t *(*XwcResetIC_dylibloader_wrapper_xlib)(XIC); +char *(*XmbResetIC_dylibloader_wrapper_xlib)(XIC); +char *(*Xutf8ResetIC_dylibloader_wrapper_xlib)(XIC); +char *(*XSetICValues_dylibloader_wrapper_xlib)(XIC, ...); +char *(*XGetICValues_dylibloader_wrapper_xlib)(XIC, ...); +XIM (*XIMOfIC_dylibloader_wrapper_xlib)(XIC); +int (*XFilterEvent_dylibloader_wrapper_xlib)(XEvent *, Window); +int (*XmbLookupString_dylibloader_wrapper_xlib)(XIC, XKeyPressedEvent *, char *, int, KeySym *, int *); +int (*XwcLookupString_dylibloader_wrapper_xlib)(XIC, XKeyPressedEvent *, wchar_t *, int, KeySym *, int *); +int (*Xutf8LookupString_dylibloader_wrapper_xlib)(XIC, XKeyPressedEvent *, char *, int, KeySym *, int *); +XVaNestedList (*XVaCreateNestedList_dylibloader_wrapper_xlib)(int, ...); +int (*XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, char *, char *, XIDProc, XPointer); +int (*XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, char *, char *, XIDProc, XPointer); +int (*XInternalConnectionNumbers_dylibloader_wrapper_xlib)(Display *, int **, int *); +void (*XProcessInternalConnection_dylibloader_wrapper_xlib)(Display *, int); +int (*XAddConnectionWatch_dylibloader_wrapper_xlib)(Display *, XConnectionWatchProc, XPointer); +void (*XRemoveConnectionWatch_dylibloader_wrapper_xlib)(Display *, XConnectionWatchProc, XPointer); +void (*XSetAuthorization_dylibloader_wrapper_xlib)(char *, int, char *, int); +int (*_Xmbtowc_dylibloader_wrapper_xlib)(wchar_t *, char *, int); +int (*_Xwctomb_dylibloader_wrapper_xlib)(char *, wchar_t); +int (*XGetEventData_dylibloader_wrapper_xlib)(Display *, XGenericEventCookie *); +void (*XFreeEventData_dylibloader_wrapper_xlib)(Display *, XGenericEventCookie *); +int (*XFreeThreads_dylibloader_wrapper_xlib)(void); +XClassHint *(*XAllocClassHint_dylibloader_wrapper_xlib)(void); +XIconSize *(*XAllocIconSize_dylibloader_wrapper_xlib)(void); +XSizeHints *(*XAllocSizeHints_dylibloader_wrapper_xlib)(void); +XStandardColormap *(*XAllocStandardColormap_dylibloader_wrapper_xlib)(void); +XWMHints *(*XAllocWMHints_dylibloader_wrapper_xlib)(void); +int (*XClipBox_dylibloader_wrapper_xlib)(Region, XRectangle *); +Region (*XCreateRegion_dylibloader_wrapper_xlib)(void); +const char *(*XDefaultString_dylibloader_wrapper_xlib)(void); +int (*XDeleteContext_dylibloader_wrapper_xlib)(Display *, XID, XContext); +int (*XDestroyRegion_dylibloader_wrapper_xlib)(Region); +int (*XEmptyRegion_dylibloader_wrapper_xlib)(Region); +int (*XEqualRegion_dylibloader_wrapper_xlib)(Region, Region); +int (*XFindContext_dylibloader_wrapper_xlib)(Display *, XID, XContext, XPointer *); +int (*XGetClassHint_dylibloader_wrapper_xlib)(Display *, Window, XClassHint *); +int (*XGetIconSizes_dylibloader_wrapper_xlib)(Display *, Window, XIconSize **, int *); +int (*XGetNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +int (*XGetRGBColormaps_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap **, int *, Atom); +int (*XGetSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, Atom); +int (*XGetStandardColormap_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap *, Atom); +int (*XGetTextProperty_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *, Atom); +XVisualInfo *(*XGetVisualInfo_dylibloader_wrapper_xlib)(Display *, long, XVisualInfo *, int *); +int (*XGetWMClientMachine_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +XWMHints *(*XGetWMHints_dylibloader_wrapper_xlib)(Display *, Window); +int (*XGetWMIconName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +int (*XGetWMName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +int (*XGetWMNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, long *); +int (*XGetWMSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, long *, Atom); +int (*XGetZoomHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +int (*XIntersectRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +void (*XConvertCase_dylibloader_wrapper_xlib)(KeySym, KeySym *, KeySym *); +int (*XLookupString_dylibloader_wrapper_xlib)(XKeyEvent *, char *, int, KeySym *, XComposeStatus *); +int (*XMatchVisualInfo_dylibloader_wrapper_xlib)(Display *, int, int, int, XVisualInfo *); +int (*XOffsetRegion_dylibloader_wrapper_xlib)(Region, int, int); +int (*XPointInRegion_dylibloader_wrapper_xlib)(Region, int, int); +Region (*XPolygonRegion_dylibloader_wrapper_xlib)(XPoint *, int, int); +int (*XRectInRegion_dylibloader_wrapper_xlib)(Region, int, int, unsigned int, unsigned int); +int (*XSaveContext_dylibloader_wrapper_xlib)(Display *, XID, XContext, const char *); +int (*XSetClassHint_dylibloader_wrapper_xlib)(Display *, Window, XClassHint *); +int (*XSetIconSizes_dylibloader_wrapper_xlib)(Display *, Window, XIconSize *, int); +int (*XSetNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +void (*XSetRGBColormaps_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap *, int, Atom); +int (*XSetSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, Atom); +int (*XSetStandardProperties_dylibloader_wrapper_xlib)(Display *, Window, const char *, const char *, Pixmap, char **, int, XSizeHints *); +void (*XSetTextProperty_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *, Atom); +void (*XSetWMClientMachine_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +int (*XSetWMHints_dylibloader_wrapper_xlib)(Display *, Window, XWMHints *); +void (*XSetWMIconName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +void (*XSetWMName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +void (*XSetWMNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +void (*XSetWMProperties_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *, XTextProperty *, char **, int, XSizeHints *, XWMHints *, XClassHint *); +void (*XmbSetWMProperties_dylibloader_wrapper_xlib)(Display *, Window, const char *, const char *, char **, int, XSizeHints *, XWMHints *, XClassHint *); +void (*Xutf8SetWMProperties_dylibloader_wrapper_xlib)(Display *, Window, const char *, const char *, char **, int, XSizeHints *, XWMHints *, XClassHint *); +void (*XSetWMSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, Atom); +int (*XSetRegion_dylibloader_wrapper_xlib)(Display *, GC, Region); +void (*XSetStandardColormap_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap *, Atom); +int (*XSetZoomHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +int (*XShrinkRegion_dylibloader_wrapper_xlib)(Region, int, int); +int (*XStringListToTextProperty_dylibloader_wrapper_xlib)(char **, int, XTextProperty *); +int (*XSubtractRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +int (*XmbTextListToTextProperty_dylibloader_wrapper_xlib)(Display *, char **, int, XICCEncodingStyle, XTextProperty *); +int (*XwcTextListToTextProperty_dylibloader_wrapper_xlib)(Display *, wchar_t **, int, XICCEncodingStyle, XTextProperty *); +int (*Xutf8TextListToTextProperty_dylibloader_wrapper_xlib)(Display *, char **, int, XICCEncodingStyle, XTextProperty *); +void (*XwcFreeStringList_dylibloader_wrapper_xlib)(wchar_t **); +int (*XTextPropertyToStringList_dylibloader_wrapper_xlib)(XTextProperty *, char ***, int *); +int (*XmbTextPropertyToTextList_dylibloader_wrapper_xlib)(Display *, const XTextProperty *, char ***, int *); +int (*XwcTextPropertyToTextList_dylibloader_wrapper_xlib)(Display *, const XTextProperty *, wchar_t ***, int *); +int (*Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib)(Display *, const XTextProperty *, char ***, int *); +int (*XUnionRectWithRegion_dylibloader_wrapper_xlib)(XRectangle *, Region, Region); +int (*XUnionRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +int (*XWMGeometry_dylibloader_wrapper_xlib)(Display *, int, const char *, const char *, unsigned int, XSizeHints *, int *, int *, int *, int *, int *); +int (*XXorRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +int (*XkbIgnoreExtension_dylibloader_wrapper_xlib)(int); +Display *(*XkbOpenDisplay_dylibloader_wrapper_xlib)(char *, int *, int *, int *, int *, int *); +int (*XkbQueryExtension_dylibloader_wrapper_xlib)(Display *, int *, int *, int *, int *, int *); +int (*XkbUseExtension_dylibloader_wrapper_xlib)(Display *, int *, int *); +int (*XkbLibraryVersion_dylibloader_wrapper_xlib)(int *, int *); +unsigned int (*XkbSetXlibControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +unsigned int (*XkbGetXlibControls_dylibloader_wrapper_xlib)(Display *); +unsigned int (*XkbXlibControlsImplemented_dylibloader_wrapper_xlib)(void); +void (*XkbSetAtomFuncs_dylibloader_wrapper_xlib)(XkbInternAtomFunc, XkbGetAtomNameFunc); +KeySym (*XkbKeycodeToKeysym_dylibloader_wrapper_xlib)(Display *, KeyCode, int, int); +unsigned int (*XkbKeysymToModifiers_dylibloader_wrapper_xlib)(Display *, KeySym); +int (*XkbLookupKeySym_dylibloader_wrapper_xlib)(Display *, KeyCode, unsigned int, unsigned int *, KeySym *); +int (*XkbLookupKeyBinding_dylibloader_wrapper_xlib)(Display *, KeySym, unsigned int, char *, int, int *); +int (*XkbTranslateKeyCode_dylibloader_wrapper_xlib)(XkbDescPtr, KeyCode, unsigned int, unsigned int *, KeySym *); +int (*XkbTranslateKeySym_dylibloader_wrapper_xlib)(Display *, KeySym *, unsigned int, char *, int, int *); +int (*XkbSetAutoRepeatRate_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +int (*XkbGetAutoRepeatRate_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *, unsigned int *); +int (*XkbChangeEnabledControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +int (*XkbDeviceBell_dylibloader_wrapper_xlib)(Display *, Window, int, int, int, int, Atom); +int (*XkbForceDeviceBell_dylibloader_wrapper_xlib)(Display *, int, int, int, int); +int (*XkbDeviceBellEvent_dylibloader_wrapper_xlib)(Display *, Window, int, int, int, int, Atom); +int (*XkbBell_dylibloader_wrapper_xlib)(Display *, Window, int, Atom); +int (*XkbForceBell_dylibloader_wrapper_xlib)(Display *, int); +int (*XkbBellEvent_dylibloader_wrapper_xlib)(Display *, Window, int, Atom); +int (*XkbSelectEvents_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +int (*XkbSelectEventDetails_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned long, unsigned long); +void (*XkbNoteMapChanges_dylibloader_wrapper_xlib)(XkbMapChangesPtr, XkbMapNotifyEvent *, unsigned int); +void (*XkbNoteNameChanges_dylibloader_wrapper_xlib)(XkbNameChangesPtr, XkbNamesNotifyEvent *, unsigned int); +int (*XkbGetIndicatorState_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *); +int (*XkbGetIndicatorMap_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +int (*XkbSetIndicatorMap_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +int (*XkbGetNamedIndicator_dylibloader_wrapper_xlib)(Display *, Atom, int *, int *, XkbIndicatorMapPtr, int *); +int (*XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, Atom, int *, int *, XkbIndicatorMapPtr, int *); +int (*XkbSetNamedIndicator_dylibloader_wrapper_xlib)(Display *, Atom, int, int, int, XkbIndicatorMapPtr); +int (*XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, Atom, int, int, int, XkbIndicatorMapPtr); +int (*XkbLockModifiers_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +int (*XkbLatchModifiers_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +int (*XkbLockGroup_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +int (*XkbLatchGroup_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +int (*XkbSetServerInternalMods_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); +int (*XkbSetIgnoreLockMods_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); +int (*XkbVirtualModsToReal_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int *); +int (*XkbComputeEffectiveMap_dylibloader_wrapper_xlib)(XkbDescPtr, XkbKeyTypePtr, unsigned char *); +int (*XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +XkbDescPtr (*XkbAllocKeyboard_dylibloader_wrapper_xlib)(void); +void (*XkbFreeKeyboard_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +int (*XkbAllocClientMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int); +int (*XkbAllocServerMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int); +void (*XkbFreeClientMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +void (*XkbFreeServerMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +XkbKeyTypePtr (*XkbAddKeyType_dylibloader_wrapper_xlib)(XkbDescPtr, Atom, int, int, int); +int (*XkbAllocIndicatorMaps_dylibloader_wrapper_xlib)(XkbDescPtr); +void (*XkbFreeIndicatorMaps_dylibloader_wrapper_xlib)(XkbDescPtr); +XkbDescPtr (*XkbGetMap_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +int (*XkbGetUpdatedMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +int (*XkbGetMapChanges_dylibloader_wrapper_xlib)(Display *, XkbDescPtr, XkbMapChangesPtr); +int (*XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib)(XkbMapNotifyEvent *); +int (*XkbGetKeyTypes_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +int (*XkbGetKeySyms_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +int (*XkbGetKeyActions_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +int (*XkbGetKeyBehaviors_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +int (*XkbGetVirtualMods_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +int (*XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +int (*XkbGetKeyModifierMap_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +int (*XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +int (*XkbAllocControls_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int); +void (*XkbFreeControls_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +int (*XkbGetControls_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +int (*XkbSetControls_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +void (*XkbNoteControlsChanges_dylibloader_wrapper_xlib)(XkbControlsChangesPtr, XkbControlsNotifyEvent *, unsigned int); +int (*XkbAllocCompatMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int); +void (*XkbFreeCompatMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +int (*XkbGetCompatMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +int (*XkbSetCompatMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr, int); +int (*XkbAllocNames_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int, int); +int (*XkbGetNames_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +int (*XkbSetNames_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, XkbDescPtr); +int (*XkbChangeNames_dylibloader_wrapper_xlib)(Display *, XkbDescPtr, XkbNameChangesPtr); +void (*XkbFreeNames_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +int (*XkbGetState_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbStatePtr); +int (*XkbSetMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +int (*XkbChangeMap_dylibloader_wrapper_xlib)(Display *, XkbDescPtr, XkbMapChangesPtr); +int (*XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib)(Display *, int, int *); +int (*XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib)(Display *, int *); +int (*XkbSetAutoResetControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *, unsigned int *); +int (*XkbGetAutoResetControls_dylibloader_wrapper_xlib)(Display *, unsigned int *, unsigned int *); +int (*XkbSetPerClientControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *); +int (*XkbGetPerClientControls_dylibloader_wrapper_xlib)(Display *, unsigned int *); +int (*XkbCopyKeyType_dylibloader_wrapper_xlib)(XkbKeyTypePtr, XkbKeyTypePtr); +int (*XkbCopyKeyTypes_dylibloader_wrapper_xlib)(XkbKeyTypePtr, XkbKeyTypePtr, int); +int (*XkbResizeKeyType_dylibloader_wrapper_xlib)(XkbDescPtr, int, int, int, int); +KeySym *(*XkbResizeKeySyms_dylibloader_wrapper_xlib)(XkbDescPtr, int, int); +XkbAction *(*XkbResizeKeyActions_dylibloader_wrapper_xlib)(XkbDescPtr, int, int); +int (*XkbChangeTypesOfKey_dylibloader_wrapper_xlib)(XkbDescPtr, int, int, unsigned int, int *, XkbMapChangesPtr); +int (*XkbChangeKeycodeRange_dylibloader_wrapper_xlib)(XkbDescPtr, int, int, XkbChangesPtr); +XkbComponentListPtr (*XkbListComponents_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbComponentNamesPtr, int *); +void (*XkbFreeComponentList_dylibloader_wrapper_xlib)(XkbComponentListPtr); +XkbDescPtr (*XkbGetKeyboard_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +XkbDescPtr (*XkbGetKeyboardByName_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbComponentNamesPtr, unsigned int, unsigned int, int); +int (*XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib)(XkbDescPtr, int, KeySym *, unsigned int, int *, KeySym *); +int (*XkbApplyCompatMapToKey_dylibloader_wrapper_xlib)(XkbDescPtr, KeyCode, XkbChangesPtr); +int (*XkbUpdateMapFromCore_dylibloader_wrapper_xlib)(XkbDescPtr, KeyCode, int, int, KeySym *, XkbChangesPtr); +XkbDeviceLedInfoPtr (*XkbAddDeviceLedInfo_dylibloader_wrapper_xlib)(XkbDeviceInfoPtr, unsigned int, unsigned int); +int (*XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib)(XkbDeviceInfoPtr, unsigned int); +XkbDeviceInfoPtr (*XkbAllocDeviceInfo_dylibloader_wrapper_xlib)(unsigned int, unsigned int, unsigned int); +void (*XkbFreeDeviceInfo_dylibloader_wrapper_xlib)(XkbDeviceInfoPtr, unsigned int, int); +void (*XkbNoteDeviceChanges_dylibloader_wrapper_xlib)(XkbDeviceChangesPtr, XkbExtensionDeviceNotifyEvent *, unsigned int); +XkbDeviceInfoPtr (*XkbGetDeviceInfo_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, unsigned int); +int (*XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, XkbDeviceChangesPtr); +int (*XkbGetDeviceButtonActions_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, int, unsigned int, unsigned int); +int (*XkbGetDeviceLedInfo_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); +int (*XkbSetDeviceInfo_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDeviceInfoPtr); +int (*XkbChangeDeviceInfo_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, XkbDeviceChangesPtr); +int (*XkbSetDeviceLedInfo_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); +int (*XkbSetDeviceButtonActions_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, unsigned int, unsigned int); +char (*XkbToControl_dylibloader_wrapper_xlib)(char); +int (*XkbSetDebuggingFlags_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, char *, unsigned int, unsigned int, unsigned int *, unsigned int *); +int (*XkbApplyVirtualModChanges_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, XkbChangesPtr); +int (*XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib)(XkbDescPtr, XkbAction *, unsigned int); +void (*XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib)(XkbDescPtr, XkbKeyTypePtr, unsigned int, XkbChangesPtr); int initialize_xlib(int verbose) { void *handle; char *error; @@ -2548,6 +2548,14 @@ int initialize_xlib(int verbose) { fprintf(stderr, "%s\n", error); } } +// XSetIOErrorExitHandler + *(void **) (&XSetIOErrorExitHandler_dylibloader_wrapper_xlib) = dlsym(handle, "XSetIOErrorExitHandler"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } // XListPixmapFormats *(void **) (&XListPixmapFormats_dylibloader_wrapper_xlib) = dlsym(handle, "XListPixmapFormats"); if (verbose) { @@ -5132,6 +5140,14 @@ int initialize_xlib(int verbose) { fprintf(stderr, "%s\n", error); } } +// XFreeThreads + *(void **) (&XFreeThreads_dylibloader_wrapper_xlib) = dlsym(handle, "XFreeThreads"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } // XAllocClassHint *(void **) (&XAllocClassHint_dylibloader_wrapper_xlib) = dlsym(handle, "XAllocClassHint"); if (verbose) { diff --git a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h index 5bad21002d..3f556a7cda 100644 --- a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h +++ b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h @@ -2,16 +2,9 @@ #define DYLIBLOAD_WRAPPER_XLIB // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:26 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include "thirdparty/linuxbsd_headers/X11/Xlib.h" --sys-include "thirdparty/linuxbsd_headers/X11/Xutil.h" --sys-include "thirdparty/linuxbsd_headers/X11/XKBlib.h" --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c~ +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:36 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include thirdparty/linuxbsd_headers/X11/Xlib.h --sys-include thirdparty/linuxbsd_headers/X11/Xutil.h --sys-include thirdparty/linuxbsd_headers/X11/XKBlib.h --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c // -// NOTE: Generated from Xlib 1.6.9. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, the type of the third argument of -// XIfEvent, XPeekIfEvent and XCheckIfEvent had to be fixed as it wasn't parsed -// fully (it's a Bool function pointer, but it was just being parsed as an int -// pointer). - #include <stdint.h> #define _Xmblen _Xmblen_dylibloader_orig_xlib @@ -103,6 +96,7 @@ #define XScreenNumberOfScreen XScreenNumberOfScreen_dylibloader_orig_xlib #define XSetErrorHandler XSetErrorHandler_dylibloader_orig_xlib #define XSetIOErrorHandler XSetIOErrorHandler_dylibloader_orig_xlib +#define XSetIOErrorExitHandler XSetIOErrorExitHandler_dylibloader_orig_xlib #define XListPixmapFormats XListPixmapFormats_dylibloader_orig_xlib #define XListDepths XListDepths_dylibloader_orig_xlib #define XReconfigureWMWindow XReconfigureWMWindow_dylibloader_orig_xlib @@ -426,6 +420,7 @@ #define _Xwctomb _Xwctomb_dylibloader_orig_xlib #define XGetEventData XGetEventData_dylibloader_orig_xlib #define XFreeEventData XFreeEventData_dylibloader_orig_xlib +#define XFreeThreads XFreeThreads_dylibloader_orig_xlib #define XAllocClassHint XAllocClassHint_dylibloader_orig_xlib #define XAllocIconSize XAllocIconSize_dylibloader_orig_xlib #define XAllocSizeHints XAllocSizeHints_dylibloader_orig_xlib @@ -709,6 +704,7 @@ #undef XScreenNumberOfScreen #undef XSetErrorHandler #undef XSetIOErrorHandler +#undef XSetIOErrorExitHandler #undef XListPixmapFormats #undef XListDepths #undef XReconfigureWMWindow @@ -1032,6 +1028,7 @@ #undef _Xwctomb #undef XGetEventData #undef XFreeEventData +#undef XFreeThreads #undef XAllocClassHint #undef XAllocIconSize #undef XAllocSizeHints @@ -1315,6 +1312,7 @@ extern "C" { #define XScreenNumberOfScreen XScreenNumberOfScreen_dylibloader_wrapper_xlib #define XSetErrorHandler XSetErrorHandler_dylibloader_wrapper_xlib #define XSetIOErrorHandler XSetIOErrorHandler_dylibloader_wrapper_xlib +#define XSetIOErrorExitHandler XSetIOErrorExitHandler_dylibloader_wrapper_xlib #define XListPixmapFormats XListPixmapFormats_dylibloader_wrapper_xlib #define XListDepths XListDepths_dylibloader_wrapper_xlib #define XReconfigureWMWindow XReconfigureWMWindow_dylibloader_wrapper_xlib @@ -1638,6 +1636,7 @@ extern "C" { #define _Xwctomb _Xwctomb_dylibloader_wrapper_xlib #define XGetEventData XGetEventData_dylibloader_wrapper_xlib #define XFreeEventData XFreeEventData_dylibloader_wrapper_xlib +#define XFreeThreads XFreeThreads_dylibloader_wrapper_xlib #define XAllocClassHint XAllocClassHint_dylibloader_wrapper_xlib #define XAllocIconSize XAllocIconSize_dylibloader_wrapper_xlib #define XAllocSizeHints XAllocSizeHints_dylibloader_wrapper_xlib @@ -1829,609 +1828,611 @@ extern "C" { #define XkbApplyVirtualModChanges XkbApplyVirtualModChanges_dylibloader_wrapper_xlib #define XkbUpdateActionVirtualMods XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib #define XkbUpdateKeyTypeVirtualMods XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib -extern int (*_Xmblen_dylibloader_wrapper_xlib)( char*, int); -extern XFontStruct* (*XLoadQueryFont_dylibloader_wrapper_xlib)( Display*,const char*); -extern XFontStruct* (*XQueryFont_dylibloader_wrapper_xlib)( Display*, XID); -extern XTimeCoord* (*XGetMotionEvents_dylibloader_wrapper_xlib)( Display*, Window, Time, Time, int*); -extern XModifierKeymap* (*XDeleteModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int); -extern XModifierKeymap* (*XGetModifierMapping_dylibloader_wrapper_xlib)( Display*); -extern XModifierKeymap* (*XInsertModifiermapEntry_dylibloader_wrapper_xlib)( XModifierKeymap*, KeyCode, int); -extern XModifierKeymap* (*XNewModifiermap_dylibloader_wrapper_xlib)( int); -extern XImage* (*XCreateImage_dylibloader_wrapper_xlib)( Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int); -extern int (*XInitImage_dylibloader_wrapper_xlib)( XImage*); -extern XImage* (*XGetImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int); -extern XImage* (*XGetSubImage_dylibloader_wrapper_xlib)( Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int, XImage*, int, int); -extern Display* (*XOpenDisplay_dylibloader_wrapper_xlib)(const char*); -extern void (*XrmInitialize_dylibloader_wrapper_xlib)( void); -extern char* (*XFetchBytes_dylibloader_wrapper_xlib)( Display*, int*); -extern char* (*XFetchBuffer_dylibloader_wrapper_xlib)( Display*, int*, int); -extern char* (*XGetAtomName_dylibloader_wrapper_xlib)( Display*, Atom); -extern int (*XGetAtomNames_dylibloader_wrapper_xlib)( Display*, Atom*, int, char**); -extern char* (*XGetDefault_dylibloader_wrapper_xlib)( Display*,const char*,const char*); -extern char* (*XDisplayName_dylibloader_wrapper_xlib)(const char*); -extern char* (*XKeysymToString_dylibloader_wrapper_xlib)( KeySym); -extern int* (*XSynchronize_dylibloader_wrapper_xlib)( Display*, int); -extern int* (*XSetAfterFunction_dylibloader_wrapper_xlib)( Display*, int*); -extern Atom (*XInternAtom_dylibloader_wrapper_xlib)( Display*,const char*, int); -extern int (*XInternAtoms_dylibloader_wrapper_xlib)( Display*, char**, int, int, Atom*); -extern Colormap (*XCopyColormapAndFree_dylibloader_wrapper_xlib)( Display*, Colormap); -extern Colormap (*XCreateColormap_dylibloader_wrapper_xlib)( Display*, Window, Visual*, int); -extern Cursor (*XCreatePixmapCursor_dylibloader_wrapper_xlib)( Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int); -extern Cursor (*XCreateGlyphCursor_dylibloader_wrapper_xlib)( Display*, Font, Font, unsigned int, unsigned int,const XColor*,const XColor*); -extern Cursor (*XCreateFontCursor_dylibloader_wrapper_xlib)( Display*, unsigned int); -extern Font (*XLoadFont_dylibloader_wrapper_xlib)( Display*,const char*); -extern GC (*XCreateGC_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned long, XGCValues*); -extern GContext (*XGContextFromGC_dylibloader_wrapper_xlib)( GC); -extern void (*XFlushGC_dylibloader_wrapper_xlib)( Display*, GC); -extern Pixmap (*XCreatePixmap_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int); -extern Pixmap (*XCreateBitmapFromData_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int, unsigned int); -extern Pixmap (*XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib)( Display*, Drawable, char*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int); -extern Window (*XCreateSimpleWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); -extern Window (*XGetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom); -extern Window (*XCreateWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*); -extern Colormap* (*XListInstalledColormaps_dylibloader_wrapper_xlib)( Display*, Window, int*); -extern char** (*XListFonts_dylibloader_wrapper_xlib)( Display*,const char*, int, int*); -extern char** (*XListFontsWithInfo_dylibloader_wrapper_xlib)( Display*,const char*, int, int*, XFontStruct**); -extern char** (*XGetFontPath_dylibloader_wrapper_xlib)( Display*, int*); -extern char** (*XListExtensions_dylibloader_wrapper_xlib)( Display*, int*); -extern Atom* (*XListProperties_dylibloader_wrapper_xlib)( Display*, Window, int*); -extern XHostAddress* (*XListHosts_dylibloader_wrapper_xlib)( Display*, int*, int*); -extern KeySym (*XKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int); -extern KeySym (*XLookupKeysym_dylibloader_wrapper_xlib)( XKeyEvent*, int); -extern KeySym* (*XGetKeyboardMapping_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int*); -extern KeySym (*XStringToKeysym_dylibloader_wrapper_xlib)(const char*); -extern long (*XMaxRequestSize_dylibloader_wrapper_xlib)( Display*); -extern long (*XExtendedMaxRequestSize_dylibloader_wrapper_xlib)( Display*); -extern char* (*XResourceManagerString_dylibloader_wrapper_xlib)( Display*); -extern char* (*XScreenResourceString_dylibloader_wrapper_xlib)( Screen*); -extern unsigned long (*XDisplayMotionBufferSize_dylibloader_wrapper_xlib)( Display*); -extern VisualID (*XVisualIDFromVisual_dylibloader_wrapper_xlib)( Visual*); -extern int (*XInitThreads_dylibloader_wrapper_xlib)( void); -extern void (*XLockDisplay_dylibloader_wrapper_xlib)( Display*); -extern void (*XUnlockDisplay_dylibloader_wrapper_xlib)( Display*); -extern XExtCodes* (*XInitExtension_dylibloader_wrapper_xlib)( Display*,const char*); -extern XExtCodes* (*XAddExtension_dylibloader_wrapper_xlib)( Display*); -extern XExtData* (*XFindOnExtensionList_dylibloader_wrapper_xlib)( XExtData**, int); -extern XExtData** (*XEHeadOfExtensionList_dylibloader_wrapper_xlib)( XEDataObject); -extern Window (*XRootWindow_dylibloader_wrapper_xlib)( Display*, int); -extern Window (*XDefaultRootWindow_dylibloader_wrapper_xlib)( Display*); -extern Window (*XRootWindowOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern Visual* (*XDefaultVisual_dylibloader_wrapper_xlib)( Display*, int); -extern Visual* (*XDefaultVisualOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern GC (*XDefaultGC_dylibloader_wrapper_xlib)( Display*, int); -extern GC (*XDefaultGCOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern unsigned long (*XBlackPixel_dylibloader_wrapper_xlib)( Display*, int); -extern unsigned long (*XWhitePixel_dylibloader_wrapper_xlib)( Display*, int); -extern unsigned long (*XAllPlanes_dylibloader_wrapper_xlib)( void); -extern unsigned long (*XBlackPixelOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern unsigned long (*XWhitePixelOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern unsigned long (*XNextRequest_dylibloader_wrapper_xlib)( Display*); -extern unsigned long (*XLastKnownRequestProcessed_dylibloader_wrapper_xlib)( Display*); -extern char* (*XServerVendor_dylibloader_wrapper_xlib)( Display*); -extern char* (*XDisplayString_dylibloader_wrapper_xlib)( Display*); -extern Colormap (*XDefaultColormap_dylibloader_wrapper_xlib)( Display*, int); -extern Colormap (*XDefaultColormapOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern Display* (*XDisplayOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern Screen* (*XScreenOfDisplay_dylibloader_wrapper_xlib)( Display*, int); -extern Screen* (*XDefaultScreenOfDisplay_dylibloader_wrapper_xlib)( Display*); -extern long (*XEventMaskOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XScreenNumberOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern XErrorHandler (*XSetErrorHandler_dylibloader_wrapper_xlib)( XErrorHandler); -extern XIOErrorHandler (*XSetIOErrorHandler_dylibloader_wrapper_xlib)( XIOErrorHandler); -extern XPixmapFormatValues* (*XListPixmapFormats_dylibloader_wrapper_xlib)( Display*, int*); -extern int* (*XListDepths_dylibloader_wrapper_xlib)( Display*, int, int*); -extern int (*XReconfigureWMWindow_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, XWindowChanges*); -extern int (*XGetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom**, int*); -extern int (*XSetWMProtocols_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int); -extern int (*XIconifyWindow_dylibloader_wrapper_xlib)( Display*, Window, int); -extern int (*XWithdrawWindow_dylibloader_wrapper_xlib)( Display*, Window, int); -extern int (*XGetCommand_dylibloader_wrapper_xlib)( Display*, Window, char***, int*); -extern int (*XGetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window**, int*); -extern int (*XSetWMColormapWindows_dylibloader_wrapper_xlib)( Display*, Window, Window*, int); -extern void (*XFreeStringList_dylibloader_wrapper_xlib)( char**); -extern int (*XSetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window); -extern int (*XActivateScreenSaver_dylibloader_wrapper_xlib)( Display*); -extern int (*XAddHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*); -extern int (*XAddHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int); -extern int (*XAddToExtensionList_dylibloader_wrapper_xlib)(struct _XExtData**, XExtData*); -extern int (*XAddToSaveSet_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XAllocColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*); -extern int (*XAllocColorCells_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, unsigned int, unsigned long*, unsigned int); -extern int (*XAllocColorPlanes_dylibloader_wrapper_xlib)( Display*, Colormap, int, unsigned long*, int, int, int, int, unsigned long*, unsigned long*, unsigned long*); -extern int (*XAllocNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*); -extern int (*XAllowEvents_dylibloader_wrapper_xlib)( Display*, int, Time); -extern int (*XAutoRepeatOff_dylibloader_wrapper_xlib)( Display*); -extern int (*XAutoRepeatOn_dylibloader_wrapper_xlib)( Display*); -extern int (*XBell_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XBitmapBitOrder_dylibloader_wrapper_xlib)( Display*); -extern int (*XBitmapPad_dylibloader_wrapper_xlib)( Display*); -extern int (*XBitmapUnit_dylibloader_wrapper_xlib)( Display*); -extern int (*XCellsOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XChangeActivePointerGrab_dylibloader_wrapper_xlib)( Display*, unsigned int, Cursor, Time); -extern int (*XChangeGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*); -extern int (*XChangeKeyboardControl_dylibloader_wrapper_xlib)( Display*, unsigned long, XKeyboardControl*); -extern int (*XChangeKeyboardMapping_dylibloader_wrapper_xlib)( Display*, int, int, KeySym*, int); -extern int (*XChangePointerControl_dylibloader_wrapper_xlib)( Display*, int, int, int, int, int); -extern int (*XChangeProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, Atom, int, int,const unsigned char*, int); -extern int (*XChangeSaveSet_dylibloader_wrapper_xlib)( Display*, Window, int); -extern int (*XChangeWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, unsigned long, XSetWindowAttributes*); -extern int (*XCheckIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer); -extern int (*XCheckMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*); -extern int (*XCheckTypedEvent_dylibloader_wrapper_xlib)( Display*, int, XEvent*); -extern int (*XCheckTypedWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, int, XEvent*); -extern int (*XCheckWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*); -extern int (*XCirculateSubwindows_dylibloader_wrapper_xlib)( Display*, Window, int); -extern int (*XCirculateSubwindowsDown_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XCirculateSubwindowsUp_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XClearArea_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int, int); -extern int (*XClearWindow_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XCloseDisplay_dylibloader_wrapper_xlib)( Display*); -extern int (*XConfigureWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, XWindowChanges*); -extern int (*XConnectionNumber_dylibloader_wrapper_xlib)( Display*); -extern int (*XConvertSelection_dylibloader_wrapper_xlib)( Display*, Atom, Atom, Atom, Window, Time); -extern int (*XCopyArea_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int); -extern int (*XCopyGC_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, GC); -extern int (*XCopyPlane_dylibloader_wrapper_xlib)( Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long); -extern int (*XDefaultDepth_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XDefaultDepthOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XDefaultScreen_dylibloader_wrapper_xlib)( Display*); -extern int (*XDefineCursor_dylibloader_wrapper_xlib)( Display*, Window, Cursor); -extern int (*XDeleteProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom); -extern int (*XDestroyWindow_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XDestroySubwindows_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XDoesBackingStore_dylibloader_wrapper_xlib)( Screen*); -extern int (*XDoesSaveUnders_dylibloader_wrapper_xlib)( Screen*); -extern int (*XDisableAccessControl_dylibloader_wrapper_xlib)( Display*); -extern int (*XDisplayCells_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XDisplayHeight_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XDisplayHeightMM_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XDisplayKeycodes_dylibloader_wrapper_xlib)( Display*, int*, int*); -extern int (*XDisplayPlanes_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XDisplayWidth_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XDisplayWidthMM_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XDrawArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int); -extern int (*XDrawArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int); -extern int (*XDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int); -extern int (*XDrawImageString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int); -extern int (*XDrawLine_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, int, int); -extern int (*XDrawLines_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int); -extern int (*XDrawPoint_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int); -extern int (*XDrawPoints_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int); -extern int (*XDrawRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int); -extern int (*XDrawRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int); -extern int (*XDrawSegments_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XSegment*, int); -extern int (*XDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const char*, int); -extern int (*XDrawString16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int,const XChar2b*, int); -extern int (*XDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem*, int); -extern int (*XDrawText16_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XTextItem16*, int); -extern int (*XEnableAccessControl_dylibloader_wrapper_xlib)( Display*); -extern int (*XEventsQueued_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XFetchName_dylibloader_wrapper_xlib)( Display*, Window, char**); -extern int (*XFillArc_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int, int, int); -extern int (*XFillArcs_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XArc*, int); -extern int (*XFillPolygon_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XPoint*, int, int, int); -extern int (*XFillRectangle_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, unsigned int, unsigned int); -extern int (*XFillRectangles_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XRectangle*, int); -extern int (*XFlush_dylibloader_wrapper_xlib)( Display*); -extern int (*XForceScreenSaver_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XFree_dylibloader_wrapper_xlib)( void*); -extern int (*XFreeColormap_dylibloader_wrapper_xlib)( Display*, Colormap); -extern int (*XFreeColors_dylibloader_wrapper_xlib)( Display*, Colormap, unsigned long*, int, unsigned long); -extern int (*XFreeCursor_dylibloader_wrapper_xlib)( Display*, Cursor); -extern int (*XFreeExtensionList_dylibloader_wrapper_xlib)( char**); -extern int (*XFreeFont_dylibloader_wrapper_xlib)( Display*, XFontStruct*); -extern int (*XFreeFontInfo_dylibloader_wrapper_xlib)( char**, XFontStruct*, int); -extern int (*XFreeFontNames_dylibloader_wrapper_xlib)( char**); -extern int (*XFreeFontPath_dylibloader_wrapper_xlib)( char**); -extern int (*XFreeGC_dylibloader_wrapper_xlib)( Display*, GC); -extern int (*XFreeModifiermap_dylibloader_wrapper_xlib)( XModifierKeymap*); -extern int (*XFreePixmap_dylibloader_wrapper_xlib)( Display*, Pixmap); -extern int (*XGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, unsigned int, unsigned int, int, int, int*, int*, int*, int*); -extern int (*XGetErrorDatabaseText_dylibloader_wrapper_xlib)( Display*,const char*,const char*,const char*, char*, int); -extern int (*XGetErrorText_dylibloader_wrapper_xlib)( Display*, int, char*, int); -extern int (*XGetFontProperty_dylibloader_wrapper_xlib)( XFontStruct*, Atom, unsigned long*); -extern int (*XGetGCValues_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, XGCValues*); -extern int (*XGetGeometry_dylibloader_wrapper_xlib)( Display*, Drawable, Window*, int*, int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*); -extern int (*XGetIconName_dylibloader_wrapper_xlib)( Display*, Window, char**); -extern int (*XGetInputFocus_dylibloader_wrapper_xlib)( Display*, Window*, int*); -extern int (*XGetKeyboardControl_dylibloader_wrapper_xlib)( Display*, XKeyboardState*); -extern int (*XGetPointerControl_dylibloader_wrapper_xlib)( Display*, int*, int*, int*); -extern int (*XGetPointerMapping_dylibloader_wrapper_xlib)( Display*, unsigned char*, int); -extern int (*XGetScreenSaver_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*); -extern int (*XGetTransientForHint_dylibloader_wrapper_xlib)( Display*, Window, Window*); -extern int (*XGetWindowProperty_dylibloader_wrapper_xlib)( Display*, Window, Atom, long, long, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -extern int (*XGetWindowAttributes_dylibloader_wrapper_xlib)( Display*, Window, XWindowAttributes*); -extern int (*XGrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window, int, unsigned int, int, int, Window, Cursor); -extern int (*XGrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window, int, int, int); -extern int (*XGrabKeyboard_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, Time); -extern int (*XGrabPointer_dylibloader_wrapper_xlib)( Display*, Window, int, unsigned int, int, int, Window, Cursor, Time); -extern int (*XGrabServer_dylibloader_wrapper_xlib)( Display*); -extern int (*XHeightMMOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XHeightOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer); -extern int (*XImageByteOrder_dylibloader_wrapper_xlib)( Display*); -extern int (*XInstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap); -extern KeyCode (*XKeysymToKeycode_dylibloader_wrapper_xlib)( Display*, KeySym); -extern int (*XKillClient_dylibloader_wrapper_xlib)( Display*, XID); -extern int (*XLookupColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*, XColor*); -extern int (*XLowerWindow_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XMapRaised_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XMapSubwindows_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XMapWindow_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XMaskEvent_dylibloader_wrapper_xlib)( Display*, long, XEvent*); -extern int (*XMaxCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XMinCmapsOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XMoveResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int, unsigned int, unsigned int); -extern int (*XMoveWindow_dylibloader_wrapper_xlib)( Display*, Window, int, int); -extern int (*XNextEvent_dylibloader_wrapper_xlib)( Display*, XEvent*); -extern int (*XNoOp_dylibloader_wrapper_xlib)( Display*); -extern int (*XParseColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, XColor*); -extern int (*XParseGeometry_dylibloader_wrapper_xlib)(const char*, int*, int*, unsigned int*, unsigned int*); -extern int (*XPeekEvent_dylibloader_wrapper_xlib)( Display*, XEvent*); -extern int (*XPeekIfEvent_dylibloader_wrapper_xlib)( Display*, XEvent*, Bool (*) (Display*, XEvent*, XPointer), XPointer); -extern int (*XPending_dylibloader_wrapper_xlib)( Display*); -extern int (*XPlanesOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XProtocolRevision_dylibloader_wrapper_xlib)( Display*); -extern int (*XProtocolVersion_dylibloader_wrapper_xlib)( Display*); -extern int (*XPutBackEvent_dylibloader_wrapper_xlib)( Display*, XEvent*); -extern int (*XPutImage_dylibloader_wrapper_xlib)( Display*, Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int); -extern int (*XQLength_dylibloader_wrapper_xlib)( Display*); -extern int (*XQueryBestCursor_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -extern int (*XQueryBestSize_dylibloader_wrapper_xlib)( Display*, int, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -extern int (*XQueryBestStipple_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -extern int (*XQueryBestTile_dylibloader_wrapper_xlib)( Display*, Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*); -extern int (*XQueryColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*); -extern int (*XQueryColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int); -extern int (*XQueryExtension_dylibloader_wrapper_xlib)( Display*,const char*, int*, int*, int*); -extern int (*XQueryKeymap_dylibloader_wrapper_xlib)( Display*, char [32]); -extern int (*XQueryPointer_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, int*, int*, int*, int*, unsigned int*); -extern int (*XQueryTextExtents_dylibloader_wrapper_xlib)( Display*, XID,const char*, int, int*, int*, int*, XCharStruct*); -extern int (*XQueryTextExtents16_dylibloader_wrapper_xlib)( Display*, XID,const XChar2b*, int, int*, int*, int*, XCharStruct*); -extern int (*XQueryTree_dylibloader_wrapper_xlib)( Display*, Window, Window*, Window*, Window**, unsigned int*); -extern int (*XRaiseWindow_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XReadBitmapFile_dylibloader_wrapper_xlib)( Display*, Drawable,const char*, unsigned int*, unsigned int*, Pixmap*, int*, int*); -extern int (*XReadBitmapFileData_dylibloader_wrapper_xlib)(const char*, unsigned int*, unsigned int*, unsigned char**, int*, int*); -extern int (*XRebindKeysym_dylibloader_wrapper_xlib)( Display*, KeySym, KeySym*, int,const unsigned char*, int); -extern int (*XRecolorCursor_dylibloader_wrapper_xlib)( Display*, Cursor, XColor*, XColor*); -extern int (*XRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XMappingEvent*); -extern int (*XRemoveFromSaveSet_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XRemoveHost_dylibloader_wrapper_xlib)( Display*, XHostAddress*); -extern int (*XRemoveHosts_dylibloader_wrapper_xlib)( Display*, XHostAddress*, int); -extern int (*XReparentWindow_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int); -extern int (*XResetScreenSaver_dylibloader_wrapper_xlib)( Display*); -extern int (*XResizeWindow_dylibloader_wrapper_xlib)( Display*, Window, unsigned int, unsigned int); -extern int (*XRestackWindows_dylibloader_wrapper_xlib)( Display*, Window*, int); -extern int (*XRotateBuffers_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XRotateWindowProperties_dylibloader_wrapper_xlib)( Display*, Window, Atom*, int, int); -extern int (*XScreenCount_dylibloader_wrapper_xlib)( Display*); -extern int (*XSelectInput_dylibloader_wrapper_xlib)( Display*, Window, long); -extern int (*XSendEvent_dylibloader_wrapper_xlib)( Display*, Window, int, long, XEvent*); -extern int (*XSetAccessControl_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XSetArcMode_dylibloader_wrapper_xlib)( Display*, GC, int); -extern int (*XSetBackground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long); -extern int (*XSetClipMask_dylibloader_wrapper_xlib)( Display*, GC, Pixmap); -extern int (*XSetClipOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int); -extern int (*XSetClipRectangles_dylibloader_wrapper_xlib)( Display*, GC, int, int, XRectangle*, int, int); -extern int (*XSetCloseDownMode_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XSetCommand_dylibloader_wrapper_xlib)( Display*, Window, char**, int); -extern int (*XSetDashes_dylibloader_wrapper_xlib)( Display*, GC, int,const char*, int); -extern int (*XSetFillRule_dylibloader_wrapper_xlib)( Display*, GC, int); -extern int (*XSetFillStyle_dylibloader_wrapper_xlib)( Display*, GC, int); -extern int (*XSetFont_dylibloader_wrapper_xlib)( Display*, GC, Font); -extern int (*XSetFontPath_dylibloader_wrapper_xlib)( Display*, char**, int); -extern int (*XSetForeground_dylibloader_wrapper_xlib)( Display*, GC, unsigned long); -extern int (*XSetFunction_dylibloader_wrapper_xlib)( Display*, GC, int); -extern int (*XSetGraphicsExposures_dylibloader_wrapper_xlib)( Display*, GC, int); -extern int (*XSetIconName_dylibloader_wrapper_xlib)( Display*, Window,const char*); -extern int (*XSetInputFocus_dylibloader_wrapper_xlib)( Display*, Window, int, Time); -extern int (*XSetLineAttributes_dylibloader_wrapper_xlib)( Display*, GC, unsigned int, int, int, int); -extern int (*XSetModifierMapping_dylibloader_wrapper_xlib)( Display*, XModifierKeymap*); -extern int (*XSetPlaneMask_dylibloader_wrapper_xlib)( Display*, GC, unsigned long); -extern int (*XSetPointerMapping_dylibloader_wrapper_xlib)( Display*,const unsigned char*, int); -extern int (*XSetScreenSaver_dylibloader_wrapper_xlib)( Display*, int, int, int, int); -extern int (*XSetSelectionOwner_dylibloader_wrapper_xlib)( Display*, Atom, Window, Time); -extern int (*XSetState_dylibloader_wrapper_xlib)( Display*, GC, unsigned long, unsigned long, int, unsigned long); -extern int (*XSetStipple_dylibloader_wrapper_xlib)( Display*, GC, Pixmap); -extern int (*XSetSubwindowMode_dylibloader_wrapper_xlib)( Display*, GC, int); -extern int (*XSetTSOrigin_dylibloader_wrapper_xlib)( Display*, GC, int, int); -extern int (*XSetTile_dylibloader_wrapper_xlib)( Display*, GC, Pixmap); -extern int (*XSetWindowBackground_dylibloader_wrapper_xlib)( Display*, Window, unsigned long); -extern int (*XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap); -extern int (*XSetWindowBorder_dylibloader_wrapper_xlib)( Display*, Window, unsigned long); -extern int (*XSetWindowBorderPixmap_dylibloader_wrapper_xlib)( Display*, Window, Pixmap); -extern int (*XSetWindowBorderWidth_dylibloader_wrapper_xlib)( Display*, Window, unsigned int); -extern int (*XSetWindowColormap_dylibloader_wrapper_xlib)( Display*, Window, Colormap); -extern int (*XStoreBuffer_dylibloader_wrapper_xlib)( Display*,const char*, int, int); -extern int (*XStoreBytes_dylibloader_wrapper_xlib)( Display*,const char*, int); -extern int (*XStoreColor_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*); -extern int (*XStoreColors_dylibloader_wrapper_xlib)( Display*, Colormap, XColor*, int); -extern int (*XStoreName_dylibloader_wrapper_xlib)( Display*, Window,const char*); -extern int (*XStoreNamedColor_dylibloader_wrapper_xlib)( Display*, Colormap,const char*, unsigned long, int); -extern int (*XSync_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XTextExtents_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int, int*, int*, int*, XCharStruct*); -extern int (*XTextExtents16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int, int*, int*, int*, XCharStruct*); -extern int (*XTextWidth_dylibloader_wrapper_xlib)( XFontStruct*,const char*, int); -extern int (*XTextWidth16_dylibloader_wrapper_xlib)( XFontStruct*,const XChar2b*, int); -extern int (*XTranslateCoordinates_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, int*, int*, Window*); -extern int (*XUndefineCursor_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XUngrabButton_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, Window); -extern int (*XUngrabKey_dylibloader_wrapper_xlib)( Display*, int, unsigned int, Window); -extern int (*XUngrabKeyboard_dylibloader_wrapper_xlib)( Display*, Time); -extern int (*XUngrabPointer_dylibloader_wrapper_xlib)( Display*, Time); -extern int (*XUngrabServer_dylibloader_wrapper_xlib)( Display*); -extern int (*XUninstallColormap_dylibloader_wrapper_xlib)( Display*, Colormap); -extern int (*XUnloadFont_dylibloader_wrapper_xlib)( Display*, Font); -extern int (*XUnmapSubwindows_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XUnmapWindow_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XVendorRelease_dylibloader_wrapper_xlib)( Display*); -extern int (*XWarpPointer_dylibloader_wrapper_xlib)( Display*, Window, Window, int, int, unsigned int, unsigned int, int, int); -extern int (*XWidthMMOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XWidthOfScreen_dylibloader_wrapper_xlib)( Screen*); -extern int (*XWindowEvent_dylibloader_wrapper_xlib)( Display*, Window, long, XEvent*); -extern int (*XWriteBitmapFile_dylibloader_wrapper_xlib)( Display*,const char*, Pixmap, unsigned int, unsigned int, int, int); -extern int (*XSupportsLocale_dylibloader_wrapper_xlib)( void); -extern char* (*XSetLocaleModifiers_dylibloader_wrapper_xlib)(const char*); -extern XOM (*XOpenOM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*,const char*,const char*); -extern int (*XCloseOM_dylibloader_wrapper_xlib)( XOM); -extern char* (*XSetOMValues_dylibloader_wrapper_xlib)( XOM,...); -extern char* (*XGetOMValues_dylibloader_wrapper_xlib)( XOM,...); -extern Display* (*XDisplayOfOM_dylibloader_wrapper_xlib)( XOM); -extern char* (*XLocaleOfOM_dylibloader_wrapper_xlib)( XOM); -extern XOC (*XCreateOC_dylibloader_wrapper_xlib)( XOM,...); -extern void (*XDestroyOC_dylibloader_wrapper_xlib)( XOC); -extern XOM (*XOMOfOC_dylibloader_wrapper_xlib)( XOC); -extern char* (*XSetOCValues_dylibloader_wrapper_xlib)( XOC,...); -extern char* (*XGetOCValues_dylibloader_wrapper_xlib)( XOC,...); -extern XFontSet (*XCreateFontSet_dylibloader_wrapper_xlib)( Display*,const char*, char***, int*, char**); -extern void (*XFreeFontSet_dylibloader_wrapper_xlib)( Display*, XFontSet); -extern int (*XFontsOfFontSet_dylibloader_wrapper_xlib)( XFontSet, XFontStruct***, char***); -extern char* (*XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib)( XFontSet); -extern char* (*XLocaleOfFontSet_dylibloader_wrapper_xlib)( XFontSet); -extern int (*XContextDependentDrawing_dylibloader_wrapper_xlib)( XFontSet); -extern int (*XDirectionalDependentDrawing_dylibloader_wrapper_xlib)( XFontSet); -extern int (*XContextualDrawing_dylibloader_wrapper_xlib)( XFontSet); -extern XFontSetExtents* (*XExtentsOfFontSet_dylibloader_wrapper_xlib)( XFontSet); -extern int (*XmbTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int); -extern int (*XwcTextEscapement_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int); -extern int (*Xutf8TextEscapement_dylibloader_wrapper_xlib)( XFontSet,const char*, int); -extern int (*XmbTextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*); -extern int (*XwcTextExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*); -extern int (*Xutf8TextExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*); -extern int (*XmbTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*); -extern int (*XwcTextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const wchar_t*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*); -extern int (*Xutf8TextPerCharExtents_dylibloader_wrapper_xlib)( XFontSet,const char*, int, XRectangle*, XRectangle*, int, int*, XRectangle*, XRectangle*); -extern void (*XmbDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int); -extern void (*XwcDrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XwcTextItem*, int); -extern void (*Xutf8DrawText_dylibloader_wrapper_xlib)( Display*, Drawable, GC, int, int, XmbTextItem*, int); -extern void (*XmbDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -extern void (*XwcDrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int); -extern void (*Xutf8DrawString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -extern void (*XmbDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -extern void (*XwcDrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const wchar_t*, int); -extern void (*Xutf8DrawImageString_dylibloader_wrapper_xlib)( Display*, Drawable, XFontSet, GC, int, int,const char*, int); -extern XIM (*XOpenIM_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*); -extern int (*XCloseIM_dylibloader_wrapper_xlib)( XIM); -extern char* (*XGetIMValues_dylibloader_wrapper_xlib)( XIM,...); -extern char* (*XSetIMValues_dylibloader_wrapper_xlib)( XIM,...); -extern Display* (*XDisplayOfIM_dylibloader_wrapper_xlib)( XIM); -extern char* (*XLocaleOfIM_dylibloader_wrapper_xlib)( XIM); -extern XIC (*XCreateIC_dylibloader_wrapper_xlib)( XIM,...); -extern void (*XDestroyIC_dylibloader_wrapper_xlib)( XIC); -extern void (*XSetICFocus_dylibloader_wrapper_xlib)( XIC); -extern void (*XUnsetICFocus_dylibloader_wrapper_xlib)( XIC); -extern wchar_t* (*XwcResetIC_dylibloader_wrapper_xlib)( XIC); -extern char* (*XmbResetIC_dylibloader_wrapper_xlib)( XIC); -extern char* (*Xutf8ResetIC_dylibloader_wrapper_xlib)( XIC); -extern char* (*XSetICValues_dylibloader_wrapper_xlib)( XIC,...); -extern char* (*XGetICValues_dylibloader_wrapper_xlib)( XIC,...); -extern XIM (*XIMOfIC_dylibloader_wrapper_xlib)( XIC); -extern int (*XFilterEvent_dylibloader_wrapper_xlib)( XEvent*, Window); -extern int (*XmbLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*); -extern int (*XwcLookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, wchar_t*, int, KeySym*, int*); -extern int (*Xutf8LookupString_dylibloader_wrapper_xlib)( XIC, XKeyPressedEvent*, char*, int, KeySym*, int*); -extern XVaNestedList (*XVaCreateNestedList_dylibloader_wrapper_xlib)( int,...); -extern int (*XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer); -extern int (*XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib)( Display*,struct _XrmHashBucketRec*, char*, char*, XIDProc, XPointer); -extern int (*XInternalConnectionNumbers_dylibloader_wrapper_xlib)( Display*, int**, int*); -extern void (*XProcessInternalConnection_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XAddConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer); -extern void (*XRemoveConnectionWatch_dylibloader_wrapper_xlib)( Display*, XConnectionWatchProc, XPointer); -extern void (*XSetAuthorization_dylibloader_wrapper_xlib)( char*, int, char*, int); -extern int (*_Xmbtowc_dylibloader_wrapper_xlib)( wchar_t*, char*, int); -extern int (*_Xwctomb_dylibloader_wrapper_xlib)( char*, wchar_t); -extern int (*XGetEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*); -extern void (*XFreeEventData_dylibloader_wrapper_xlib)( Display*, XGenericEventCookie*); -extern XClassHint* (*XAllocClassHint_dylibloader_wrapper_xlib)( void); -extern XIconSize* (*XAllocIconSize_dylibloader_wrapper_xlib)( void); -extern XSizeHints* (*XAllocSizeHints_dylibloader_wrapper_xlib)( void); -extern XStandardColormap* (*XAllocStandardColormap_dylibloader_wrapper_xlib)( void); -extern XWMHints* (*XAllocWMHints_dylibloader_wrapper_xlib)( void); -extern int (*XClipBox_dylibloader_wrapper_xlib)( Region, XRectangle*); -extern Region (*XCreateRegion_dylibloader_wrapper_xlib)( void); -extern const char* (*XDefaultString_dylibloader_wrapper_xlib)( void); -extern int (*XDeleteContext_dylibloader_wrapper_xlib)( Display*, XID, XContext); -extern int (*XDestroyRegion_dylibloader_wrapper_xlib)( Region); -extern int (*XEmptyRegion_dylibloader_wrapper_xlib)( Region); -extern int (*XEqualRegion_dylibloader_wrapper_xlib)( Region, Region); -extern int (*XFindContext_dylibloader_wrapper_xlib)( Display*, XID, XContext, XPointer*); -extern int (*XGetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*); -extern int (*XGetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize**, int*); -extern int (*XGetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -extern int (*XGetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap**, int*, Atom); -extern int (*XGetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom); -extern int (*XGetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom); -extern int (*XGetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom); -extern XVisualInfo* (*XGetVisualInfo_dylibloader_wrapper_xlib)( Display*, long, XVisualInfo*, int*); -extern int (*XGetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -extern XWMHints* (*XGetWMHints_dylibloader_wrapper_xlib)( Display*, Window); -extern int (*XGetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -extern int (*XGetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -extern int (*XGetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*); -extern int (*XGetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, long*, Atom); -extern int (*XGetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -extern int (*XIntersectRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -extern void (*XConvertCase_dylibloader_wrapper_xlib)( KeySym, KeySym*, KeySym*); -extern int (*XLookupString_dylibloader_wrapper_xlib)( XKeyEvent*, char*, int, KeySym*, XComposeStatus*); -extern int (*XMatchVisualInfo_dylibloader_wrapper_xlib)( Display*, int, int, int, XVisualInfo*); -extern int (*XOffsetRegion_dylibloader_wrapper_xlib)( Region, int, int); -extern int (*XPointInRegion_dylibloader_wrapper_xlib)( Region, int, int); -extern Region (*XPolygonRegion_dylibloader_wrapper_xlib)( XPoint*, int, int); -extern int (*XRectInRegion_dylibloader_wrapper_xlib)( Region, int, int, unsigned int, unsigned int); -extern int (*XSaveContext_dylibloader_wrapper_xlib)( Display*, XID, XContext,const char*); -extern int (*XSetClassHint_dylibloader_wrapper_xlib)( Display*, Window, XClassHint*); -extern int (*XSetIconSizes_dylibloader_wrapper_xlib)( Display*, Window, XIconSize*, int); -extern int (*XSetNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -extern void (*XSetRGBColormaps_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, int, Atom); -extern int (*XSetSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom); -extern int (*XSetStandardProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, Pixmap, char**, int, XSizeHints*); -extern void (*XSetTextProperty_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, Atom); -extern void (*XSetWMClientMachine_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -extern int (*XSetWMHints_dylibloader_wrapper_xlib)( Display*, Window, XWMHints*); -extern void (*XSetWMIconName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -extern void (*XSetWMName_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*); -extern void (*XSetWMNormalHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -extern void (*XSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*); -extern void (*XmbSetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*); -extern void (*Xutf8SetWMProperties_dylibloader_wrapper_xlib)( Display*, Window,const char*,const char*, char**, int, XSizeHints*, XWMHints*, XClassHint*); -extern void (*XSetWMSizeHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*, Atom); -extern int (*XSetRegion_dylibloader_wrapper_xlib)( Display*, GC, Region); -extern void (*XSetStandardColormap_dylibloader_wrapper_xlib)( Display*, Window, XStandardColormap*, Atom); -extern int (*XSetZoomHints_dylibloader_wrapper_xlib)( Display*, Window, XSizeHints*); -extern int (*XShrinkRegion_dylibloader_wrapper_xlib)( Region, int, int); -extern int (*XStringListToTextProperty_dylibloader_wrapper_xlib)( char**, int, XTextProperty*); -extern int (*XSubtractRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -extern int (*XmbTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*); -extern int (*XwcTextListToTextProperty_dylibloader_wrapper_xlib)( Display*, wchar_t**, int, XICCEncodingStyle, XTextProperty*); -extern int (*Xutf8TextListToTextProperty_dylibloader_wrapper_xlib)( Display*, char**, int, XICCEncodingStyle, XTextProperty*); -extern void (*XwcFreeStringList_dylibloader_wrapper_xlib)( wchar_t**); -extern int (*XTextPropertyToStringList_dylibloader_wrapper_xlib)( XTextProperty*, char***, int*); -extern int (*XmbTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*); -extern int (*XwcTextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, wchar_t***, int*); -extern int (*Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib)( Display*,const XTextProperty*, char***, int*); -extern int (*XUnionRectWithRegion_dylibloader_wrapper_xlib)( XRectangle*, Region, Region); -extern int (*XUnionRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -extern int (*XWMGeometry_dylibloader_wrapper_xlib)( Display*, int,const char*,const char*, unsigned int, XSizeHints*, int*, int*, int*, int*, int*); -extern int (*XXorRegion_dylibloader_wrapper_xlib)( Region, Region, Region); -extern int (*XkbIgnoreExtension_dylibloader_wrapper_xlib)( int); -extern Display* (*XkbOpenDisplay_dylibloader_wrapper_xlib)( char*, int*, int*, int*, int*, int*); -extern int (*XkbQueryExtension_dylibloader_wrapper_xlib)( Display*, int*, int*, int*, int*, int*); -extern int (*XkbUseExtension_dylibloader_wrapper_xlib)( Display*, int*, int*); -extern int (*XkbLibraryVersion_dylibloader_wrapper_xlib)( int*, int*); -extern unsigned int (*XkbSetXlibControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -extern unsigned int (*XkbGetXlibControls_dylibloader_wrapper_xlib)( Display*); -extern unsigned int (*XkbXlibControlsImplemented_dylibloader_wrapper_xlib)( void); -extern void (*XkbSetAtomFuncs_dylibloader_wrapper_xlib)( XkbInternAtomFunc, XkbGetAtomNameFunc); -extern KeySym (*XkbKeycodeToKeysym_dylibloader_wrapper_xlib)( Display*, KeyCode, int, int); -extern unsigned int (*XkbKeysymToModifiers_dylibloader_wrapper_xlib)( Display*, KeySym); -extern int (*XkbLookupKeySym_dylibloader_wrapper_xlib)( Display*, KeyCode, unsigned int, unsigned int*, KeySym*); -extern int (*XkbLookupKeyBinding_dylibloader_wrapper_xlib)( Display*, KeySym, unsigned int, char*, int, int*); -extern int (*XkbTranslateKeyCode_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, unsigned int, unsigned int*, KeySym*); -extern int (*XkbTranslateKeySym_dylibloader_wrapper_xlib)( Display*, KeySym*, unsigned int, char*, int, int*); -extern int (*XkbSetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -extern int (*XkbGetAutoRepeatRate_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*); -extern int (*XkbChangeEnabledControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -extern int (*XkbDeviceBell_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom); -extern int (*XkbForceDeviceBell_dylibloader_wrapper_xlib)( Display*, int, int, int, int); -extern int (*XkbDeviceBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, int, int, int, Atom); -extern int (*XkbBell_dylibloader_wrapper_xlib)( Display*, Window, int, Atom); -extern int (*XkbForceBell_dylibloader_wrapper_xlib)( Display*, int); -extern int (*XkbBellEvent_dylibloader_wrapper_xlib)( Display*, Window, int, Atom); -extern int (*XkbSelectEvents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -extern int (*XkbSelectEventDetails_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned long, unsigned long); -extern void (*XkbNoteMapChanges_dylibloader_wrapper_xlib)( XkbMapChangesPtr, XkbMapNotifyEvent*, unsigned int); -extern void (*XkbNoteNameChanges_dylibloader_wrapper_xlib)( XkbNameChangesPtr, XkbNamesNotifyEvent*, unsigned int); -extern int (*XkbGetIndicatorState_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*); -extern int (*XkbGetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -extern int (*XkbSetIndicatorMap_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -extern int (*XkbGetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int*, int*, XkbIndicatorMapPtr, int*); -extern int (*XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int*, int*, XkbIndicatorMapPtr, int*); -extern int (*XkbSetNamedIndicator_dylibloader_wrapper_xlib)( Display*, Atom, int, int, int, XkbIndicatorMapPtr); -extern int (*XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, Atom, int, int, int, XkbIndicatorMapPtr); -extern int (*XkbLockModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -extern int (*XkbLatchModifiers_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int); -extern int (*XkbLockGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -extern int (*XkbLatchGroup_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -extern int (*XkbSetServerInternalMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -extern int (*XkbSetIgnoreLockMods_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -extern int (*XkbVirtualModsToReal_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int*); -extern int (*XkbComputeEffectiveMap_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned char*); -extern int (*XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -extern XkbDescPtr (*XkbAllocKeyboard_dylibloader_wrapper_xlib)( void); -extern void (*XkbFreeKeyboard_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -extern int (*XkbAllocClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int); -extern int (*XkbAllocServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int); -extern void (*XkbFreeClientMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -extern void (*XkbFreeServerMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -extern XkbKeyTypePtr (*XkbAddKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, Atom, int, int, int); -extern int (*XkbAllocIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr); -extern void (*XkbFreeIndicatorMaps_dylibloader_wrapper_xlib)( XkbDescPtr); -extern XkbDescPtr (*XkbGetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -extern int (*XkbGetUpdatedMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -extern int (*XkbGetMapChanges_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr); -extern int (*XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib)( XkbMapNotifyEvent*); -extern int (*XkbGetKeyTypes_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbGetKeySyms_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbGetKeyActions_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbGetKeyBehaviors_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbGetVirtualMods_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -extern int (*XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbGetKeyModifierMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbAllocControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int); -extern void (*XkbFreeControls_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -extern int (*XkbGetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -extern int (*XkbSetControls_dylibloader_wrapper_xlib)( Display*, unsigned long, XkbDescPtr); -extern void (*XkbNoteControlsChanges_dylibloader_wrapper_xlib)( XkbControlsChangesPtr, XkbControlsNotifyEvent*, unsigned int); -extern int (*XkbAllocCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, unsigned int); -extern void (*XkbFreeCompatMap_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -extern int (*XkbGetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -extern int (*XkbSetCompatMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr, int); -extern int (*XkbAllocNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int, int); -extern int (*XkbGetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -extern int (*XkbSetNames_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, XkbDescPtr); -extern int (*XkbChangeNames_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbNameChangesPtr); -extern void (*XkbFreeNames_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, int); -extern int (*XkbGetState_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbStatePtr); -extern int (*XkbSetMap_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDescPtr); -extern int (*XkbChangeMap_dylibloader_wrapper_xlib)( Display*, XkbDescPtr, XkbMapChangesPtr); -extern int (*XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int, int*); -extern int (*XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib)( Display*, int*); -extern int (*XkbSetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*, unsigned int*); -extern int (*XkbGetAutoResetControls_dylibloader_wrapper_xlib)( Display*, unsigned int*, unsigned int*); -extern int (*XkbSetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int*); -extern int (*XkbGetPerClientControls_dylibloader_wrapper_xlib)( Display*, unsigned int*); -extern int (*XkbCopyKeyType_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr); -extern int (*XkbCopyKeyTypes_dylibloader_wrapper_xlib)( XkbKeyTypePtr, XkbKeyTypePtr, int); -extern int (*XkbResizeKeyType_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, int, int); -extern KeySym* (*XkbResizeKeySyms_dylibloader_wrapper_xlib)( XkbDescPtr, int, int); -extern XkbAction* (*XkbResizeKeyActions_dylibloader_wrapper_xlib)( XkbDescPtr, int, int); -extern int (*XkbChangeTypesOfKey_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, unsigned int, int*, XkbMapChangesPtr); -extern int (*XkbChangeKeycodeRange_dylibloader_wrapper_xlib)( XkbDescPtr, int, int, XkbChangesPtr); -extern XkbComponentListPtr (*XkbListComponents_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, int*); -extern void (*XkbFreeComponentList_dylibloader_wrapper_xlib)( XkbComponentListPtr); -extern XkbDescPtr (*XkbGetKeyboard_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int); -extern XkbDescPtr (*XkbGetKeyboardByName_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbComponentNamesPtr, unsigned int, unsigned int, int); -extern int (*XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib)( XkbDescPtr, int, KeySym*, unsigned int, int*, KeySym*); -extern int (*XkbApplyCompatMapToKey_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, XkbChangesPtr); -extern int (*XkbUpdateMapFromCore_dylibloader_wrapper_xlib)( XkbDescPtr, KeyCode, int, int, KeySym*, XkbChangesPtr); -extern XkbDeviceLedInfoPtr (*XkbAddDeviceLedInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, unsigned int); -extern int (*XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int); -extern XkbDeviceInfoPtr (*XkbAllocDeviceInfo_dylibloader_wrapper_xlib)( unsigned int, unsigned int, unsigned int); -extern void (*XkbFreeDeviceInfo_dylibloader_wrapper_xlib)( XkbDeviceInfoPtr, unsigned int, int); -extern void (*XkbNoteDeviceChanges_dylibloader_wrapper_xlib)( XkbDeviceChangesPtr, XkbExtensionDeviceNotifyEvent*, unsigned int); -extern XkbDeviceInfoPtr (*XkbGetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, unsigned int, unsigned int); -extern int (*XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr); -extern int (*XkbGetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, int, unsigned int, unsigned int); -extern int (*XkbGetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); -extern int (*XkbSetDeviceInfo_dylibloader_wrapper_xlib)( Display*, unsigned int, XkbDeviceInfoPtr); -extern int (*XkbChangeDeviceInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, XkbDeviceChangesPtr); -extern int (*XkbSetDeviceLedInfo_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); -extern int (*XkbSetDeviceButtonActions_dylibloader_wrapper_xlib)( Display*, XkbDeviceInfoPtr, unsigned int, unsigned int); -extern char (*XkbToControl_dylibloader_wrapper_xlib)( char); -extern int (*XkbSetDebuggingFlags_dylibloader_wrapper_xlib)( Display*, unsigned int, unsigned int, char*, unsigned int, unsigned int, unsigned int*, unsigned int*); -extern int (*XkbApplyVirtualModChanges_dylibloader_wrapper_xlib)( XkbDescPtr, unsigned int, XkbChangesPtr); -extern int (*XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbAction*, unsigned int); -extern void (*XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib)( XkbDescPtr, XkbKeyTypePtr, unsigned int, XkbChangesPtr); +extern int (*_Xmblen_dylibloader_wrapper_xlib)(char *, int); +extern XFontStruct *(*XLoadQueryFont_dylibloader_wrapper_xlib)(Display *, const char *); +extern XFontStruct *(*XQueryFont_dylibloader_wrapper_xlib)(Display *, XID); +extern XTimeCoord *(*XGetMotionEvents_dylibloader_wrapper_xlib)(Display *, Window, Time, Time, int *); +extern XModifierKeymap *(*XDeleteModifiermapEntry_dylibloader_wrapper_xlib)(XModifierKeymap *, KeyCode, int); +extern XModifierKeymap *(*XGetModifierMapping_dylibloader_wrapper_xlib)(Display *); +extern XModifierKeymap *(*XInsertModifiermapEntry_dylibloader_wrapper_xlib)(XModifierKeymap *, KeyCode, int); +extern XModifierKeymap *(*XNewModifiermap_dylibloader_wrapper_xlib)(int); +extern XImage *(*XCreateImage_dylibloader_wrapper_xlib)(Display *, Visual *, unsigned int, int, int, char *, unsigned int, unsigned int, int, int); +extern int (*XInitImage_dylibloader_wrapper_xlib)(XImage *); +extern XImage *(*XGetImage_dylibloader_wrapper_xlib)(Display *, Drawable, int, int, unsigned int, unsigned int, unsigned long, int); +extern XImage *(*XGetSubImage_dylibloader_wrapper_xlib)(Display *, Drawable, int, int, unsigned int, unsigned int, unsigned long, int, XImage *, int, int); +extern Display *(*XOpenDisplay_dylibloader_wrapper_xlib)(const char *); +extern void (*XrmInitialize_dylibloader_wrapper_xlib)(void); +extern char *(*XFetchBytes_dylibloader_wrapper_xlib)(Display *, int *); +extern char *(*XFetchBuffer_dylibloader_wrapper_xlib)(Display *, int *, int); +extern char *(*XGetAtomName_dylibloader_wrapper_xlib)(Display *, Atom); +extern int (*XGetAtomNames_dylibloader_wrapper_xlib)(Display *, Atom *, int, char **); +extern char *(*XGetDefault_dylibloader_wrapper_xlib)(Display *, const char *, const char *); +extern char *(*XDisplayName_dylibloader_wrapper_xlib)(const char *); +extern char *(*XKeysymToString_dylibloader_wrapper_xlib)(KeySym); +extern int (*(*XSynchronize_dylibloader_wrapper_xlib)(Display *, int))(Display *); +extern int (*(*XSetAfterFunction_dylibloader_wrapper_xlib)(Display *, int (*)(Display *)))(Display *); +extern Atom (*XInternAtom_dylibloader_wrapper_xlib)(Display *, const char *, int); +extern int (*XInternAtoms_dylibloader_wrapper_xlib)(Display *, char **, int, int, Atom *); +extern Colormap (*XCopyColormapAndFree_dylibloader_wrapper_xlib)(Display *, Colormap); +extern Colormap (*XCreateColormap_dylibloader_wrapper_xlib)(Display *, Window, Visual *, int); +extern Cursor (*XCreatePixmapCursor_dylibloader_wrapper_xlib)(Display *, Pixmap, Pixmap, XColor *, XColor *, unsigned int, unsigned int); +extern Cursor (*XCreateGlyphCursor_dylibloader_wrapper_xlib)(Display *, Font, Font, unsigned int, unsigned int, const XColor *, const XColor *); +extern Cursor (*XCreateFontCursor_dylibloader_wrapper_xlib)(Display *, unsigned int); +extern Font (*XLoadFont_dylibloader_wrapper_xlib)(Display *, const char *); +extern GC (*XCreateGC_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned long, XGCValues *); +extern GContext (*XGContextFromGC_dylibloader_wrapper_xlib)(GC); +extern void (*XFlushGC_dylibloader_wrapper_xlib)(Display *, GC); +extern Pixmap (*XCreatePixmap_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int); +extern Pixmap (*XCreateBitmapFromData_dylibloader_wrapper_xlib)(Display *, Drawable, const char *, unsigned int, unsigned int); +extern Pixmap (*XCreatePixmapFromBitmapData_dylibloader_wrapper_xlib)(Display *, Drawable, char *, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int); +extern Window (*XCreateSimpleWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); +extern Window (*XGetSelectionOwner_dylibloader_wrapper_xlib)(Display *, Atom); +extern Window (*XCreateWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *); +extern Colormap *(*XListInstalledColormaps_dylibloader_wrapper_xlib)(Display *, Window, int *); +extern char **(*XListFonts_dylibloader_wrapper_xlib)(Display *, const char *, int, int *); +extern char **(*XListFontsWithInfo_dylibloader_wrapper_xlib)(Display *, const char *, int, int *, XFontStruct **); +extern char **(*XGetFontPath_dylibloader_wrapper_xlib)(Display *, int *); +extern char **(*XListExtensions_dylibloader_wrapper_xlib)(Display *, int *); +extern Atom *(*XListProperties_dylibloader_wrapper_xlib)(Display *, Window, int *); +extern XHostAddress *(*XListHosts_dylibloader_wrapper_xlib)(Display *, int *, int *); +extern KeySym (*XKeycodeToKeysym_dylibloader_wrapper_xlib)(Display *, KeyCode, int); +extern KeySym (*XLookupKeysym_dylibloader_wrapper_xlib)(XKeyEvent *, int); +extern KeySym *(*XGetKeyboardMapping_dylibloader_wrapper_xlib)(Display *, KeyCode, int, int *); +extern KeySym (*XStringToKeysym_dylibloader_wrapper_xlib)(const char *); +extern long (*XMaxRequestSize_dylibloader_wrapper_xlib)(Display *); +extern long (*XExtendedMaxRequestSize_dylibloader_wrapper_xlib)(Display *); +extern char *(*XResourceManagerString_dylibloader_wrapper_xlib)(Display *); +extern char *(*XScreenResourceString_dylibloader_wrapper_xlib)(Screen *); +extern unsigned long (*XDisplayMotionBufferSize_dylibloader_wrapper_xlib)(Display *); +extern VisualID (*XVisualIDFromVisual_dylibloader_wrapper_xlib)(Visual *); +extern int (*XInitThreads_dylibloader_wrapper_xlib)(void); +extern void (*XLockDisplay_dylibloader_wrapper_xlib)(Display *); +extern void (*XUnlockDisplay_dylibloader_wrapper_xlib)(Display *); +extern XExtCodes *(*XInitExtension_dylibloader_wrapper_xlib)(Display *, const char *); +extern XExtCodes *(*XAddExtension_dylibloader_wrapper_xlib)(Display *); +extern XExtData *(*XFindOnExtensionList_dylibloader_wrapper_xlib)(XExtData **, int); +extern XExtData **(*XEHeadOfExtensionList_dylibloader_wrapper_xlib)(XEDataObject); +extern Window (*XRootWindow_dylibloader_wrapper_xlib)(Display *, int); +extern Window (*XDefaultRootWindow_dylibloader_wrapper_xlib)(Display *); +extern Window (*XRootWindowOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern Visual *(*XDefaultVisual_dylibloader_wrapper_xlib)(Display *, int); +extern Visual *(*XDefaultVisualOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern GC (*XDefaultGC_dylibloader_wrapper_xlib)(Display *, int); +extern GC (*XDefaultGCOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern unsigned long (*XBlackPixel_dylibloader_wrapper_xlib)(Display *, int); +extern unsigned long (*XWhitePixel_dylibloader_wrapper_xlib)(Display *, int); +extern unsigned long (*XAllPlanes_dylibloader_wrapper_xlib)(void); +extern unsigned long (*XBlackPixelOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern unsigned long (*XWhitePixelOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern unsigned long (*XNextRequest_dylibloader_wrapper_xlib)(Display *); +extern unsigned long (*XLastKnownRequestProcessed_dylibloader_wrapper_xlib)(Display *); +extern char *(*XServerVendor_dylibloader_wrapper_xlib)(Display *); +extern char *(*XDisplayString_dylibloader_wrapper_xlib)(Display *); +extern Colormap (*XDefaultColormap_dylibloader_wrapper_xlib)(Display *, int); +extern Colormap (*XDefaultColormapOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern Display *(*XDisplayOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern Screen *(*XScreenOfDisplay_dylibloader_wrapper_xlib)(Display *, int); +extern Screen *(*XDefaultScreenOfDisplay_dylibloader_wrapper_xlib)(Display *); +extern long (*XEventMaskOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XScreenNumberOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern XErrorHandler (*XSetErrorHandler_dylibloader_wrapper_xlib)(XErrorHandler); +extern XIOErrorHandler (*XSetIOErrorHandler_dylibloader_wrapper_xlib)(XIOErrorHandler); +extern void (*XSetIOErrorExitHandler_dylibloader_wrapper_xlib)(Display *, XIOErrorExitHandler, void *); +extern XPixmapFormatValues *(*XListPixmapFormats_dylibloader_wrapper_xlib)(Display *, int *); +extern int *(*XListDepths_dylibloader_wrapper_xlib)(Display *, int, int *); +extern int (*XReconfigureWMWindow_dylibloader_wrapper_xlib)(Display *, Window, int, unsigned int, XWindowChanges *); +extern int (*XGetWMProtocols_dylibloader_wrapper_xlib)(Display *, Window, Atom **, int *); +extern int (*XSetWMProtocols_dylibloader_wrapper_xlib)(Display *, Window, Atom *, int); +extern int (*XIconifyWindow_dylibloader_wrapper_xlib)(Display *, Window, int); +extern int (*XWithdrawWindow_dylibloader_wrapper_xlib)(Display *, Window, int); +extern int (*XGetCommand_dylibloader_wrapper_xlib)(Display *, Window, char ***, int *); +extern int (*XGetWMColormapWindows_dylibloader_wrapper_xlib)(Display *, Window, Window **, int *); +extern int (*XSetWMColormapWindows_dylibloader_wrapper_xlib)(Display *, Window, Window *, int); +extern void (*XFreeStringList_dylibloader_wrapper_xlib)(char **); +extern int (*XSetTransientForHint_dylibloader_wrapper_xlib)(Display *, Window, Window); +extern int (*XActivateScreenSaver_dylibloader_wrapper_xlib)(Display *); +extern int (*XAddHost_dylibloader_wrapper_xlib)(Display *, XHostAddress *); +extern int (*XAddHosts_dylibloader_wrapper_xlib)(Display *, XHostAddress *, int); +extern int (*XAddToExtensionList_dylibloader_wrapper_xlib)(struct _XExtData **, XExtData *); +extern int (*XAddToSaveSet_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XAllocColor_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *); +extern int (*XAllocColorCells_dylibloader_wrapper_xlib)(Display *, Colormap, int, unsigned long *, unsigned int, unsigned long *, unsigned int); +extern int (*XAllocColorPlanes_dylibloader_wrapper_xlib)(Display *, Colormap, int, unsigned long *, int, int, int, int, unsigned long *, unsigned long *, unsigned long *); +extern int (*XAllocNamedColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, XColor *, XColor *); +extern int (*XAllowEvents_dylibloader_wrapper_xlib)(Display *, int, Time); +extern int (*XAutoRepeatOff_dylibloader_wrapper_xlib)(Display *); +extern int (*XAutoRepeatOn_dylibloader_wrapper_xlib)(Display *); +extern int (*XBell_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XBitmapBitOrder_dylibloader_wrapper_xlib)(Display *); +extern int (*XBitmapPad_dylibloader_wrapper_xlib)(Display *); +extern int (*XBitmapUnit_dylibloader_wrapper_xlib)(Display *); +extern int (*XCellsOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XChangeActivePointerGrab_dylibloader_wrapper_xlib)(Display *, unsigned int, Cursor, Time); +extern int (*XChangeGC_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, XGCValues *); +extern int (*XChangeKeyboardControl_dylibloader_wrapper_xlib)(Display *, unsigned long, XKeyboardControl *); +extern int (*XChangeKeyboardMapping_dylibloader_wrapper_xlib)(Display *, int, int, KeySym *, int); +extern int (*XChangePointerControl_dylibloader_wrapper_xlib)(Display *, int, int, int, int, int); +extern int (*XChangeProperty_dylibloader_wrapper_xlib)(Display *, Window, Atom, Atom, int, int, const unsigned char *, int); +extern int (*XChangeSaveSet_dylibloader_wrapper_xlib)(Display *, Window, int); +extern int (*XChangeWindowAttributes_dylibloader_wrapper_xlib)(Display *, Window, unsigned long, XSetWindowAttributes *); +extern int (*XCheckIfEvent_dylibloader_wrapper_xlib)(Display *, XEvent *, int (*)(Display *, XEvent *, XPointer), XPointer); +extern int (*XCheckMaskEvent_dylibloader_wrapper_xlib)(Display *, long, XEvent *); +extern int (*XCheckTypedEvent_dylibloader_wrapper_xlib)(Display *, int, XEvent *); +extern int (*XCheckTypedWindowEvent_dylibloader_wrapper_xlib)(Display *, Window, int, XEvent *); +extern int (*XCheckWindowEvent_dylibloader_wrapper_xlib)(Display *, Window, long, XEvent *); +extern int (*XCirculateSubwindows_dylibloader_wrapper_xlib)(Display *, Window, int); +extern int (*XCirculateSubwindowsDown_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XCirculateSubwindowsUp_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XClearArea_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int, int); +extern int (*XClearWindow_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XCloseDisplay_dylibloader_wrapper_xlib)(Display *); +extern int (*XConfigureWindow_dylibloader_wrapper_xlib)(Display *, Window, unsigned int, XWindowChanges *); +extern int (*XConnectionNumber_dylibloader_wrapper_xlib)(Display *); +extern int (*XConvertSelection_dylibloader_wrapper_xlib)(Display *, Atom, Atom, Atom, Window, Time); +extern int (*XCopyArea_dylibloader_wrapper_xlib)(Display *, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int); +extern int (*XCopyGC_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, GC); +extern int (*XCopyPlane_dylibloader_wrapper_xlib)(Display *, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long); +extern int (*XDefaultDepth_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XDefaultDepthOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XDefaultScreen_dylibloader_wrapper_xlib)(Display *); +extern int (*XDefineCursor_dylibloader_wrapper_xlib)(Display *, Window, Cursor); +extern int (*XDeleteProperty_dylibloader_wrapper_xlib)(Display *, Window, Atom); +extern int (*XDestroyWindow_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XDestroySubwindows_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XDoesBackingStore_dylibloader_wrapper_xlib)(Screen *); +extern int (*XDoesSaveUnders_dylibloader_wrapper_xlib)(Screen *); +extern int (*XDisableAccessControl_dylibloader_wrapper_xlib)(Display *); +extern int (*XDisplayCells_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XDisplayHeight_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XDisplayHeightMM_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XDisplayKeycodes_dylibloader_wrapper_xlib)(Display *, int *, int *); +extern int (*XDisplayPlanes_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XDisplayWidth_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XDisplayWidthMM_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XDrawArc_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int, int, int); +extern int (*XDrawArcs_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XArc *, int); +extern int (*XDrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const char *, int); +extern int (*XDrawImageString16_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const XChar2b *, int); +extern int (*XDrawLine_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, int, int); +extern int (*XDrawLines_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XPoint *, int, int); +extern int (*XDrawPoint_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int); +extern int (*XDrawPoints_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XPoint *, int, int); +extern int (*XDrawRectangle_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int); +extern int (*XDrawRectangles_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XRectangle *, int); +extern int (*XDrawSegments_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XSegment *, int); +extern int (*XDrawString_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const char *, int); +extern int (*XDrawString16_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, const XChar2b *, int); +extern int (*XDrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XTextItem *, int); +extern int (*XDrawText16_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XTextItem16 *, int); +extern int (*XEnableAccessControl_dylibloader_wrapper_xlib)(Display *); +extern int (*XEventsQueued_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XFetchName_dylibloader_wrapper_xlib)(Display *, Window, char **); +extern int (*XFillArc_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int, int, int); +extern int (*XFillArcs_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XArc *, int); +extern int (*XFillPolygon_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XPoint *, int, int, int); +extern int (*XFillRectangle_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, unsigned int, unsigned int); +extern int (*XFillRectangles_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XRectangle *, int); +extern int (*XFlush_dylibloader_wrapper_xlib)(Display *); +extern int (*XForceScreenSaver_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XFree_dylibloader_wrapper_xlib)(void *); +extern int (*XFreeColormap_dylibloader_wrapper_xlib)(Display *, Colormap); +extern int (*XFreeColors_dylibloader_wrapper_xlib)(Display *, Colormap, unsigned long *, int, unsigned long); +extern int (*XFreeCursor_dylibloader_wrapper_xlib)(Display *, Cursor); +extern int (*XFreeExtensionList_dylibloader_wrapper_xlib)(char **); +extern int (*XFreeFont_dylibloader_wrapper_xlib)(Display *, XFontStruct *); +extern int (*XFreeFontInfo_dylibloader_wrapper_xlib)(char **, XFontStruct *, int); +extern int (*XFreeFontNames_dylibloader_wrapper_xlib)(char **); +extern int (*XFreeFontPath_dylibloader_wrapper_xlib)(char **); +extern int (*XFreeGC_dylibloader_wrapper_xlib)(Display *, GC); +extern int (*XFreeModifiermap_dylibloader_wrapper_xlib)(XModifierKeymap *); +extern int (*XFreePixmap_dylibloader_wrapper_xlib)(Display *, Pixmap); +extern int (*XGeometry_dylibloader_wrapper_xlib)(Display *, int, const char *, const char *, unsigned int, unsigned int, unsigned int, int, int, int *, int *, int *, int *); +extern int (*XGetErrorDatabaseText_dylibloader_wrapper_xlib)(Display *, const char *, const char *, const char *, char *, int); +extern int (*XGetErrorText_dylibloader_wrapper_xlib)(Display *, int, char *, int); +extern int (*XGetFontProperty_dylibloader_wrapper_xlib)(XFontStruct *, Atom, unsigned long *); +extern int (*XGetGCValues_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, XGCValues *); +extern int (*XGetGeometry_dylibloader_wrapper_xlib)(Display *, Drawable, Window *, int *, int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *); +extern int (*XGetIconName_dylibloader_wrapper_xlib)(Display *, Window, char **); +extern int (*XGetInputFocus_dylibloader_wrapper_xlib)(Display *, Window *, int *); +extern int (*XGetKeyboardControl_dylibloader_wrapper_xlib)(Display *, XKeyboardState *); +extern int (*XGetPointerControl_dylibloader_wrapper_xlib)(Display *, int *, int *, int *); +extern int (*XGetPointerMapping_dylibloader_wrapper_xlib)(Display *, unsigned char *, int); +extern int (*XGetScreenSaver_dylibloader_wrapper_xlib)(Display *, int *, int *, int *, int *); +extern int (*XGetTransientForHint_dylibloader_wrapper_xlib)(Display *, Window, Window *); +extern int (*XGetWindowProperty_dylibloader_wrapper_xlib)(Display *, Window, Atom, long, long, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +extern int (*XGetWindowAttributes_dylibloader_wrapper_xlib)(Display *, Window, XWindowAttributes *); +extern int (*XGrabButton_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, Window, int, unsigned int, int, int, Window, Cursor); +extern int (*XGrabKey_dylibloader_wrapper_xlib)(Display *, int, unsigned int, Window, int, int, int); +extern int (*XGrabKeyboard_dylibloader_wrapper_xlib)(Display *, Window, int, int, int, Time); +extern int (*XGrabPointer_dylibloader_wrapper_xlib)(Display *, Window, int, unsigned int, int, int, Window, Cursor, Time); +extern int (*XGrabServer_dylibloader_wrapper_xlib)(Display *); +extern int (*XHeightMMOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XHeightOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XIfEvent_dylibloader_wrapper_xlib)(Display *, XEvent *, int (*)(Display *, XEvent *, XPointer), XPointer); +extern int (*XImageByteOrder_dylibloader_wrapper_xlib)(Display *); +extern int (*XInstallColormap_dylibloader_wrapper_xlib)(Display *, Colormap); +extern KeyCode (*XKeysymToKeycode_dylibloader_wrapper_xlib)(Display *, KeySym); +extern int (*XKillClient_dylibloader_wrapper_xlib)(Display *, XID); +extern int (*XLookupColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, XColor *, XColor *); +extern int (*XLowerWindow_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XMapRaised_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XMapSubwindows_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XMapWindow_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XMaskEvent_dylibloader_wrapper_xlib)(Display *, long, XEvent *); +extern int (*XMaxCmapsOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XMinCmapsOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XMoveResizeWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int, unsigned int, unsigned int); +extern int (*XMoveWindow_dylibloader_wrapper_xlib)(Display *, Window, int, int); +extern int (*XNextEvent_dylibloader_wrapper_xlib)(Display *, XEvent *); +extern int (*XNoOp_dylibloader_wrapper_xlib)(Display *); +extern int (*XParseColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, XColor *); +extern int (*XParseGeometry_dylibloader_wrapper_xlib)(const char *, int *, int *, unsigned int *, unsigned int *); +extern int (*XPeekEvent_dylibloader_wrapper_xlib)(Display *, XEvent *); +extern int (*XPeekIfEvent_dylibloader_wrapper_xlib)(Display *, XEvent *, int (*)(Display *, XEvent *, XPointer), XPointer); +extern int (*XPending_dylibloader_wrapper_xlib)(Display *); +extern int (*XPlanesOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XProtocolRevision_dylibloader_wrapper_xlib)(Display *); +extern int (*XProtocolVersion_dylibloader_wrapper_xlib)(Display *); +extern int (*XPutBackEvent_dylibloader_wrapper_xlib)(Display *, XEvent *); +extern int (*XPutImage_dylibloader_wrapper_xlib)(Display *, Drawable, GC, XImage *, int, int, int, int, unsigned int, unsigned int); +extern int (*XQLength_dylibloader_wrapper_xlib)(Display *); +extern int (*XQueryBestCursor_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +extern int (*XQueryBestSize_dylibloader_wrapper_xlib)(Display *, int, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +extern int (*XQueryBestStipple_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +extern int (*XQueryBestTile_dylibloader_wrapper_xlib)(Display *, Drawable, unsigned int, unsigned int, unsigned int *, unsigned int *); +extern int (*XQueryColor_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *); +extern int (*XQueryColors_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *, int); +extern int (*XQueryExtension_dylibloader_wrapper_xlib)(Display *, const char *, int *, int *, int *); +extern int (*XQueryKeymap_dylibloader_wrapper_xlib)(Display *, char [32]); +extern int (*XQueryPointer_dylibloader_wrapper_xlib)(Display *, Window, Window *, Window *, int *, int *, int *, int *, unsigned int *); +extern int (*XQueryTextExtents_dylibloader_wrapper_xlib)(Display *, XID, const char *, int, int *, int *, int *, XCharStruct *); +extern int (*XQueryTextExtents16_dylibloader_wrapper_xlib)(Display *, XID, const XChar2b *, int, int *, int *, int *, XCharStruct *); +extern int (*XQueryTree_dylibloader_wrapper_xlib)(Display *, Window, Window *, Window *, Window **, unsigned int *); +extern int (*XRaiseWindow_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XReadBitmapFile_dylibloader_wrapper_xlib)(Display *, Drawable, const char *, unsigned int *, unsigned int *, Pixmap *, int *, int *); +extern int (*XReadBitmapFileData_dylibloader_wrapper_xlib)(const char *, unsigned int *, unsigned int *, unsigned char **, int *, int *); +extern int (*XRebindKeysym_dylibloader_wrapper_xlib)(Display *, KeySym, KeySym *, int, const unsigned char *, int); +extern int (*XRecolorCursor_dylibloader_wrapper_xlib)(Display *, Cursor, XColor *, XColor *); +extern int (*XRefreshKeyboardMapping_dylibloader_wrapper_xlib)(XMappingEvent *); +extern int (*XRemoveFromSaveSet_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XRemoveHost_dylibloader_wrapper_xlib)(Display *, XHostAddress *); +extern int (*XRemoveHosts_dylibloader_wrapper_xlib)(Display *, XHostAddress *, int); +extern int (*XReparentWindow_dylibloader_wrapper_xlib)(Display *, Window, Window, int, int); +extern int (*XResetScreenSaver_dylibloader_wrapper_xlib)(Display *); +extern int (*XResizeWindow_dylibloader_wrapper_xlib)(Display *, Window, unsigned int, unsigned int); +extern int (*XRestackWindows_dylibloader_wrapper_xlib)(Display *, Window *, int); +extern int (*XRotateBuffers_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XRotateWindowProperties_dylibloader_wrapper_xlib)(Display *, Window, Atom *, int, int); +extern int (*XScreenCount_dylibloader_wrapper_xlib)(Display *); +extern int (*XSelectInput_dylibloader_wrapper_xlib)(Display *, Window, long); +extern int (*XSendEvent_dylibloader_wrapper_xlib)(Display *, Window, int, long, XEvent *); +extern int (*XSetAccessControl_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XSetArcMode_dylibloader_wrapper_xlib)(Display *, GC, int); +extern int (*XSetBackground_dylibloader_wrapper_xlib)(Display *, GC, unsigned long); +extern int (*XSetClipMask_dylibloader_wrapper_xlib)(Display *, GC, Pixmap); +extern int (*XSetClipOrigin_dylibloader_wrapper_xlib)(Display *, GC, int, int); +extern int (*XSetClipRectangles_dylibloader_wrapper_xlib)(Display *, GC, int, int, XRectangle *, int, int); +extern int (*XSetCloseDownMode_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XSetCommand_dylibloader_wrapper_xlib)(Display *, Window, char **, int); +extern int (*XSetDashes_dylibloader_wrapper_xlib)(Display *, GC, int, const char *, int); +extern int (*XSetFillRule_dylibloader_wrapper_xlib)(Display *, GC, int); +extern int (*XSetFillStyle_dylibloader_wrapper_xlib)(Display *, GC, int); +extern int (*XSetFont_dylibloader_wrapper_xlib)(Display *, GC, Font); +extern int (*XSetFontPath_dylibloader_wrapper_xlib)(Display *, char **, int); +extern int (*XSetForeground_dylibloader_wrapper_xlib)(Display *, GC, unsigned long); +extern int (*XSetFunction_dylibloader_wrapper_xlib)(Display *, GC, int); +extern int (*XSetGraphicsExposures_dylibloader_wrapper_xlib)(Display *, GC, int); +extern int (*XSetIconName_dylibloader_wrapper_xlib)(Display *, Window, const char *); +extern int (*XSetInputFocus_dylibloader_wrapper_xlib)(Display *, Window, int, Time); +extern int (*XSetLineAttributes_dylibloader_wrapper_xlib)(Display *, GC, unsigned int, int, int, int); +extern int (*XSetModifierMapping_dylibloader_wrapper_xlib)(Display *, XModifierKeymap *); +extern int (*XSetPlaneMask_dylibloader_wrapper_xlib)(Display *, GC, unsigned long); +extern int (*XSetPointerMapping_dylibloader_wrapper_xlib)(Display *, const unsigned char *, int); +extern int (*XSetScreenSaver_dylibloader_wrapper_xlib)(Display *, int, int, int, int); +extern int (*XSetSelectionOwner_dylibloader_wrapper_xlib)(Display *, Atom, Window, Time); +extern int (*XSetState_dylibloader_wrapper_xlib)(Display *, GC, unsigned long, unsigned long, int, unsigned long); +extern int (*XSetStipple_dylibloader_wrapper_xlib)(Display *, GC, Pixmap); +extern int (*XSetSubwindowMode_dylibloader_wrapper_xlib)(Display *, GC, int); +extern int (*XSetTSOrigin_dylibloader_wrapper_xlib)(Display *, GC, int, int); +extern int (*XSetTile_dylibloader_wrapper_xlib)(Display *, GC, Pixmap); +extern int (*XSetWindowBackground_dylibloader_wrapper_xlib)(Display *, Window, unsigned long); +extern int (*XSetWindowBackgroundPixmap_dylibloader_wrapper_xlib)(Display *, Window, Pixmap); +extern int (*XSetWindowBorder_dylibloader_wrapper_xlib)(Display *, Window, unsigned long); +extern int (*XSetWindowBorderPixmap_dylibloader_wrapper_xlib)(Display *, Window, Pixmap); +extern int (*XSetWindowBorderWidth_dylibloader_wrapper_xlib)(Display *, Window, unsigned int); +extern int (*XSetWindowColormap_dylibloader_wrapper_xlib)(Display *, Window, Colormap); +extern int (*XStoreBuffer_dylibloader_wrapper_xlib)(Display *, const char *, int, int); +extern int (*XStoreBytes_dylibloader_wrapper_xlib)(Display *, const char *, int); +extern int (*XStoreColor_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *); +extern int (*XStoreColors_dylibloader_wrapper_xlib)(Display *, Colormap, XColor *, int); +extern int (*XStoreName_dylibloader_wrapper_xlib)(Display *, Window, const char *); +extern int (*XStoreNamedColor_dylibloader_wrapper_xlib)(Display *, Colormap, const char *, unsigned long, int); +extern int (*XSync_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XTextExtents_dylibloader_wrapper_xlib)(XFontStruct *, const char *, int, int *, int *, int *, XCharStruct *); +extern int (*XTextExtents16_dylibloader_wrapper_xlib)(XFontStruct *, const XChar2b *, int, int *, int *, int *, XCharStruct *); +extern int (*XTextWidth_dylibloader_wrapper_xlib)(XFontStruct *, const char *, int); +extern int (*XTextWidth16_dylibloader_wrapper_xlib)(XFontStruct *, const XChar2b *, int); +extern int (*XTranslateCoordinates_dylibloader_wrapper_xlib)(Display *, Window, Window, int, int, int *, int *, Window *); +extern int (*XUndefineCursor_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XUngrabButton_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, Window); +extern int (*XUngrabKey_dylibloader_wrapper_xlib)(Display *, int, unsigned int, Window); +extern int (*XUngrabKeyboard_dylibloader_wrapper_xlib)(Display *, Time); +extern int (*XUngrabPointer_dylibloader_wrapper_xlib)(Display *, Time); +extern int (*XUngrabServer_dylibloader_wrapper_xlib)(Display *); +extern int (*XUninstallColormap_dylibloader_wrapper_xlib)(Display *, Colormap); +extern int (*XUnloadFont_dylibloader_wrapper_xlib)(Display *, Font); +extern int (*XUnmapSubwindows_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XUnmapWindow_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XVendorRelease_dylibloader_wrapper_xlib)(Display *); +extern int (*XWarpPointer_dylibloader_wrapper_xlib)(Display *, Window, Window, int, int, unsigned int, unsigned int, int, int); +extern int (*XWidthMMOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XWidthOfScreen_dylibloader_wrapper_xlib)(Screen *); +extern int (*XWindowEvent_dylibloader_wrapper_xlib)(Display *, Window, long, XEvent *); +extern int (*XWriteBitmapFile_dylibloader_wrapper_xlib)(Display *, const char *, Pixmap, unsigned int, unsigned int, int, int); +extern int (*XSupportsLocale_dylibloader_wrapper_xlib)(void); +extern char *(*XSetLocaleModifiers_dylibloader_wrapper_xlib)(const char *); +extern XOM (*XOpenOM_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, const char *, const char *); +extern int (*XCloseOM_dylibloader_wrapper_xlib)(XOM); +extern char *(*XSetOMValues_dylibloader_wrapper_xlib)(XOM, ...); +extern char *(*XGetOMValues_dylibloader_wrapper_xlib)(XOM, ...); +extern Display *(*XDisplayOfOM_dylibloader_wrapper_xlib)(XOM); +extern char *(*XLocaleOfOM_dylibloader_wrapper_xlib)(XOM); +extern XOC (*XCreateOC_dylibloader_wrapper_xlib)(XOM, ...); +extern void (*XDestroyOC_dylibloader_wrapper_xlib)(XOC); +extern XOM (*XOMOfOC_dylibloader_wrapper_xlib)(XOC); +extern char *(*XSetOCValues_dylibloader_wrapper_xlib)(XOC, ...); +extern char *(*XGetOCValues_dylibloader_wrapper_xlib)(XOC, ...); +extern XFontSet (*XCreateFontSet_dylibloader_wrapper_xlib)(Display *, const char *, char ***, int *, char **); +extern void (*XFreeFontSet_dylibloader_wrapper_xlib)(Display *, XFontSet); +extern int (*XFontsOfFontSet_dylibloader_wrapper_xlib)(XFontSet, XFontStruct ***, char ***); +extern char *(*XBaseFontNameListOfFontSet_dylibloader_wrapper_xlib)(XFontSet); +extern char *(*XLocaleOfFontSet_dylibloader_wrapper_xlib)(XFontSet); +extern int (*XContextDependentDrawing_dylibloader_wrapper_xlib)(XFontSet); +extern int (*XDirectionalDependentDrawing_dylibloader_wrapper_xlib)(XFontSet); +extern int (*XContextualDrawing_dylibloader_wrapper_xlib)(XFontSet); +extern XFontSetExtents *(*XExtentsOfFontSet_dylibloader_wrapper_xlib)(XFontSet); +extern int (*XmbTextEscapement_dylibloader_wrapper_xlib)(XFontSet, const char *, int); +extern int (*XwcTextEscapement_dylibloader_wrapper_xlib)(XFontSet, const wchar_t *, int); +extern int (*Xutf8TextEscapement_dylibloader_wrapper_xlib)(XFontSet, const char *, int); +extern int (*XmbTextExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *); +extern int (*XwcTextExtents_dylibloader_wrapper_xlib)(XFontSet, const wchar_t *, int, XRectangle *, XRectangle *); +extern int (*Xutf8TextExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *); +extern int (*XmbTextPerCharExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *, int, int *, XRectangle *, XRectangle *); +extern int (*XwcTextPerCharExtents_dylibloader_wrapper_xlib)(XFontSet, const wchar_t *, int, XRectangle *, XRectangle *, int, int *, XRectangle *, XRectangle *); +extern int (*Xutf8TextPerCharExtents_dylibloader_wrapper_xlib)(XFontSet, const char *, int, XRectangle *, XRectangle *, int, int *, XRectangle *, XRectangle *); +extern void (*XmbDrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XmbTextItem *, int); +extern void (*XwcDrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XwcTextItem *, int); +extern void (*Xutf8DrawText_dylibloader_wrapper_xlib)(Display *, Drawable, GC, int, int, XmbTextItem *, int); +extern void (*XmbDrawString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +extern void (*XwcDrawString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const wchar_t *, int); +extern void (*Xutf8DrawString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +extern void (*XmbDrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +extern void (*XwcDrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const wchar_t *, int); +extern void (*Xutf8DrawImageString_dylibloader_wrapper_xlib)(Display *, Drawable, XFontSet, GC, int, int, const char *, int); +extern XIM (*XOpenIM_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, char *, char *); +extern int (*XCloseIM_dylibloader_wrapper_xlib)(XIM); +extern char *(*XGetIMValues_dylibloader_wrapper_xlib)(XIM, ...); +extern char *(*XSetIMValues_dylibloader_wrapper_xlib)(XIM, ...); +extern Display *(*XDisplayOfIM_dylibloader_wrapper_xlib)(XIM); +extern char *(*XLocaleOfIM_dylibloader_wrapper_xlib)(XIM); +extern XIC (*XCreateIC_dylibloader_wrapper_xlib)(XIM, ...); +extern void (*XDestroyIC_dylibloader_wrapper_xlib)(XIC); +extern void (*XSetICFocus_dylibloader_wrapper_xlib)(XIC); +extern void (*XUnsetICFocus_dylibloader_wrapper_xlib)(XIC); +extern wchar_t *(*XwcResetIC_dylibloader_wrapper_xlib)(XIC); +extern char *(*XmbResetIC_dylibloader_wrapper_xlib)(XIC); +extern char *(*Xutf8ResetIC_dylibloader_wrapper_xlib)(XIC); +extern char *(*XSetICValues_dylibloader_wrapper_xlib)(XIC, ...); +extern char *(*XGetICValues_dylibloader_wrapper_xlib)(XIC, ...); +extern XIM (*XIMOfIC_dylibloader_wrapper_xlib)(XIC); +extern int (*XFilterEvent_dylibloader_wrapper_xlib)(XEvent *, Window); +extern int (*XmbLookupString_dylibloader_wrapper_xlib)(XIC, XKeyPressedEvent *, char *, int, KeySym *, int *); +extern int (*XwcLookupString_dylibloader_wrapper_xlib)(XIC, XKeyPressedEvent *, wchar_t *, int, KeySym *, int *); +extern int (*Xutf8LookupString_dylibloader_wrapper_xlib)(XIC, XKeyPressedEvent *, char *, int, KeySym *, int *); +extern XVaNestedList (*XVaCreateNestedList_dylibloader_wrapper_xlib)(int, ...); +extern int (*XRegisterIMInstantiateCallback_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, char *, char *, XIDProc, XPointer); +extern int (*XUnregisterIMInstantiateCallback_dylibloader_wrapper_xlib)(Display *, struct _XrmHashBucketRec *, char *, char *, XIDProc, XPointer); +extern int (*XInternalConnectionNumbers_dylibloader_wrapper_xlib)(Display *, int **, int *); +extern void (*XProcessInternalConnection_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XAddConnectionWatch_dylibloader_wrapper_xlib)(Display *, XConnectionWatchProc, XPointer); +extern void (*XRemoveConnectionWatch_dylibloader_wrapper_xlib)(Display *, XConnectionWatchProc, XPointer); +extern void (*XSetAuthorization_dylibloader_wrapper_xlib)(char *, int, char *, int); +extern int (*_Xmbtowc_dylibloader_wrapper_xlib)(wchar_t *, char *, int); +extern int (*_Xwctomb_dylibloader_wrapper_xlib)(char *, wchar_t); +extern int (*XGetEventData_dylibloader_wrapper_xlib)(Display *, XGenericEventCookie *); +extern void (*XFreeEventData_dylibloader_wrapper_xlib)(Display *, XGenericEventCookie *); +extern int (*XFreeThreads_dylibloader_wrapper_xlib)(void); +extern XClassHint *(*XAllocClassHint_dylibloader_wrapper_xlib)(void); +extern XIconSize *(*XAllocIconSize_dylibloader_wrapper_xlib)(void); +extern XSizeHints *(*XAllocSizeHints_dylibloader_wrapper_xlib)(void); +extern XStandardColormap *(*XAllocStandardColormap_dylibloader_wrapper_xlib)(void); +extern XWMHints *(*XAllocWMHints_dylibloader_wrapper_xlib)(void); +extern int (*XClipBox_dylibloader_wrapper_xlib)(Region, XRectangle *); +extern Region (*XCreateRegion_dylibloader_wrapper_xlib)(void); +extern const char *(*XDefaultString_dylibloader_wrapper_xlib)(void); +extern int (*XDeleteContext_dylibloader_wrapper_xlib)(Display *, XID, XContext); +extern int (*XDestroyRegion_dylibloader_wrapper_xlib)(Region); +extern int (*XEmptyRegion_dylibloader_wrapper_xlib)(Region); +extern int (*XEqualRegion_dylibloader_wrapper_xlib)(Region, Region); +extern int (*XFindContext_dylibloader_wrapper_xlib)(Display *, XID, XContext, XPointer *); +extern int (*XGetClassHint_dylibloader_wrapper_xlib)(Display *, Window, XClassHint *); +extern int (*XGetIconSizes_dylibloader_wrapper_xlib)(Display *, Window, XIconSize **, int *); +extern int (*XGetNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +extern int (*XGetRGBColormaps_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap **, int *, Atom); +extern int (*XGetSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, Atom); +extern int (*XGetStandardColormap_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap *, Atom); +extern int (*XGetTextProperty_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *, Atom); +extern XVisualInfo *(*XGetVisualInfo_dylibloader_wrapper_xlib)(Display *, long, XVisualInfo *, int *); +extern int (*XGetWMClientMachine_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +extern XWMHints *(*XGetWMHints_dylibloader_wrapper_xlib)(Display *, Window); +extern int (*XGetWMIconName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +extern int (*XGetWMName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +extern int (*XGetWMNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, long *); +extern int (*XGetWMSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, long *, Atom); +extern int (*XGetZoomHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +extern int (*XIntersectRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +extern void (*XConvertCase_dylibloader_wrapper_xlib)(KeySym, KeySym *, KeySym *); +extern int (*XLookupString_dylibloader_wrapper_xlib)(XKeyEvent *, char *, int, KeySym *, XComposeStatus *); +extern int (*XMatchVisualInfo_dylibloader_wrapper_xlib)(Display *, int, int, int, XVisualInfo *); +extern int (*XOffsetRegion_dylibloader_wrapper_xlib)(Region, int, int); +extern int (*XPointInRegion_dylibloader_wrapper_xlib)(Region, int, int); +extern Region (*XPolygonRegion_dylibloader_wrapper_xlib)(XPoint *, int, int); +extern int (*XRectInRegion_dylibloader_wrapper_xlib)(Region, int, int, unsigned int, unsigned int); +extern int (*XSaveContext_dylibloader_wrapper_xlib)(Display *, XID, XContext, const char *); +extern int (*XSetClassHint_dylibloader_wrapper_xlib)(Display *, Window, XClassHint *); +extern int (*XSetIconSizes_dylibloader_wrapper_xlib)(Display *, Window, XIconSize *, int); +extern int (*XSetNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +extern void (*XSetRGBColormaps_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap *, int, Atom); +extern int (*XSetSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, Atom); +extern int (*XSetStandardProperties_dylibloader_wrapper_xlib)(Display *, Window, const char *, const char *, Pixmap, char **, int, XSizeHints *); +extern void (*XSetTextProperty_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *, Atom); +extern void (*XSetWMClientMachine_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +extern int (*XSetWMHints_dylibloader_wrapper_xlib)(Display *, Window, XWMHints *); +extern void (*XSetWMIconName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +extern void (*XSetWMName_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *); +extern void (*XSetWMNormalHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +extern void (*XSetWMProperties_dylibloader_wrapper_xlib)(Display *, Window, XTextProperty *, XTextProperty *, char **, int, XSizeHints *, XWMHints *, XClassHint *); +extern void (*XmbSetWMProperties_dylibloader_wrapper_xlib)(Display *, Window, const char *, const char *, char **, int, XSizeHints *, XWMHints *, XClassHint *); +extern void (*Xutf8SetWMProperties_dylibloader_wrapper_xlib)(Display *, Window, const char *, const char *, char **, int, XSizeHints *, XWMHints *, XClassHint *); +extern void (*XSetWMSizeHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *, Atom); +extern int (*XSetRegion_dylibloader_wrapper_xlib)(Display *, GC, Region); +extern void (*XSetStandardColormap_dylibloader_wrapper_xlib)(Display *, Window, XStandardColormap *, Atom); +extern int (*XSetZoomHints_dylibloader_wrapper_xlib)(Display *, Window, XSizeHints *); +extern int (*XShrinkRegion_dylibloader_wrapper_xlib)(Region, int, int); +extern int (*XStringListToTextProperty_dylibloader_wrapper_xlib)(char **, int, XTextProperty *); +extern int (*XSubtractRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +extern int (*XmbTextListToTextProperty_dylibloader_wrapper_xlib)(Display *, char **, int, XICCEncodingStyle, XTextProperty *); +extern int (*XwcTextListToTextProperty_dylibloader_wrapper_xlib)(Display *, wchar_t **, int, XICCEncodingStyle, XTextProperty *); +extern int (*Xutf8TextListToTextProperty_dylibloader_wrapper_xlib)(Display *, char **, int, XICCEncodingStyle, XTextProperty *); +extern void (*XwcFreeStringList_dylibloader_wrapper_xlib)(wchar_t **); +extern int (*XTextPropertyToStringList_dylibloader_wrapper_xlib)(XTextProperty *, char ***, int *); +extern int (*XmbTextPropertyToTextList_dylibloader_wrapper_xlib)(Display *, const XTextProperty *, char ***, int *); +extern int (*XwcTextPropertyToTextList_dylibloader_wrapper_xlib)(Display *, const XTextProperty *, wchar_t ***, int *); +extern int (*Xutf8TextPropertyToTextList_dylibloader_wrapper_xlib)(Display *, const XTextProperty *, char ***, int *); +extern int (*XUnionRectWithRegion_dylibloader_wrapper_xlib)(XRectangle *, Region, Region); +extern int (*XUnionRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +extern int (*XWMGeometry_dylibloader_wrapper_xlib)(Display *, int, const char *, const char *, unsigned int, XSizeHints *, int *, int *, int *, int *, int *); +extern int (*XXorRegion_dylibloader_wrapper_xlib)(Region, Region, Region); +extern int (*XkbIgnoreExtension_dylibloader_wrapper_xlib)(int); +extern Display *(*XkbOpenDisplay_dylibloader_wrapper_xlib)(char *, int *, int *, int *, int *, int *); +extern int (*XkbQueryExtension_dylibloader_wrapper_xlib)(Display *, int *, int *, int *, int *, int *); +extern int (*XkbUseExtension_dylibloader_wrapper_xlib)(Display *, int *, int *); +extern int (*XkbLibraryVersion_dylibloader_wrapper_xlib)(int *, int *); +extern unsigned int (*XkbSetXlibControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +extern unsigned int (*XkbGetXlibControls_dylibloader_wrapper_xlib)(Display *); +extern unsigned int (*XkbXlibControlsImplemented_dylibloader_wrapper_xlib)(void); +extern void (*XkbSetAtomFuncs_dylibloader_wrapper_xlib)(XkbInternAtomFunc, XkbGetAtomNameFunc); +extern KeySym (*XkbKeycodeToKeysym_dylibloader_wrapper_xlib)(Display *, KeyCode, int, int); +extern unsigned int (*XkbKeysymToModifiers_dylibloader_wrapper_xlib)(Display *, KeySym); +extern int (*XkbLookupKeySym_dylibloader_wrapper_xlib)(Display *, KeyCode, unsigned int, unsigned int *, KeySym *); +extern int (*XkbLookupKeyBinding_dylibloader_wrapper_xlib)(Display *, KeySym, unsigned int, char *, int, int *); +extern int (*XkbTranslateKeyCode_dylibloader_wrapper_xlib)(XkbDescPtr, KeyCode, unsigned int, unsigned int *, KeySym *); +extern int (*XkbTranslateKeySym_dylibloader_wrapper_xlib)(Display *, KeySym *, unsigned int, char *, int, int *); +extern int (*XkbSetAutoRepeatRate_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +extern int (*XkbGetAutoRepeatRate_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *, unsigned int *); +extern int (*XkbChangeEnabledControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +extern int (*XkbDeviceBell_dylibloader_wrapper_xlib)(Display *, Window, int, int, int, int, Atom); +extern int (*XkbForceDeviceBell_dylibloader_wrapper_xlib)(Display *, int, int, int, int); +extern int (*XkbDeviceBellEvent_dylibloader_wrapper_xlib)(Display *, Window, int, int, int, int, Atom); +extern int (*XkbBell_dylibloader_wrapper_xlib)(Display *, Window, int, Atom); +extern int (*XkbForceBell_dylibloader_wrapper_xlib)(Display *, int); +extern int (*XkbBellEvent_dylibloader_wrapper_xlib)(Display *, Window, int, Atom); +extern int (*XkbSelectEvents_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +extern int (*XkbSelectEventDetails_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned long, unsigned long); +extern void (*XkbNoteMapChanges_dylibloader_wrapper_xlib)(XkbMapChangesPtr, XkbMapNotifyEvent *, unsigned int); +extern void (*XkbNoteNameChanges_dylibloader_wrapper_xlib)(XkbNameChangesPtr, XkbNamesNotifyEvent *, unsigned int); +extern int (*XkbGetIndicatorState_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *); +extern int (*XkbGetIndicatorMap_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +extern int (*XkbSetIndicatorMap_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +extern int (*XkbGetNamedIndicator_dylibloader_wrapper_xlib)(Display *, Atom, int *, int *, XkbIndicatorMapPtr, int *); +extern int (*XkbGetNamedDeviceIndicator_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, Atom, int *, int *, XkbIndicatorMapPtr, int *); +extern int (*XkbSetNamedIndicator_dylibloader_wrapper_xlib)(Display *, Atom, int, int, int, XkbIndicatorMapPtr); +extern int (*XkbSetNamedDeviceIndicator_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, Atom, int, int, int, XkbIndicatorMapPtr); +extern int (*XkbLockModifiers_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +extern int (*XkbLatchModifiers_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int); +extern int (*XkbLockGroup_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +extern int (*XkbLatchGroup_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +extern int (*XkbSetServerInternalMods_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); +extern int (*XkbSetIgnoreLockMods_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); +extern int (*XkbVirtualModsToReal_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int *); +extern int (*XkbComputeEffectiveMap_dylibloader_wrapper_xlib)(XkbDescPtr, XkbKeyTypePtr, unsigned char *); +extern int (*XkbInitCanonicalKeyTypes_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +extern XkbDescPtr (*XkbAllocKeyboard_dylibloader_wrapper_xlib)(void); +extern void (*XkbFreeKeyboard_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +extern int (*XkbAllocClientMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int); +extern int (*XkbAllocServerMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int); +extern void (*XkbFreeClientMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +extern void (*XkbFreeServerMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +extern XkbKeyTypePtr (*XkbAddKeyType_dylibloader_wrapper_xlib)(XkbDescPtr, Atom, int, int, int); +extern int (*XkbAllocIndicatorMaps_dylibloader_wrapper_xlib)(XkbDescPtr); +extern void (*XkbFreeIndicatorMaps_dylibloader_wrapper_xlib)(XkbDescPtr); +extern XkbDescPtr (*XkbGetMap_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +extern int (*XkbGetUpdatedMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +extern int (*XkbGetMapChanges_dylibloader_wrapper_xlib)(Display *, XkbDescPtr, XkbMapChangesPtr); +extern int (*XkbRefreshKeyboardMapping_dylibloader_wrapper_xlib)(XkbMapNotifyEvent *); +extern int (*XkbGetKeyTypes_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbGetKeySyms_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbGetKeyActions_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbGetKeyBehaviors_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbGetVirtualMods_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +extern int (*XkbGetKeyExplicitComponents_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbGetKeyModifierMap_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbGetKeyVirtualModMap_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbAllocControls_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int); +extern void (*XkbFreeControls_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +extern int (*XkbGetControls_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +extern int (*XkbSetControls_dylibloader_wrapper_xlib)(Display *, unsigned long, XkbDescPtr); +extern void (*XkbNoteControlsChanges_dylibloader_wrapper_xlib)(XkbControlsChangesPtr, XkbControlsNotifyEvent *, unsigned int); +extern int (*XkbAllocCompatMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, unsigned int); +extern void (*XkbFreeCompatMap_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +extern int (*XkbGetCompatMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +extern int (*XkbSetCompatMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr, int); +extern int (*XkbAllocNames_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int, int); +extern int (*XkbGetNames_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +extern int (*XkbSetNames_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, XkbDescPtr); +extern int (*XkbChangeNames_dylibloader_wrapper_xlib)(Display *, XkbDescPtr, XkbNameChangesPtr); +extern void (*XkbFreeNames_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, int); +extern int (*XkbGetState_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbStatePtr); +extern int (*XkbSetMap_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDescPtr); +extern int (*XkbChangeMap_dylibloader_wrapper_xlib)(Display *, XkbDescPtr, XkbMapChangesPtr); +extern int (*XkbSetDetectableAutoRepeat_dylibloader_wrapper_xlib)(Display *, int, int *); +extern int (*XkbGetDetectableAutoRepeat_dylibloader_wrapper_xlib)(Display *, int *); +extern int (*XkbSetAutoResetControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *, unsigned int *); +extern int (*XkbGetAutoResetControls_dylibloader_wrapper_xlib)(Display *, unsigned int *, unsigned int *); +extern int (*XkbSetPerClientControls_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int *); +extern int (*XkbGetPerClientControls_dylibloader_wrapper_xlib)(Display *, unsigned int *); +extern int (*XkbCopyKeyType_dylibloader_wrapper_xlib)(XkbKeyTypePtr, XkbKeyTypePtr); +extern int (*XkbCopyKeyTypes_dylibloader_wrapper_xlib)(XkbKeyTypePtr, XkbKeyTypePtr, int); +extern int (*XkbResizeKeyType_dylibloader_wrapper_xlib)(XkbDescPtr, int, int, int, int); +extern KeySym *(*XkbResizeKeySyms_dylibloader_wrapper_xlib)(XkbDescPtr, int, int); +extern XkbAction *(*XkbResizeKeyActions_dylibloader_wrapper_xlib)(XkbDescPtr, int, int); +extern int (*XkbChangeTypesOfKey_dylibloader_wrapper_xlib)(XkbDescPtr, int, int, unsigned int, int *, XkbMapChangesPtr); +extern int (*XkbChangeKeycodeRange_dylibloader_wrapper_xlib)(XkbDescPtr, int, int, XkbChangesPtr); +extern XkbComponentListPtr (*XkbListComponents_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbComponentNamesPtr, int *); +extern void (*XkbFreeComponentList_dylibloader_wrapper_xlib)(XkbComponentListPtr); +extern XkbDescPtr (*XkbGetKeyboard_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int); +extern XkbDescPtr (*XkbGetKeyboardByName_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbComponentNamesPtr, unsigned int, unsigned int, int); +extern int (*XkbKeyTypesForCoreSymbols_dylibloader_wrapper_xlib)(XkbDescPtr, int, KeySym *, unsigned int, int *, KeySym *); +extern int (*XkbApplyCompatMapToKey_dylibloader_wrapper_xlib)(XkbDescPtr, KeyCode, XkbChangesPtr); +extern int (*XkbUpdateMapFromCore_dylibloader_wrapper_xlib)(XkbDescPtr, KeyCode, int, int, KeySym *, XkbChangesPtr); +extern XkbDeviceLedInfoPtr (*XkbAddDeviceLedInfo_dylibloader_wrapper_xlib)(XkbDeviceInfoPtr, unsigned int, unsigned int); +extern int (*XkbResizeDeviceButtonActions_dylibloader_wrapper_xlib)(XkbDeviceInfoPtr, unsigned int); +extern XkbDeviceInfoPtr (*XkbAllocDeviceInfo_dylibloader_wrapper_xlib)(unsigned int, unsigned int, unsigned int); +extern void (*XkbFreeDeviceInfo_dylibloader_wrapper_xlib)(XkbDeviceInfoPtr, unsigned int, int); +extern void (*XkbNoteDeviceChanges_dylibloader_wrapper_xlib)(XkbDeviceChangesPtr, XkbExtensionDeviceNotifyEvent *, unsigned int); +extern XkbDeviceInfoPtr (*XkbGetDeviceInfo_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, unsigned int, unsigned int); +extern int (*XkbGetDeviceInfoChanges_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, XkbDeviceChangesPtr); +extern int (*XkbGetDeviceButtonActions_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, int, unsigned int, unsigned int); +extern int (*XkbGetDeviceLedInfo_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); +extern int (*XkbSetDeviceInfo_dylibloader_wrapper_xlib)(Display *, unsigned int, XkbDeviceInfoPtr); +extern int (*XkbChangeDeviceInfo_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, XkbDeviceChangesPtr); +extern int (*XkbSetDeviceLedInfo_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, unsigned int, unsigned int, unsigned int); +extern int (*XkbSetDeviceButtonActions_dylibloader_wrapper_xlib)(Display *, XkbDeviceInfoPtr, unsigned int, unsigned int); +extern char (*XkbToControl_dylibloader_wrapper_xlib)(char); +extern int (*XkbSetDebuggingFlags_dylibloader_wrapper_xlib)(Display *, unsigned int, unsigned int, char *, unsigned int, unsigned int, unsigned int *, unsigned int *); +extern int (*XkbApplyVirtualModChanges_dylibloader_wrapper_xlib)(XkbDescPtr, unsigned int, XkbChangesPtr); +extern int (*XkbUpdateActionVirtualMods_dylibloader_wrapper_xlib)(XkbDescPtr, XkbAction *, unsigned int); +extern void (*XkbUpdateKeyTypeVirtualMods_dylibloader_wrapper_xlib)(XkbDescPtr, XkbKeyTypePtr, unsigned int, XkbChangesPtr); int initialize_xlib(int verbose); #ifdef __cplusplus } diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c index 05f98d2506..bc9de62caa 100644 --- a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c +++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c @@ -1,12 +1,8 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:54 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h" --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:37 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c --ignore-other // -// NOTE: Generated from Xrandr 1.5.2. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11 and libXrender, but absent in libXrandr.so.2, were removed. #include <stdint.h> #define XRRQueryExtension XRRQueryExtension_dylibloader_orig_xrandr @@ -152,76 +148,76 @@ #undef XRRFreeMonitors #include <dlfcn.h> #include <stdio.h> -int (*XRRQueryExtension_dylibloader_wrapper_xrandr)( Display*, int*, int*); -int (*XRRQueryVersion_dylibloader_wrapper_xrandr)( Display*, int*, int*); -XRRScreenConfiguration* (*XRRGetScreenInfo_dylibloader_wrapper_xrandr)( Display*, Window); -void (*XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*); -int (*XRRSetScreenConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, Time); -int (*XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, short, Time); -Rotation (*XRRConfigRotations_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*); -Time (*XRRConfigTimes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Time*); -XRRScreenSize* (*XRRConfigSizes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int*); -short* (*XRRConfigRates_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int, int*); -SizeID (*XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*); -short (*XRRConfigCurrentRate_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*); -int (*XRRRootToScreen_dylibloader_wrapper_xrandr)( Display*, Window); -void (*XRRSelectInput_dylibloader_wrapper_xrandr)( Display*, Window, int); -Rotation (*XRRRotations_dylibloader_wrapper_xrandr)( Display*, int, Rotation*); -XRRScreenSize* (*XRRSizes_dylibloader_wrapper_xrandr)( Display*, int, int*); -short* (*XRRRates_dylibloader_wrapper_xrandr)( Display*, int, int, int*); -Time (*XRRTimes_dylibloader_wrapper_xrandr)( Display*, int, Time*); -int (*XRRGetScreenSizeRange_dylibloader_wrapper_xrandr)( Display*, Window, int*, int*, int*, int*); -void (*XRRSetScreenSize_dylibloader_wrapper_xrandr)( Display*, Window, int, int, int, int); -XRRScreenResources* (*XRRGetScreenResources_dylibloader_wrapper_xrandr)( Display*, Window); -void (*XRRFreeScreenResources_dylibloader_wrapper_xrandr)( XRRScreenResources*); -XRROutputInfo* (*XRRGetOutputInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RROutput); -void (*XRRFreeOutputInfo_dylibloader_wrapper_xrandr)( XRROutputInfo*); -Atom* (*XRRListOutputProperties_dylibloader_wrapper_xrandr)( Display*, RROutput, int*); -XRRPropertyInfo* (*XRRQueryOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom); -void (*XRRConfigureOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, int, int, int, long*); -void (*XRRChangeOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, Atom, int, int,const unsigned char*, int); -void (*XRRDeleteOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom); -int (*XRRGetOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -XRRModeInfo* (*XRRAllocModeInfo_dylibloader_wrapper_xrandr)(const char*, int); -RRMode (*XRRCreateMode_dylibloader_wrapper_xrandr)( Display*, Window, XRRModeInfo*); -void (*XRRDestroyMode_dylibloader_wrapper_xrandr)( Display*, RRMode); -void (*XRRAddOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode); -void (*XRRDeleteOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode); -void (*XRRFreeModeInfo_dylibloader_wrapper_xrandr)( XRRModeInfo*); -XRRCrtcInfo* (*XRRGetCrtcInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc); -void (*XRRFreeCrtcInfo_dylibloader_wrapper_xrandr)( XRRCrtcInfo*); -int (*XRRSetCrtcConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, Time, int, int, RRMode, Rotation, RROutput*, int); -int (*XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr)( Display*, RRCrtc); -XRRCrtcGamma* (*XRRGetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc); -XRRCrtcGamma* (*XRRAllocGamma_dylibloader_wrapper_xrandr)( int); -void (*XRRSetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcGamma*); -void (*XRRFreeGamma_dylibloader_wrapper_xrandr)( XRRCrtcGamma*); -XRRScreenResources* (*XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr)( Display*, Window); -void (*XRRSetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XTransform*,const char*, XFixed*, int); -int (*XRRGetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcTransformAttributes**); -int (*XRRUpdateConfiguration_dylibloader_wrapper_xrandr)( XEvent*); -XRRPanning* (*XRRGetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc); -void (*XRRFreePanning_dylibloader_wrapper_xrandr)( XRRPanning*); -int (*XRRSetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, XRRPanning*); -void (*XRRSetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window, RROutput); -RROutput (*XRRGetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window); -XRRProviderResources* (*XRRGetProviderResources_dylibloader_wrapper_xrandr)( Display*, Window); -void (*XRRFreeProviderResources_dylibloader_wrapper_xrandr)( XRRProviderResources*); -XRRProviderInfo* (*XRRGetProviderInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRProvider); -void (*XRRFreeProviderInfo_dylibloader_wrapper_xrandr)( XRRProviderInfo*); -int (*XRRSetProviderOutputSource_dylibloader_wrapper_xrandr)( Display*, XID, XID); -int (*XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr)( Display*, XID, XID); -Atom* (*XRRListProviderProperties_dylibloader_wrapper_xrandr)( Display*, RRProvider, int*); -XRRPropertyInfo* (*XRRQueryProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom); -void (*XRRConfigureProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, int, int, int, long*); -void (*XRRChangeProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, Atom, int, int,const unsigned char*, int); -void (*XRRDeleteProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom); -int (*XRRGetProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -XRRMonitorInfo* (*XRRAllocateMonitor_dylibloader_wrapper_xrandr)( Display*, int); -XRRMonitorInfo* (*XRRGetMonitors_dylibloader_wrapper_xrandr)( Display*, Window, int, int*); -void (*XRRSetMonitor_dylibloader_wrapper_xrandr)( Display*, Window, XRRMonitorInfo*); -void (*XRRDeleteMonitor_dylibloader_wrapper_xrandr)( Display*, Window, Atom); -void (*XRRFreeMonitors_dylibloader_wrapper_xrandr)( XRRMonitorInfo*); +int (*XRRQueryExtension_dylibloader_wrapper_xrandr)(Display *, int *, int *); +int (*XRRQueryVersion_dylibloader_wrapper_xrandr)(Display *, int *, int *); +XRRScreenConfiguration *(*XRRGetScreenInfo_dylibloader_wrapper_xrandr)(Display *, Window); +void (*XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *); +int (*XRRSetScreenConfig_dylibloader_wrapper_xrandr)(Display *, XRRScreenConfiguration *, Drawable, int, Rotation, Time); +int (*XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr)(Display *, XRRScreenConfiguration *, Drawable, int, Rotation, short, Time); +Rotation (*XRRConfigRotations_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, Rotation *); +Time (*XRRConfigTimes_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, Time *); +XRRScreenSize *(*XRRConfigSizes_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, int *); +short *(*XRRConfigRates_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, int, int *); +SizeID (*XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, Rotation *); +short (*XRRConfigCurrentRate_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *); +int (*XRRRootToScreen_dylibloader_wrapper_xrandr)(Display *, Window); +void (*XRRSelectInput_dylibloader_wrapper_xrandr)(Display *, Window, int); +Rotation (*XRRRotations_dylibloader_wrapper_xrandr)(Display *, int, Rotation *); +XRRScreenSize *(*XRRSizes_dylibloader_wrapper_xrandr)(Display *, int, int *); +short *(*XRRRates_dylibloader_wrapper_xrandr)(Display *, int, int, int *); +Time (*XRRTimes_dylibloader_wrapper_xrandr)(Display *, int, Time *); +int (*XRRGetScreenSizeRange_dylibloader_wrapper_xrandr)(Display *, Window, int *, int *, int *, int *); +void (*XRRSetScreenSize_dylibloader_wrapper_xrandr)(Display *, Window, int, int, int, int); +XRRScreenResources *(*XRRGetScreenResources_dylibloader_wrapper_xrandr)(Display *, Window); +void (*XRRFreeScreenResources_dylibloader_wrapper_xrandr)(XRRScreenResources *); +XRROutputInfo *(*XRRGetOutputInfo_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RROutput); +void (*XRRFreeOutputInfo_dylibloader_wrapper_xrandr)(XRROutputInfo *); +Atom *(*XRRListOutputProperties_dylibloader_wrapper_xrandr)(Display *, RROutput, int *); +XRRPropertyInfo *(*XRRQueryOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom); +void (*XRRConfigureOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom, int, int, int, long *); +void (*XRRChangeOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom, Atom, int, int, const unsigned char *, int); +void (*XRRDeleteOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom); +int (*XRRGetOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom, long, long, int, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +XRRModeInfo *(*XRRAllocModeInfo_dylibloader_wrapper_xrandr)(const char *, int); +RRMode (*XRRCreateMode_dylibloader_wrapper_xrandr)(Display *, Window, XRRModeInfo *); +void (*XRRDestroyMode_dylibloader_wrapper_xrandr)(Display *, RRMode); +void (*XRRAddOutputMode_dylibloader_wrapper_xrandr)(Display *, RROutput, RRMode); +void (*XRRDeleteOutputMode_dylibloader_wrapper_xrandr)(Display *, RROutput, RRMode); +void (*XRRFreeModeInfo_dylibloader_wrapper_xrandr)(XRRModeInfo *); +XRRCrtcInfo *(*XRRGetCrtcInfo_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc); +void (*XRRFreeCrtcInfo_dylibloader_wrapper_xrandr)(XRRCrtcInfo *); +int (*XRRSetCrtcConfig_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc, Time, int, int, RRMode, Rotation, RROutput *, int); +int (*XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr)(Display *, RRCrtc); +XRRCrtcGamma *(*XRRGetCrtcGamma_dylibloader_wrapper_xrandr)(Display *, RRCrtc); +XRRCrtcGamma *(*XRRAllocGamma_dylibloader_wrapper_xrandr)(int); +void (*XRRSetCrtcGamma_dylibloader_wrapper_xrandr)(Display *, RRCrtc, XRRCrtcGamma *); +void (*XRRFreeGamma_dylibloader_wrapper_xrandr)(XRRCrtcGamma *); +XRRScreenResources *(*XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr)(Display *, Window); +void (*XRRSetCrtcTransform_dylibloader_wrapper_xrandr)(Display *, RRCrtc, XTransform *, const char *, XFixed *, int); +int (*XRRGetCrtcTransform_dylibloader_wrapper_xrandr)(Display *, RRCrtc, XRRCrtcTransformAttributes **); +int (*XRRUpdateConfiguration_dylibloader_wrapper_xrandr)(XEvent *); +XRRPanning *(*XRRGetPanning_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc); +void (*XRRFreePanning_dylibloader_wrapper_xrandr)(XRRPanning *); +int (*XRRSetPanning_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc, XRRPanning *); +void (*XRRSetOutputPrimary_dylibloader_wrapper_xrandr)(Display *, Window, RROutput); +RROutput (*XRRGetOutputPrimary_dylibloader_wrapper_xrandr)(Display *, Window); +XRRProviderResources *(*XRRGetProviderResources_dylibloader_wrapper_xrandr)(Display *, Window); +void (*XRRFreeProviderResources_dylibloader_wrapper_xrandr)(XRRProviderResources *); +XRRProviderInfo *(*XRRGetProviderInfo_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRProvider); +void (*XRRFreeProviderInfo_dylibloader_wrapper_xrandr)(XRRProviderInfo *); +int (*XRRSetProviderOutputSource_dylibloader_wrapper_xrandr)(Display *, XID, XID); +int (*XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr)(Display *, XID, XID); +Atom *(*XRRListProviderProperties_dylibloader_wrapper_xrandr)(Display *, RRProvider, int *); +XRRPropertyInfo *(*XRRQueryProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom); +void (*XRRConfigureProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom, int, int, int, long *); +void (*XRRChangeProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom, Atom, int, int, const unsigned char *, int); +void (*XRRDeleteProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom); +int (*XRRGetProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom, long, long, int, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +XRRMonitorInfo *(*XRRAllocateMonitor_dylibloader_wrapper_xrandr)(Display *, int); +XRRMonitorInfo *(*XRRGetMonitors_dylibloader_wrapper_xrandr)(Display *, Window, int, int *); +void (*XRRSetMonitor_dylibloader_wrapper_xrandr)(Display *, Window, XRRMonitorInfo *); +void (*XRRDeleteMonitor_dylibloader_wrapper_xrandr)(Display *, Window, Atom); +void (*XRRFreeMonitors_dylibloader_wrapper_xrandr)(XRRMonitorInfo *); int initialize_xrandr(int verbose) { void *handle; char *error; diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h index db5d44203d..c055705f69 100644 --- a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h +++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h @@ -2,13 +2,9 @@ #define DYLIBLOAD_WRAPPER_XRANDR // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:54 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h" --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:37 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c --ignore-other // -// NOTE: Generated from Xrandr 1.5.2. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11 and libXrender, but absent in libXrandr.so.2, were removed. #include <stdint.h> #define XRRQueryExtension XRRQueryExtension_dylibloader_orig_xrandr @@ -225,76 +221,76 @@ extern "C" { #define XRRSetMonitor XRRSetMonitor_dylibloader_wrapper_xrandr #define XRRDeleteMonitor XRRDeleteMonitor_dylibloader_wrapper_xrandr #define XRRFreeMonitors XRRFreeMonitors_dylibloader_wrapper_xrandr -extern int (*XRRQueryExtension_dylibloader_wrapper_xrandr)( Display*, int*, int*); -extern int (*XRRQueryVersion_dylibloader_wrapper_xrandr)( Display*, int*, int*); -extern XRRScreenConfiguration* (*XRRGetScreenInfo_dylibloader_wrapper_xrandr)( Display*, Window); -extern void (*XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*); -extern int (*XRRSetScreenConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, Time); -extern int (*XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr)( Display*, XRRScreenConfiguration*, Drawable, int, Rotation, short, Time); -extern Rotation (*XRRConfigRotations_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*); -extern Time (*XRRConfigTimes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Time*); -extern XRRScreenSize* (*XRRConfigSizes_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int*); -extern short* (*XRRConfigRates_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, int, int*); -extern SizeID (*XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*, Rotation*); -extern short (*XRRConfigCurrentRate_dylibloader_wrapper_xrandr)( XRRScreenConfiguration*); -extern int (*XRRRootToScreen_dylibloader_wrapper_xrandr)( Display*, Window); -extern void (*XRRSelectInput_dylibloader_wrapper_xrandr)( Display*, Window, int); -extern Rotation (*XRRRotations_dylibloader_wrapper_xrandr)( Display*, int, Rotation*); -extern XRRScreenSize* (*XRRSizes_dylibloader_wrapper_xrandr)( Display*, int, int*); -extern short* (*XRRRates_dylibloader_wrapper_xrandr)( Display*, int, int, int*); -extern Time (*XRRTimes_dylibloader_wrapper_xrandr)( Display*, int, Time*); -extern int (*XRRGetScreenSizeRange_dylibloader_wrapper_xrandr)( Display*, Window, int*, int*, int*, int*); -extern void (*XRRSetScreenSize_dylibloader_wrapper_xrandr)( Display*, Window, int, int, int, int); -extern XRRScreenResources* (*XRRGetScreenResources_dylibloader_wrapper_xrandr)( Display*, Window); -extern void (*XRRFreeScreenResources_dylibloader_wrapper_xrandr)( XRRScreenResources*); -extern XRROutputInfo* (*XRRGetOutputInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RROutput); -extern void (*XRRFreeOutputInfo_dylibloader_wrapper_xrandr)( XRROutputInfo*); -extern Atom* (*XRRListOutputProperties_dylibloader_wrapper_xrandr)( Display*, RROutput, int*); -extern XRRPropertyInfo* (*XRRQueryOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom); -extern void (*XRRConfigureOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, int, int, int, long*); -extern void (*XRRChangeOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, Atom, int, int,const unsigned char*, int); -extern void (*XRRDeleteOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom); -extern int (*XRRGetOutputProperty_dylibloader_wrapper_xrandr)( Display*, RROutput, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -extern XRRModeInfo* (*XRRAllocModeInfo_dylibloader_wrapper_xrandr)(const char*, int); -extern RRMode (*XRRCreateMode_dylibloader_wrapper_xrandr)( Display*, Window, XRRModeInfo*); -extern void (*XRRDestroyMode_dylibloader_wrapper_xrandr)( Display*, RRMode); -extern void (*XRRAddOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode); -extern void (*XRRDeleteOutputMode_dylibloader_wrapper_xrandr)( Display*, RROutput, RRMode); -extern void (*XRRFreeModeInfo_dylibloader_wrapper_xrandr)( XRRModeInfo*); -extern XRRCrtcInfo* (*XRRGetCrtcInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc); -extern void (*XRRFreeCrtcInfo_dylibloader_wrapper_xrandr)( XRRCrtcInfo*); -extern int (*XRRSetCrtcConfig_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, Time, int, int, RRMode, Rotation, RROutput*, int); -extern int (*XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr)( Display*, RRCrtc); -extern XRRCrtcGamma* (*XRRGetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc); -extern XRRCrtcGamma* (*XRRAllocGamma_dylibloader_wrapper_xrandr)( int); -extern void (*XRRSetCrtcGamma_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcGamma*); -extern void (*XRRFreeGamma_dylibloader_wrapper_xrandr)( XRRCrtcGamma*); -extern XRRScreenResources* (*XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr)( Display*, Window); -extern void (*XRRSetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XTransform*,const char*, XFixed*, int); -extern int (*XRRGetCrtcTransform_dylibloader_wrapper_xrandr)( Display*, RRCrtc, XRRCrtcTransformAttributes**); -extern int (*XRRUpdateConfiguration_dylibloader_wrapper_xrandr)( XEvent*); -extern XRRPanning* (*XRRGetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc); -extern void (*XRRFreePanning_dylibloader_wrapper_xrandr)( XRRPanning*); -extern int (*XRRSetPanning_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRCrtc, XRRPanning*); -extern void (*XRRSetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window, RROutput); -extern RROutput (*XRRGetOutputPrimary_dylibloader_wrapper_xrandr)( Display*, Window); -extern XRRProviderResources* (*XRRGetProviderResources_dylibloader_wrapper_xrandr)( Display*, Window); -extern void (*XRRFreeProviderResources_dylibloader_wrapper_xrandr)( XRRProviderResources*); -extern XRRProviderInfo* (*XRRGetProviderInfo_dylibloader_wrapper_xrandr)( Display*, XRRScreenResources*, RRProvider); -extern void (*XRRFreeProviderInfo_dylibloader_wrapper_xrandr)( XRRProviderInfo*); -extern int (*XRRSetProviderOutputSource_dylibloader_wrapper_xrandr)( Display*, XID, XID); -extern int (*XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr)( Display*, XID, XID); -extern Atom* (*XRRListProviderProperties_dylibloader_wrapper_xrandr)( Display*, RRProvider, int*); -extern XRRPropertyInfo* (*XRRQueryProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom); -extern void (*XRRConfigureProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, int, int, int, long*); -extern void (*XRRChangeProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, Atom, int, int,const unsigned char*, int); -extern void (*XRRDeleteProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom); -extern int (*XRRGetProviderProperty_dylibloader_wrapper_xrandr)( Display*, RRProvider, Atom, long, long, int, int, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**); -extern XRRMonitorInfo* (*XRRAllocateMonitor_dylibloader_wrapper_xrandr)( Display*, int); -extern XRRMonitorInfo* (*XRRGetMonitors_dylibloader_wrapper_xrandr)( Display*, Window, int, int*); -extern void (*XRRSetMonitor_dylibloader_wrapper_xrandr)( Display*, Window, XRRMonitorInfo*); -extern void (*XRRDeleteMonitor_dylibloader_wrapper_xrandr)( Display*, Window, Atom); -extern void (*XRRFreeMonitors_dylibloader_wrapper_xrandr)( XRRMonitorInfo*); +extern int (*XRRQueryExtension_dylibloader_wrapper_xrandr)(Display *, int *, int *); +extern int (*XRRQueryVersion_dylibloader_wrapper_xrandr)(Display *, int *, int *); +extern XRRScreenConfiguration *(*XRRGetScreenInfo_dylibloader_wrapper_xrandr)(Display *, Window); +extern void (*XRRFreeScreenConfigInfo_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *); +extern int (*XRRSetScreenConfig_dylibloader_wrapper_xrandr)(Display *, XRRScreenConfiguration *, Drawable, int, Rotation, Time); +extern int (*XRRSetScreenConfigAndRate_dylibloader_wrapper_xrandr)(Display *, XRRScreenConfiguration *, Drawable, int, Rotation, short, Time); +extern Rotation (*XRRConfigRotations_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, Rotation *); +extern Time (*XRRConfigTimes_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, Time *); +extern XRRScreenSize *(*XRRConfigSizes_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, int *); +extern short *(*XRRConfigRates_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, int, int *); +extern SizeID (*XRRConfigCurrentConfiguration_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *, Rotation *); +extern short (*XRRConfigCurrentRate_dylibloader_wrapper_xrandr)(XRRScreenConfiguration *); +extern int (*XRRRootToScreen_dylibloader_wrapper_xrandr)(Display *, Window); +extern void (*XRRSelectInput_dylibloader_wrapper_xrandr)(Display *, Window, int); +extern Rotation (*XRRRotations_dylibloader_wrapper_xrandr)(Display *, int, Rotation *); +extern XRRScreenSize *(*XRRSizes_dylibloader_wrapper_xrandr)(Display *, int, int *); +extern short *(*XRRRates_dylibloader_wrapper_xrandr)(Display *, int, int, int *); +extern Time (*XRRTimes_dylibloader_wrapper_xrandr)(Display *, int, Time *); +extern int (*XRRGetScreenSizeRange_dylibloader_wrapper_xrandr)(Display *, Window, int *, int *, int *, int *); +extern void (*XRRSetScreenSize_dylibloader_wrapper_xrandr)(Display *, Window, int, int, int, int); +extern XRRScreenResources *(*XRRGetScreenResources_dylibloader_wrapper_xrandr)(Display *, Window); +extern void (*XRRFreeScreenResources_dylibloader_wrapper_xrandr)(XRRScreenResources *); +extern XRROutputInfo *(*XRRGetOutputInfo_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RROutput); +extern void (*XRRFreeOutputInfo_dylibloader_wrapper_xrandr)(XRROutputInfo *); +extern Atom *(*XRRListOutputProperties_dylibloader_wrapper_xrandr)(Display *, RROutput, int *); +extern XRRPropertyInfo *(*XRRQueryOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom); +extern void (*XRRConfigureOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom, int, int, int, long *); +extern void (*XRRChangeOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom, Atom, int, int, const unsigned char *, int); +extern void (*XRRDeleteOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom); +extern int (*XRRGetOutputProperty_dylibloader_wrapper_xrandr)(Display *, RROutput, Atom, long, long, int, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +extern XRRModeInfo *(*XRRAllocModeInfo_dylibloader_wrapper_xrandr)(const char *, int); +extern RRMode (*XRRCreateMode_dylibloader_wrapper_xrandr)(Display *, Window, XRRModeInfo *); +extern void (*XRRDestroyMode_dylibloader_wrapper_xrandr)(Display *, RRMode); +extern void (*XRRAddOutputMode_dylibloader_wrapper_xrandr)(Display *, RROutput, RRMode); +extern void (*XRRDeleteOutputMode_dylibloader_wrapper_xrandr)(Display *, RROutput, RRMode); +extern void (*XRRFreeModeInfo_dylibloader_wrapper_xrandr)(XRRModeInfo *); +extern XRRCrtcInfo *(*XRRGetCrtcInfo_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc); +extern void (*XRRFreeCrtcInfo_dylibloader_wrapper_xrandr)(XRRCrtcInfo *); +extern int (*XRRSetCrtcConfig_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc, Time, int, int, RRMode, Rotation, RROutput *, int); +extern int (*XRRGetCrtcGammaSize_dylibloader_wrapper_xrandr)(Display *, RRCrtc); +extern XRRCrtcGamma *(*XRRGetCrtcGamma_dylibloader_wrapper_xrandr)(Display *, RRCrtc); +extern XRRCrtcGamma *(*XRRAllocGamma_dylibloader_wrapper_xrandr)(int); +extern void (*XRRSetCrtcGamma_dylibloader_wrapper_xrandr)(Display *, RRCrtc, XRRCrtcGamma *); +extern void (*XRRFreeGamma_dylibloader_wrapper_xrandr)(XRRCrtcGamma *); +extern XRRScreenResources *(*XRRGetScreenResourcesCurrent_dylibloader_wrapper_xrandr)(Display *, Window); +extern void (*XRRSetCrtcTransform_dylibloader_wrapper_xrandr)(Display *, RRCrtc, XTransform *, const char *, XFixed *, int); +extern int (*XRRGetCrtcTransform_dylibloader_wrapper_xrandr)(Display *, RRCrtc, XRRCrtcTransformAttributes **); +extern int (*XRRUpdateConfiguration_dylibloader_wrapper_xrandr)(XEvent *); +extern XRRPanning *(*XRRGetPanning_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc); +extern void (*XRRFreePanning_dylibloader_wrapper_xrandr)(XRRPanning *); +extern int (*XRRSetPanning_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRCrtc, XRRPanning *); +extern void (*XRRSetOutputPrimary_dylibloader_wrapper_xrandr)(Display *, Window, RROutput); +extern RROutput (*XRRGetOutputPrimary_dylibloader_wrapper_xrandr)(Display *, Window); +extern XRRProviderResources *(*XRRGetProviderResources_dylibloader_wrapper_xrandr)(Display *, Window); +extern void (*XRRFreeProviderResources_dylibloader_wrapper_xrandr)(XRRProviderResources *); +extern XRRProviderInfo *(*XRRGetProviderInfo_dylibloader_wrapper_xrandr)(Display *, XRRScreenResources *, RRProvider); +extern void (*XRRFreeProviderInfo_dylibloader_wrapper_xrandr)(XRRProviderInfo *); +extern int (*XRRSetProviderOutputSource_dylibloader_wrapper_xrandr)(Display *, XID, XID); +extern int (*XRRSetProviderOffloadSink_dylibloader_wrapper_xrandr)(Display *, XID, XID); +extern Atom *(*XRRListProviderProperties_dylibloader_wrapper_xrandr)(Display *, RRProvider, int *); +extern XRRPropertyInfo *(*XRRQueryProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom); +extern void (*XRRConfigureProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom, int, int, int, long *); +extern void (*XRRChangeProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom, Atom, int, int, const unsigned char *, int); +extern void (*XRRDeleteProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom); +extern int (*XRRGetProviderProperty_dylibloader_wrapper_xrandr)(Display *, RRProvider, Atom, long, long, int, int, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); +extern XRRMonitorInfo *(*XRRAllocateMonitor_dylibloader_wrapper_xrandr)(Display *, int); +extern XRRMonitorInfo *(*XRRGetMonitors_dylibloader_wrapper_xrandr)(Display *, Window, int, int *); +extern void (*XRRSetMonitor_dylibloader_wrapper_xrandr)(Display *, Window, XRRMonitorInfo *); +extern void (*XRRDeleteMonitor_dylibloader_wrapper_xrandr)(Display *, Window, Atom); +extern void (*XRRFreeMonitors_dylibloader_wrapper_xrandr)(XRRMonitorInfo *); int initialize_xrandr(int verbose); #ifdef __cplusplus } diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c index 7421f94601..e1cd987eca 100644 --- a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c +++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c @@ -1,12 +1,8 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:14:14 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrender.h" --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c~ +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:37 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c --ignore-other // -// NOTE: Generated from Xrender 0.9.10. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXrender.so.1, were removed. #include <stdint.h> #define XRenderQueryExtension XRenderQueryExtension_dylibloader_orig_xrender @@ -100,50 +96,50 @@ #undef XRenderCreateConicalGradient #include <dlfcn.h> #include <stdio.h> -int (*XRenderQueryExtension_dylibloader_wrapper_xrender)( Display*, int*, int*); -int (*XRenderQueryVersion_dylibloader_wrapper_xrender)( Display*, int*, int*); -int (*XRenderQueryFormats_dylibloader_wrapper_xrender)( Display*); -int (*XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender)( Display*, int); -int (*XRenderSetSubpixelOrder_dylibloader_wrapper_xrender)( Display*, int, int); -XRenderPictFormat* (*XRenderFindVisualFormat_dylibloader_wrapper_xrender)( Display*,const Visual*); -XRenderPictFormat* (*XRenderFindFormat_dylibloader_wrapper_xrender)( Display*, unsigned long,const XRenderPictFormat*, int); -XRenderPictFormat* (*XRenderFindStandardFormat_dylibloader_wrapper_xrender)( Display*, int); -XIndexValue* (*XRenderQueryPictIndexValues_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*, int*); -Picture (*XRenderCreatePicture_dylibloader_wrapper_xrender)( Display*, Drawable,const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*); -void (*XRenderChangePicture_dylibloader_wrapper_xrender)( Display*, Picture, unsigned long,const XRenderPictureAttributes*); -void (*XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XRectangle*, int); -void (*XRenderSetPictureClipRegion_dylibloader_wrapper_xrender)( Display*, Picture, Region); -void (*XRenderSetPictureTransform_dylibloader_wrapper_xrender)( Display*, Picture, XTransform*); -void (*XRenderFreePicture_dylibloader_wrapper_xrender)( Display*, Picture); -void (*XRenderComposite_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture, Picture, int, int, int, int, int, int, unsigned int, unsigned int); -GlyphSet (*XRenderCreateGlyphSet_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*); -GlyphSet (*XRenderReferenceGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet); -void (*XRenderFreeGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet); -void (*XRenderAddGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*,const XGlyphInfo*, int,const char*, int); -void (*XRenderFreeGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*, int); -void (*XRenderCompositeString8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const char*, int); -void (*XRenderCompositeString16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned short*, int); -void (*XRenderCompositeString32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned int*, int); -void (*XRenderCompositeText8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt8*, int); -void (*XRenderCompositeText16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt16*, int); -void (*XRenderCompositeText32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt32*, int); -void (*XRenderFillRectangle_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*, int, int, unsigned int, unsigned int); -void (*XRenderFillRectangles_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*,const XRectangle*, int); -void (*XRenderCompositeTrapezoids_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTrapezoid*, int); -void (*XRenderCompositeTriangles_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTriangle*, int); -void (*XRenderCompositeTriStrip_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int); -void (*XRenderCompositeTriFan_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int); -void (*XRenderCompositeDoublePoly_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XPointDouble*, int, int); -int (*XRenderParseColor_dylibloader_wrapper_xrender)( Display*, char*, XRenderColor*); -Cursor (*XRenderCreateCursor_dylibloader_wrapper_xrender)( Display*, Picture, unsigned int, unsigned int); -XFilters* (*XRenderQueryFilters_dylibloader_wrapper_xrender)( Display*, Drawable); -void (*XRenderSetPictureFilter_dylibloader_wrapper_xrender)( Display*, Picture,const char*, XFixed*, int); -Cursor (*XRenderCreateAnimCursor_dylibloader_wrapper_xrender)( Display*, int, XAnimCursor*); -void (*XRenderAddTraps_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XTrap*, int); -Picture (*XRenderCreateSolidFill_dylibloader_wrapper_xrender)( Display*,const XRenderColor*); -Picture (*XRenderCreateLinearGradient_dylibloader_wrapper_xrender)( Display*,const XLinearGradient*,const XFixed*,const XRenderColor*, int); -Picture (*XRenderCreateRadialGradient_dylibloader_wrapper_xrender)( Display*,const XRadialGradient*,const XFixed*,const XRenderColor*, int); -Picture (*XRenderCreateConicalGradient_dylibloader_wrapper_xrender)( Display*,const XConicalGradient*,const XFixed*,const XRenderColor*, int); +int (*XRenderQueryExtension_dylibloader_wrapper_xrender)(Display *, int *, int *); +int (*XRenderQueryVersion_dylibloader_wrapper_xrender)(Display *, int *, int *); +int (*XRenderQueryFormats_dylibloader_wrapper_xrender)(Display *); +int (*XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender)(Display *, int); +int (*XRenderSetSubpixelOrder_dylibloader_wrapper_xrender)(Display *, int, int); +XRenderPictFormat *(*XRenderFindVisualFormat_dylibloader_wrapper_xrender)(Display *, const Visual *); +XRenderPictFormat *(*XRenderFindFormat_dylibloader_wrapper_xrender)(Display *, unsigned long, const XRenderPictFormat *, int); +XRenderPictFormat *(*XRenderFindStandardFormat_dylibloader_wrapper_xrender)(Display *, int); +XIndexValue *(*XRenderQueryPictIndexValues_dylibloader_wrapper_xrender)(Display *, const XRenderPictFormat *, int *); +Picture (*XRenderCreatePicture_dylibloader_wrapper_xrender)(Display *, Drawable, const XRenderPictFormat *, unsigned long, const XRenderPictureAttributes *); +void (*XRenderChangePicture_dylibloader_wrapper_xrender)(Display *, Picture, unsigned long, const XRenderPictureAttributes *); +void (*XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender)(Display *, Picture, int, int, const XRectangle *, int); +void (*XRenderSetPictureClipRegion_dylibloader_wrapper_xrender)(Display *, Picture, Region); +void (*XRenderSetPictureTransform_dylibloader_wrapper_xrender)(Display *, Picture, XTransform *); +void (*XRenderFreePicture_dylibloader_wrapper_xrender)(Display *, Picture); +void (*XRenderComposite_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, Picture, int, int, int, int, int, int, unsigned int, unsigned int); +GlyphSet (*XRenderCreateGlyphSet_dylibloader_wrapper_xrender)(Display *, const XRenderPictFormat *); +GlyphSet (*XRenderReferenceGlyphSet_dylibloader_wrapper_xrender)(Display *, GlyphSet); +void (*XRenderFreeGlyphSet_dylibloader_wrapper_xrender)(Display *, GlyphSet); +void (*XRenderAddGlyphs_dylibloader_wrapper_xrender)(Display *, GlyphSet, const Glyph *, const XGlyphInfo *, int, const char *, int); +void (*XRenderFreeGlyphs_dylibloader_wrapper_xrender)(Display *, GlyphSet, const Glyph *, int); +void (*XRenderCompositeString8_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, GlyphSet, int, int, int, int, const char *, int); +void (*XRenderCompositeString16_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, GlyphSet, int, int, int, int, const unsigned short *, int); +void (*XRenderCompositeString32_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, GlyphSet, int, int, int, int, const unsigned int *, int); +void (*XRenderCompositeText8_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XGlyphElt8 *, int); +void (*XRenderCompositeText16_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XGlyphElt16 *, int); +void (*XRenderCompositeText32_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XGlyphElt32 *, int); +void (*XRenderFillRectangle_dylibloader_wrapper_xrender)(Display *, int, Picture, const XRenderColor *, int, int, unsigned int, unsigned int); +void (*XRenderFillRectangles_dylibloader_wrapper_xrender)(Display *, int, Picture, const XRenderColor *, const XRectangle *, int); +void (*XRenderCompositeTrapezoids_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XTrapezoid *, int); +void (*XRenderCompositeTriangles_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XTriangle *, int); +void (*XRenderCompositeTriStrip_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XPointFixed *, int); +void (*XRenderCompositeTriFan_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XPointFixed *, int); +void (*XRenderCompositeDoublePoly_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XPointDouble *, int, int); +int (*XRenderParseColor_dylibloader_wrapper_xrender)(Display *, char *, XRenderColor *); +Cursor (*XRenderCreateCursor_dylibloader_wrapper_xrender)(Display *, Picture, unsigned int, unsigned int); +XFilters *(*XRenderQueryFilters_dylibloader_wrapper_xrender)(Display *, Drawable); +void (*XRenderSetPictureFilter_dylibloader_wrapper_xrender)(Display *, Picture, const char *, XFixed *, int); +Cursor (*XRenderCreateAnimCursor_dylibloader_wrapper_xrender)(Display *, int, XAnimCursor *); +void (*XRenderAddTraps_dylibloader_wrapper_xrender)(Display *, Picture, int, int, const XTrap *, int); +Picture (*XRenderCreateSolidFill_dylibloader_wrapper_xrender)(Display *, const XRenderColor *); +Picture (*XRenderCreateLinearGradient_dylibloader_wrapper_xrender)(Display *, const XLinearGradient *, const XFixed *, const XRenderColor *, int); +Picture (*XRenderCreateRadialGradient_dylibloader_wrapper_xrender)(Display *, const XRadialGradient *, const XFixed *, const XRenderColor *, int); +Picture (*XRenderCreateConicalGradient_dylibloader_wrapper_xrender)(Display *, const XConicalGradient *, const XFixed *, const XRenderColor *, int); int initialize_xrender(int verbose) { void *handle; char *error; diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h index 5d3f695959..3d0e8901ea 100644 --- a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h +++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h @@ -2,13 +2,9 @@ #define DYLIBLOAD_WRAPPER_XRENDER // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by generate-wrapper.py 0.3 on 2023-01-23 15:14:14 -// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrender.h" --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c~ +// generated by generate-wrapper.py 0.6 on 2024-11-09 02:52:37 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c --ignore-other // -// NOTE: Generated from Xrender 0.9.10. -// This has been handpatched to workaround some issues with the generator that -// will be eventually fixed. In this case, non-existent symbols inherited from -// libX11, but absent in libXrender.so.1, were removed. #include <stdint.h> #define XRenderQueryExtension XRenderQueryExtension_dylibloader_orig_xrender @@ -147,50 +143,50 @@ extern "C" { #define XRenderCreateLinearGradient XRenderCreateLinearGradient_dylibloader_wrapper_xrender #define XRenderCreateRadialGradient XRenderCreateRadialGradient_dylibloader_wrapper_xrender #define XRenderCreateConicalGradient XRenderCreateConicalGradient_dylibloader_wrapper_xrender -extern int (*XRenderQueryExtension_dylibloader_wrapper_xrender)( Display*, int*, int*); -extern int (*XRenderQueryVersion_dylibloader_wrapper_xrender)( Display*, int*, int*); -extern int (*XRenderQueryFormats_dylibloader_wrapper_xrender)( Display*); -extern int (*XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender)( Display*, int); -extern int (*XRenderSetSubpixelOrder_dylibloader_wrapper_xrender)( Display*, int, int); -extern XRenderPictFormat* (*XRenderFindVisualFormat_dylibloader_wrapper_xrender)( Display*,const Visual*); -extern XRenderPictFormat* (*XRenderFindFormat_dylibloader_wrapper_xrender)( Display*, unsigned long,const XRenderPictFormat*, int); -extern XRenderPictFormat* (*XRenderFindStandardFormat_dylibloader_wrapper_xrender)( Display*, int); -extern XIndexValue* (*XRenderQueryPictIndexValues_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*, int*); -extern Picture (*XRenderCreatePicture_dylibloader_wrapper_xrender)( Display*, Drawable,const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*); -extern void (*XRenderChangePicture_dylibloader_wrapper_xrender)( Display*, Picture, unsigned long,const XRenderPictureAttributes*); -extern void (*XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XRectangle*, int); -extern void (*XRenderSetPictureClipRegion_dylibloader_wrapper_xrender)( Display*, Picture, Region); -extern void (*XRenderSetPictureTransform_dylibloader_wrapper_xrender)( Display*, Picture, XTransform*); -extern void (*XRenderFreePicture_dylibloader_wrapper_xrender)( Display*, Picture); -extern void (*XRenderComposite_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture, Picture, int, int, int, int, int, int, unsigned int, unsigned int); -extern GlyphSet (*XRenderCreateGlyphSet_dylibloader_wrapper_xrender)( Display*,const XRenderPictFormat*); -extern GlyphSet (*XRenderReferenceGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet); -extern void (*XRenderFreeGlyphSet_dylibloader_wrapper_xrender)( Display*, GlyphSet); -extern void (*XRenderAddGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*,const XGlyphInfo*, int,const char*, int); -extern void (*XRenderFreeGlyphs_dylibloader_wrapper_xrender)( Display*, GlyphSet,const Glyph*, int); -extern void (*XRenderCompositeString8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const char*, int); -extern void (*XRenderCompositeString16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned short*, int); -extern void (*XRenderCompositeString32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, GlyphSet, int, int, int, int,const unsigned int*, int); -extern void (*XRenderCompositeText8_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt8*, int); -extern void (*XRenderCompositeText16_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt16*, int); -extern void (*XRenderCompositeText32_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XGlyphElt32*, int); -extern void (*XRenderFillRectangle_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*, int, int, unsigned int, unsigned int); -extern void (*XRenderFillRectangles_dylibloader_wrapper_xrender)( Display*, int, Picture,const XRenderColor*,const XRectangle*, int); -extern void (*XRenderCompositeTrapezoids_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTrapezoid*, int); -extern void (*XRenderCompositeTriangles_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XTriangle*, int); -extern void (*XRenderCompositeTriStrip_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int); -extern void (*XRenderCompositeTriFan_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int,const XPointFixed*, int); -extern void (*XRenderCompositeDoublePoly_dylibloader_wrapper_xrender)( Display*, int, Picture, Picture,const XRenderPictFormat*, int, int, int, int,const XPointDouble*, int, int); -extern int (*XRenderParseColor_dylibloader_wrapper_xrender)( Display*, char*, XRenderColor*); -extern Cursor (*XRenderCreateCursor_dylibloader_wrapper_xrender)( Display*, Picture, unsigned int, unsigned int); -extern XFilters* (*XRenderQueryFilters_dylibloader_wrapper_xrender)( Display*, Drawable); -extern void (*XRenderSetPictureFilter_dylibloader_wrapper_xrender)( Display*, Picture,const char*, XFixed*, int); -extern Cursor (*XRenderCreateAnimCursor_dylibloader_wrapper_xrender)( Display*, int, XAnimCursor*); -extern void (*XRenderAddTraps_dylibloader_wrapper_xrender)( Display*, Picture, int, int,const XTrap*, int); -extern Picture (*XRenderCreateSolidFill_dylibloader_wrapper_xrender)( Display*,const XRenderColor*); -extern Picture (*XRenderCreateLinearGradient_dylibloader_wrapper_xrender)( Display*,const XLinearGradient*,const XFixed*,const XRenderColor*, int); -extern Picture (*XRenderCreateRadialGradient_dylibloader_wrapper_xrender)( Display*,const XRadialGradient*,const XFixed*,const XRenderColor*, int); -extern Picture (*XRenderCreateConicalGradient_dylibloader_wrapper_xrender)( Display*,const XConicalGradient*,const XFixed*,const XRenderColor*, int); +extern int (*XRenderQueryExtension_dylibloader_wrapper_xrender)(Display *, int *, int *); +extern int (*XRenderQueryVersion_dylibloader_wrapper_xrender)(Display *, int *, int *); +extern int (*XRenderQueryFormats_dylibloader_wrapper_xrender)(Display *); +extern int (*XRenderQuerySubpixelOrder_dylibloader_wrapper_xrender)(Display *, int); +extern int (*XRenderSetSubpixelOrder_dylibloader_wrapper_xrender)(Display *, int, int); +extern XRenderPictFormat *(*XRenderFindVisualFormat_dylibloader_wrapper_xrender)(Display *, const Visual *); +extern XRenderPictFormat *(*XRenderFindFormat_dylibloader_wrapper_xrender)(Display *, unsigned long, const XRenderPictFormat *, int); +extern XRenderPictFormat *(*XRenderFindStandardFormat_dylibloader_wrapper_xrender)(Display *, int); +extern XIndexValue *(*XRenderQueryPictIndexValues_dylibloader_wrapper_xrender)(Display *, const XRenderPictFormat *, int *); +extern Picture (*XRenderCreatePicture_dylibloader_wrapper_xrender)(Display *, Drawable, const XRenderPictFormat *, unsigned long, const XRenderPictureAttributes *); +extern void (*XRenderChangePicture_dylibloader_wrapper_xrender)(Display *, Picture, unsigned long, const XRenderPictureAttributes *); +extern void (*XRenderSetPictureClipRectangles_dylibloader_wrapper_xrender)(Display *, Picture, int, int, const XRectangle *, int); +extern void (*XRenderSetPictureClipRegion_dylibloader_wrapper_xrender)(Display *, Picture, Region); +extern void (*XRenderSetPictureTransform_dylibloader_wrapper_xrender)(Display *, Picture, XTransform *); +extern void (*XRenderFreePicture_dylibloader_wrapper_xrender)(Display *, Picture); +extern void (*XRenderComposite_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, Picture, int, int, int, int, int, int, unsigned int, unsigned int); +extern GlyphSet (*XRenderCreateGlyphSet_dylibloader_wrapper_xrender)(Display *, const XRenderPictFormat *); +extern GlyphSet (*XRenderReferenceGlyphSet_dylibloader_wrapper_xrender)(Display *, GlyphSet); +extern void (*XRenderFreeGlyphSet_dylibloader_wrapper_xrender)(Display *, GlyphSet); +extern void (*XRenderAddGlyphs_dylibloader_wrapper_xrender)(Display *, GlyphSet, const Glyph *, const XGlyphInfo *, int, const char *, int); +extern void (*XRenderFreeGlyphs_dylibloader_wrapper_xrender)(Display *, GlyphSet, const Glyph *, int); +extern void (*XRenderCompositeString8_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, GlyphSet, int, int, int, int, const char *, int); +extern void (*XRenderCompositeString16_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, GlyphSet, int, int, int, int, const unsigned short *, int); +extern void (*XRenderCompositeString32_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, GlyphSet, int, int, int, int, const unsigned int *, int); +extern void (*XRenderCompositeText8_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XGlyphElt8 *, int); +extern void (*XRenderCompositeText16_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XGlyphElt16 *, int); +extern void (*XRenderCompositeText32_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XGlyphElt32 *, int); +extern void (*XRenderFillRectangle_dylibloader_wrapper_xrender)(Display *, int, Picture, const XRenderColor *, int, int, unsigned int, unsigned int); +extern void (*XRenderFillRectangles_dylibloader_wrapper_xrender)(Display *, int, Picture, const XRenderColor *, const XRectangle *, int); +extern void (*XRenderCompositeTrapezoids_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XTrapezoid *, int); +extern void (*XRenderCompositeTriangles_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XTriangle *, int); +extern void (*XRenderCompositeTriStrip_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XPointFixed *, int); +extern void (*XRenderCompositeTriFan_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, const XPointFixed *, int); +extern void (*XRenderCompositeDoublePoly_dylibloader_wrapper_xrender)(Display *, int, Picture, Picture, const XRenderPictFormat *, int, int, int, int, const XPointDouble *, int, int); +extern int (*XRenderParseColor_dylibloader_wrapper_xrender)(Display *, char *, XRenderColor *); +extern Cursor (*XRenderCreateCursor_dylibloader_wrapper_xrender)(Display *, Picture, unsigned int, unsigned int); +extern XFilters *(*XRenderQueryFilters_dylibloader_wrapper_xrender)(Display *, Drawable); +extern void (*XRenderSetPictureFilter_dylibloader_wrapper_xrender)(Display *, Picture, const char *, XFixed *, int); +extern Cursor (*XRenderCreateAnimCursor_dylibloader_wrapper_xrender)(Display *, int, XAnimCursor *); +extern void (*XRenderAddTraps_dylibloader_wrapper_xrender)(Display *, Picture, int, int, const XTrap *, int); +extern Picture (*XRenderCreateSolidFill_dylibloader_wrapper_xrender)(Display *, const XRenderColor *); +extern Picture (*XRenderCreateLinearGradient_dylibloader_wrapper_xrender)(Display *, const XLinearGradient *, const XFixed *, const XRenderColor *, int); +extern Picture (*XRenderCreateRadialGradient_dylibloader_wrapper_xrender)(Display *, const XRadialGradient *, const XFixed *, const XRenderColor *, int); +extern Picture (*XRenderCreateConicalGradient_dylibloader_wrapper_xrender)(Display *, const XConicalGradient *, const XFixed *, const XRenderColor *, int); int initialize_xrender(int verbose); #ifdef __cplusplus } diff --git a/platform/macos/SCsub b/platform/macos/SCsub index 3924e79fb6..598444ae24 100644 --- a/platform/macos/SCsub +++ b/platform/macos/SCsub @@ -27,7 +27,9 @@ def generate_bundle(target, source, env): target_bin = lipo(bin_dir + "/" + prefix, env.extra_suffix + env.module_version_string) # Assemble .app bundle and update version info. - app_dir = Dir("#bin/" + (prefix + env.extra_suffix + env.module_version_string).replace(".", "_") + ".app").abspath + app_dir = Dir( + "#bin/" + (prefix + env.extra_suffix + env.module_version_string).replace(".", "_") + ".app" + ).abspath templ = Dir("#misc/dist/macos_tools.app").abspath if os.path.exists(app_dir): shutil.rmtree(app_dir) diff --git a/platform/macos/crash_handler_macos.h b/platform/macos/crash_handler_macos.h index f821283167..d52cb7234a 100644 --- a/platform/macos/crash_handler_macos.h +++ b/platform/macos/crash_handler_macos.h @@ -38,7 +38,7 @@ public: void initialize(); void disable(); - bool is_disabled() const { return disabled; }; + bool is_disabled() const { return disabled; } CrashHandler(); ~CrashHandler(); diff --git a/platform/macos/detect.py b/platform/macos/detect.py index a8968b592e..3575e93c68 100644 --- a/platform/macos/detect.py +++ b/platform/macos/detect.py @@ -2,8 +2,8 @@ import os import sys from typing import TYPE_CHECKING -from methods import detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang, print_error, print_warning -from platform_methods import detect_arch, detect_mvk +from methods import detect_darwin_sdk_path, get_compiler_version, is_apple_clang, print_error, print_warning +from platform_methods import detect_arch, detect_mvk, validate_arch if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -68,12 +68,7 @@ def get_flags(): def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["x86_64", "arm64"] - if env["arch"] not in supported_arches: - print_error( - 'Unsupported CPU architecture "%s" for macOS. Supported architectures are: %s.' - % (env["arch"], ", ".join(supported_arches)) - ) - sys.exit(255) + validate_arch(env["arch"], get_name(), supported_arches) ## Build type @@ -106,10 +101,9 @@ def configure(env: "SConsEnvironment"): cc_version = get_compiler_version(env) cc_version_major = cc_version["apple_major"] cc_version_minor = cc_version["apple_minor"] - vanilla = is_vanilla_clang(env) # Workaround for Xcode 15 linker bug. - if not vanilla and cc_version_major == 1500 and cc_version_minor == 0: + if is_apple_clang(env) and cc_version_major == 1500 and cc_version_minor == 0: env.Prepend(LINKFLAGS=["-ld_classic"]) env.Append(CCFLAGS=["-fobjc-arc"]) diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 48cc7bbba3..f1078d9868 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -752,6 +752,7 @@ bool DisplayServerMacOS::has_feature(Feature p_feature) const { case FEATURE_NATIVE_DIALOG: case FEATURE_NATIVE_DIALOG_INPUT: case FEATURE_NATIVE_DIALOG_FILE: + case FEATURE_NATIVE_DIALOG_FILE_EXTRA: case FEATURE_IME: case FEATURE_WINDOW_TRANSPARENCY: case FEATURE_HIDPI: @@ -2676,6 +2677,18 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W } return 0; } + case EGL_DISPLAY: { + if (gl_manager_angle) { + return (int64_t)gl_manager_angle->get_display(p_window); + } + return 0; + } + case EGL_CONFIG: { + if (gl_manager_angle) { + return (int64_t)gl_manager_angle->get_config(p_window); + } + return 0; + } #endif default: { return 0; @@ -3611,6 +3624,39 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM //TODO - do Vulkan and OpenGL support checks, driver selection and fallback rendering_driver = p_rendering_driver; +#if defined(RD_ENABLED) +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + rendering_context = memnew(RenderingContextDriverVulkanMacOS); + } +#endif +#if defined(METAL_ENABLED) + if (rendering_driver == "metal") { + rendering_context = memnew(RenderingContextDriverMetal); + } +#endif + + if (rendering_context) { + if (rendering_context->initialize() != OK) { + memdelete(rendering_context); + rendering_context = nullptr; +#if defined(GLES3_ENABLED) + bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); + if (fallback_to_opengl3 && rendering_driver != "opengl3") { + WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3."); + rendering_driver = "opengl3"; + OS::get_singleton()->set_current_rendering_method("gl_compatibility"); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + } else +#endif + { + r_error = ERR_CANT_CREATE; + ERR_FAIL_MSG("Could not initialize " + rendering_driver); + } + } + } +#endif + #if defined(GLES3_ENABLED) if (rendering_driver == "opengl3_angle") { gl_manager_angle = memnew(GLManagerANGLE_MacOS); @@ -3643,35 +3689,6 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM } } #endif -#if defined(RD_ENABLED) -#if defined(VULKAN_ENABLED) - if (rendering_driver == "vulkan") { - rendering_context = memnew(RenderingContextDriverVulkanMacOS); - } -#endif -#if defined(METAL_ENABLED) - if (rendering_driver == "metal") { - rendering_context = memnew(RenderingContextDriverMetal); - } -#endif - - if (rendering_context) { - if (rendering_context->initialize() != OK) { - memdelete(rendering_context); - rendering_context = nullptr; - bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); - if (fallback_to_opengl3 && rendering_driver != "opengl3") { - WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3."); - rendering_driver = "opengl3"; - OS::get_singleton()->set_current_rendering_method("gl_compatibility"); - OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); - } else { - r_error = ERR_CANT_CREATE; - ERR_FAIL_MSG("Could not initialize " + rendering_driver); - } - } - } -#endif Point2i window_position; if (p_position != nullptr) { diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp index 7887e5d0ab..b9f9d8d613 100644 --- a/platform/macos/export/export_plugin.cpp +++ b/platform/macos/export/export_plugin.cpp @@ -65,6 +65,11 @@ void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset } else { ERR_PRINT("Invalid architecture"); } + + if (architecture == "universal") { + r_features->push_back("x86_64"); + r_features->push_back("arm64"); + } } String EditorExportPlatformMacOS::get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const { @@ -965,7 +970,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres return Error::FAILED; } else { print_verbose("rcodesign (" + p_path + "):\n" + str); - int next_nl = str.find("\n", rq_offset); + int next_nl = str.find_char('\n', rq_offset); String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 23, -1) : str.substr(rq_offset + 23, next_nl - rq_offset - 23); add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour.")); @@ -1049,7 +1054,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres return Error::FAILED; } else { print_verbose("notarytool (" + p_path + "):\n" + str); - int next_nl = str.find("\n", rq_offset); + int next_nl = str.find_char('\n', rq_offset); String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 4, -1) : str.substr(rq_offset + 4, next_nl - rq_offset - 4); add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour.")); diff --git a/platform/macos/export/export_plugin.h b/platform/macos/export/export_plugin.h index d88d347359..ef8d1bb8ab 100644 --- a/platform/macos/export/export_plugin.h +++ b/platform/macos/export/export_plugin.h @@ -34,6 +34,7 @@ #include "core/config/project_settings.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" +#include "core/io/image.h" #include "core/io/marshalls.h" #include "core/io/resource_saver.h" #include "core/os/os.h" @@ -75,7 +76,7 @@ class EditorExportPlatformMacOS : public EditorExportPlatform { ssh_args = p_ssh_arg; cmd_args = p_cmd_args; wait = p_wait; - }; + } }; Ref<ImageTexture> run_icon; diff --git a/platform/macos/godot_open_save_delegate.mm b/platform/macos/godot_open_save_delegate.mm index 6ffd939545..0d6bfa0c53 100644 --- a/platform/macos/godot_open_save_delegate.mm +++ b/platform/macos/godot_open_save_delegate.mm @@ -130,7 +130,7 @@ } if ([type_filters count] > 0) { - NSString *name_str = [NSString stringWithUTF8String:((tokens.size() == 1) ? tokens[0] : vformat("%s (%s)", tokens[1].strip_edges(), tokens[0].strip_edges())).utf8().get_data()]; + NSString *name_str = [NSString stringWithUTF8String:((tokens.size() == 1) ? tokens[0] : tokens[1].strip_edges()).utf8().get_data()]; [new_allowed_types addObject:type_filters]; [popup addItemWithTitle:name_str]; } diff --git a/platform/macos/os_macos.h b/platform/macos/os_macos.h index 303fc112bf..4fb4507837 100644 --- a/platform/macos/os_macos.h +++ b/platform/macos/os_macos.h @@ -114,6 +114,8 @@ public: virtual String get_unique_id() const override; virtual String get_processor_name() const override; + virtual String get_model_name() const override; + virtual bool is_sandboxed() const override; virtual Vector<String> get_granted_permissions() const override; virtual void revoke_granted_permissions() override; diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm index d9086b8c38..08ff391aab 100644 --- a/platform/macos/os_macos.mm +++ b/platform/macos/os_macos.mm @@ -67,6 +67,15 @@ void OS_MacOS::initialize() { initialize_core(); } +String OS_MacOS::get_model_name() const { + char buffer[256]; + size_t buffer_len = 256; + if (sysctlbyname("hw.model", &buffer, &buffer_len, nullptr, 0) == 0 && buffer_len != 0) { + return String::utf8(buffer, buffer_len); + } + return OS_Unix::get_model_name(); +} + String OS_MacOS::get_processor_name() const { char buffer[256]; size_t buffer_len = 256; diff --git a/platform/web/SCsub b/platform/web/SCsub index b30bf20f26..9a2eea9e07 100644 --- a/platform/web/SCsub +++ b/platform/web/SCsub @@ -27,9 +27,11 @@ web_files = [ "javascript_bridge_singleton.cpp", "web_main.cpp", "os_web.cpp", - "api/web_tools_editor_plugin.cpp", ] +if env["target"] == "editor": + env.add_source_files(web_files, "editor/*.cpp") + sys_env = env.Clone() sys_env.AddJSLibraries( [ @@ -59,7 +61,7 @@ for ext in sys_env["JS_EXTERNS"]: sys_env["ENV"]["EMCC_CLOSURE_ARGS"] += " --externs " + ext.abspath build = [] -build_targets = ["#bin/godot${PROGSUFFIX}.js", "#bin/godot${PROGSUFFIX}.wasm", "#bin/godot${PROGSUFFIX}.worker.js"] +build_targets = ["#bin/godot${PROGSUFFIX}.js", "#bin/godot${PROGSUFFIX}.wasm"] if env["dlink_enabled"]: # Reset libraries. The main runtime will only link emscripten libraries, not godot ones. sys_env["LIBS"] = [] @@ -108,6 +110,5 @@ js_wrapped = env.Textfile("#bin/godot", [env.File(f) for f in wrap_list], TEXTFI # 0 - unwrapped js file (use wrapped one instead) # 1 - wasm file -# 2 - worker file -# 3 - wasm side (when dlink is enabled). -env.CreateTemplateZip(js_wrapped, build[1], build[2], build[3] if len(build) > 3 else None) +# 2 - wasm side (when dlink is enabled). +env.CreateTemplateZip(js_wrapped, build[1], build[2] if len(build) > 2 else None) diff --git a/platform/web/api/api.cpp b/platform/web/api/api.cpp index 40417bde7e..f9c1f0fd91 100644 --- a/platform/web/api/api.cpp +++ b/platform/web/api/api.cpp @@ -31,14 +31,12 @@ #include "api.h" #include "javascript_bridge_singleton.h" -#include "web_tools_editor_plugin.h" #include "core/config/engine.h" static JavaScriptBridge *javascript_bridge_singleton; void register_web_api() { - WebToolsEditorPlugin::initialize(); GDREGISTER_ABSTRACT_CLASS(JavaScriptObject); GDREGISTER_ABSTRACT_CLASS(JavaScriptBridge); javascript_bridge_singleton = memnew(JavaScriptBridge); diff --git a/platform/web/detect.py b/platform/web/detect.py index 735e2eaf4f..25a5bbe5a5 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -14,6 +14,7 @@ from emscripten_helpers import ( from SCons.Util import WhereIs from methods import get_compiler_version, print_error, print_warning +from platform_methods import validate_arch if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -86,12 +87,7 @@ def get_flags(): def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["wasm32"] - if env["arch"] not in supported_arches: - print_error( - 'Unsupported CPU architecture "%s" for Web. Supported architectures are: %s.' - % (env["arch"], ", ".join(supported_arches)) - ) - sys.exit(255) + validate_arch(env["arch"], get_name(), supported_arches) try: env["initial_memory"] = int(env["initial_memory"]) @@ -205,7 +201,7 @@ def configure(env: "SConsEnvironment"): sys.exit(255) env.Prepend(CPPPATH=["#platform/web"]) - env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"]) + env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED", "UNIX_SOCKET_UNAVAILABLE"]) if env["opengl3"]: env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"]) diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 4e55cc137a..b2db62ea2f 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -1133,6 +1133,7 @@ bool DisplayServerWeb::has_feature(Feature p_feature) const { //case FEATURE_NATIVE_DIALOG: //case FEATURE_NATIVE_DIALOG_INPUT: //case FEATURE_NATIVE_DIALOG_FILE: + //case FEATURE_NATIVE_DIALOG_FILE_EXTRA: //case FEATURE_NATIVE_ICON: //case FEATURE_WINDOW_TRANSPARENCY: //case FEATURE_KEEP_SCREEN_ON: diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index 352b3fe523..c28a6fd082 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -209,6 +209,7 @@ public: virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual void screen_set_keep_on(bool p_enable) override {} virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override; virtual void virtual_keyboard_hide() override; @@ -265,6 +266,7 @@ public: virtual bool can_any_window_draw() const override; + virtual void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override {} virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; // events diff --git a/platform/web/doc_classes/EditorExportPlatformWeb.xml b/platform/web/doc_classes/EditorExportPlatformWeb.xml index 755308de9a..955e3a0232 100644 --- a/platform/web/doc_classes/EditorExportPlatformWeb.xml +++ b/platform/web/doc_classes/EditorExportPlatformWeb.xml @@ -60,15 +60,15 @@ </member> <member name="progressive_web_app/icon_144x144" type="String" setter="" getter=""> File path to the smallest icon for this web application. If not defined, defaults to the project icon. - [b]Note:[/b] If the icon is not 144x144, it will be automatically resized for the final build. + [b]Note:[/b] If the icon is not 144×144, it will be automatically resized for the final build. </member> <member name="progressive_web_app/icon_180x180" type="String" setter="" getter=""> File path to the small icon for this web application. If not defined, defaults to the project icon. - [b]Note:[/b] If the icon is not 180x180, it will be automatically resized for the final build. + [b]Note:[/b] If the icon is not 180×180, it will be automatically resized for the final build. </member> <member name="progressive_web_app/icon_512x512" type="String" setter="" getter=""> - File path to the smallest icon for this web application. If not defined, defaults to the project icon. - [b]Note:[/b] If the icon is not 512x512, it will be automatically resized for the final build. + File path to the largest icon for this web application. If not defined, defaults to the project icon. + [b]Note:[/b] If the icon is not 512×512, it will be automatically resized for the final build. </member> <member name="progressive_web_app/offline_page" type="String" setter="" getter=""> The page to display, should the server hosting the page not be available. This page is saved in the client's machine. diff --git a/platform/web/api/web_tools_editor_plugin.cpp b/platform/web/editor/web_tools_editor_plugin.cpp index d39773bde2..a98d45a49a 100644 --- a/platform/web/api/web_tools_editor_plugin.cpp +++ b/platform/web/editor/web_tools_editor_plugin.cpp @@ -30,8 +30,6 @@ #include "web_tools_editor_plugin.h" -#if defined(TOOLS_ENABLED) && defined(WEB_ENABLED) - #include "core/config/engine.h" #include "core/config/project_settings.h" #include "core/io/dir_access.h" @@ -80,7 +78,7 @@ void WebToolsEditorPlugin::_download_zip() { const String output_path = String("/tmp").path_join(output_name); zipFile zip = zipOpen2(output_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io); - const String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/"; + const String base_path = resource_path.substr(0, resource_path.rfind_char('/')) + "/"; _zip_recursive(resource_path, base_path, zip); zipClose(zip, nullptr); { @@ -155,5 +153,3 @@ void WebToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zip cur = dir->get_next(); } } - -#endif // TOOLS_ENABLED && WEB_ENABLED diff --git a/platform/web/api/web_tools_editor_plugin.h b/platform/web/editor/web_tools_editor_plugin.h index 2902f60f24..70b47ab49c 100644 --- a/platform/web/api/web_tools_editor_plugin.h +++ b/platform/web/editor/web_tools_editor_plugin.h @@ -31,8 +31,6 @@ #ifndef WEB_TOOLS_EDITOR_PLUGIN_H #define WEB_TOOLS_EDITOR_PLUGIN_H -#if defined(TOOLS_ENABLED) && defined(WEB_ENABLED) - #include "core/io/zip_io.h" #include "editor/plugins/editor_plugin.h" @@ -57,6 +55,4 @@ public: static void initialize() {} }; -#endif // TOOLS_ENABLED && WEB_ENABLED - #endif // WEB_TOOLS_EDITOR_PLUGIN_H diff --git a/platform/web/emscripten_helpers.py b/platform/web/emscripten_helpers.py index 8fcabb21c7..aca5d4ecba 100644 --- a/platform/web/emscripten_helpers.py +++ b/platform/web/emscripten_helpers.py @@ -3,6 +3,8 @@ import os from SCons.Util import WhereIs +from platform_methods import get_build_version + def run_closure_compiler(target, source, env, for_signature): closure_bin = os.path.join( @@ -21,22 +23,6 @@ def run_closure_compiler(target, source, env, for_signature): return " ".join(cmd) -def get_build_version(): - import version - - name = "custom_build" - if os.getenv("BUILD_NAME") is not None: - name = os.getenv("BUILD_NAME") - v = "%d.%d" % (version.major, version.minor) - if version.patch > 0: - v += ".%d" % version.patch - status = version.status - if os.getenv("GODOT_VERSION_STATUS") is not None: - status = str(os.getenv("GODOT_VERSION_STATUS")) - v += ".%s.%s" % (status, name) - return v - - def create_engine_file(env, target, source, externs, threads_enabled): if env["use_closure_compiler"]: return env.BuildJS(target, source, JSEXTERNS=externs) @@ -44,7 +30,7 @@ def create_engine_file(env, target, source, externs, threads_enabled): return env.Substfile(target=target, source=[env.File(s) for s in source], SUBST_DICT=subst_dict) -def create_template_zip(env, js, wasm, worker, side): +def create_template_zip(env, js, wasm, side): binary_name = "godot.editor" if env.editor_build else "godot" zip_dir = env.Dir(env.GetTemplateZipPath()) in_files = [ @@ -59,9 +45,6 @@ def create_template_zip(env, js, wasm, worker, side): zip_dir.File(binary_name + ".audio.worklet.js"), zip_dir.File(binary_name + ".audio.position.worklet.js"), ] - if env["threads"]: - in_files.append(worker) - out_files.append(zip_dir.File(binary_name + ".worker.js")) # Dynamic linking (extensions) specific. if env["dlink_enabled"]: in_files.append(side) # Side wasm (contains the actual Godot code). @@ -80,11 +63,9 @@ def create_template_zip(env, js, wasm, worker, side): "logo.svg", "favicon.png", ] - if env["threads"]: - cache.append("godot.editor.worker.js") opt_cache = ["godot.editor.wasm"] subst_dict = { - "___GODOT_VERSION___": get_build_version(), + "___GODOT_VERSION___": get_build_version(False), "___GODOT_NAME___": "GodotEngine", "___GODOT_CACHE___": json.dumps(cache), "___GODOT_OPT_CACHE___": json.dumps(opt_cache), diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp index efe3c95496..9e60a76fdc 100644 --- a/platform/web/export/export_plugin.cpp +++ b/platform/web/export/export_plugin.cpp @@ -169,6 +169,7 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito replaces["$GODOT_PROJECT_NAME"] = GLOBAL_GET("application/config/name"); replaces["$GODOT_HEAD_INCLUDE"] = head_include + custom_head_include; replaces["$GODOT_CONFIG"] = str_config; + replaces["$GODOT_SPLASH_COLOR"] = "#" + Color(GLOBAL_GET("application/boot_splash/bg_color")).to_html(false); replaces["$GODOT_SPLASH"] = p_name + ".png"; if (p_preset->get("variant/thread_support")) { @@ -214,9 +215,6 @@ Error EditorExportPlatformWeb::_add_manifest_icon(const String &p_path, const St } Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_preset, const String p_path, const Vector<SharedObject> &p_shared_objects) { - List<String> preset_features; - get_preset_features(p_preset, &preset_features); - String proj_name = GLOBAL_GET("application/config/name"); if (proj_name.is_empty()) { proj_name = "Godot Game"; @@ -243,9 +241,6 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese cache_files.push_back(name + ".apple-touch-icon.png"); } - if (preset_features.find("threads")) { - cache_files.push_back(name + ".worker.js"); - } cache_files.push_back(name + ".audio.worklet.js"); cache_files.push_back(name + ".audio.position.worklet.js"); replaces["___GODOT_CACHE___"] = Variant(cache_files).to_json_string(); @@ -839,7 +834,6 @@ Error EditorExportPlatformWeb::_export_project(const Ref<EditorExportPreset> &p_ DirAccess::remove_file_or_error(basepath + ".html"); DirAccess::remove_file_or_error(basepath + ".offline.html"); DirAccess::remove_file_or_error(basepath + ".js"); - DirAccess::remove_file_or_error(basepath + ".worker.js"); DirAccess::remove_file_or_error(basepath + ".audio.worklet.js"); DirAccess::remove_file_or_error(basepath + ".audio.position.worklet.js"); DirAccess::remove_file_or_error(basepath + ".service.worker.js"); diff --git a/platform/web/js/engine/config.js b/platform/web/js/engine/config.js index 61b488cf81..3947195fa1 100644 --- a/platform/web/js/engine/config.js +++ b/platform/web/js/engine/config.js @@ -295,8 +295,6 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- 'locateFile': function (path) { if (!path.startsWith('godot.')) { return path; - } else if (path.endsWith('.worker.js')) { - return `${loadPath}.worker.js`; } else if (path.endsWith('.audio.worklet.js')) { return `${loadPath}.audio.worklet.js`; } else if (path.endsWith('.audio.position.worklet.js')) { diff --git a/platform/web/js/libs/library_godot_fetch.js b/platform/web/js/libs/library_godot_fetch.js index 00616bc1a5..eeb3978256 100644 --- a/platform/web/js/libs/library_godot_fetch.js +++ b/platform/web/js/libs/library_godot_fetch.js @@ -59,7 +59,12 @@ const GodotFetch = { }); obj.status = response.status; obj.response = response; - obj.reader = response.body.getReader(); + // `body` can be null per spec (for example, in cases where the request method is HEAD). + // As of the time of writing, Chromium (127.0.6533.72) does not follow the spec but Firefox (131.0.3) does. + // See godotengine/godot#76825 for more information. + // See Chromium revert (of the change to follow the spec): + // https://chromium.googlesource.com/chromium/src/+/135354b7bdb554cd03c913af7c90aceead03c4d4 + obj.reader = response.body?.getReader(); obj.chunked = chunked; }, @@ -121,6 +126,10 @@ const GodotFetch = { } obj.reading = true; obj.reader.read().then(GodotFetch.onread.bind(null, id)).catch(GodotFetch.onerror.bind(null, id)); + } else if (obj.reader == null && obj.response.body == null) { + // Emulate a stream closure to maintain the request lifecycle. + obj.reading = true; + GodotFetch.onread(id, { value: undefined, done: true }); } }, }, @@ -159,7 +168,10 @@ const GodotFetch = { if (!obj.response) { return 0; } - if (obj.reader) { + // If the reader is nullish, but there is no body, and the request is not marked as done, + // the same status should be returned as though the request is currently being read + // so that the proper lifecycle closure can be handled in `read()`. + if (obj.reader || (obj.response.body == null && !obj.done)) { return 1; } if (obj.done) { diff --git a/platform/web/js/libs/library_godot_input.js b/platform/web/js/libs/library_godot_input.js index 6e3b97023d..8134631f1b 100644 --- a/platform/web/js/libs/library_godot_input.js +++ b/platform/web/js/libs/library_godot_input.js @@ -38,41 +38,57 @@ const GodotIME = { $GodotIME: { ime: null, active: false, + focusTimerIntervalId: -1, getModifiers: function (evt) { return (evt.shiftKey + 0) + ((evt.altKey + 0) << 1) + ((evt.ctrlKey + 0) << 2) + ((evt.metaKey + 0) << 3); }, ime_active: function (active) { - function focus_timer() { - GodotIME.active = true; - GodotIME.ime.focus(); + function clearFocusTimerInterval() { + clearInterval(GodotIME.focusTimerIntervalId); + GodotIME.focusTimerIntervalId = -1; } - if (GodotIME.ime) { - if (active) { - GodotIME.ime.style.display = 'block'; - setInterval(focus_timer, 100); - } else { - GodotIME.ime.style.display = 'none'; - GodotConfig.canvas.focus(); - GodotIME.active = false; + function focusTimer() { + if (GodotIME.ime == null) { + clearFocusTimerInterval(); + return; } + GodotIME.ime.focus(); + } + + if (GodotIME.focusTimerIntervalId > -1) { + clearFocusTimerInterval(); + } + + if (GodotIME.ime == null) { + return; + } + + GodotIME.active = active; + if (active) { + GodotIME.ime.style.display = 'block'; + GodotIME.focusTimerIntervalId = setInterval(focusTimer, 100); + } else { + GodotIME.ime.style.display = 'none'; + GodotConfig.canvas.focus(); } }, ime_position: function (x, y) { - if (GodotIME.ime) { - const canvas = GodotConfig.canvas; - const rect = canvas.getBoundingClientRect(); - const rw = canvas.width / rect.width; - const rh = canvas.height / rect.height; - const clx = (x / rw) + rect.x; - const cly = (y / rh) + rect.y; - - GodotIME.ime.style.left = `${clx}px`; - GodotIME.ime.style.top = `${cly}px`; + if (GodotIME.ime == null) { + return; } + const canvas = GodotConfig.canvas; + const rect = canvas.getBoundingClientRect(); + const rw = canvas.width / rect.width; + const rh = canvas.height / rect.height; + const clx = (x / rw) + rect.x; + const cly = (y / rh) + rect.y; + + GodotIME.ime.style.left = `${clx}px`; + GodotIME.ime.style.top = `${cly}px`; }, init: function (ime_cb, key_cb, code, key) { @@ -84,20 +100,27 @@ const GodotIME = { evt.preventDefault(); } function ime_event_cb(event) { - if (GodotIME.ime) { - if (event.type === 'compositionstart') { - ime_cb(0, null); - GodotIME.ime.innerHTML = ''; - } else if (event.type === 'compositionupdate') { - const ptr = GodotRuntime.allocString(event.data); - ime_cb(1, ptr); - GodotRuntime.free(ptr); - } else if (event.type === 'compositionend') { - const ptr = GodotRuntime.allocString(event.data); - ime_cb(2, ptr); - GodotRuntime.free(ptr); - GodotIME.ime.innerHTML = ''; - } + if (GodotIME.ime == null) { + return; + } + switch (event.type) { + case 'compositionstart': + ime_cb(0, null); + GodotIME.ime.innerHTML = ''; + break; + case 'compositionupdate': { + const ptr = GodotRuntime.allocString(event.data); + ime_cb(1, ptr); + GodotRuntime.free(ptr); + } break; + case 'compositionend': { + const ptr = GodotRuntime.allocString(event.data); + ime_cb(2, ptr); + GodotRuntime.free(ptr); + GodotIME.ime.innerHTML = ''; + } break; + default: + // Do nothing. } } @@ -133,10 +156,15 @@ const GodotIME = { }, clear: function () { - if (GodotIME.ime) { - GodotIME.ime.remove(); - GodotIME.ime = null; + if (GodotIME.ime == null) { + return; + } + if (GodotIME.focusTimerIntervalId > -1) { + clearInterval(GodotIME.focusTimerIntervalId); + GodotIME.focusTimerIntervalId = -1; } + GodotIME.ime.remove(); + GodotIME.ime = null; }, }, }; diff --git a/platform/web/package-lock.json b/platform/web/package-lock.json index a2e0fd3b27..7947fb96e4 100644 --- a/platform/web/package-lock.json +++ b/platform/web/package-lock.json @@ -9,14 +9,14 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@eslint/js": "^9.3.0", - "@html-eslint/eslint-plugin": "^0.24.1", - "@html-eslint/parser": "^0.24.1", - "@stylistic/eslint-plugin": "^2.1.0", - "eslint": "^9.3.0", + "@eslint/js": "^9.12.0", + "@html-eslint/eslint-plugin": "^0.27.0", + "@html-eslint/parser": "^0.27.0", + "@stylistic/eslint-plugin": "^2.9.0", + "eslint": "^9.12.0", "eslint-plugin-html": "^8.1.1", "espree": "^10.0.1", - "globals": "^15.3.0", + "globals": "^15.9.0", "jsdoc": "^4.0.3" } }, @@ -60,14 +60,40 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -104,28 +130,54 @@ } }, "node_modules/@eslint/js": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.3.0.tgz", - "integrity": "sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz", + "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@html-eslint/eslint-plugin": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/@html-eslint/eslint-plugin/-/eslint-plugin-0.24.1.tgz", - "integrity": "sha512-JwNDQBrNIWEPcxgSpla/2jaUXyQCqL7Xp8CmON4Bk5qg8MwiDLXOgjylfVC+tN52i8JeHWMca34I9DqBGRj9Qg==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@html-eslint/eslint-plugin/-/eslint-plugin-0.27.0.tgz", + "integrity": "sha512-aAF14sgDKidMCCQpJ4kIhe+fwyAaAbvDlgVTIgd99F+HOWxokTTXDt39a3gewMBo76IeEHDaoizUDJQ/Vc7Mdg==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@html-eslint/parser": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/@html-eslint/parser/-/parser-0.24.1.tgz", - "integrity": "sha512-O13xX/+Ldh0P7VZMpDDYc3XtWiE1cYm5QhVJ0VB5i7D8Q69HrrGN+5BjS17vkCoLTz+3zWWIiJv4oFmyS5LReA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@html-eslint/parser/-/parser-0.27.0.tgz", + "integrity": "sha512-F/A1M0jnDAYoRvJiiSC7pIBD9DAsf4EhbndbvEi81aozD/wI8WWXON50xZPUaGHCI1C+2syTVifxDz8MvDKaQA==", "dev": true, + "license": "MIT", "dependencies": { "es-html-parser": "^0.0.9" }, @@ -133,18 +185,28 @@ "node": ">=8.10.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -160,17 +222,12 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -227,50 +284,15 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.1.0.tgz", - "integrity": "sha512-cBBowKP2u/+uE5CzgH5w8pE9VKqcM7BXdIDPIbGt2rmLJGnA6MJPr9vYGaqgMoJFs7R/FzsMQerMvvEP40g2uw==", - "dev": true, - "dependencies": { - "@stylistic/eslint-plugin-js": "2.1.0", - "@stylistic/eslint-plugin-jsx": "2.1.0", - "@stylistic/eslint-plugin-plus": "2.1.0", - "@stylistic/eslint-plugin-ts": "2.1.0", - "@types/eslint": "^8.56.10" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.1.0.tgz", - "integrity": "sha512-gdXUjGNSsnY6nPyqxu6lmDTtVrwCOjun4x8PUn0x04d5ucLI74N3MT1Q0UhdcOR9No3bo5PGDyBgXK+KmD787A==", - "dev": true, - "dependencies": { - "@types/eslint": "^8.56.10", - "acorn": "^8.11.3", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.1.0.tgz", - "integrity": "sha512-mMD7S+IndZo2vxmwpHVTCwx2O1VdtE5tmpeNwgaEcXODzWV1WTWpnsc/PECQKIr/mkLPFWiSIqcuYNhQ/3l6AQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.9.0.tgz", + "integrity": "sha512-OrDyFAYjBT61122MIY1a3SfEgy3YCMgt2vL4eoPmvTwDBwyQhAXurxNQznlRD/jESNfYWfID8Ej+31LljvF7Xg==", "dev": true, + "license": "MIT", "dependencies": { - "@stylistic/eslint-plugin-js": "^2.1.0", - "@types/eslint": "^8.56.10", + "@typescript-eslint/utils": "^8.8.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -281,101 +303,19 @@ "eslint": ">=8.40.0" } }, - "node_modules/@stylistic/eslint-plugin-plus": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.1.0.tgz", - "integrity": "sha512-S5QAlgYXESJaSBFhBSBLZy9o36gXrXQwWSt6QkO+F0SrT9vpV5JF/VKoh+ojO7tHzd8Ckmyouq02TT9Sv2B0zQ==", - "dev": true, - "dependencies": { - "@types/eslint": "^8.56.10", - "@typescript-eslint/utils": "^7.8.0" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@stylistic/eslint-plugin-plus/node_modules/@typescript-eslint/utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", - "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@stylistic/eslint-plugin-ts": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.1.0.tgz", - "integrity": "sha512-2ioFibufHYBALx2TBrU4KXovCkN8qCqcb9yIHc0fyOfTaO5jw4d56WW7YRcF3Zgde6qFyXwAN6z/+w4pnmos1g==", - "dev": true, - "dependencies": { - "@stylistic/eslint-plugin-js": "2.1.0", - "@types/eslint": "^8.56.10", - "@typescript-eslint/utils": "^7.8.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-ts/node_modules/@typescript-eslint/utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", - "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/linkify-it": { "version": "5.0.0", @@ -400,16 +340,17 @@ "dev": true }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz", - "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", + "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0" + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -417,12 +358,13 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz", - "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", + "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -430,22 +372,23 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz", - "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", + "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -462,15 +405,17 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -481,17 +426,41 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/utils": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", + "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz", - "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", + "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/types": "8.11.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -503,6 +472,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -511,10 +481,11 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -547,15 +518,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -577,15 +539,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -613,6 +566,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -718,18 +672,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -816,28 +758,33 @@ } }, "node_modules/eslint": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.3.0.tgz", - "integrity": "sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.3.0", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -846,14 +793,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { @@ -863,7 +807,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-plugin-html": { @@ -879,10 +831,11 @@ } }, "node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -895,10 +848,11 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -907,14 +861,15 @@ } }, "node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -940,6 +895,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -976,6 +932,7 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -992,6 +949,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1037,6 +995,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1092,10 +1051,11 @@ } }, "node_modules/globals": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.3.0.tgz", - "integrity": "sha512-cCdyVjIUVTtX8ZsPkq1oCsOsLmGIswqnjZYMJJTGaNApj1yHtLSymKhwH51ttirREn75z3p4k051clwg7rvNKA==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -1103,26 +1063,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1217,19 +1157,11 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1430,15 +1362,17 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -1452,6 +1386,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -1572,20 +1507,12 @@ "node": ">=8" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -1692,10 +1619,11 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -1724,27 +1652,6 @@ "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1780,6 +1687,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -1792,6 +1700,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -1812,10 +1721,11 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "license": "Apache-2.0", "peer": true, "bin": { "tsc": "bin/tsc", diff --git a/platform/web/package.json b/platform/web/package.json index 588af2ff3b..bf61eb184c 100644 --- a/platform/web/package.json +++ b/platform/web/package.json @@ -11,14 +11,14 @@ "format": "npm run lint -- --fix" }, "devDependencies": { - "@eslint/js": "^9.3.0", - "@html-eslint/eslint-plugin": "^0.24.1", - "@html-eslint/parser": "^0.24.1", - "@stylistic/eslint-plugin": "^2.1.0", - "eslint": "^9.3.0", + "@eslint/js": "^9.12.0", + "@html-eslint/eslint-plugin": "^0.27.0", + "@html-eslint/parser": "^0.27.0", + "@stylistic/eslint-plugin": "^2.9.0", + "eslint": "^9.12.0", "eslint-plugin-html": "^8.1.1", "espree": "^10.0.1", - "globals": "^15.3.0", + "globals": "^15.9.0", "jsdoc": "^4.0.3" } } diff --git a/platform/web/web_main.cpp b/platform/web/web_main.cpp index d0c3bd7c0e..3487ed2ded 100644 --- a/platform/web/web_main.cpp +++ b/platform/web/web_main.cpp @@ -38,6 +38,10 @@ #include "scene/main/scene_tree.h" #include "scene/main/window.h" // SceneTree only forward declares it. +#ifdef TOOLS_ENABLED +#include "editor/web_tools_editor_plugin.h" +#endif + #include <emscripten/emscripten.h> #include <stdlib.h> @@ -104,6 +108,10 @@ void main_loop_callback() { extern EMSCRIPTEN_KEEPALIVE int godot_web_main(int argc, char *argv[]) { os = new OS_Web(); +#ifdef TOOLS_ENABLED + WebToolsEditorPlugin::initialize(); +#endif + // We must override main when testing is enabled TEST_MAIN_OVERRIDE diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 1d17e7b325..1ddefb9c33 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -24,6 +24,7 @@ common_win = [ "gl_manager_windows_angle.cpp", "wgl_detect_version.cpp", "rendering_context_driver_vulkan_windows.cpp", + "drop_target_windows.cpp", ] if env.msvc: @@ -59,6 +60,9 @@ sources += res_obj prog = env.add_program("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"]) arrange_program_clean(prog) +if env.msvc: + env.Depends(prog, "godot.natvis") + # Build console wrapper app. if env["windows_subsystem"] == "gui": env_wrap = env.Clone() @@ -79,16 +83,6 @@ if env["windows_subsystem"] == "gui": env_wrap.Depends(prog_wrap, prog) sources += common_win_wrap + res_wrap_obj -# Microsoft Visual Studio Project Generation -if env["vsproj"]: - env.vs_srcs += ["platform/windows/" + res_file] - env.vs_srcs += ["platform/windows/godot.natvis"] - for x in common_win: - env.vs_srcs += ["platform/windows/" + str(x)] - if env["windows_subsystem"] == "gui": - for x in common_win_wrap: - env.vs_srcs += ["platform/windows/" + str(x)] - if env["d3d12"]: dxc_target_aliases = { "x86_32": "x86", diff --git a/platform/windows/crash_handler_windows.h b/platform/windows/crash_handler_windows.h index a0a0b610d0..f47d9ec66e 100644 --- a/platform/windows/crash_handler_windows.h +++ b/platform/windows/crash_handler_windows.h @@ -51,7 +51,7 @@ public: void initialize(); void disable(); - bool is_disabled() const { return disabled; }; + bool is_disabled() const { return disabled; } CrashHandler(); ~CrashHandler(); diff --git a/platform/windows/crash_handler_windows_signal.cpp b/platform/windows/crash_handler_windows_signal.cpp index e11a60bdc7..c3a0d08ad6 100644 --- a/platform/windows/crash_handler_windows_signal.cpp +++ b/platform/windows/crash_handler_windows_signal.cpp @@ -159,7 +159,7 @@ extern void CrashHandlerException(int signal) { // Load process and image info to determine ASLR addresses offset. MODULEINFO mi; - GetModuleInformation(GetCurrentProcess(), GetModuleHandle(NULL), &mi, sizeof(mi)); + GetModuleInformation(GetCurrentProcess(), GetModuleHandle(nullptr), &mi, sizeof(mi)); int64_t image_mem_base = reinterpret_cast<int64_t>(mi.lpBaseOfDll); int64_t image_file_base = get_image_base(_execpath); data.offset = image_mem_base - image_file_base; diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 0ee52a09a7..e1109db24f 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING import methods from methods import print_error, print_warning -from platform_methods import detect_arch +from platform_methods import detect_arch, validate_arch if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -68,23 +68,23 @@ def can_build(): def get_mingw_bin_prefix(prefix, arch): - if not prefix: - mingw_bin_prefix = "" - elif prefix[-1] != "/": - mingw_bin_prefix = prefix + "/bin/" - else: - mingw_bin_prefix = prefix + "bin/" + bin_prefix = (os.path.normpath(os.path.join(prefix, "bin")) + os.sep) if prefix else "" + ARCH_PREFIXES = { + "x86_64": "x86_64-w64-mingw32-", + "x86_32": "i686-w64-mingw32-", + "arm32": "armv7-w64-mingw32-", + "arm64": "aarch64-w64-mingw32-", + } + arch_prefix = ARCH_PREFIXES[arch] if arch else "" + return bin_prefix + arch_prefix - if arch == "x86_64": - mingw_bin_prefix += "x86_64-w64-mingw32-" - elif arch == "x86_32": - mingw_bin_prefix += "i686-w64-mingw32-" - elif arch == "arm32": - mingw_bin_prefix += "armv7-w64-mingw32-" - elif arch == "arm64": - mingw_bin_prefix += "aarch64-w64-mingw32-" - return mingw_bin_prefix +def get_detected(env: "SConsEnvironment", tool: str) -> str: + checks = [ + get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) + tool, + get_mingw_bin_prefix(env["mingw_prefix"], "") + tool, + ] + return str(env.Detect(checks)) def detect_build_env_arch(): @@ -245,41 +245,6 @@ def get_flags(): } -def build_res_file(target, source, env: "SConsEnvironment"): - arch_aliases = { - "x86_32": "pe-i386", - "x86_64": "pe-x86-64", - "arm32": "armv7-w64-mingw32", - "arm64": "aarch64-w64-mingw32", - } - cmdbase = "windres --include-dir . --target=" + arch_aliases[env["arch"]] - - mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) - - for x in range(len(source)): - ok = True - # Try prefixed executable (MinGW on Linux). - cmd = mingw_bin_prefix + cmdbase + " -i " + str(source[x]) + " -o " + str(target[x]) - try: - out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate() - if len(out[1]): - ok = False - except Exception: - ok = False - - # Try generic executable (MSYS2). - if not ok: - cmd = cmdbase + " -i " + str(source[x]) + " -o " + str(target[x]) - try: - out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate() - if len(out[1]): - return -1 - except Exception: - return -1 - - return 0 - - def setup_msvc_manual(env: "SConsEnvironment"): """Running from VCVARS environment""" @@ -361,6 +326,10 @@ def setup_mingw(env: "SConsEnvironment"): print_error("No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.") sys.exit(255) + env.Tool("mingw") + env.AppendUnique(CCFLAGS=env.get("ccflags", "").split()) + env.AppendUnique(RCFLAGS=env.get("rcflags", "").split()) + print("Using MinGW, arch %s" % (env["arch"])) @@ -483,9 +452,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config): else: print_warning("Missing environment variable: WindowsSdkDir") - if int(env["target_win_version"], 16) < 0x0601: - print_error("`target_win_version` should be 0x0601 or higher (Windows 7).") - sys.exit(255) + validate_win_version(env) env.AppendUnique( CPPDEFINES=[ @@ -549,15 +516,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config): LIBS += ["vulkan"] if env["d3d12"]: - # Check whether we have d3d12 dependencies installed. - if not os.path.exists(env["mesa_libs"]): - print_error( - "The Direct3D 12 rendering driver requires dependencies to be installed.\n" - "You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n" - "See the documentation for more information:\n\t" - "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html" - ) - sys.exit(255) + check_d3d12_installed(env) env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"]) LIBS += ["dxgi", "dxguid"] @@ -716,6 +675,13 @@ def configure_mingw(env: "SConsEnvironment"): # https://www.scons.org/wiki/LongCmdLinesOnWin32 env.use_windows_spawn_fix() + # HACK: For some reason, Windows-native shells have their MinGW tools + # frequently fail as a result of parsing path separators incorrectly. + # For some other reason, this issue is circumvented entirely if the + # `mingw_prefix` bin is prepended to PATH. + if os.sep == "\\": + env.PrependENVPath("PATH", os.path.join(env["mingw_prefix"], "bin")) + # In case the command line to AR is too long, use a response file. env["ARCOM_ORIG"] = env["ARCOM"] env["ARCOM"] = "${TEMPFILE('$ARCOM_ORIG', '$ARCOMSTR')}" @@ -753,9 +719,6 @@ def configure_mingw(env: "SConsEnvironment"): ## Compiler configuration - if os.name != "nt": - env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation - if env["arch"] == "x86_32": if env["use_static_cpp"]: env.Append(LINKFLAGS=["-static"]) @@ -770,29 +733,31 @@ def configure_mingw(env: "SConsEnvironment"): env.Append(CCFLAGS=["-ffp-contract=off"]) - mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) - if env["use_llvm"]: - env["CC"] = mingw_bin_prefix + "clang" - env["CXX"] = mingw_bin_prefix + "clang++" - if try_cmd("as --version", env["mingw_prefix"], env["arch"]): - env["AS"] = mingw_bin_prefix + "as" - env.Append(ASFLAGS=["-c"]) - if try_cmd("ar --version", env["mingw_prefix"], env["arch"]): - env["AR"] = mingw_bin_prefix + "ar" - if try_cmd("ranlib --version", env["mingw_prefix"], env["arch"]): - env["RANLIB"] = mingw_bin_prefix + "ranlib" + env["CC"] = get_detected(env, "clang") + env["CXX"] = get_detected(env, "clang++") + env["AR"] = get_detected(env, "ar") + env["RANLIB"] = get_detected(env, "ranlib") + env.Append(ASFLAGS=["-c"]) env.extra_suffix = ".llvm" + env.extra_suffix else: - env["CC"] = mingw_bin_prefix + "gcc" - env["CXX"] = mingw_bin_prefix + "g++" - if try_cmd("as --version", env["mingw_prefix"], env["arch"]): - env["AS"] = mingw_bin_prefix + "as" - ar = "ar" if os.name == "nt" else "gcc-ar" - if try_cmd(f"{ar} --version", env["mingw_prefix"], env["arch"]): - env["AR"] = mingw_bin_prefix + ar - if try_cmd("gcc-ranlib --version", env["mingw_prefix"], env["arch"]): - env["RANLIB"] = mingw_bin_prefix + "gcc-ranlib" + env["CC"] = get_detected(env, "gcc") + env["CXX"] = get_detected(env, "g++") + env["AR"] = get_detected(env, "gcc-ar" if os.name != "nt" else "ar") + env["RANLIB"] = get_detected(env, "gcc-ranlib") + + env["RC"] = get_detected(env, "windres") + ARCH_TARGETS = { + "x86_32": "pe-i386", + "x86_64": "pe-x86-64", + "arm32": "armv7-w64-mingw32", + "arm64": "aarch64-w64-mingw32", + } + env.AppendUnique(RCFLAGS=f"--target={ARCH_TARGETS[env['arch']]}") + + env["AS"] = get_detected(env, "as") + env["OBJCOPY"] = get_detected(env, "objcopy") + env["STRIP"] = get_detected(env, "strip") ## LTO @@ -820,9 +785,7 @@ def configure_mingw(env: "SConsEnvironment"): ## Compile flags - if int(env["target_win_version"], 16) < 0x0601: - print_error("`target_win_version` should be 0x0601 or higher (Windows 7).") - sys.exit(255) + validate_win_version(env) if not env["use_llvm"]: env.Append(CCFLAGS=["-mwindows"]) @@ -900,15 +863,7 @@ def configure_mingw(env: "SConsEnvironment"): env.Append(LIBS=["vulkan"]) if env["d3d12"]: - # Check whether we have d3d12 dependencies installed. - if not os.path.exists(env["mesa_libs"]): - print_error( - "The Direct3D 12 rendering driver requires dependencies to be installed.\n" - "You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n" - "See the documentation for more information:\n\t" - "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html" - ) - sys.exit(255) + check_d3d12_installed(env) env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"]) env.Append(LIBS=["dxgi", "dxguid"]) @@ -944,19 +899,11 @@ def configure_mingw(env: "SConsEnvironment"): env.Append(CPPDEFINES=["MINGW_ENABLED", ("MINGW_HAS_SECURE_API", 1)]) - # resrc - env.Append(BUILDERS={"RES": env.Builder(action=build_res_file, suffix=".o", src_suffix=".rc")}) - def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["x86_32", "x86_64", "arm32", "arm64"] - if env["arch"] not in supported_arches: - print_error( - 'Unsupported CPU architecture "%s" for Windows. Supported architectures are: %s.' - % (env["arch"], ", ".join(supported_arches)) - ) - sys.exit(255) + validate_arch(env["arch"], get_name(), supported_arches) # At this point the env has been set up with basic tools/compilers. env.Prepend(CPPPATH=["#platform/windows"]) @@ -984,3 +931,20 @@ def configure(env: "SConsEnvironment"): else: # MinGW configure_mingw(env) + + +def check_d3d12_installed(env): + if not os.path.exists(env["mesa_libs"]): + print_error( + "The Direct3D 12 rendering driver requires dependencies to be installed.\n" + "You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n" + "See the documentation for more information:\n\t" + "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html" + ) + sys.exit(255) + + +def validate_win_version(env): + if int(env["target_win_version"], 16) < 0x0601: + print_error("`target_win_version` should be 0x0601 or higher (Windows 7).") + sys.exit(255) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index ffa3840181..e300bd1c47 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -30,6 +30,7 @@ #include "display_server_windows.h" +#include "drop_target_windows.h" #include "os_windows.h" #include "wgl_detect_version.h" @@ -67,6 +68,18 @@ #define DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 19 #endif +#ifndef DWMWA_WINDOW_CORNER_PREFERENCE +#define DWMWA_WINDOW_CORNER_PREFERENCE 33 +#endif + +#ifndef DWMWCP_DEFAULT +#define DWMWCP_DEFAULT 0 +#endif + +#ifndef DWMWCP_DONOTROUND +#define DWMWCP_DONOTROUND 1 +#endif + #define WM_INDICATOR_CALLBACK_MESSAGE (WM_USER + 1) #if defined(__GNUC__) @@ -117,6 +130,7 @@ bool DisplayServerWindows::has_feature(Feature p_feature) const { case FEATURE_NATIVE_DIALOG: case FEATURE_NATIVE_DIALOG_INPUT: case FEATURE_NATIVE_DIALOG_FILE: + case FEATURE_NATIVE_DIALOG_FILE_EXTRA: case FEATURE_SWAP_BUFFERS: case FEATURE_KEEP_SCREEN_ON: case FEATURE_TEXT_TO_SPEECH: @@ -304,8 +318,8 @@ public: } // IFileDialogEvents methods - HRESULT STDMETHODCALLTYPE OnFileOk(IFileDialog *) { return S_OK; }; - HRESULT STDMETHODCALLTYPE OnFolderChange(IFileDialog *) { return S_OK; }; + HRESULT STDMETHODCALLTYPE OnFileOk(IFileDialog *) { return S_OK; } + HRESULT STDMETHODCALLTYPE OnFolderChange(IFileDialog *) { return S_OK; } HRESULT STDMETHODCALLTYPE OnFolderChanging(IFileDialog *p_pfd, IShellItem *p_item) { if (root.is_empty()) { @@ -324,11 +338,11 @@ public: return S_OK; } - HRESULT STDMETHODCALLTYPE OnHelp(IFileDialog *) { return S_OK; }; - HRESULT STDMETHODCALLTYPE OnSelectionChange(IFileDialog *) { return S_OK; }; - HRESULT STDMETHODCALLTYPE OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; }; - HRESULT STDMETHODCALLTYPE OnTypeChange(IFileDialog *pfd) { return S_OK; }; - HRESULT STDMETHODCALLTYPE OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; }; + HRESULT STDMETHODCALLTYPE OnHelp(IFileDialog *) { return S_OK; } + HRESULT STDMETHODCALLTYPE OnSelectionChange(IFileDialog *) { return S_OK; } + HRESULT STDMETHODCALLTYPE OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; } + HRESULT STDMETHODCALLTYPE OnTypeChange(IFileDialog *pfd) { return S_OK; } + HRESULT STDMETHODCALLTYPE OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; } // IFileDialogControlEvents methods HRESULT STDMETHODCALLTYPE OnItemSelected(IFileDialogCustomize *p_pfdc, DWORD p_ctl_id, DWORD p_item_idx) { @@ -338,14 +352,14 @@ public: return S_OK; } - HRESULT STDMETHODCALLTYPE OnButtonClicked(IFileDialogCustomize *, DWORD) { return S_OK; }; + HRESULT STDMETHODCALLTYPE OnButtonClicked(IFileDialogCustomize *, DWORD) { return S_OK; } HRESULT STDMETHODCALLTYPE OnCheckButtonToggled(IFileDialogCustomize *p_pfdc, DWORD p_ctl_id, BOOL p_checked) { if (ctls.has(p_ctl_id)) { selected[ctls[p_ctl_id]] = (bool)p_checked; } return S_OK; } - HRESULT STDMETHODCALLTYPE OnControlActivating(IFileDialogCustomize *, DWORD) { return S_OK; }; + HRESULT STDMETHODCALLTYPE OnControlActivating(IFileDialogCustomize *, DWORD) { return S_OK; } Dictionary get_selected() { return selected; @@ -491,7 +505,7 @@ void DisplayServerWindows::_thread_fd_monitor(void *p_ud) { } if (filter_names.is_empty()) { filter_exts.push_back(String("*.*").utf16()); - filter_names.push_back(RTR("All Files").utf16()); + filter_names.push_back((RTR("All Files") + " (*)").utf16()); } Vector<COMDLG_FILTERSPEC> filters; @@ -722,7 +736,7 @@ Error DisplayServerWindows::_file_dialog_with_options_show(const String &p_title GetWindowRect(fd->hwnd_owner, &crect); fd->wrect = Rect2i(crect.left, crect.top, crect.right - crect.left, crect.bottom - crect.top); } else { - fd->hwnd_owner = 0; + fd->hwnd_owner = nullptr; fd->wrect = Rect2i(CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT); } fd->appid = appname; @@ -1483,6 +1497,9 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod if (p_flags & WINDOW_FLAG_ALWAYS_ON_TOP_BIT && p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) { wd.always_on_top = true; } + if (p_flags & WINDOW_FLAG_SHARP_CORNERS_BIT) { + wd.sharp_corners = true; + } if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) { wd.no_focus = true; } @@ -1601,11 +1618,17 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) { } #endif - if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window].wtctx) { - wintab_WTClose(windows[p_window].wtctx); - windows[p_window].wtctx = nullptr; + if ((tablet_get_current_driver() == "wintab") && wintab_available && wd.wtctx) { + wintab_WTClose(wd.wtctx); + wd.wtctx = nullptr; + } + + if (wd.drop_target != nullptr) { + RevokeDragDrop(wd.hWnd); + wd.drop_target->Release(); } - DestroyWindow(windows[p_window].hWnd); + + DestroyWindow(wd.hWnd); windows.erase(p_window); if (last_focused_window == p_window) { @@ -1650,6 +1673,18 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type, } return 0; } + case EGL_DISPLAY: { + if (gl_manager_angle) { + return (int64_t)gl_manager_angle->get_display(p_window); + } + return 0; + } + case EGL_CONFIG: { + if (gl_manager_angle) { + return (int64_t)gl_manager_angle->get_config(p_window); + } + return 0; + } #endif default: { return 0; @@ -1703,7 +1738,14 @@ void DisplayServerWindows::window_set_drop_files_callback(const Callable &p_call _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - windows[p_window].drop_files_callback = p_callable; + WindowData &window_data = windows[p_window]; + + window_data.drop_files_callback = p_callable; + + if (window_data.drop_target == nullptr) { + window_data.drop_target = memnew(DropTargetWindows(&window_data)); + ERR_FAIL_COND(RegisterDragDrop(window_data.hWnd, window_data.drop_target) != S_OK); + } } void DisplayServerWindows::window_set_title(const String &p_title, WindowID p_window) { @@ -2297,6 +2339,12 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W wd.always_on_top = p_enabled; _update_window_style(p_window); } break; + case WINDOW_FLAG_SHARP_CORNERS: { + wd.sharp_corners = p_enabled; + DWORD value = wd.sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT; + ::DwmSetWindowAttribute(wd.hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value)); + _update_window_style(p_window); + } break; case WINDOW_FLAG_TRANSPARENT: { if (p_enabled) { // Enable per-pixel alpha. @@ -3196,6 +3244,10 @@ void DisplayServerWindows::process_events() { } _THREAD_SAFE_UNLOCK_ + if (tts) { + tts->process_events(); + } + if (!drop_events) { _process_key_events(); Input::get_singleton()->flush_buffered_events(); @@ -3994,6 +4046,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA native_menu->_menu_activate(HMENU(lParam), (int)wParam); } break; case WM_CREATE: { + { + DWORD value = windows[window_id].sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT; + ::DwmSetWindowAttribute(windows[window_id].hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value)); + } if (is_dark_mode_supported() && dark_title_available) { BOOL value = is_dark_mode(); @@ -4740,9 +4796,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA break; } - DisplayServer::WindowID receiving_window_id = _get_focused_window_or_popup(); - if (receiving_window_id == INVALID_WINDOW_ID) { - receiving_window_id = window_id; + DisplayServer::WindowID receiving_window_id = window_id; + if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { + receiving_window_id = _get_focused_window_or_popup(); + if (receiving_window_id == INVALID_WINDOW_ID) { + receiving_window_id = window_id; + } } const BitField<WinKeyModifierMask> &mods = _get_mods(); @@ -5282,32 +5341,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } } break; - case WM_DROPFILES: { - HDROP hDropInfo = (HDROP)wParam; - const int buffsize = 4096; - WCHAR buf[buffsize]; - - int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, nullptr, 0); - - Vector<String> files; - - for (int i = 0; i < fcount; i++) { - DragQueryFileW(hDropInfo, i, buf, buffsize); - String file = String::utf16((const char16_t *)buf); - files.push_back(file); - } - - if (files.size() && windows[window_id].drop_files_callback.is_valid()) { - Variant v_files = files; - const Variant *v_args[1] = { &v_files }; - Variant ret; - Callable::CallError ce; - windows[window_id].drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(windows[window_id].drop_files_callback, v_args, 1, ce))); - } - } - } break; default: { if (user_proc) { return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); @@ -5412,7 +5445,7 @@ void DisplayServerWindows::_process_key_events() { k->set_physical_keycode(physical_keycode); k->set_key_label(key_label); k->set_unicode(fix_unicode(unicode)); - if (k->get_unicode() && ke.altgr) { + if (k->get_unicode() && ke.altgr && windows[ke.window_id].ime_active) { k->set_alt_pressed(false); k->set_ctrl_pressed(false); } @@ -5488,7 +5521,7 @@ void DisplayServerWindows::_process_key_events() { } k->set_unicode(fix_unicode(unicode)); } - if (k->get_unicode() && ke.altgr) { + if (k->get_unicode() && ke.altgr && windows[ke.window_id].ime_active) { k->set_alt_pressed(false); k->set_ctrl_pressed(false); } @@ -5645,6 +5678,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, wd_transient_parent->transient_children.insert(id); } + wd.sharp_corners = p_flags & WINDOW_FLAG_SHARP_CORNERS_BIT; + { + DWORD value = wd.sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT; + ::DwmSetWindowAttribute(wd.hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value)); + } + if (is_dark_mode_supported() && dark_title_available) { BOOL value = is_dark_mode(); ::DwmSetWindowAttribute(wd.hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value)); @@ -6130,6 +6169,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win FreeLibrary(comctl32); } + OleInitialize(nullptr); + memset(&wc, 0, sizeof(WNDCLASSEXW)); wc.cbSize = sizeof(WNDCLASSEXW); wc.style = CS_OWNDC | CS_DBLCLKS; @@ -6195,6 +6236,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } } #endif +#if defined(GLES3_ENABLED) bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); if (failed && fallback_to_opengl3 && rendering_driver != "opengl3") { memdelete(rendering_context); @@ -6206,6 +6248,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); failed = false; } +#endif if (failed) { memdelete(rendering_context); rendering_context = nullptr; @@ -6369,7 +6412,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution), false, INVALID_WINDOW_ID); - ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window."); + if (main_window == INVALID_WINDOW_ID) { + r_error = ERR_UNAVAILABLE; + ERR_FAIL_MSG("Failed to create main window."); + } joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd); @@ -6557,6 +6603,12 @@ DisplayServerWindows::~DisplayServerWindows() { wintab_WTClose(windows[MAIN_WINDOW_ID].wtctx); windows[MAIN_WINDOW_ID].wtctx = nullptr; } + + if (windows[MAIN_WINDOW_ID].drop_target != nullptr) { + RevokeDragDrop(windows[MAIN_WINDOW_ID].hWnd); + windows[MAIN_WINDOW_ID].drop_target->Release(); + } + DestroyWindow(windows[MAIN_WINDOW_ID].hWnd); } @@ -6588,4 +6640,6 @@ DisplayServerWindows::~DisplayServerWindows() { if (tts) { memdelete(tts); } + + OleUninitialize(); } diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 7d6a3e96a6..32ed8823d3 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -38,8 +38,8 @@ #include "core/config/project_settings.h" #include "core/input/input.h" +#include "core/io/image.h" #include "core/os/os.h" -#include "drivers/unix/ip_unix.h" #include "drivers/wasapi/audio_driver_wasapi.h" #include "drivers/winmidi/midi_driver_winmidi.h" #include "servers/audio_server.h" @@ -356,9 +356,13 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS { SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2, } SHC_PROCESS_DPI_AWARENESS; +class DropTargetWindows; + class DisplayServerWindows : public DisplayServer { // No need to register with GDCLASS, it's platform-specific and nothing is added. + friend class DropTargetWindows; + _THREAD_SAFE_CLASS_ // UXTheme API @@ -473,6 +477,7 @@ class DisplayServerWindows : public DisplayServer { bool exclusive = false; bool context_created = false; bool mpass = false; + bool sharp_corners = false; // Used to transfer data between events using timer. WPARAM saved_wparam; @@ -519,6 +524,9 @@ class DisplayServerWindows : public DisplayServer { Callable input_text_callback; Callable drop_files_callback; + // OLE API + DropTargetWindows *drop_target = nullptr; + WindowID transient_parent = INVALID_WINDOW_ID; HashSet<WindowID> transient_children; diff --git a/platform/windows/drop_target_windows.cpp b/platform/windows/drop_target_windows.cpp new file mode 100644 index 0000000000..d04924a9cf --- /dev/null +++ b/platform/windows/drop_target_windows.cpp @@ -0,0 +1,375 @@ +/**************************************************************************/ +/* drop_target_windows.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "drop_target_windows.h" + +#include "core/io/dir_access.h" +#include "core/math/random_pcg.h" +#include "core/os/time.h" + +#include <fileapi.h> + +// Helpers + +static String create_temp_dir() { + Char16String buf; + int bufsize = GetTempPathW(0, nullptr) + 1; + buf.resize(bufsize); + if (GetTempPathW(bufsize, (LPWSTR)buf.ptrw()) == 0) { + return ""; + } + + String tmp_dir = String::utf16((const char16_t *)buf.ptr()); + RandomPCG gen(Time::get_singleton()->get_ticks_usec()); + + const int attempts = 4; + + for (int i = 0; i < attempts; ++i) { + uint32_t rnd = gen.rand(); + String dirname = "godot_tmp_" + String::num_uint64(rnd); + String res_dir = tmp_dir.path_join(dirname); + Char16String res_dir16 = res_dir.utf16(); + + if (CreateDirectoryW((LPCWSTR)res_dir16.ptr(), nullptr)) { + return res_dir; + } + } + + return ""; +} + +static bool remove_dir_recursive(const String &p_dir) { + Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + if (dir_access->change_dir(p_dir) != OK) { + return false; + } + return dir_access->erase_contents_recursive() == OK; +} + +static bool stream2file(IStream *p_stream, FILEDESCRIPTORW *p_desc, const String &p_path) { + if (DirAccess::make_dir_recursive_absolute(p_path.get_base_dir()) != OK) { + return false; + } + + Char16String path16 = p_path.utf16(); + DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + + if (p_desc->dwFlags & FD_ATTRIBUTES) { + dwFlagsAndAttributes = p_desc->dwFileAttributes; + } + + HANDLE file = CreateFileW( + (LPCWSTR)path16.ptr(), + GENERIC_WRITE, + 0, + nullptr, + CREATE_NEW, + dwFlagsAndAttributes, + nullptr); + + if (!file) { + return false; + } + + const int bufsize = 4096; + char buf[bufsize]; + ULONG nread = 0; + DWORD nwritten = 0; + HRESULT read_result = S_OK; + bool result = true; + + while (true) { + read_result = p_stream->Read(buf, bufsize, &nread); + if (read_result != S_OK && read_result != S_FALSE) { + result = false; + goto cleanup; + } + + if (!nread) { + break; + } + + while (nread > 0) { + if (!WriteFile(file, buf, nread, &nwritten, nullptr) || !nwritten) { + result = false; + goto cleanup; + } + nread -= nwritten; + } + } + +cleanup: + CloseHandle(file); + return result; +} + +// DropTargetWindows + +bool DropTargetWindows::is_valid_filedescriptor() { + return cf_filedescriptor != 0 && cf_filecontents != 0; +} + +HRESULT DropTargetWindows::handle_hdrop_format(Vector<String> *p_files, IDataObject *pDataObj) { + FORMATETC fmt = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM stg; + HRESULT res = S_OK; + + if (pDataObj->GetData(&fmt, &stg) != S_OK) { + return E_UNEXPECTED; + } + + HDROP hDropInfo = (HDROP)GlobalLock(stg.hGlobal); + + Char16String buf; + + if (hDropInfo == nullptr) { + ReleaseStgMedium(&stg); + return E_UNEXPECTED; + } + + int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, nullptr, 0); + + for (int i = 0; i < fcount; i++) { + int buffsize = DragQueryFileW(hDropInfo, i, nullptr, 0); + buf.resize(buffsize + 1); + if (DragQueryFileW(hDropInfo, i, (LPWSTR)buf.ptrw(), buffsize + 1) == 0) { + res = E_UNEXPECTED; + goto cleanup; + } + String file = String::utf16((const char16_t *)buf.ptr()); + p_files->push_back(file); + } + +cleanup: + GlobalUnlock(stg.hGlobal); + ReleaseStgMedium(&stg); + + return res; +} + +HRESULT DropTargetWindows::handle_filedescriptor_format(Vector<String> *p_files, IDataObject *pDataObj) { + FORMATETC fmt = { cf_filedescriptor, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM stg; + HRESULT res = S_OK; + + if (pDataObj->GetData(&fmt, &stg) != S_OK) { + return E_UNEXPECTED; + } + + FILEGROUPDESCRIPTORW *filegroup_desc = (FILEGROUPDESCRIPTORW *)GlobalLock(stg.hGlobal); + + if (!filegroup_desc) { + ReleaseStgMedium(&stg); + return E_UNEXPECTED; + } + + tmp_path = create_temp_dir(); + Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + PackedStringArray copied; + + if (dir_access->change_dir(tmp_path) != OK) { + res = E_UNEXPECTED; + goto cleanup; + } + + for (int i = 0; i < (int)filegroup_desc->cItems; ++i) { + res = save_as_file(tmp_path, filegroup_desc->fgd + i, pDataObj, i); + if (res != S_OK) { + res = E_UNEXPECTED; + goto cleanup; + } + } + + copied = dir_access->get_files(); + for (const String &file : copied) { + p_files->push_back(tmp_path.path_join(file)); + } + + copied = dir_access->get_directories(); + for (const String &dir : copied) { + p_files->push_back(tmp_path.path_join(dir)); + } + +cleanup: + GlobalUnlock(filegroup_desc); + ReleaseStgMedium(&stg); + if (res != S_OK) { + remove_dir_recursive(tmp_path); + tmp_path.clear(); + } + return res; +} + +HRESULT DropTargetWindows::save_as_file(const String &p_out_dir, FILEDESCRIPTORW *p_file_desc, IDataObject *pDataObj, int p_file_idx) { + String relpath = String::utf16((const char16_t *)p_file_desc->cFileName); + String fullpath = p_out_dir.path_join(relpath); + + if (p_file_desc->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (DirAccess::make_dir_recursive_absolute(fullpath) != OK) { + return E_UNEXPECTED; + } + return S_OK; + } + + FORMATETC fmt = { cf_filecontents, nullptr, DVASPECT_CONTENT, p_file_idx, TYMED_ISTREAM }; + STGMEDIUM stg; + HRESULT res = S_OK; + + if (pDataObj->GetData(&fmt, &stg) != S_OK) { + return E_UNEXPECTED; + } + + IStream *stream = stg.pstm; + if (stream == nullptr) { + res = E_UNEXPECTED; + goto cleanup; + } + + if (!stream2file(stream, p_file_desc, fullpath)) { + res = E_UNEXPECTED; + goto cleanup; + } + +cleanup: + ReleaseStgMedium(&stg); + return res; +} + +DropTargetWindows::DropTargetWindows(DisplayServerWindows::WindowData *p_window_data) : + ref_count(1), window_data(p_window_data) { + cf_filedescriptor = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW); + cf_filecontents = RegisterClipboardFormat(CFSTR_FILECONTENTS); +} + +HRESULT STDMETHODCALLTYPE DropTargetWindows::QueryInterface(REFIID riid, void **ppvObject) { + if (riid == IID_IUnknown || riid == IID_IDropTarget) { + *ppvObject = static_cast<IDropTarget *>(this); + AddRef(); + return S_OK; + } + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE DropTargetWindows::AddRef() { + return InterlockedIncrement(&ref_count); +} + +ULONG STDMETHODCALLTYPE DropTargetWindows::Release() { + ULONG count = InterlockedDecrement(&ref_count); + if (count == 0) { + memfree(this); + } + return count; +} + +HRESULT STDMETHODCALLTYPE DropTargetWindows::DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { + (void)grfKeyState; + (void)pt; + + FORMATETC hdrop_fmt = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + FORMATETC filedesc_fmt = { cf_filedescriptor, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + + if (!window_data->drop_files_callback.is_valid()) { + *pdwEffect = DROPEFFECT_NONE; + } else if (pDataObj->QueryGetData(&hdrop_fmt) == S_OK) { + *pdwEffect = DROPEFFECT_COPY; + } else if (is_valid_filedescriptor() && pDataObj->QueryGetData(&filedesc_fmt) == S_OK) { + *pdwEffect = DROPEFFECT_COPY; + } else { + *pdwEffect = DROPEFFECT_NONE; + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DropTargetWindows::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { + (void)grfKeyState; + (void)pt; + + *pdwEffect = DROPEFFECT_COPY; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DropTargetWindows::DragLeave() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DropTargetWindows::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { + (void)grfKeyState; + (void)pt; + + *pdwEffect = DROPEFFECT_NONE; + + if (!window_data->drop_files_callback.is_valid()) { + return S_OK; + } + + FORMATETC hdrop_fmt = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + FORMATETC filedesc_fmt = { cf_filedescriptor, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + Vector<String> files; + + if (pDataObj->QueryGetData(&hdrop_fmt) == S_OK) { + HRESULT res = handle_hdrop_format(&files, pDataObj); + if (res != S_OK) { + return res; + } + } else if (pDataObj->QueryGetData(&filedesc_fmt) == S_OK && is_valid_filedescriptor()) { + HRESULT res = handle_filedescriptor_format(&files, pDataObj); + if (res != S_OK) { + return res; + } + } else { + return E_UNEXPECTED; + } + + if (!files.size()) { + return S_OK; + } + + Variant v_files = files; + const Variant *v_args[1] = { &v_files }; + Variant ret; + Callable::CallError ce; + window_data->drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce); + + if (!tmp_path.is_empty()) { + remove_dir_recursive(tmp_path); + tmp_path.clear(); + } + + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(window_data->drop_files_callback, v_args, 1, ce))); + return E_UNEXPECTED; + } + + *pdwEffect = DROPEFFECT_COPY; + return S_OK; +} diff --git a/platform/windows/drop_target_windows.h b/platform/windows/drop_target_windows.h new file mode 100644 index 0000000000..bd0e0270c6 --- /dev/null +++ b/platform/windows/drop_target_windows.h @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* drop_target_windows.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DROP_TARGET_WINDOWS_H +#define DROP_TARGET_WINDOWS_H + +#include "display_server_windows.h" + +#include <shlobj.h> + +// Silence warning due to a COM API weirdness. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +// https://learn.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-dodragdrop#remarks +class DropTargetWindows : public IDropTarget { + LONG ref_count; + DisplayServerWindows::WindowData *window_data = nullptr; + CLIPFORMAT cf_filedescriptor = 0; + CLIPFORMAT cf_filecontents = 0; + String tmp_path; + + bool is_valid_filedescriptor(); + HRESULT handle_hdrop_format(Vector<String> *p_files, IDataObject *pDataObj); + HRESULT handle_filedescriptor_format(Vector<String> *p_files, IDataObject *pDataObj); + HRESULT save_as_file(const String &p_out_dir, FILEDESCRIPTORW *p_file_desc, IDataObject *pDataObj, int p_file_idx); + +public: + DropTargetWindows(DisplayServerWindows::WindowData *p_window_data); + virtual ~DropTargetWindows() {} + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; + ULONG STDMETHODCALLTYPE AddRef() override; + ULONG STDMETHODCALLTYPE Release() override; + + // IDropTarget + HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override; + HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override; + HRESULT STDMETHODCALLTYPE DragLeave() override; + HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override; +}; + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // DROP_TARGET_WINDOWS_H diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 1972b36845..89db449424 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -59,7 +59,7 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC { ssh_args = p_ssh_arg; cmd_args = p_cmd_args; wait = p_wait; - }; + } }; Ref<ImageTexture> run_icon; diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis index 14536fa130..e3a535580f 100644 --- a/platform/windows/godot.natvis +++ b/platform/windows/godot.natvis @@ -1,5 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + <Type Name="Ref<*>"> + <SmartPointer Usage="Minimal">reference</SmartPointer> + <DisplayString Condition="!reference">[empty]</DisplayString> + <DisplayString Condition="!!reference">{*reference}</DisplayString> + <Expand> + <Item Condition="!!reference" Name="[ptr]">reference</Item> + <Item Condition="!!reference" Name="[refcount]">reference->refcount.count.value</Item> + </Expand> + </Type> + <Type Name="Vector<*>"> <Expand> <Item Name="[size]">_cowdata._ptr ? (((const unsigned long long *)(_cowdata._ptr))[-1]) : 0</Item> @@ -20,16 +30,6 @@ </Expand> </Type> - <Type Name="TypedArray<*>"> - <Expand> - <Item Name="[size]"> _p->array._cowdata._ptr ? (((const unsigned long long *)(_p->array._cowdata._ptr))[-1]) : 0</Item> - <ArrayItems> - <Size>_p->array._cowdata._ptr ? (((const unsigned long long *)(_p->array._cowdata._ptr))[-1]) : 0</Size> - <ValuePointer >(Variant *) _p->array._cowdata._ptr</ValuePointer> - </ArrayItems> - </Expand> - </Type> - <Type Name="Dictionary"> <Expand> <Item Name="[size]">_p && _p->variant_map.head_element ? _p->variant_map.num_elements : 0</Item> @@ -91,6 +91,16 @@ <StringView Condition="_data && !_data->cname">_data->name,s32b</StringView> </Type> + <Type Name="HashSet<*,*,*>"> + <Expand> + <Item Name="[size]">num_elements</Item> + <ArrayItems> + <Size>num_elements</Size> + <ValuePointer>($T1 *) keys._cowdata._ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + <Type Name="HashMapElement<*,*>"> <DisplayString>{{Key = {($T1 *) &data.key} Value = {($T2 *) &data.value}}}</DisplayString> <Expand> @@ -133,7 +143,7 @@ <Type Name="HashMapElement<*,*>" IncludeView="MapHelper"> <DisplayString>{data.value}</DisplayString> <Expand> - <Item Name="[key]" >($T1 *) &data.key</Item> + <Item Name="[key]">($T1 *) &data.key</Item> <Item Name="[value]">($T2 *) &data.value</Item> </Expand> </Type> @@ -265,39 +275,164 @@ </Type> <Type Name="Vector2"> - <DisplayString>{{{x},{y}}}</DisplayString> + <DisplayString>({x,g}, {y,g})</DisplayString> + <Expand> + <Item Name="[x]">x</Item> + <Item Name="[y]">y</Item> + </Expand> + </Type> + <Type Name="Vector2i"> + <DisplayString>({x}, {y})</DisplayString> <Expand> - <Item Name="x">x</Item> - <Item Name="y">y</Item> + <Item Name="[x]">x</Item> + <Item Name="[y]">y</Item> </Expand> </Type> <Type Name="Vector3"> - <DisplayString>{{{x},{y},{z}}}</DisplayString> + <DisplayString>({x,g}, {y,g}, {z,g})</DisplayString> + <Expand> + <Item Name="[x]">x</Item> + <Item Name="[y]">y</Item> + <Item Name="[z]">z</Item> + </Expand> + </Type> + <Type Name="Vector3i"> + <DisplayString>({x}, {y}, {z})</DisplayString> + <Expand> + <Item Name="[x]">x</Item> + <Item Name="[y]">y</Item> + <Item Name="[z]">z</Item> + </Expand> + </Type> + + <Type Name="Vector4"> + <DisplayString>({x,g}, {y,g}, {z,g}, {w,g})</DisplayString> + <Expand> + <Item Name="[x]">x</Item> + <Item Name="[y]">y</Item> + <Item Name="[z]">z</Item> + <Item Name="[w]">w</Item> + </Expand> + </Type> + <Type Name="Vector4i"> + <DisplayString>({x}, {y}, {z}, {w})</DisplayString> <Expand> - <Item Name="x">x</Item> - <Item Name="y">y</Item> - <Item Name="z">z</Item> + <Item Name="[x]">x</Item> + <Item Name="[y]">y</Item> + <Item Name="[z]">z</Item> + <Item Name="[w]">w</Item> </Expand> </Type> <Type Name="Quaternion"> - <DisplayString>Quaternion {{{x},{y},{z},{w}}}</DisplayString> + <DisplayString>({x,g}, {y,g}, {z,g}, {w,g})</DisplayString> <Expand> - <Item Name="x">x</Item> - <Item Name="y">y</Item> - <Item Name="z">z</Item> - <Item Name="w">w</Item> + <Item Name="[x]">x</Item> + <Item Name="[y]">y</Item> + <Item Name="[z]">z</Item> + <Item Name="[w]">w</Item> </Expand> </Type> <Type Name="Color"> - <DisplayString>Color {{{r},{g},{b},{a}}}</DisplayString> + <DisplayString>({r,g}, {g,g}, {b,g}, {a,g})</DisplayString> + <Expand> + <Item Name="[red]">r</Item> + <Item Name="[green]">g</Item> + <Item Name="[blue]">b</Item> + <Item Name="[alpha]">a</Item> + </Expand> + </Type> + + <Type Name="Rect2"> + <DisplayString>[P: {position}, S: {size}]</DisplayString> + <Expand> + <Item Name="[position]">position,nr</Item> + <Item Name="[size]">size,nr</Item> + </Expand> + </Type> + <Type Name="Rect2i"> + <DisplayString>[P: {position}, S: {size}]</DisplayString> + <Expand> + <Item Name="[position]">position,nr</Item> + <Item Name="[size]">size,nr</Item> + </Expand> + </Type> + + <Type Name="AABB"> + <DisplayString>[P: {position}, S: {size}]</DisplayString> + <Expand> + <Item Name="[position]">position,nr</Item> + <Item Name="[size]">size,nr</Item> + </Expand> + </Type> + + <Type Name="Plane"> + <DisplayString>[N: {normal}, D: {d,g}]</DisplayString> + <Expand> + <Item Name="[normal]">normal,nr</Item> + <Item Name="[d]">d</Item> + </Expand> + </Type> + + <Type Name="Basis"> + <DisplayString>[X: {rows[0]}, Y: {rows[1]}, Z: {rows[2]}]</DisplayString> + <Expand> + <Item Name="[x]">rows[0],nr</Item> + <Item Name="[y]">rows[1],nr</Item> + <Item Name="[z]">rows[2],nr</Item> + </Expand> + </Type> + + <Type Name="Transform2D"> + <DisplayString>[X: {columns[0]}, Y: {columns[1]}, O: {columns[2]}]</DisplayString> + <Expand> + <Item Name="[x]">columns[0],nr</Item> + <Item Name="[y]">columns[1],nr</Item> + <Item Name="[origin]">columns[2],nr</Item> + </Expand> + </Type> + + <Type Name="Transform3D"> + <!-- Can't call column functions, so just pretend we can via obscene code duplication. --> + <DisplayString>[X: ({basis.rows[0].x,g}, {basis.rows[1].x,g}, {basis.rows[2].x,g}), Y: ({basis.rows[0].y,g}, {basis.rows[1].y,g}, {basis.rows[2].y,g}), Z: ({basis.rows[0].z,g}, {basis.rows[1].z,g}, {basis.rows[2].z,g}), O: {origin}]</DisplayString> + <Expand> + <Synthetic Name="[x]"> + <DisplayString>({basis.rows[0].x,g}, {basis.rows[1].x,g}, {basis.rows[2].x,g})</DisplayString> + <Expand> + <Item Name="[x]">basis.rows[0].x</Item> + <Item Name="[y]">basis.rows[1].x</Item> + <Item Name="[z]">basis.rows[2].x</Item> + </Expand> + </Synthetic> + <Synthetic Name="[y]"> + <DisplayString>({basis.rows[0].y,g}, {basis.rows[1].y,g}, {basis.rows[2].y,g})</DisplayString> + <Expand> + <Item Name="[x]">basis.rows[0].y</Item> + <Item Name="[y]">basis.rows[1].y</Item> + <Item Name="[z]">basis.rows[2].y</Item> + </Expand> + </Synthetic> + <Synthetic Name="[z]"> + <DisplayString>({basis.rows[0].z,g}, {basis.rows[1].z,g}, {basis.rows[2].z,g})</DisplayString> + <Expand> + <Item Name="[x]">basis.rows[0].z</Item> + <Item Name="[y]">basis.rows[1].z</Item> + <Item Name="[z]">basis.rows[2].z</Item> + </Expand> + </Synthetic> + <Item Name="[origin]">origin,nr</Item> + </Expand> + </Type> + + <Type Name="Projection"> + <DisplayString>[X: {columns[0]}, Y: {columns[1]}, Z: {columns[2]}, W: {columns[3]}]</DisplayString> <Expand> - <Item Name="red">r</Item> - <Item Name="green">g</Item> - <Item Name="blue">b</Item> - <Item Name="alpha">a</Item> + <Item Name="[x]">columns[0],nr</Item> + <Item Name="[y]">columns[1],nr</Item> + <Item Name="[z]">columns[2],nr</Item> + <Item Name="[w]">columns[3],nr</Item> </Expand> </Type> </AutoVisualizer> diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index a5f1629cf0..0f55cda5d7 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -122,8 +122,9 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) { memcmp(p_guid, &IID_XOneSWirelessGamepad, sizeof(*p_guid)) == 0 || memcmp(p_guid, &IID_XOneSBluetoothGamepad, sizeof(*p_guid)) == 0 || memcmp(p_guid, &IID_XOneEliteWirelessGamepad, sizeof(*p_guid)) == 0 || - memcmp(p_guid, &IID_XOneElite2WirelessGamepad, sizeof(*p_guid)) == 0) + memcmp(p_guid, &IID_XOneElite2WirelessGamepad, sizeof(*p_guid)) == 0) { return true; + } PRAWINPUTDEVICELIST dev_list = nullptr; unsigned int dev_list_count = 0; diff --git a/platform/windows/native_menu_windows.cpp b/platform/windows/native_menu_windows.cpp index fde55918e4..9fa2849e7b 100644 --- a/platform/windows/native_menu_windows.cpp +++ b/platform/windows/native_menu_windows.cpp @@ -158,7 +158,7 @@ Size2 NativeMenuWindows::get_size(const RID &p_rid) const { int count = GetMenuItemCount(md->menu); for (int i = 0; i < count; i++) { RECT rect; - if (GetMenuItemRect(NULL, md->menu, i, &rect)) { + if (GetMenuItemRect(nullptr, md->menu, i, &rect)) { size.x = MAX(size.x, rect.right - rect.left); size.y += rect.bottom - rect.top; } @@ -992,7 +992,7 @@ void NativeMenuWindows::set_item_submenu(const RID &p_rid, int p_idx, const RID if (p_submenu_rid.is_valid()) { item.hSubMenu = md_sub->menu; } else { - item.hSubMenu = 0; + item.hSubMenu = nullptr; } SetMenuItemInfoW(md->menu, p_idx, true, &item); } @@ -1095,7 +1095,7 @@ void NativeMenuWindows::set_item_icon(const RID &p_rid, int p_idx, const Ref<Tex item_data->bmp = _make_bitmap(item_data->img); } else { item_data->img = Ref<Image>(); - item_data->bmp = 0; + item_data->bmp = nullptr; } item.hbmpItem = item_data->bmp; SetMenuItemInfoW(md->menu, p_idx, true, &item); diff --git a/platform/windows/native_menu_windows.h b/platform/windows/native_menu_windows.h index 235a4b332a..09e4640b40 100644 --- a/platform/windows/native_menu_windows.h +++ b/platform/windows/native_menu_windows.h @@ -31,6 +31,7 @@ #ifndef NATIVE_MENU_WINDOWS_H #define NATIVE_MENU_WINDOWS_H +#include "core/io/image.h" #include "core/templates/hash_map.h" #include "core/templates/rid_owner.h" #include "servers/display/native_menu.h" diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index adc72a79e9..a25b7ea4ca 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -40,10 +40,11 @@ #include "core/debugger/script_debugger.h" #include "core/io/marshalls.h" #include "core/version_generated.gen.h" -#include "drivers/unix/net_socket_posix.h" #include "drivers/windows/dir_access_windows.h" #include "drivers/windows/file_access_windows.h" #include "drivers/windows/file_access_windows_pipe.h" +#include "drivers/windows/ip_windows.h" +#include "drivers/windows/net_socket_winsock.h" #include "main/main.h" #include "servers/audio_server.h" #include "servers/rendering/rendering_server_default.h" @@ -69,6 +70,7 @@ extern "C" { __declspec(dllexport) DWORD NvOptimusEnablement = 1; __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; +__declspec(dllexport) void NoHotPatch() {} // Disable Nahimic code injection. } // Workaround mingw-w64 < 4.0 bug @@ -139,13 +141,13 @@ void RedirectIOToConsole() { if (AttachConsole(ATTACH_PARENT_PROCESS)) { // Restore redirection (Note: if not redirected it's NULL handles not INVALID_HANDLE_VALUE). - if (h_stdin != 0) { + if (h_stdin != nullptr) { SetStdHandle(STD_INPUT_HANDLE, h_stdin); } - if (h_stdout != 0) { + if (h_stdout != nullptr) { SetStdHandle(STD_OUTPUT_HANDLE, h_stdout); } - if (h_stderr != 0) { + if (h_stderr != nullptr) { SetStdHandle(STD_ERROR_HANDLE, h_stderr); } @@ -156,6 +158,52 @@ void RedirectIOToConsole() { } } +bool OS_Windows::is_using_con_wrapper() const { + static String exe_renames[] = { + ".console.exe", + "_console.exe", + " console.exe", + "console.exe", + String(), + }; + + bool found_exe = false; + bool found_conwrap_exe = false; + String exe_name = get_executable_path().to_lower(); + String exe_dir = exe_name.get_base_dir(); + String exe_fname = exe_name.get_file().get_basename(); + + DWORD pids[256]; + DWORD count = GetConsoleProcessList(&pids[0], 256); + for (DWORD i = 0; i < count; i++) { + HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pids[i]); + if (process != NULL) { + WCHAR proc_name[MAX_PATH]; + DWORD len = MAX_PATH; + if (QueryFullProcessImageNameW(process, 0, &proc_name[0], &len)) { + String name = String::utf16((const char16_t *)&proc_name[0], len).replace("\\", "/").to_lower(); + if (name == exe_name) { + found_exe = true; + } + for (int j = 0; !exe_renames[j].is_empty(); j++) { + if (name == exe_dir.path_join(exe_fname + exe_renames[j])) { + found_conwrap_exe = true; + } + } + } + CloseHandle(process); + if (found_conwrap_exe && found_exe) { + break; + } + } + } + if (!found_exe) { + return true; // Unable to read console info, assume true. + } + + return found_conwrap_exe; +} + BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) { if (!EngineDebugger::is_active()) { return FALSE; @@ -209,7 +257,7 @@ void OS_Windows::initialize() { DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA); DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM); - NetSocketPosix::make_default(); + NetSocketWinSock::make_default(); // We need to know how often the clock is updated QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second); @@ -228,7 +276,7 @@ void OS_Windows::initialize() { current_pi.pi.hProcess = GetCurrentProcess(); process_map->insert(GetCurrentProcessId(), current_pi); - IPUnix::make_default(); + IPWindows::make_default(); main_loop = nullptr; HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory)); @@ -303,7 +351,7 @@ void OS_Windows::finalize_core() { timeEndPeriod(1); memdelete(process_map); - NetSocketPosix::cleanup(); + NetSocketWinSock::cleanup(); #ifdef WINDOWS_DEBUG_OUTPUT_ENABLED remove_error_handler(&error_handlers); @@ -769,10 +817,22 @@ double OS_Windows::get_unix_time() const { } void OS_Windows::delay_usec(uint32_t p_usec) const { - if (p_usec < 1000) { - Sleep(1); - } else { - Sleep(p_usec / 1000); + constexpr uint32_t tolerance = 1000 + 20; + + uint64_t t0 = get_ticks_usec(); + uint64_t target_time = t0 + p_usec; + + // Calculate sleep duration with a tolerance for fine-tuning. + if (p_usec > tolerance) { + uint32_t coarse_sleep_usec = p_usec - tolerance; + if (coarse_sleep_usec >= 1000) { + Sleep(coarse_sleep_usec / 1000); + } + } + + // Spin-wait until we reach the precise target time. + while (get_ticks_usec() < target_time) { + YieldProcessor(); } } @@ -908,9 +968,9 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String } // Create pipes. - HANDLE pipe_in[2] = { 0, 0 }; - HANDLE pipe_out[2] = { 0, 0 }; - HANDLE pipe_err[2] = { 0, 0 }; + HANDLE pipe_in[2] = { nullptr, nullptr }; + HANDLE pipe_out[2] = { nullptr, nullptr }; + HANDLE pipe_err[2] = { nullptr, nullptr }; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -918,18 +978,10 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String sa.lpSecurityDescriptor = nullptr; ERR_FAIL_COND_V(!CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0), ret); - if (!SetHandleInformation(pipe_in[1], HANDLE_FLAG_INHERIT, 0)) { - CLEAN_PIPES - ERR_FAIL_V(ret); - } if (!CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0)) { CLEAN_PIPES ERR_FAIL_V(ret); } - if (!SetHandleInformation(pipe_out[0], HANDLE_FLAG_INHERIT, 0)) { - CLEAN_PIPES - ERR_FAIL_V(ret); - } if (!CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0)) { CLEAN_PIPES ERR_FAIL_V(ret); @@ -939,16 +991,37 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String // Create process. ProcessInfo pi; ZeroMemory(&pi.si, sizeof(pi.si)); - pi.si.cb = sizeof(pi.si); + pi.si.StartupInfo.cb = sizeof(pi.si); ZeroMemory(&pi.pi, sizeof(pi.pi)); - LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; + LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo; - pi.si.dwFlags |= STARTF_USESTDHANDLES; - pi.si.hStdInput = pipe_in[0]; - pi.si.hStdOutput = pipe_out[1]; - pi.si.hStdError = pipe_err[1]; + pi.si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + pi.si.StartupInfo.hStdInput = pipe_in[0]; + pi.si.StartupInfo.hStdOutput = pipe_out[1]; + pi.si.StartupInfo.hStdError = pipe_err[1]; + + SIZE_T attr_list_size = 0; + InitializeProcThreadAttributeList(nullptr, 1, 0, &attr_list_size); + pi.si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(attr_list_size); + if (!InitializeProcThreadAttributeList(pi.si.lpAttributeList, 1, 0, &attr_list_size)) { + CLEAN_PIPES + ERR_FAIL_V(ret); + } + HANDLE handles_to_inherit[] = { pipe_in[0], pipe_out[1], pipe_err[1] }; + if (!UpdateProcThreadAttribute( + pi.si.lpAttributeList, + 0, + PROC_THREAD_ATTRIBUTE_HANDLE_LIST, + handles_to_inherit, + sizeof(handles_to_inherit), + nullptr, + nullptr)) { + CLEAN_PIPES + DeleteProcThreadAttributeList(pi.si.lpAttributeList); + ERR_FAIL_V(ret); + } - DWORD creation_flags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW; + DWORD creation_flags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT; Char16String current_dir_name; size_t str_len = GetCurrentDirectoryW(0, nullptr); @@ -964,11 +1037,13 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String if (!CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, true, creation_flags, nullptr, (LPWSTR)current_dir_name.ptr(), si_w, &pi.pi)) { CLEAN_PIPES + DeleteProcThreadAttributeList(pi.si.lpAttributeList); ERR_FAIL_V_MSG(ret, "Could not create child process: " + command); } CloseHandle(pipe_in[0]); CloseHandle(pipe_out[1]); CloseHandle(pipe_err[1]); + DeleteProcThreadAttributeList(pi.si.lpAttributeList); ProcessID pid = pi.pi.dwProcessId; process_map_mutex.lock(); @@ -981,7 +1056,7 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String Ref<FileAccessWindowsPipe> err_pipe; err_pipe.instantiate(); - err_pipe->open_existing(pipe_err[0], 0, p_blocking); + err_pipe->open_existing(pipe_err[0], nullptr, p_blocking); ret["stdio"] = main_pipe; ret["stderr"] = err_pipe; @@ -1000,9 +1075,9 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, ProcessInfo pi; ZeroMemory(&pi.si, sizeof(pi.si)); - pi.si.cb = sizeof(pi.si); + pi.si.StartupInfo.cb = sizeof(pi.si); ZeroMemory(&pi.pi, sizeof(pi.pi)); - LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; + LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo; bool inherit_handles = false; HANDLE pipe[2] = { nullptr, nullptr }; @@ -1014,16 +1089,40 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, sa.lpSecurityDescriptor = nullptr; ERR_FAIL_COND_V(!CreatePipe(&pipe[0], &pipe[1], &sa, 0), ERR_CANT_FORK); - ERR_FAIL_COND_V(!SetHandleInformation(pipe[0], HANDLE_FLAG_INHERIT, 0), ERR_CANT_FORK); // Read handle is for host process only and should not be inherited. - pi.si.dwFlags |= STARTF_USESTDHANDLES; - pi.si.hStdOutput = pipe[1]; + pi.si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + pi.si.StartupInfo.hStdOutput = pipe[1]; if (read_stderr) { - pi.si.hStdError = pipe[1]; + pi.si.StartupInfo.hStdError = pipe[1]; + } + + SIZE_T attr_list_size = 0; + InitializeProcThreadAttributeList(nullptr, 1, 0, &attr_list_size); + pi.si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(attr_list_size); + if (!InitializeProcThreadAttributeList(pi.si.lpAttributeList, 1, 0, &attr_list_size)) { + CloseHandle(pipe[0]); // Cleanup pipe handles. + CloseHandle(pipe[1]); + ERR_FAIL_V(ERR_CANT_FORK); + } + if (!UpdateProcThreadAttribute( + pi.si.lpAttributeList, + 0, + PROC_THREAD_ATTRIBUTE_HANDLE_LIST, + &pipe[1], + sizeof(HANDLE), + nullptr, + nullptr)) { + CloseHandle(pipe[0]); // Cleanup pipe handles. + CloseHandle(pipe[1]); + DeleteProcThreadAttributeList(pi.si.lpAttributeList); + ERR_FAIL_V(ERR_CANT_FORK); } inherit_handles = true; } DWORD creation_flags = NORMAL_PRIORITY_CLASS; + if (inherit_handles) { + creation_flags |= EXTENDED_STARTUPINFO_PRESENT; + } if (p_open_console) { creation_flags |= CREATE_NEW_CONSOLE; } else { @@ -1046,6 +1145,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, if (!ret && r_pipe) { CloseHandle(pipe[0]); // Cleanup pipe handles. CloseHandle(pipe[1]); + DeleteProcThreadAttributeList(pi.si.lpAttributeList); } ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); @@ -1101,6 +1201,9 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, CloseHandle(pi.pi.hProcess); CloseHandle(pi.pi.hThread); + if (r_pipe) { + DeleteProcThreadAttributeList(pi.si.lpAttributeList); + } return OK; } @@ -1114,9 +1217,9 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg ProcessInfo pi; ZeroMemory(&pi.si, sizeof(pi.si)); - pi.si.cb = sizeof(pi.si); + pi.si.StartupInfo.cb = sizeof(pi.si.StartupInfo); ZeroMemory(&pi.pi, sizeof(pi.pi)); - LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; + LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo; DWORD creation_flags = NORMAL_PRIORITY_CLASS; if (p_open_console) { @@ -1363,7 +1466,7 @@ public: locale = p_locale; n_sub = p_nsub; rtl = p_rtl; - }; + } virtual ~FallbackTextAnalysisSource() {} }; @@ -1639,16 +1742,115 @@ void OS_Windows::unset_environment(const String &p_var) const { SetEnvironmentVariableW((LPCWSTR)(p_var.utf16().get_data()), nullptr); // Null to delete. } -String OS_Windows::get_stdin_string() { - char buff[1024]; +String OS_Windows::get_stdin_string(int64_t p_buffer_size) { + if (get_stdin_type() == STD_HANDLE_INVALID) { + return String(); + } + + Vector<uint8_t> data; + data.resize(p_buffer_size); DWORD count = 0; - if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buff, 1024, &count, nullptr)) { - return String::utf8((const char *)buff, count); + if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), data.ptrw(), data.size(), &count, nullptr)) { + return String::utf8((const char *)data.ptr(), count); } return String(); } +PackedByteArray OS_Windows::get_stdin_buffer(int64_t p_buffer_size) { + Vector<uint8_t> data; + data.resize(p_buffer_size); + DWORD count = 0; + if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), data.ptrw(), data.size(), &count, nullptr)) { + return data; + } + + return PackedByteArray(); +} + +OS_Windows::StdHandleType OS_Windows::get_stdin_type() const { + HANDLE h = GetStdHandle(STD_INPUT_HANDLE); + if (h == 0 || h == INVALID_HANDLE_VALUE) { + return STD_HANDLE_INVALID; + } + DWORD ftype = GetFileType(h); + if (ftype == FILE_TYPE_UNKNOWN && GetLastError() != ERROR_SUCCESS) { + return STD_HANDLE_UNKNOWN; + } + ftype &= ~(FILE_TYPE_REMOTE); + + if (ftype == FILE_TYPE_DISK) { + return STD_HANDLE_FILE; + } else if (ftype == FILE_TYPE_PIPE) { + return STD_HANDLE_PIPE; + } else { + DWORD conmode = 0; + BOOL res = GetConsoleMode(h, &conmode); + if (!res && (GetLastError() == ERROR_INVALID_HANDLE)) { + return STD_HANDLE_UNKNOWN; // Unknown character device. + } else { +#ifndef WINDOWS_SUBSYSTEM_CONSOLE + if (!is_using_con_wrapper()) { + return STD_HANDLE_INVALID; // Window app can't read stdin input without werapper. + } +#endif + return STD_HANDLE_CONSOLE; + } + } +} + +OS_Windows::StdHandleType OS_Windows::get_stdout_type() const { + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + if (h == 0 || h == INVALID_HANDLE_VALUE) { + return STD_HANDLE_INVALID; + } + DWORD ftype = GetFileType(h); + if (ftype == FILE_TYPE_UNKNOWN && GetLastError() != ERROR_SUCCESS) { + return STD_HANDLE_UNKNOWN; + } + ftype &= ~(FILE_TYPE_REMOTE); + + if (ftype == FILE_TYPE_DISK) { + return STD_HANDLE_FILE; + } else if (ftype == FILE_TYPE_PIPE) { + return STD_HANDLE_PIPE; + } else { + DWORD conmode = 0; + BOOL res = GetConsoleMode(h, &conmode); + if (!res && (GetLastError() == ERROR_INVALID_HANDLE)) { + return STD_HANDLE_UNKNOWN; // Unknown character device. + } else { + return STD_HANDLE_CONSOLE; + } + } +} + +OS_Windows::StdHandleType OS_Windows::get_stderr_type() const { + HANDLE h = GetStdHandle(STD_ERROR_HANDLE); + if (h == 0 || h == INVALID_HANDLE_VALUE) { + return STD_HANDLE_INVALID; + } + DWORD ftype = GetFileType(h); + if (ftype == FILE_TYPE_UNKNOWN && GetLastError() != ERROR_SUCCESS) { + return STD_HANDLE_UNKNOWN; + } + ftype &= ~(FILE_TYPE_REMOTE); + + if (ftype == FILE_TYPE_DISK) { + return STD_HANDLE_FILE; + } else if (ftype == FILE_TYPE_PIPE) { + return STD_HANDLE_PIPE; + } else { + DWORD conmode = 0; + BOOL res = GetConsoleMode(h, &conmode); + if (!res && (GetLastError() == ERROR_INVALID_HANDLE)) { + return STD_HANDLE_UNKNOWN; // Unknown character device. + } else { + return STD_HANDLE_CONSOLE; + } + } +} + Error OS_Windows::shell_open(const String &p_uri) { INT_PTR ret = (INT_PTR)ShellExecuteW(nullptr, nullptr, (LPCWSTR)(p_uri.utf16().get_data()), nullptr, nullptr, SW_SHOWNORMAL); if (ret > 32) { @@ -1740,6 +1942,34 @@ String OS_Windows::get_locale() const { return "en"; } +String OS_Windows::get_model_name() const { + HKEY hkey; + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Hardware\\Description\\System\\BIOS", 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) { + return OS::get_model_name(); + } + + String sys_name; + String board_name; + WCHAR buffer[256]; + DWORD buffer_len = 256; + DWORD vtype = REG_SZ; + if (RegQueryValueExW(hkey, L"SystemProductName", nullptr, &vtype, (LPBYTE)buffer, &buffer_len) == ERROR_SUCCESS && buffer_len != 0) { + sys_name = String::utf16((const char16_t *)buffer, buffer_len).strip_edges(); + } + buffer_len = 256; + if (RegQueryValueExW(hkey, L"BaseBoardProduct", nullptr, &vtype, (LPBYTE)buffer, &buffer_len) == ERROR_SUCCESS && buffer_len != 0) { + board_name = String::utf16((const char16_t *)buffer, buffer_len).strip_edges(); + } + RegCloseKey(hkey); + if (!sys_name.is_empty() && sys_name.to_lower() != "system product name") { + return sys_name; + } + if (!board_name.is_empty() && board_name.to_lower() != "base board product") { + return board_name; + } + return OS::get_model_name(); +} + String OS_Windows::get_processor_name() const { const String id = "Hardware\\Description\\System\\CentralProcessor\\0"; diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 4f9bc049ee..fd98f9b14b 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -37,7 +37,6 @@ #include "core/config/project_settings.h" #include "core/input/input.h" #include "core/os/os.h" -#include "drivers/unix/ip_unix.h" #include "drivers/wasapi/audio_driver_wasapi.h" #include "drivers/winmidi/midi_driver_winmidi.h" #include "servers/audio_server.h" @@ -134,6 +133,8 @@ class OS_Windows : public OS { DWRITE_FONT_WEIGHT _weight_to_dw(int p_weight) const; DWRITE_FONT_STRETCH _stretch_to_dw(int p_stretch) const; + bool is_using_con_wrapper() const; + // functions used by main to initialize/deinitialize the OS protected: virtual void initialize() override; @@ -143,12 +144,17 @@ protected: virtual void finalize() override; virtual void finalize_core() override; - virtual String get_stdin_string() override; + + virtual String get_stdin_string(int64_t p_buffer_size = 1024) override; + virtual PackedByteArray get_stdin_buffer(int64_t p_buffer_size = 1024) override; + virtual StdHandleType get_stdin_type() const override; + virtual StdHandleType get_stdout_type() const override; + virtual StdHandleType get_stderr_type() const override; String _quote_command_line_argument(const String &p_text) const; struct ProcessInfo { - STARTUPINFO si; + STARTUPINFOEX si; PROCESS_INFORMATION pi; mutable bool is_running = true; mutable int exit_code = -1; @@ -210,6 +216,8 @@ public: virtual String get_processor_name() const override; + virtual String get_model_name() const override; + virtual uint64_t get_embedded_pck_offset() const override; virtual String get_config_path() const override; diff --git a/platform/windows/platform_windows_builders.py b/platform/windows/platform_windows_builders.py index 3fd9e1a581..2020e68748 100644 --- a/platform/windows/platform_windows_builders.py +++ b/platform/windows/platform_windows_builders.py @@ -2,23 +2,11 @@ import os -from detect import get_mingw_bin_prefix, try_cmd - def make_debug_mingw(target, source, env): dst = str(target[0]) # Force separate debug symbols if executable size is larger than 1.9 GB. if env["separate_debug_symbols"] or os.stat(dst).st_size >= 2040109465: - mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) - if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]): - os.system(mingw_bin_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(dst)) - else: - os.system("objcopy --only-keep-debug {0} {0}.debugsymbols".format(dst)) - if try_cmd("strip --version", env["mingw_prefix"], env["arch"]): - os.system(mingw_bin_prefix + "strip --strip-debug --strip-unneeded {0}".format(dst)) - else: - os.system("strip --strip-debug --strip-unneeded {0}".format(dst)) - if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]): - os.system(mingw_bin_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(dst)) - else: - os.system("objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(dst)) + os.system("{0} --only-keep-debug {1} {1}.debugsymbols".format(env["OBJCOPY"], dst)) + os.system("{0} --strip-debug --strip-unneeded {1}".format(env["STRIP"], dst)) + os.system("{0} --add-gnu-debuglink={1}.debugsymbols {1}".format(env["OBJCOPY"], dst)) diff --git a/platform/windows/tts_windows.cpp b/platform/windows/tts_windows.cpp index 39a8f3e120..e9ef50d736 100644 --- a/platform/windows/tts_windows.cpp +++ b/platform/windows/tts_windows.cpp @@ -43,7 +43,7 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam) } else if (event.eEventId == SPEI_END_INPUT_STREAM) { DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_ENDED, tts->ids[stream_num].id); tts->ids.erase(stream_num); - tts->_update_tts(); + tts->update_requested = true; } else if (event.eEventId == SPEI_WORD_BOUNDARY) { const Char16String &string = tts->ids[stream_num].string; int pos = 0; @@ -60,8 +60,8 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam) } } -void TTS_Windows::_update_tts() { - if (!is_speaking() && !paused && queue.size() > 0) { +void TTS_Windows::process_events() { + if (update_requested && !paused && queue.size() > 0 && !is_speaking()) { DisplayServer::TTSUtterance &message = queue.front()->get(); String text; @@ -110,6 +110,8 @@ void TTS_Windows::_update_tts() { ids[(uint32_t)stream_number] = ut; queue.pop_front(); + + update_requested = false; } } @@ -207,7 +209,7 @@ void TTS_Windows::speak(const String &p_text, const String &p_voice, int p_volum if (is_paused()) { resume(); } else { - _update_tts(); + update_requested = true; } } diff --git a/platform/windows/tts_windows.h b/platform/windows/tts_windows.h index 33b597c612..657cb608d6 100644 --- a/platform/windows/tts_windows.h +++ b/platform/windows/tts_windows.h @@ -55,9 +55,9 @@ class TTS_Windows { int id; }; HashMap<uint32_t, UTData> ids; + bool update_requested = false; static void __stdcall speech_event_callback(WPARAM wParam, LPARAM lParam); - void _update_tts(); static TTS_Windows *singleton; @@ -73,6 +73,8 @@ public: void resume(); void stop(); + void process_events(); + TTS_Windows(); ~TTS_Windows(); }; diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp index 6c54faa13a..e25c612008 100644 --- a/platform/windows/windows_terminal_logger.cpp +++ b/platform/windows/windows_terminal_logger.cpp @@ -30,6 +30,8 @@ #include "windows_terminal_logger.h" +#include "core/os/os.h" + #ifdef WINDOWS_ENABLED #include <stdio.h> @@ -78,7 +80,7 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file } HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); - if (!hCon || hCon == INVALID_HANDLE_VALUE) { + if (OS::get_singleton()->get_stdout_type() != OS::STD_HANDLE_CONSOLE || !hCon || hCon == INVALID_HANDLE_VALUE) { StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type); } else { CONSOLE_SCREEN_BUFFER_INFO sbi; //original diff --git a/platform/windows/windows_utils.cpp b/platform/windows/windows_utils.cpp index 30743c6900..3b9bfb50f7 100644 --- a/platform/windows/windows_utils.cpp +++ b/platform/windows/windows_utils.cpp @@ -67,11 +67,11 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) { { // The custom LoadLibraryExW is used instead of open_dynamic_library // to avoid loading the original PDB into the debugger. - HMODULE library_ptr = LoadLibraryExW((LPCWSTR)(p_dll_path.utf16().get_data()), NULL, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE); + HMODULE library_ptr = LoadLibraryExW((LPCWSTR)(p_dll_path.utf16().get_data()), nullptr, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE); ERR_FAIL_NULL_V_MSG(library_ptr, ERR_FILE_CANT_OPEN, vformat("Failed to load library '%s'.", p_dll_path)); - IMAGE_DEBUG_DIRECTORY *dbg_dir = (IMAGE_DEBUG_DIRECTORY *)ImageDirectoryEntryToDataEx(library_ptr, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dbg_info_size, NULL); + IMAGE_DEBUG_DIRECTORY *dbg_dir = (IMAGE_DEBUG_DIRECTORY *)ImageDirectoryEntryToDataEx(library_ptr, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dbg_info_size, nullptr); bool has_debug = dbg_dir && dbg_dir->Type == IMAGE_DEBUG_TYPE_CODEVIEW; if (has_debug) { diff --git a/platform_methods.py b/platform_methods.py index 2b157da22b..201df3c0b5 100644 --- a/platform_methods.py +++ b/platform_methods.py @@ -1,12 +1,20 @@ import os import platform import subprocess +import sys import methods # NOTE: The multiprocessing module is not compatible with SCons due to conflict on cPickle +compatibility_platform_aliases = { + "osx": "macos", + "iphone": "ios", + "x11": "linuxbsd", + "javascript": "web", +} + # CPU architecture options. architectures = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64", "wasm32"] architecture_aliases = { @@ -40,6 +48,15 @@ def detect_arch(): return "x86_64" +def validate_arch(arch, platform_name, supported_arches): + if arch not in supported_arches: + methods.print_error( + 'Unsupported CPU architecture "%s" for %s. Supported architectures are: %s.' + % (arch, platform_name, ", ".join(supported_arches)) + ) + sys.exit(255) + + def get_build_version(short): import version diff --git a/pyproject.toml b/pyproject.toml index a4bfd27816..403d9fd675 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,14 +1,14 @@ [tool.mypy] -ignore_missing_imports = true disallow_any_generics = true +explicit_package_bases = true +ignore_missing_imports = true +namespace_packages = true no_implicit_optional = true pretty = true show_column_numbers = true warn_redundant_casts = true warn_return_any = true warn_unreachable = true -namespace_packages = true -explicit_package_bases = true exclude = ["thirdparty/"] python_version = "3.8" @@ -16,7 +16,7 @@ python_version = "3.8" extend-exclude = ["thirdparty"] extend-include = ["SConstruct", "SCsub"] line-length = 120 -target-version = "py37" +target-version = "py38" [tool.ruff.lint] extend-select = [ @@ -42,50 +42,50 @@ section-order = [ ] [tool.codespell] -enable-colors = "" -write-changes = "" -check-hidden = "" +enable-colors = true +write-changes = true +check-hidden = true quiet-level = 3 -builtin = "clear,rare,en-GB_to_en-US" -skip = """\ - .mailmap, - *.desktop, - *.gitignore, - *.po, - *.pot, - *.rc, - AUTHORS.md, - COPYRIGHT.txt, - core/input/gamecontrollerdb.txt, - core/string/locales.h, - DONORS.md, - editor/project_converter_3_to_4.cpp, - platform/android/java/lib/src/com/*, - platform/web/package-lock.json -""" -ignore-words-list = """\ - breaked, - cancelled, - checkin, - colour, - curvelinear, - doubleclick, - expct, - findn, - gird, - hel, - inout, - labelin, - lod, - mis, - nd, - numer, - ot, - outin, - parm, - requestor, - te, - textin, - thirdparty, - vai -""" +builtin = ["clear", "rare", "en-GB_to_en-US"] +skip = [ + ".mailmap", + "*.desktop", + "*.gitignore", + "*.po", + "*.pot", + "*.rc", + "AUTHORS.md", + "COPYRIGHT.txt", + "core/input/gamecontrollerdb.txt", + "core/string/locales.h", + "DONORS.md", + "editor/project_converter_3_to_4.cpp", + "platform/android/java/lib/src/com/*", + "platform/web/package-lock.json", +] +ignore-words-list = [ + "breaked", + "cancelled", + "checkin", + "colour", + "curvelinear", + "doubleclick", + "expct", + "findn", + "gird", + "hel", + "inout", + "labelin", + "lod", + "mis", + "nd", + "numer", + "ot", + "outin", + "parm", + "requestor", + "te", + "textin", + "thirdparty", + "vai", +] diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 1cab29f383..108f200613 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -56,7 +56,9 @@ Point2 AnimatedSprite2D::_edit_get_pivot() const { bool AnimatedSprite2D::_edit_use_pivot() const { return true; } +#endif // TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 AnimatedSprite2D::_edit_get_rect() const { return _get_rect(); } @@ -75,7 +77,7 @@ bool AnimatedSprite2D::_edit_use_rect() const { } return t.is_valid(); } -#endif +#endif // DEBUG_ENABLED Rect2 AnimatedSprite2D::get_anchorable_rect() const { return _get_rect(); @@ -593,7 +595,7 @@ void AnimatedSprite2D::get_argument_options(const StringName &p_function, int p_ } Node2D::get_argument_options(p_function, p_idx, r_options); } -#endif +#endif // TOOLS_ENABLED #ifndef DISABLE_DEPRECATED bool AnimatedSprite2D::_set(const StringName &p_name, const Variant &p_value) { diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h index 914dc405ab..3de36e7cab 100644 --- a/scene/2d/animated_sprite_2d.h +++ b/scene/2d/animated_sprite_2d.h @@ -66,7 +66,7 @@ class AnimatedSprite2D : public Node2D { protected: #ifndef DISABLE_DEPRECATED bool _set(const StringName &p_name, const Variant &p_value); -#endif +#endif // DISABLE_DEPRECATED static void _bind_methods(); void _notification(int p_what); void _validate_property(PropertyInfo &p_property) const; @@ -79,9 +79,12 @@ public: virtual void _edit_set_pivot(const Point2 &p_pivot) override; virtual Point2 _edit_get_pivot() const override; virtual bool _edit_use_pivot() const override; +#endif // TOOLS_ENABLED + +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED virtual Rect2 get_anchorable_rect() const override; @@ -129,7 +132,7 @@ public: #ifdef TOOLS_ENABLED virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; -#endif +#endif // TOOLS_ENABLED AnimatedSprite2D(); }; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 7c60e47e64..8aaa230075 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -410,7 +410,7 @@ void AudioStreamPlayer2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,24,suffix:dB"), "set_volume_db", "get_volume_db"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_ONESHOT, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "1,4096,1,or_greater,exp,suffix:px"), "set_max_distance", "get_max_distance"); diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index 4cae1affc3..045dd3be02 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -45,7 +45,7 @@ void BackBufferCopy::_update_copy_mode() { } } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 BackBufferCopy::_edit_get_rect() const { return rect; } @@ -53,7 +53,7 @@ Rect2 BackBufferCopy::_edit_get_rect() const { bool BackBufferCopy::_edit_use_rect() const { return true; } -#endif +#endif // DEBUG_ENABLED Rect2 BackBufferCopy::get_anchorable_rect() const { return rect; diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h index e918995708..9bcb731b50 100644 --- a/scene/2d/back_buffer_copy.h +++ b/scene/2d/back_buffer_copy.h @@ -54,10 +54,10 @@ protected: void _validate_property(PropertyInfo &p_property) const; public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 7020d162fe..74f26df706 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -115,11 +115,11 @@ void Camera2D::set_zoom(const Vector2 &p_zoom) { Point2 old_smoothed_camera_pos = smoothed_camera_pos; _update_scroll(); smoothed_camera_pos = old_smoothed_camera_pos; -}; +} Vector2 Camera2D::get_zoom() const { return zoom; -}; +} Transform2D Camera2D::get_camera_transform() { if (!get_tree()) { @@ -302,6 +302,7 @@ void Camera2D::_notification(int p_what) { _interpolation_data.xform_prev = _interpolation_data.xform_curr; } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (is_physics_interpolated_and_enabled()) { _update_scroll(); diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 754afb0527..5c1524b211 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -506,6 +506,10 @@ bool CPUParticles2D::get_split_scale() { } void CPUParticles2D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "emitting") { + p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE; + } + if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { p_property.usage = PROPERTY_USAGE_NONE; } @@ -1285,7 +1289,7 @@ void CPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &CPUParticles2D::restart); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime"); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index cfdcbee86a..8dac13c38b 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -384,6 +384,9 @@ Ref<Texture2D> GPUParticles2D::get_texture() const { } void GPUParticles2D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "emitting") { + p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE; + } } void GPUParticles2D::emit_particle(const Transform2D &p_transform2d, const Vector2 &p_velocity2d, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { @@ -696,6 +699,8 @@ void GPUParticles2D::_notification(int p_what) { RS::get_singleton()->particles_set_subemitter(particles, RID()); } break; + case NOTIFICATION_SUSPENDED: + case NOTIFICATION_UNSUSPENDED: case NOTIFICATION_PAUSED: case NOTIFICATION_UNPAUSED: { if (is_inside_tree()) { @@ -816,7 +821,7 @@ void GPUParticles2D::_bind_methods() { ADD_SIGNAL(MethodInfo("finished")); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting"); ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001"), "set_amount_ratio", "get_amount_ratio"); diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 50c5873781..0b54d1e604 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -54,7 +54,7 @@ void Light2D::_update_light_visibility() { if (editor_only) { editor_ok = false; } -#endif +#endif // TOOLS_ENABLED RS::get_singleton()->canvas_light_set_enabled(canvas_light, enabled && is_visible_in_tree() && editor_ok); } @@ -343,7 +343,6 @@ Light2D::~Light2D() { ////////////////////////////// #ifdef TOOLS_ENABLED - Dictionary PointLight2D::_edit_get_state() const { Dictionary state = Node2D::_edit_get_state(); state["offset"] = get_texture_offset(); @@ -367,7 +366,9 @@ Point2 PointLight2D::_edit_get_pivot() const { bool PointLight2D::_edit_use_pivot() const { return true; } +#endif // TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 PointLight2D::_edit_get_rect() const { if (texture.is_null()) { return Rect2(); @@ -380,7 +381,7 @@ Rect2 PointLight2D::_edit_get_rect() const { bool PointLight2D::_edit_use_rect() const { return !texture.is_null(); } -#endif +#endif // DEBUG_ENABLED Rect2 PointLight2D::get_anchorable_rect() const { if (texture.is_null()) { @@ -417,7 +418,7 @@ Vector2 PointLight2D::get_texture_offset() const { } PackedStringArray PointLight2D::get_configuration_warnings() const { - PackedStringArray warnings = Node2D::get_configuration_warnings(); + PackedStringArray warnings = Light2D::get_configuration_warnings(); if (!texture.is_valid()) { warnings.push_back(RTR("A texture with the shape of the light must be supplied to the \"Texture\" property.")); diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 8a0c2a2a92..0c1dae071c 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -160,9 +160,12 @@ public: virtual void _edit_set_pivot(const Point2 &p_pivot) override; virtual Point2 _edit_get_pivot() const override; virtual bool _edit_use_pivot() const override; +#endif // TOOLS_ENABLED + +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED virtual Rect2 get_anchorable_rect() const override; diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index 7c3fb61d04..e2e4125d1f 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -35,7 +35,7 @@ #define LINE_GRAB_WIDTH 8 -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 OccluderPolygon2D::_edit_get_rect() const { if (rect_cache_dirty) { if (closed) { @@ -83,13 +83,14 @@ bool OccluderPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double return false; } } -#endif +#endif // DEBUG_ENABLED void OccluderPolygon2D::set_polygon(const Vector<Vector2> &p_polygon) { polygon = p_polygon; rect_cache_dirty = true; RS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, p_polygon, closed); emit_changed(); + update_configuration_warning(); } Vector<Vector2> OccluderPolygon2D::get_polygon() const { @@ -155,7 +156,7 @@ OccluderPolygon2D::~OccluderPolygon2D() { void LightOccluder2D::_poly_changed() { #ifdef DEBUG_ENABLED queue_redraw(); -#endif +#endif // DEBUG_ENABLED } void LightOccluder2D::_physics_interpolated_changed() { @@ -217,7 +218,7 @@ void LightOccluder2D::_notification(int p_what) { } } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 LightOccluder2D::_edit_get_rect() const { return occluder_polygon.is_valid() ? occluder_polygon->_edit_get_rect() : Rect2(); } @@ -225,14 +226,14 @@ Rect2 LightOccluder2D::_edit_get_rect() const { bool LightOccluder2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return occluder_polygon.is_valid() ? occluder_polygon->_edit_is_selected_on_click(p_point, p_tolerance) : false; } -#endif +#endif // DEBUG_ENABLED void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon) { #ifdef DEBUG_ENABLED if (occluder_polygon.is_valid()) { occluder_polygon->disconnect_changed(callable_mp(this, &LightOccluder2D::_poly_changed)); } -#endif +#endif // DEBUG_ENABLED occluder_polygon = p_polygon; if (occluder_polygon.is_valid()) { @@ -246,7 +247,7 @@ void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polyg occluder_polygon->connect_changed(callable_mp(this, &LightOccluder2D::_poly_changed)); } queue_redraw(); -#endif +#endif // DEBUG_ENABLED } Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const { diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index 4c499d0465..b9f7eec33d 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -56,11 +56,10 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; -#endif - +#endif // DEBUG_ENABLED void set_polygon(const Vector<Vector2> &p_polygon); Vector<Vector2> get_polygon() const; @@ -93,10 +92,10 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; -#endif +#endif // DEBUG_ENABLED void set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon); Ref<OccluderPolygon2D> get_occluder_polygon() const; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index be58875e0e..734db2ea2b 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -36,7 +36,7 @@ Line2D::Line2D() { } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 Line2D::_edit_get_rect() const { if (_points.size() == 0) { return Rect2(0, 0, 0, 0); diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 1d750ca456..0156336403 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -55,7 +55,7 @@ public: LINE_TEXTURE_STRETCH }; -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; diff --git a/scene/2d/marker_2d.cpp b/scene/2d/marker_2d.cpp index b1b9705bf8..1f4ea172e9 100644 --- a/scene/2d/marker_2d.cpp +++ b/scene/2d/marker_2d.cpp @@ -61,7 +61,7 @@ void Marker2D::_draw_cross() { draw_multiline_colors(points, colors); } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 Marker2D::_edit_get_rect() const { real_t extents = get_gizmo_extents(); return Rect2(Point2(-extents, -extents), Size2(extents * 2, extents * 2)); @@ -70,7 +70,7 @@ Rect2 Marker2D::_edit_get_rect() const { bool Marker2D::_edit_use_rect() const { return false; } -#endif +#endif // DEBUG_ENABLED void Marker2D::_notification(int p_what) { switch (p_what) { diff --git a/scene/2d/marker_2d.h b/scene/2d/marker_2d.h index e81454797b..6a1dfb1cb2 100644 --- a/scene/2d/marker_2d.h +++ b/scene/2d/marker_2d.h @@ -45,10 +45,10 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED void set_gizmo_extents(real_t p_extents); real_t get_gizmo_extents() const; diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp index 1031a67343..9b7a89fe3b 100644 --- a/scene/2d/mesh_instance_2d.cpp +++ b/scene/2d/mesh_instance_2d.cpp @@ -88,7 +88,7 @@ Ref<Texture2D> MeshInstance2D::get_texture() const { return texture; } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 MeshInstance2D::_edit_get_rect() const { if (mesh.is_valid()) { AABB aabb = mesh->get_aabb(); @@ -101,7 +101,7 @@ Rect2 MeshInstance2D::_edit_get_rect() const { bool MeshInstance2D::_edit_use_rect() const { return mesh.is_valid(); } -#endif +#endif // DEBUG_ENABLED MeshInstance2D::MeshInstance2D() { } diff --git a/scene/2d/mesh_instance_2d.h b/scene/2d/mesh_instance_2d.h index c914f13ade..b23b2ca907 100644 --- a/scene/2d/mesh_instance_2d.h +++ b/scene/2d/mesh_instance_2d.h @@ -45,10 +45,10 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED void set_mesh(const Ref<Mesh> &p_mesh); Ref<Mesh> get_mesh() const; diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp index 417e628517..811dccab4a 100644 --- a/scene/2d/multimesh_instance_2d.cpp +++ b/scene/2d/multimesh_instance_2d.cpp @@ -84,7 +84,7 @@ Ref<Texture2D> MultiMeshInstance2D::get_texture() const { return texture; } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 MultiMeshInstance2D::_edit_get_rect() const { if (multimesh.is_valid()) { AABB aabb = multimesh->get_aabb(); @@ -93,7 +93,7 @@ Rect2 MultiMeshInstance2D::_edit_get_rect() const { return Node2D::_edit_get_rect(); } -#endif +#endif // DEBUG_ENABLED MultiMeshInstance2D::MultiMeshInstance2D() { } diff --git a/scene/2d/multimesh_instance_2d.h b/scene/2d/multimesh_instance_2d.h index 0647412294..fec27a601a 100644 --- a/scene/2d/multimesh_instance_2d.h +++ b/scene/2d/multimesh_instance_2d.h @@ -46,9 +46,9 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; -#endif +#endif // DEBUG_ENABLED void set_multimesh(const Ref<MultiMesh> &p_multimesh); Ref<MultiMesh> get_multimesh() const; diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index d0fae611d8..f030473c4b 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -253,12 +253,20 @@ void NavigationAgent2D::_notification(int p_what) { #endif // DEBUG_ENABLED } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (agent_parent) { NavigationServer2D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process()); } } break; + case NOTIFICATION_UNSUSPENDED: { + if (get_tree()->is_paused()) { + break; + } + [[fallthrough]]; + } + case NOTIFICATION_UNPAUSED: { if (agent_parent) { NavigationServer2D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process()); diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp index 4961e18dc9..d90793a4c5 100644 --- a/scene/2d/navigation_link_2d.cpp +++ b/scene/2d/navigation_link_2d.cpp @@ -132,7 +132,7 @@ void NavigationLink2D::_notification(int p_what) { } } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 NavigationLink2D::_edit_get_rect() const { if (!is_inside_tree()) { return Rect2(); @@ -152,7 +152,7 @@ bool NavigationLink2D::_edit_is_selected_on_click(const Point2 &p_point, double Vector2 closest_point = Geometry2D::get_closest_point_to_segment(p_point, segment); return p_point.distance_to(closest_point) < p_tolerance; } -#endif // TOOLS_ENABLED +#endif // DEBUG_ENABLED RID NavigationLink2D::get_rid() const { return link; diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h index c724096607..232efdd0e5 100644 --- a/scene/2d/navigation_link_2d.h +++ b/scene/2d/navigation_link_2d.h @@ -62,10 +62,10 @@ protected: #endif // DISABLE_DEPRECATED public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; -#endif +#endif // DEBUG_ENABLED RID get_rid() const; void set_enabled(bool p_enabled); diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index 3bf90249f8..46bcda9c6d 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -89,7 +89,7 @@ void NavigationObstacle2D::_notification(int p_what) { previous_transform = get_global_transform(); // need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); - _update_position(get_global_position()); + _update_transform(); set_physics_process_internal(true); #ifdef DEBUG_ENABLED RS::get_singleton()->canvas_item_set_parent(debug_canvas_item, get_world_2d()->get_canvas()); @@ -104,6 +104,7 @@ void NavigationObstacle2D::_notification(int p_what) { #endif // DEBUG_ENABLED } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (!can_process()) { map_before_pause = map_current; @@ -115,6 +116,13 @@ void NavigationObstacle2D::_notification(int p_what) { NavigationServer2D::get_singleton()->obstacle_set_paused(obstacle, !can_process()); } break; + case NOTIFICATION_UNSUSPENDED: { + if (get_tree()->is_paused()) { + break; + } + [[fallthrough]]; + } + case NOTIFICATION_UNPAUSED: { if (!can_process()) { map_before_pause = map_current; @@ -134,7 +142,7 @@ void NavigationObstacle2D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (is_inside_tree()) { - _update_position(get_global_position()); + _update_transform(); if (velocity_submitted) { velocity_submitted = false; @@ -159,8 +167,7 @@ void NavigationObstacle2D::_notification(int p_what) { if (is_debug_enabled) { RS::get_singleton()->canvas_item_clear(debug_canvas_item); - Transform2D debug_transform = Transform2D(0.0, get_global_position()); - RS::get_singleton()->canvas_item_set_transform(debug_canvas_item, debug_transform); + RS::get_singleton()->canvas_item_set_transform(debug_canvas_item, Transform2D()); _update_fake_agent_radius_debug(); _update_static_obstacle_debug(); } @@ -199,7 +206,8 @@ NavigationObstacle2D::~NavigationObstacle2D() { void NavigationObstacle2D::set_vertices(const Vector<Vector2> &p_vertices) { vertices = p_vertices; - NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle, vertices); + const Transform2D node_transform = is_inside_tree() ? get_global_transform() : Transform2D(); + NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle, node_transform.xform(vertices)); #ifdef DEBUG_ENABLED queue_redraw(); #endif // DEBUG_ENABLED @@ -230,7 +238,8 @@ void NavigationObstacle2D::set_radius(real_t p_radius) { radius = p_radius; - NavigationServer2D::get_singleton()->obstacle_set_radius(obstacle, radius); + const Vector2 safe_scale = (is_inside_tree() ? get_global_scale() : get_scale()).abs().maxf(0.001); + NavigationServer2D::get_singleton()->obstacle_set_radius(obstacle, safe_scale[safe_scale.max_axis_index()] * radius); #ifdef DEBUG_ENABLED queue_redraw(); #endif // DEBUG_ENABLED @@ -303,6 +312,25 @@ bool NavigationObstacle2D::get_carve_navigation_mesh() const { return carve_navigation_mesh; } +PackedStringArray NavigationObstacle2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); + + const Vector2 global_scale = get_global_scale(); + if (global_scale.x < 0.001 || global_scale.y < 0.001) { + warnings.push_back(RTR("NavigationObstacle2D does not support negative or zero scaling.")); + } + + if (radius > 0.0 && !get_global_transform().is_conformal()) { + warnings.push_back(RTR("The agent radius can only be scaled uniformly. The largest value along the two axes of the global scale will be used to scale the radius. This value may change in unexpected ways when the node is rotated.")); + } + + if (radius > 0.0 && get_global_skew() != 0.0) { + warnings.push_back(RTR("Skew has no effect on the agent radius.")); + } + + return warnings; +} + void NavigationObstacle2D::_update_map(RID p_map) { map_current = p_map; NavigationServer2D::get_singleton()->obstacle_set_map(obstacle, p_map); @@ -315,12 +343,27 @@ void NavigationObstacle2D::_update_position(const Vector2 p_position) { #endif // DEBUG_ENABLED } +void NavigationObstacle2D::_update_transform() { + _update_position(get_global_position()); + // Prevent non-positive or non-uniform scaling of dynamic obstacle radius. + const Vector2 safe_scale = get_global_scale().abs().maxf(0.001); + const float scaling_max_value = safe_scale[safe_scale.max_axis_index()]; + NavigationServer2D::get_singleton()->obstacle_set_radius(obstacle, scaling_max_value * radius); + NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle, get_global_transform().translated(-get_global_position()).xform(vertices)); +#ifdef DEBUG_ENABLED + queue_redraw(); +#endif // DEBUG_ENABLED +} + #ifdef DEBUG_ENABLED void NavigationObstacle2D::_update_fake_agent_radius_debug() { if (radius > 0.0 && NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_radius()) { Color debug_radius_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_obstacles_radius_color(); - - RS::get_singleton()->canvas_item_add_circle(debug_canvas_item, Vector2(), radius, debug_radius_color); + // Prevent non-positive scaling. + const Vector2 safe_scale = get_global_scale().abs().maxf(0.001); + // Agent radius is a scalar value and does not support non-uniform scaling, choose the largest axis. + const float scaling_max_value = safe_scale[safe_scale.max_axis_index()]; + RS::get_singleton()->canvas_item_add_circle(debug_canvas_item, get_global_position(), scaling_max_value * radius, debug_radius_color); } } #endif // DEBUG_ENABLED @@ -344,7 +387,7 @@ void NavigationObstacle2D::_update_static_obstacle_debug() { debug_obstacle_polygon_colors.resize(debug_obstacle_polygon_vertices.size()); debug_obstacle_polygon_colors.fill(debug_static_obstacle_face_color); - RS::get_singleton()->canvas_item_add_polygon(debug_canvas_item, debug_obstacle_polygon_vertices, debug_obstacle_polygon_colors); + RS::get_singleton()->canvas_item_add_polygon(debug_canvas_item, get_global_transform().xform(debug_obstacle_polygon_vertices), debug_obstacle_polygon_colors); Color debug_static_obstacle_edge_color; @@ -362,7 +405,8 @@ void NavigationObstacle2D::_update_static_obstacle_debug() { debug_obstacle_line_colors.resize(debug_obstacle_line_vertices.size()); debug_obstacle_line_colors.fill(debug_static_obstacle_edge_color); - RS::get_singleton()->canvas_item_add_polyline(debug_canvas_item, debug_obstacle_line_vertices, debug_obstacle_line_colors, 4.0); + // Transforming the vertices directly instead of the canvas item in order to not affect the circle shape by non-uniform scales. + RS::get_singleton()->canvas_item_add_polyline(debug_canvas_item, get_global_transform().xform(debug_obstacle_line_vertices), debug_obstacle_line_colors, 4.0); } } #endif // DEBUG_ENABLED diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h index 30328f7086..6e3596acf4 100644 --- a/scene/2d/navigation_obstacle_2d.h +++ b/scene/2d/navigation_obstacle_2d.h @@ -84,7 +84,7 @@ public: real_t get_radius() const { return radius; } void set_vertices(const Vector<Vector2> &p_vertices); - const Vector<Vector2> &get_vertices() const { return vertices; }; + const Vector<Vector2> &get_vertices() const { return vertices; } void set_avoidance_layers(uint32_t p_layers); uint32_t get_avoidance_layers() const; @@ -96,7 +96,7 @@ public: bool get_avoidance_layer_value(int p_layer_number) const; void set_velocity(const Vector2 p_velocity); - Vector2 get_velocity() const { return velocity; }; + Vector2 get_velocity() const { return velocity; } void _avoidance_done(Vector3 p_new_velocity); // Dummy @@ -106,9 +106,12 @@ public: void set_carve_navigation_mesh(bool p_enabled); bool get_carve_navigation_mesh() const; + PackedStringArray get_configuration_warnings() const override; + private: void _update_map(RID p_map); void _update_position(const Vector2 p_position); + void _update_transform(); }; #endif // NAVIGATION_OBSTACLE_2D_H diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index f65a3c0ecc..08fbf78c33 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -142,7 +142,7 @@ RID NavigationRegion2D::get_region_rid() const { return get_rid(); } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 NavigationRegion2D::_edit_get_rect() const { return navigation_polygon.is_valid() ? navigation_polygon->_edit_get_rect() : Rect2(); } @@ -150,7 +150,7 @@ Rect2 NavigationRegion2D::_edit_get_rect() const { bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return navigation_polygon.is_valid() ? navigation_polygon->_edit_is_selected_on_click(p_point, p_tolerance) : false; } -#endif +#endif // DEBUG_ENABLED void NavigationRegion2D::_notification(int p_what) { switch (p_what) { diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 52101cb93e..f2bed0c44f 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -75,10 +75,10 @@ protected: #endif // DISABLE_DEPRECATED public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; -#endif +#endif // DEBUG_ENABLED RID get_rid() const; void set_enabled(bool p_enabled); diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 5813ab02e3..fe0cb770e0 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -37,7 +37,7 @@ #include "editor/themes/editor_scale.h" #endif -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 Path2D::_edit_get_rect() const { if (!curve.is_valid() || curve->get_point_count() == 0) { return Rect2(0, 0, 0, 0); @@ -167,17 +167,16 @@ void Path2D::_curve_changed() { return; } - if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_paths_hint()) { - return; - } - - queue_redraw(); for (int i = 0; i < get_child_count(); i++) { PathFollow2D *follow = Object::cast_to<PathFollow2D>(get_child(i)); if (follow) { follow->path_changed(); } } + + if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_paths_hint()) { + queue_redraw(); + } } void Path2D::set_curve(const Ref<Curve2D> &p_curve) { diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index bfd5cde5e9..5162f5144a 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -48,7 +48,7 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; diff --git a/scene/2d/physics/collision_polygon_2d.cpp b/scene/2d/physics/collision_polygon_2d.cpp index b49badac1f..a3e9fcce7e 100644 --- a/scene/2d/physics/collision_polygon_2d.cpp +++ b/scene/2d/physics/collision_polygon_2d.cpp @@ -217,7 +217,7 @@ CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const { return build_mode; } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 CollisionPolygon2D::_edit_get_rect() const { return aabb; } diff --git a/scene/2d/physics/collision_polygon_2d.h b/scene/2d/physics/collision_polygon_2d.h index f1ee30babe..93920124fe 100644 --- a/scene/2d/physics/collision_polygon_2d.h +++ b/scene/2d/physics/collision_polygon_2d.h @@ -65,7 +65,7 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; diff --git a/scene/2d/physics/collision_shape_2d.h b/scene/2d/physics/collision_shape_2d.h index 65436f1539..e4f04e77e4 100644 --- a/scene/2d/physics/collision_shape_2d.h +++ b/scene/2d/physics/collision_shape_2d.h @@ -59,11 +59,11 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; #else virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; -#endif // TOOLS_ENABLED +#endif // DEBUG_ENABLED void set_shape(const Ref<Shape2D> &p_shape); Ref<Shape2D> get_shape() const; diff --git a/scene/2d/physics/rigid_body_2d.cpp b/scene/2d/physics/rigid_body_2d.cpp index 402e5c8b95..4b1cde6b7a 100644 --- a/scene/2d/physics/rigid_body_2d.cpp +++ b/scene/2d/physics/rigid_body_2d.cpp @@ -641,7 +641,7 @@ void RigidBody2D::_notification(int p_what) { PackedStringArray RigidBody2D::get_configuration_warnings() const { Transform2D t = get_transform(); - PackedStringArray warnings = CollisionObject2D::get_configuration_warnings(); + PackedStringArray warnings = PhysicsBody2D::get_configuration_warnings(); if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) { warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 42f7a75c0a..dc5a08142d 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -57,7 +57,9 @@ Point2 Polygon2D::_edit_get_pivot() const { bool Polygon2D::_edit_use_pivot() const { return true; } +#endif // TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 Polygon2D::_edit_get_rect() const { if (rect_cache_dirty) { int l = polygon.size(); @@ -88,7 +90,7 @@ bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toler } return Geometry2D::is_point_in_polygon(p_point - get_offset(), polygon2d); } -#endif +#endif // DEBUG_ENABLED void Polygon2D::_validate_property(PropertyInfo &p_property) const { if (!invert && p_property.name == "invert_border") { diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index b2cd06de53..0928fa150c 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -87,11 +87,14 @@ public: virtual void _edit_set_pivot(const Point2 &p_pivot) override; virtual Point2 _edit_get_pivot() const override; virtual bool _edit_use_pivot() const override; +#endif // TOOLS_ENABLED + +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; -#endif +#endif // DEBUG_ENABLED void set_polygon(const Vector<Vector2> &p_polygon); Vector<Vector2> get_polygon() const; diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index 2b5c40f212..a182f63171 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -56,7 +56,9 @@ Point2 Sprite2D::_edit_get_pivot() const { bool Sprite2D::_edit_use_pivot() const { return true; } +#endif // TOOLS_ENABLED +#ifdef DEBUG_ENABLED bool Sprite2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return is_pixel_opaque(p_point); } @@ -68,7 +70,7 @@ Rect2 Sprite2D::_edit_get_rect() const { bool Sprite2D::_edit_use_rect() const { return texture.is_valid(); } -#endif +#endif // DEBUG_ENABLED Rect2 Sprite2D::get_anchorable_rect() const { return get_rect(); diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h index d084e9575d..5198e5efcf 100644 --- a/scene/2d/sprite_2d.h +++ b/scene/2d/sprite_2d.h @@ -74,11 +74,14 @@ public: virtual void _edit_set_pivot(const Point2 &p_pivot) override; virtual Point2 _edit_get_pivot() const override; virtual bool _edit_use_pivot() const override; +#endif // TOOLS_ENABLED + +#ifdef DEBUG_ENABLED virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED bool is_pixel_opaque(const Point2 &p_point) const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 45cfb8cf33..8e9500cdbe 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -75,7 +75,8 @@ void TileMap::_set_tile_map_data_using_compatibility_format(int p_layer, TileMap for (int i = 0; i < c; i += offset) { const uint8_t *ptr = (const uint8_t *)&r[i]; uint8_t local[12]; - for (int j = 0; j < ((p_format >= TileMapDataFormat::TILE_MAP_DATA_FORMAT_2) ? 12 : 8); j++) { + const int buffer_size = (p_format >= TILE_MAP_DATA_FORMAT_2) ? 12 : 8; + for (int j = 0; j < buffer_size; j++) { local[j] = ptr[j]; } @@ -89,8 +90,8 @@ void TileMap::_set_tile_map_data_using_compatibility_format(int p_layer, TileMap SWAP(local[8], local[11]); SWAP(local[9], local[10]); } -#endif - // Extracts position in TileMap. +#endif // BIG_ENDIAN_ENABLED + // Extracts position in TileMap. int16_t x = decode_uint16(&local[0]); int16_t y = decode_uint16(&local[2]); @@ -172,7 +173,7 @@ void TileMap::_notification(int p_what) { bool in_editor = false; #ifdef TOOLS_ENABLED in_editor = Engine::get_singleton()->is_editor_hint(); -#endif +#endif // TOOLS_ENABLED if (is_inside_tree() && collision_animatable && !in_editor) { // Update transform on the physics tick when in animatable mode. last_valid_transform = new_transform; @@ -188,7 +189,7 @@ void TileMap::_notification(int p_what) { bool in_editor = false; #ifdef TOOLS_ENABLED in_editor = Engine::get_singleton()->is_editor_hint(); -#endif +#endif // TOOLS_ENABLED if (is_inside_tree() && collision_animatable && !in_editor) { // Store last valid transform. @@ -209,7 +210,7 @@ void TileMap::force_update(int p_layer) { notify_runtime_tile_data_update(p_layer); update_internals(); } -#endif +#endif // DISABLE_DEPRECATED void TileMap::set_rendering_quadrant_size(int p_size) { ERR_FAIL_COND_MSG(p_size < 1, "TileMapQuadrant size cannot be smaller than 1."); @@ -649,7 +650,7 @@ void TileMap::notify_runtime_tile_data_update(int p_layer) { } } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 TileMap::_edit_get_rect() const { // Return the visible rect of the tilemap. if (layers.is_empty()) { @@ -667,7 +668,7 @@ Rect2 TileMap::_edit_get_rect() const { const_cast<TileMap *>(this)->item_rect_changed(any_changed); return rect; } -#endif +#endif // DEBUG_ENABLED bool TileMap::_set(const StringName &p_name, const Variant &p_value) { int index; @@ -726,7 +727,7 @@ bool TileMap::_get(const StringName &p_name, Variant &r_ret) const { r_ret = get_rendering_quadrant_size(); return true; } -#endif +#endif // DISABLE_DEPRECATED else { return property_helper.property_get_value(sname, r_ret); } diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 142dc1193f..47f5c8d996 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -107,16 +107,16 @@ protected: VisibilityMode _get_navigation_visibility_mode_bind_compat_87115(); static void _bind_compatibility_methods(); -#endif +#endif // DISABLE_DEPRECATED public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; -#endif +#endif // DEBUG_ENABLED #ifndef DISABLE_DEPRECATED void force_update(int p_layer); -#endif +#endif // DISABLE_DEPRECATED void set_rendering_quadrant_size(int p_size); int get_rendering_quadrant_size() const; diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp index ebb03e4e73..c4a2f35d31 100644 --- a/scene/2d/tile_map_layer.cpp +++ b/scene/2d/tile_map_layer.cpp @@ -823,6 +823,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) { Ref<PhysicsMaterial> physics_material = tile_set->get_physics_layer_physics_material(tile_set_physics_layer); uint32_t physics_layer = tile_set->get_physics_layer_collision_layer(tile_set_physics_layer); uint32_t physics_mask = tile_set->get_physics_layer_collision_mask(tile_set_physics_layer); + real_t physics_priority = tile_set->get_physics_layer_collision_priority(tile_set_physics_layer); RID body = r_cell_data.bodies[tile_set_physics_layer]; if (tile_data->get_collision_polygons_count(tile_set_physics_layer) == 0) { @@ -849,6 +850,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) { ps->body_attach_object_instance_id(body, tile_map_node ? tile_map_node->get_instance_id() : get_instance_id()); ps->body_set_collision_layer(body, physics_layer); ps->body_set_collision_mask(body, physics_mask); + ps->body_set_collision_priority(body, physics_priority); ps->body_set_pickable(body, false); ps->body_set_state(body, PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, tile_data->get_constant_linear_velocity(tile_set_physics_layer)); ps->body_set_state(body, PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, tile_data->get_constant_angular_velocity(tile_set_physics_layer)); @@ -946,7 +948,7 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect rs->canvas_item_add_set_transform(p_canvas_item, Transform2D()); } } -}; +} #endif // DEBUG_ENABLED /////////////////////////////// Navigation ////////////////////////////////////// @@ -1458,6 +1460,24 @@ void TileMapLayer::_clear_runtime_update_tile_data_for_cell(CellData &r_cell_dat } } +void TileMapLayer::_update_cells_callback(bool p_force_cleanup) { + if (!GDVIRTUAL_IS_OVERRIDDEN(_update_cells)) { + return; + } + + // Check if we should cleanup everything. + bool forced_cleanup = p_force_cleanup || !enabled || tile_set.is_null() || !is_visible_in_tree(); + + // List all the dirty cell's positions to notify script of cell updates. + TypedArray<Vector2i> dirty_cell_positions; + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + dirty_cell_positions.push_back(cell_data.coords); + } + + GDVIRTUAL_CALL(_update_cells, dirty_cell_positions, forced_cleanup); +} + TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) const { if (tile_set.is_null()) { return TileSet::TerrainsPattern(); @@ -1671,6 +1691,10 @@ void TileMapLayer::_internal_update(bool p_force_cleanup) { // This may add cells to the dirty list if a runtime modification has been notified. _build_runtime_update_tile_data(p_force_cleanup); + // Callback for implementing custom subsystems. + // This may add to the dirty list if some cells are changed inside _update_cells. + _update_cells_callback(p_force_cleanup); + // Update all subsystems. _rendering_update(p_force_cleanup); _physics_update(p_force_cleanup); @@ -1859,6 +1883,7 @@ void TileMapLayer::_bind_methods() { GDVIRTUAL_BIND(_use_tile_data_runtime_update, "coords"); GDVIRTUAL_BIND(_tile_data_runtime_update, "coords", "tile_data"); + GDVIRTUAL_BIND(_update_cells, "coords", "forced_cleanup"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "tile_map_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_tile_map_data_from_array", "get_tile_map_data_as_array"); diff --git a/scene/2d/tile_map_layer.h b/scene/2d/tile_map_layer.h index 6cb481849c..912fa2be15 100644 --- a/scene/2d/tile_map_layer.h +++ b/scene/2d/tile_map_layer.h @@ -321,6 +321,7 @@ private: bool _runtime_update_needs_all_cells_cleaned_up = false; void _clear_runtime_update_tile_data(); void _clear_runtime_update_tile_data_for_cell(CellData &r_cell_data); + void _update_cells_callback(bool p_force_cleanup); // Per-system methods. #ifdef DEBUG_ENABLED @@ -462,6 +463,7 @@ public: void notify_runtime_tile_data_update(); GDVIRTUAL1R(bool, _use_tile_data_runtime_update, Vector2i); GDVIRTUAL2(_tile_data_runtime_update, Vector2i, TileData *); + GDVIRTUAL2(_update_cells, TypedArray<Vector2i>, bool); // --- Shortcuts to methods defined in TileSet --- Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern); diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp index ff409272c5..220608a250 100644 --- a/scene/2d/touch_screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -185,6 +185,7 @@ void TouchScreenButton::_notification(int p_what) { } } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (is_pressed()) { _release(); @@ -329,7 +330,7 @@ void TouchScreenButton::_release(bool p_exiting_tree) { } } -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 TouchScreenButton::_edit_get_rect() const { if (texture_normal.is_null()) { return CanvasItem::_edit_get_rect(); @@ -341,7 +342,7 @@ Rect2 TouchScreenButton::_edit_get_rect() const { bool TouchScreenButton::_edit_use_rect() const { return !texture_normal.is_null(); } -#endif +#endif // DEBUG_ENABLED Rect2 TouchScreenButton::get_anchorable_rect() const { if (texture_normal.is_null()) { @@ -429,6 +430,6 @@ void TouchScreenButton::_bind_methods() { } TouchScreenButton::TouchScreenButton() { - unit_rect = Ref<RectangleShape2D>(memnew(RectangleShape2D)); + unit_rect.instantiate(); unit_rect->set_size(Vector2(1, 1)); } diff --git a/scene/2d/touch_screen_button.h b/scene/2d/touch_screen_button.h index 4467604e2b..da75fabfa0 100644 --- a/scene/2d/touch_screen_button.h +++ b/scene/2d/touch_screen_button.h @@ -76,10 +76,10 @@ protected: #endif // DISABLE_DEPRECATED public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED void set_texture_normal(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture_normal() const; diff --git a/scene/2d/visible_on_screen_notifier_2d.cpp b/scene/2d/visible_on_screen_notifier_2d.cpp index c64507fe32..7bf6371ee9 100644 --- a/scene/2d/visible_on_screen_notifier_2d.cpp +++ b/scene/2d/visible_on_screen_notifier_2d.cpp @@ -30,7 +30,7 @@ #include "visible_on_screen_notifier_2d.h" -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 VisibleOnScreenNotifier2D::_edit_get_rect() const { return rect; } @@ -38,7 +38,7 @@ Rect2 VisibleOnScreenNotifier2D::_edit_get_rect() const { bool VisibleOnScreenNotifier2D::_edit_use_rect() const { return true; } -#endif +#endif // DEBUG_ENABLED void VisibleOnScreenNotifier2D::_visibility_enter() { if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) { diff --git a/scene/2d/visible_on_screen_notifier_2d.h b/scene/2d/visible_on_screen_notifier_2d.h index df2832a976..84545a2d6a 100644 --- a/scene/2d/visible_on_screen_notifier_2d.h +++ b/scene/2d/visible_on_screen_notifier_2d.h @@ -54,10 +54,10 @@ protected: static void _bind_methods(); public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; -#endif +#endif // DEBUG_ENABLED void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 98bee2115c..eb75650399 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -834,7 +834,7 @@ void AudioStreamPlayer3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater"), "set_unit_size", "get_unit_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_db", PROPERTY_HINT_RANGE, "-24,6,suffix:dB"), "set_max_db", "get_max_db"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_ONESHOT, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,or_greater,suffix:m"), "set_max_distance", "get_max_distance"); diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index c70fa3ca2e..2b841c4e0d 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -234,6 +234,7 @@ void Camera3D::_notification(int p_what) { } } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (is_physics_interpolated_and_enabled() && is_inside_tree() && is_visible_in_tree()) { _physics_interpolation_ensure_transform_calculated(true); @@ -377,7 +378,7 @@ void Camera3D::set_projection(ProjectionType p_mode) { RID Camera3D::get_camera() const { return camera; -}; +} void Camera3D::make_current() { current = true; @@ -423,7 +424,7 @@ bool Camera3D::is_current() const { Vector3 Camera3D::project_ray_normal(const Point2 &p_pos) const { Vector3 ray = project_local_ray_normal(p_pos); return get_camera_transform().basis.xform(ray).normalized(); -}; +} Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const { ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); @@ -441,7 +442,7 @@ Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const { } return ray; -}; +} Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const { ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); @@ -470,7 +471,7 @@ Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const { } else { return get_camera_transform().origin; }; -}; +} bool Camera3D::is_position_behind(const Vector3 &p_pos) const { Transform3D t = get_global_transform(); diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 5b84bf903f..4424032653 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -543,6 +543,10 @@ AABB CPUParticles3D::capture_aabb() const { } void CPUParticles3D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "emitting") { + p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE; + } + if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { p_property.usage = PROPERTY_USAGE_NONE; } @@ -1481,7 +1485,7 @@ void CPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &CPUParticles3D::restart); ClassDB::bind_method(D_METHOD("capture_aabb"), &CPUParticles3D::capture_aabb); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime"); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index 2cef607d29..760409d9a0 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -414,6 +414,10 @@ AABB GPUParticles3D::capture_aabb() const { } void GPUParticles3D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "emitting") { + p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE; + } + if (p_property.name.begins_with("draw_pass_")) { int index = p_property.name.get_slicec('_', 2).to_int() - 1; if (index >= draw_passes.size()) { @@ -511,6 +515,8 @@ void GPUParticles3D::_notification(int p_what) { RS::get_singleton()->particles_set_subemitter(particles, RID()); } break; + case NOTIFICATION_SUSPENDED: + case NOTIFICATION_UNSUSPENDED: case NOTIFICATION_PAUSED: case NOTIFICATION_UNPAUSED: { if (is_inside_tree()) { @@ -742,7 +748,7 @@ void GPUParticles3D::_bind_methods() { ADD_SIGNAL(MethodInfo("finished")); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting"); ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001"), "set_amount_ratio", "get_amount_ratio"); diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 6b3510a72a..01f15137be 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -318,7 +318,7 @@ Ref<TriangleMesh> Label3D::generate_triangle_mesh() const { facesw[j] = vtx; } - triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh.instantiate(); triangle_mesh->create(faces); return triangle_mesh; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 7b70986adc..2d18e62b10 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -146,6 +146,15 @@ bool Light3D::get_shadow_reverse_cull_face() const { return reverse_cull; } +void Light3D::set_shadow_caster_mask(uint32_t p_caster_mask) { + shadow_caster_mask = p_caster_mask; + RS::get_singleton()->light_set_shadow_caster_mask(light, shadow_caster_mask); +} + +uint32_t Light3D::get_shadow_caster_mask() const { + return shadow_caster_mask; +} + AABB Light3D::get_aabb() const { if (type == RenderingServer::LIGHT_DIRECTIONAL) { return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); @@ -300,7 +309,7 @@ bool Light3D::is_editor_only() const { } void Light3D::_validate_property(PropertyInfo &p_property) const { - if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow")) { + if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow" || p_property.name == "shadow_caster_mask")) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } @@ -354,6 +363,9 @@ void Light3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_reverse_cull_face", "enable"), &Light3D::set_shadow_reverse_cull_face); ClassDB::bind_method(D_METHOD("get_shadow_reverse_cull_face"), &Light3D::get_shadow_reverse_cull_face); + ClassDB::bind_method(D_METHOD("set_shadow_caster_mask", "caster_mask"), &Light3D::set_shadow_caster_mask); + ClassDB::bind_method(D_METHOD("get_shadow_caster_mask"), &Light3D::get_shadow_caster_mask); + ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &Light3D::set_bake_mode); ClassDB::bind_method(D_METHOD("get_bake_mode"), &Light3D::get_bake_mode); @@ -388,6 +400,7 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_OPACITY); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR); + ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_caster_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_shadow_caster_mask", "get_shadow_caster_mask"); ADD_GROUP("Distance Fade", "distance_fade_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled"); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index d6eca8d8b6..5f549469c6 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -75,6 +75,7 @@ private: bool negative = false; bool reverse_cull = false; uint32_t cull_mask = 0; + uint32_t shadow_caster_mask = 0xFFFFFFFF; bool distance_fade_enabled = false; real_t distance_fade_begin = 40.0; real_t distance_fade_shadow = 50.0; @@ -136,6 +137,9 @@ public: void set_shadow_reverse_cull_face(bool p_enable); bool get_shadow_reverse_cull_face() const; + void set_shadow_caster_mask(uint32_t p_caster_mask); + uint32_t get_shadow_caster_mask() const; + void set_bake_mode(BakeMode p_mode); BakeMode get_bake_mode() const; diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index a1f32fccbe..aa4445a7ba 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -98,15 +98,15 @@ Array LightmapGIData::_get_user_data() const { } void LightmapGIData::set_lightmap_textures(const TypedArray<TextureLayered> &p_data) { - light_textures = p_data; + storage_light_textures = p_data; if (p_data.is_empty()) { - light_texture = Ref<TextureLayered>(); + combined_light_texture = Ref<TextureLayered>(); _reset_lightmap_textures(); return; } if (p_data.size() == 1) { - light_texture = p_data[0]; + combined_light_texture = p_data[0]; } else { Vector<Ref<Image>> images; for (int i = 0; i < p_data.size(); i++) { @@ -121,13 +121,13 @@ void LightmapGIData::set_lightmap_textures(const TypedArray<TextureLayered> &p_d combined_texture.instantiate(); combined_texture->create_from_images(images); - light_texture = combined_texture; + combined_light_texture = combined_texture; } _reset_lightmap_textures(); } TypedArray<TextureLayered> LightmapGIData::get_lightmap_textures() const { - return light_textures; + return storage_light_textures; } RID LightmapGIData::get_rid() const { @@ -139,7 +139,7 @@ void LightmapGIData::clear() { } void LightmapGIData::_reset_lightmap_textures() { - RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); + RS::get_singleton()->lightmap_set_textures(lightmap, combined_light_texture.is_valid() ? combined_light_texture->get_rid() : RID(), uses_spherical_harmonics); } void LightmapGIData::set_uses_spherical_harmonics(bool p_enable) { @@ -238,10 +238,10 @@ void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_textur } Ref<TextureLayered> LightmapGIData::get_light_texture() const { - if (light_textures.is_empty()) { + if (storage_light_textures.is_empty()) { return Ref<TextureLayered>(); } - return light_textures.get(0); + return storage_light_textures.get(0); } void LightmapGIData::_set_light_textures_data(const Array &p_data) { @@ -249,7 +249,7 @@ void LightmapGIData::_set_light_textures_data(const Array &p_data) { } Array LightmapGIData::_get_light_textures_data() const { - return Array(light_textures); + return Array(storage_light_textures); } #endif @@ -274,7 +274,7 @@ void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data); ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lightmap_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_NO_EDITOR), "set_lightmap_textures", "get_lightmap_textures"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lightmap_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY), "set_lightmap_textures", "get_lightmap_textures"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); @@ -287,8 +287,8 @@ void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_light_textures_data", "data"), &LightmapGIData::_set_light_textures_data); ClassDB::bind_method(D_METHOD("_get_light_textures_data"), &LightmapGIData::_get_light_textures_data); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR), "set_light_texture", "get_light_texture"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_NONE), "set_light_texture", "get_light_texture"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data"); #endif } @@ -333,9 +333,7 @@ void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &m mf.node_path = get_path_to(mi); mf.subindex = -1; mf.mesh = mesh; - - static const int lightmap_scale[GeometryInstance3D::LIGHTMAP_SCALE_MAX] = { 1, 2, 4, 8 }; - mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()]; + mf.lightmap_scale = mi->get_lightmap_texel_scale(); Ref<Material> all_override = mi->get_material_override(); for (int i = 0; i < mesh->get_surface_count(); i++) { @@ -369,7 +367,7 @@ void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &m mf.xform = xf * mesh_xf; mf.node_path = get_path_to(s); mf.subindex = i / 2; - mf.lightmap_scale = 1; + mf.lightmap_scale = 1.0; mf.mesh = mesh; meshes.push_back(mf); @@ -740,6 +738,74 @@ void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, f } } +LightmapGI::BakeError LightmapGI::_save_and_reimport_atlas_textures(const Ref<Lightmapper> p_lightmapper, const String &p_base_name, TypedArray<TextureLayered> &r_textures, bool p_compress) const { + Vector<Ref<Image>> images; + images.resize(p_lightmapper->get_bake_texture_count()); + + for (int i = 0; i < images.size(); i++) { + images.set(i, p_lightmapper->get_bake_texture(i)); + } + + const int slice_count = images.size(); + const int slice_width = images[0]->get_width(); + const int slice_height = images[0]->get_height(); + + const int slices_per_texture = Image::MAX_HEIGHT / slice_height; + const int texture_count = Math::ceil(slice_count / (float)slices_per_texture); + const int last_count = slice_count % slices_per_texture; + + r_textures.resize(texture_count); + + for (int i = 0; i < texture_count; i++) { + const int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture; + + Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); + + for (int j = 0; j < texture_slice_count; j++) { + texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j)); + } + + const String atlas_path = (texture_count > 1 ? p_base_name + "_" + itos(i) : p_base_name) + ".exr"; + const String config_path = atlas_path + ".import"; + + Ref<ConfigFile> config; + config.instantiate(); + + // Load an import configuration if present. + if (FileAccess::exists(config_path)) { + config->load(config_path); + } + + config->set_value("remap", "importer", "2d_array_texture"); + config->set_value("remap", "type", "CompressedTexture2DArray"); + if (!config->has_section_key("params", "compress/mode")) { + // Do not override an existing compression mode. + config->set_value("params", "compress/mode", p_compress ? 2 : 3); + } + config->set_value("params", "compress/channel_pack", 1); + config->set_value("params", "mipmaps/generate", false); + config->set_value("params", "slices/horizontal", 1); + config->set_value("params", "slices/vertical", texture_slice_count); + + config->save(config_path); + + // Save the file. + Error save_err = texture_image->save_exr(atlas_path, false); + + ERR_FAIL_COND_V(save_err, LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE); + + // Reimport the file. + ResourceLoader::import(atlas_path); + Ref<TextureLayered> t = ResourceLoader::load(atlas_path); // If already loaded, it will be updated on refocus? + ERR_FAIL_COND_V(t.is_null(), LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE); + + // Store the atlas in the array. + r_textures[i] = t; + } + + return LightmapGI::BAKE_ERROR_OK; +} + LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) { if (p_image_data_path.is_empty()) { if (get_light_data().is_null()) { @@ -1123,84 +1189,36 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa return BAKE_ERROR_MESHES_INVALID; } else if (bake_err == Lightmapper::BAKE_ERROR_ATLAS_TOO_SMALL) { return BAKE_ERROR_ATLAS_TOO_SMALL; + } else if (bake_err == Lightmapper::BAKE_ERROR_USER_ABORTED) { + return BAKE_ERROR_USER_ABORTED; } // POSTBAKE: Save Textures. - TypedArray<TextureLayered> textures; - { - Vector<Ref<Image>> images; - images.resize(lightmapper->get_bake_texture_count()); - for (int i = 0; i < images.size(); i++) { - images.set(i, lightmapper->get_bake_texture(i)); - } - - int slice_count = images.size(); - int slice_width = images[0]->get_width(); - int slice_height = images[0]->get_height(); + TypedArray<TextureLayered> lightmap_textures; - int slices_per_texture = Image::MAX_HEIGHT / slice_height; - int texture_count = Math::ceil(slice_count / (float)slices_per_texture); + const String texture_filename = p_image_data_path.get_basename(); - textures.resize(texture_count); + // Save the lightmap atlases. + BakeError save_err = _save_and_reimport_atlas_textures(lightmapper, texture_filename, lightmap_textures, false); + ERR_FAIL_COND_V(save_err != BAKE_ERROR_OK, save_err); - String base_path = p_image_data_path.get_basename(); - - int last_count = slice_count % slices_per_texture; - for (int i = 0; i < texture_count; i++) { - int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture; - - Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); - - for (int j = 0; j < texture_slice_count; j++) { - texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j)); - } - - String texture_path = texture_count > 1 ? base_path + "_" + itos(i) + ".exr" : base_path + ".exr"; - - Ref<ConfigFile> config; - config.instantiate(); - - if (FileAccess::exists(texture_path + ".import")) { - config->load(texture_path + ".import"); - } - - config->set_value("remap", "importer", "2d_array_texture"); - config->set_value("remap", "type", "CompressedTexture2DArray"); - if (!config->has_section_key("params", "compress/mode")) { - // User may want another compression, so leave it be, but default to VRAM uncompressed. - config->set_value("params", "compress/mode", 3); - } - config->set_value("params", "compress/channel_pack", 1); - config->set_value("params", "mipmaps/generate", false); - config->set_value("params", "slices/horizontal", 1); - config->set_value("params", "slices/vertical", texture_slice_count); - - config->save(texture_path + ".import"); - - Error err = texture_image->save_exr(texture_path, false); - ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE); - ResourceLoader::import(texture_path); - Ref<TextureLayered> t = ResourceLoader::load(texture_path); // If already loaded, it will be updated on refocus? - ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE); - textures[i] = t; - } - } - - /* POSTBAKE: Save Light Data */ + // POSTBAKE: Save Light Data. Ref<LightmapGIData> gi_data; + if (get_light_data().is_valid()) { gi_data = get_light_data(); - set_light_data(Ref<LightmapGIData>()); //clear + set_light_data(Ref<LightmapGIData>()); // Clear. gi_data->clear(); + } else { gi_data.instantiate(); } - gi_data->set_lightmap_textures(textures); - gi_data->_set_uses_packed_directional(directional); // New SH lightmaps are packed automatically. + gi_data->set_lightmap_textures(lightmap_textures); gi_data->set_uses_spherical_harmonics(directional); + gi_data->_set_uses_packed_directional(directional); // New SH lightmaps are packed automatically. for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) { Dictionary d = lightmapper->get_bake_mesh_userdata(i); @@ -1602,19 +1620,16 @@ Ref<CameraAttributes> LightmapGI::get_camera_attributes() const { PackedStringArray LightmapGI::get_configuration_warnings() const { PackedStringArray warnings = VisualInstance3D::get_configuration_warnings(); -#ifndef MODULE_LIGHTMAPPER_RD_ENABLED -#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED) - warnings.push_back(vformat(RTR("Lightmaps cannot be baked on %s. Rendering existing baked lightmaps will still work."), OS::get_singleton()->get_name())); -#else - warnings.push_back(RTR("Lightmaps cannot be baked, as the `lightmapper_rd` module was disabled at compile-time. Rendering existing baked lightmaps will still work.")); -#endif - return warnings; -#endif - +#ifdef MODULE_LIGHTMAPPER_RD_ENABLED if (!DisplayServer::get_singleton()->can_create_rendering_device()) { warnings.push_back(vformat(RTR("Lightmaps can only be baked from a GPU that supports the RenderingDevice backends.\nYour GPU (%s) does not support RenderingDevice, as it does not support Vulkan, Direct3D 12, or Metal.\nLightmap baking will not be available on this device, although rendering existing baked lightmaps will work."), RenderingServer::get_singleton()->get_video_adapter_name())); return warnings; } +#elif defined(ANDROID_ENABLED) || defined(IOS_ENABLED) + warnings.push_back(vformat(RTR("Lightmaps cannot be baked on %s. Rendering existing baked lightmaps will still work."), OS::get_singleton()->get_name())); +#else + warnings.push_back(RTR("Lightmaps cannot be baked, as the `lightmapper_rd` module was disabled at compile-time. Rendering existing baked lightmaps will still work.")); +#endif return warnings; } diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index 6377c420d1..faa8b84fa1 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -43,8 +43,12 @@ class LightmapGIData : public Resource { GDCLASS(LightmapGIData, Resource); RES_BASE_EXTENSION("lmbake") - Ref<TextureLayered> light_texture; - TypedArray<TextureLayered> light_textures; + // The 'merged' texture atlases actually used by the renderer. + Ref<TextureLayered> combined_light_texture; + + // The temporary texture atlas arrays which are used for storage. + // If a single atlas is too large, it's split and recombined during loading. + TypedArray<TextureLayered> storage_light_textures; bool uses_spherical_harmonics = false; bool interior = false; @@ -190,7 +194,7 @@ private: NodePath node_path; int32_t subindex = 0; Ref<Mesh> mesh; - int32_t lightmap_scale = 0; + float lightmap_scale = 0.0; Vector<Ref<Material>> overrides; }; @@ -245,6 +249,8 @@ private: void _plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle); void _gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool> &positions_used, const AABB &p_bounds); + BakeError _save_and_reimport_atlas_textures(const Ref<Lightmapper> p_lightmapper, const String &p_base_name, TypedArray<TextureLayered> &r_textures, bool p_compress = false) const; + protected: void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h index 9aa8ef8ccb..1228c63edc 100644 --- a/scene/3d/lightmapper.h +++ b/scene/3d/lightmapper.h @@ -147,6 +147,7 @@ public: BAKE_ERROR_TEXTURE_EXCEEDS_MAX_SIZE, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES, BAKE_ERROR_ATLAS_TOO_SMALL, + BAKE_ERROR_USER_ABORTED, }; enum BakeQuality { diff --git a/scene/3d/look_at_modifier_3d.cpp b/scene/3d/look_at_modifier_3d.cpp new file mode 100644 index 0000000000..ad33cd420a --- /dev/null +++ b/scene/3d/look_at_modifier_3d.cpp @@ -0,0 +1,781 @@ +/**************************************************************************/ +/* look_at_modifier_3d.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "look_at_modifier_3d.h" + +void LookAtModifier3D::_validate_property(PropertyInfo &p_property) const { + SkeletonModifier3D::_validate_property(p_property); + + if (p_property.name == "bone" || p_property.name == "origin_bone") { + Skeleton3D *skeleton = get_skeleton(); + if (skeleton) { + p_property.hint = PROPERTY_HINT_ENUM; + p_property.hint_string = skeleton->get_concatenated_bone_names(); + } else { + p_property.hint = PROPERTY_HINT_NONE; + p_property.hint_string = ""; + } + } + + if (origin_from == ORIGIN_FROM_SPECIFIC_BONE) { + if (p_property.name == "origin_external_node") { + p_property.usage = PROPERTY_USAGE_NONE; + } + } else if (origin_from == ORIGIN_FROM_EXTERNAL_NODE) { + if (p_property.name == "origin_bone") { + p_property.usage = PROPERTY_USAGE_NONE; + } + } else { + if (p_property.name == "origin_external_node" || p_property.name == "origin_bone") { + p_property.usage = PROPERTY_USAGE_NONE; + } + } + + if ((!use_angle_limitation && + (p_property.name == "symmetry_limitation" || p_property.name.ends_with("limit_angle") || p_property.name.ends_with("damp_threshold"))) || + (!use_secondary_rotation && p_property.name.begins_with("secondary_")) || + (!symmetry_limitation && (p_property.name == "primary_limit_angle" || p_property.name == "primary_damp_threshold" || p_property.name == "secondary_limit_angle" || p_property.name == "secondary_damp_threshold")) || + (symmetry_limitation && (p_property.name.begins_with("primary_positive") || p_property.name.begins_with("primary_negative") || p_property.name.begins_with("secondary_positive") || (p_property.name.begins_with("secondary_negative"))))) { + p_property.usage = PROPERTY_USAGE_NONE; + } +} + +PackedStringArray LookAtModifier3D::get_configuration_warnings() const { + PackedStringArray warnings = SkeletonModifier3D::get_configuration_warnings(); + if (get_axis_from_bone_axis(forward_axis) == primary_rotation_axis) { + warnings.push_back(RTR("Forward axis and primary rotation axis must not be parallel.")); + } + return warnings; +} + +void LookAtModifier3D::set_bone(int p_bone) { + bone = p_bone; +} + +int LookAtModifier3D::get_bone() const { + return bone; +} + +void LookAtModifier3D::set_forward_axis(BoneAxis p_axis) { + forward_axis = p_axis; + update_configuration_warnings(); +} + +LookAtModifier3D::BoneAxis LookAtModifier3D::get_forward_axis() const { + return forward_axis; +} + +void LookAtModifier3D::set_primary_rotation_axis(Vector3::Axis p_axis) { + primary_rotation_axis = p_axis; + update_configuration_warnings(); +} + +Vector3::Axis LookAtModifier3D::get_primary_rotation_axis() const { + return primary_rotation_axis; +} + +void LookAtModifier3D::set_use_secondary_rotation(bool p_enabled) { + use_secondary_rotation = p_enabled; + notify_property_list_changed(); +} + +bool LookAtModifier3D::is_using_secondary_rotation() const { + return use_secondary_rotation; +} + +void LookAtModifier3D::set_target_node(const NodePath &p_target_node) { + if (target_node != p_target_node) { + init_transition(); + } + target_node = p_target_node; +} + +NodePath LookAtModifier3D::get_target_node() const { + return target_node; +} + +// For origin settings. + +void LookAtModifier3D::set_origin_from(OriginFrom p_origin_from) { + origin_from = p_origin_from; + notify_property_list_changed(); +} + +LookAtModifier3D::OriginFrom LookAtModifier3D::get_origin_from() const { + return origin_from; +} + +void LookAtModifier3D::set_origin_bone(int p_bone) { + origin_bone = p_bone; +} + +int LookAtModifier3D::get_origin_bone() const { + return origin_bone; +} + +void LookAtModifier3D::set_origin_external_node(const NodePath &p_external_node) { + origin_external_node = p_external_node; +} + +NodePath LookAtModifier3D::get_origin_external_node() const { + return origin_external_node; +} + +void LookAtModifier3D::set_origin_offset(const Vector3 &p_offset) { + origin_offset = p_offset; +} + +Vector3 LookAtModifier3D::get_origin_offset() const { + return origin_offset; +} + +void LookAtModifier3D::set_origin_safe_margin(float p_margin) { + origin_safe_margin = p_margin; +} + +float LookAtModifier3D::get_origin_safe_margin() const { + return origin_safe_margin; +} + +// For time-based interpolation. + +void LookAtModifier3D::set_duration(float p_duration) { + duration = p_duration; + if (Math::is_zero_approx(p_duration)) { + time_step = 0; + remaining = 0; + } else { + time_step = 1.0 / p_duration; // Cache to avoid division. + } +} + +float LookAtModifier3D::get_duration() const { + return duration; +} + +void LookAtModifier3D::set_transition_type(Tween::TransitionType p_transition_type) { + transition_type = p_transition_type; +} + +Tween::TransitionType LookAtModifier3D::get_transition_type() const { + return transition_type; +} + +void LookAtModifier3D::set_ease_type(Tween::EaseType p_ease_type) { + ease_type = p_ease_type; +} + +Tween::EaseType LookAtModifier3D::get_ease_type() const { + return ease_type; +} + +// For angle limitation. + +void LookAtModifier3D::set_use_angle_limitation(bool p_enabled) { + use_angle_limitation = p_enabled; + notify_property_list_changed(); +} + +bool LookAtModifier3D::is_using_angle_limitation() const { + return use_angle_limitation; +} + +void LookAtModifier3D::set_symmetry_limitation(bool p_enabled) { + symmetry_limitation = p_enabled; + notify_property_list_changed(); +} + +bool LookAtModifier3D::is_limitation_symmetry() const { + return symmetry_limitation; +} + +void LookAtModifier3D::set_primary_limit_angle(float p_angle) { + primary_limit_angle = p_angle; +} + +float LookAtModifier3D::get_primary_limit_angle() const { + return primary_limit_angle; +} + +void LookAtModifier3D::set_primary_damp_threshold(float p_power) { + primary_damp_threshold = p_power; +} + +float LookAtModifier3D::get_primary_damp_threshold() const { + return primary_damp_threshold; +} + +void LookAtModifier3D::set_primary_positive_limit_angle(float p_angle) { + primary_positive_limit_angle = p_angle; +} + +float LookAtModifier3D::get_primary_positive_limit_angle() const { + return primary_positive_limit_angle; +} + +void LookAtModifier3D::set_primary_positive_damp_threshold(float p_power) { + primary_positive_damp_threshold = p_power; +} + +float LookAtModifier3D::get_primary_positive_damp_threshold() const { + return primary_positive_damp_threshold; +} + +void LookAtModifier3D::set_primary_negative_limit_angle(float p_angle) { + primary_negative_limit_angle = p_angle; +} + +float LookAtModifier3D::get_primary_negative_limit_angle() const { + return primary_negative_limit_angle; +} + +void LookAtModifier3D::set_primary_negative_damp_threshold(float p_power) { + primary_negative_damp_threshold = p_power; +} + +float LookAtModifier3D::get_primary_negative_damp_threshold() const { + return primary_negative_damp_threshold; +} + +void LookAtModifier3D::set_secondary_limit_angle(float p_angle) { + secondary_limit_angle = p_angle; +} + +float LookAtModifier3D::get_secondary_limit_angle() const { + return secondary_limit_angle; +} + +void LookAtModifier3D::set_secondary_damp_threshold(float p_power) { + secondary_damp_threshold = p_power; +} + +float LookAtModifier3D::get_secondary_damp_threshold() const { + return secondary_damp_threshold; +} + +void LookAtModifier3D::set_secondary_positive_limit_angle(float p_angle) { + secondary_positive_limit_angle = p_angle; +} + +float LookAtModifier3D::get_secondary_positive_limit_angle() const { + return secondary_positive_limit_angle; +} + +void LookAtModifier3D::set_secondary_positive_damp_threshold(float p_power) { + secondary_positive_damp_threshold = p_power; +} + +float LookAtModifier3D::get_secondary_positive_damp_threshold() const { + return secondary_positive_damp_threshold; +} + +void LookAtModifier3D::set_secondary_negative_limit_angle(float p_angle) { + secondary_negative_limit_angle = p_angle; +} + +float LookAtModifier3D::get_secondary_negative_limit_angle() const { + return secondary_negative_limit_angle; +} + +void LookAtModifier3D::set_secondary_negative_damp_threshold(float p_power) { + secondary_negative_damp_threshold = p_power; +} + +float LookAtModifier3D::get_secondary_negative_damp_threshold() const { + return secondary_negative_damp_threshold; +} + +bool LookAtModifier3D::is_target_within_limitation() const { + return is_within_limitations; +} + +float LookAtModifier3D::get_interpolation_remaining() const { + return remaining * duration; +} + +bool LookAtModifier3D::is_interpolating() const { + return Math::is_zero_approx(remaining); +} + +// General API. + +void LookAtModifier3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_target_node", "target_node"), &LookAtModifier3D::set_target_node); + ClassDB::bind_method(D_METHOD("get_target_node"), &LookAtModifier3D::get_target_node); + + ClassDB::bind_method(D_METHOD("set_bone", "bone"), &LookAtModifier3D::set_bone); + ClassDB::bind_method(D_METHOD("get_bone"), &LookAtModifier3D::get_bone); + ClassDB::bind_method(D_METHOD("set_forward_axis", "forward_axis"), &LookAtModifier3D::set_forward_axis); + ClassDB::bind_method(D_METHOD("get_forward_axis"), &LookAtModifier3D::get_forward_axis); + ClassDB::bind_method(D_METHOD("set_primary_rotation_axis", "axis"), &LookAtModifier3D::set_primary_rotation_axis); + ClassDB::bind_method(D_METHOD("get_primary_rotation_axis"), &LookAtModifier3D::get_primary_rotation_axis); + ClassDB::bind_method(D_METHOD("set_use_secondary_rotation", "enabled"), &LookAtModifier3D::set_use_secondary_rotation); + ClassDB::bind_method(D_METHOD("is_using_secondary_rotation"), &LookAtModifier3D::is_using_secondary_rotation); + ClassDB::bind_method(D_METHOD("set_origin_safe_margin", "margin"), &LookAtModifier3D::set_origin_safe_margin); + ClassDB::bind_method(D_METHOD("get_origin_safe_margin"), &LookAtModifier3D::get_origin_safe_margin); + + ClassDB::bind_method(D_METHOD("set_origin_from", "origin_from"), &LookAtModifier3D::set_origin_from); + ClassDB::bind_method(D_METHOD("get_origin_from"), &LookAtModifier3D::get_origin_from); + ClassDB::bind_method(D_METHOD("set_origin_bone", "bone"), &LookAtModifier3D::set_origin_bone); + ClassDB::bind_method(D_METHOD("get_origin_bone"), &LookAtModifier3D::get_origin_bone); + ClassDB::bind_method(D_METHOD("set_origin_external_node", "external_node"), &LookAtModifier3D::set_origin_external_node); + ClassDB::bind_method(D_METHOD("get_origin_external_node"), &LookAtModifier3D::get_origin_external_node); + + ClassDB::bind_method(D_METHOD("set_origin_offset", "offset"), &LookAtModifier3D::set_origin_offset); + ClassDB::bind_method(D_METHOD("get_origin_offset"), &LookAtModifier3D::get_origin_offset); + + ClassDB::bind_method(D_METHOD("set_duration", "duration"), &LookAtModifier3D::set_duration); + ClassDB::bind_method(D_METHOD("get_duration"), &LookAtModifier3D::get_duration); + ClassDB::bind_method(D_METHOD("set_transition_type", "transition_type"), &LookAtModifier3D::set_transition_type); + ClassDB::bind_method(D_METHOD("get_transition_type"), &LookAtModifier3D::get_transition_type); + ClassDB::bind_method(D_METHOD("set_ease_type", "ease_type"), &LookAtModifier3D::set_ease_type); + ClassDB::bind_method(D_METHOD("get_ease_type"), &LookAtModifier3D::get_ease_type); + + ClassDB::bind_method(D_METHOD("set_use_angle_limitation", "enabled"), &LookAtModifier3D::set_use_angle_limitation); + ClassDB::bind_method(D_METHOD("is_using_angle_limitation"), &LookAtModifier3D::is_using_angle_limitation); + ClassDB::bind_method(D_METHOD("set_symmetry_limitation", "enabled"), &LookAtModifier3D::set_symmetry_limitation); + ClassDB::bind_method(D_METHOD("is_limitation_symmetry"), &LookAtModifier3D::is_limitation_symmetry); + + ClassDB::bind_method(D_METHOD("set_primary_limit_angle", "angle"), &LookAtModifier3D::set_primary_limit_angle); + ClassDB::bind_method(D_METHOD("get_primary_limit_angle"), &LookAtModifier3D::get_primary_limit_angle); + ClassDB::bind_method(D_METHOD("set_primary_damp_threshold", "power"), &LookAtModifier3D::set_primary_damp_threshold); + ClassDB::bind_method(D_METHOD("get_primary_damp_threshold"), &LookAtModifier3D::get_primary_damp_threshold); + + ClassDB::bind_method(D_METHOD("set_primary_positive_limit_angle", "angle"), &LookAtModifier3D::set_primary_positive_limit_angle); + ClassDB::bind_method(D_METHOD("get_primary_positive_limit_angle"), &LookAtModifier3D::get_primary_positive_limit_angle); + ClassDB::bind_method(D_METHOD("set_primary_positive_damp_threshold", "power"), &LookAtModifier3D::set_primary_positive_damp_threshold); + ClassDB::bind_method(D_METHOD("get_primary_positive_damp_threshold"), &LookAtModifier3D::get_primary_positive_damp_threshold); + ClassDB::bind_method(D_METHOD("set_primary_negative_limit_angle", "angle"), &LookAtModifier3D::set_primary_negative_limit_angle); + ClassDB::bind_method(D_METHOD("get_primary_negative_limit_angle"), &LookAtModifier3D::get_primary_negative_limit_angle); + ClassDB::bind_method(D_METHOD("set_primary_negative_damp_threshold", "power"), &LookAtModifier3D::set_primary_negative_damp_threshold); + ClassDB::bind_method(D_METHOD("get_primary_negative_damp_threshold"), &LookAtModifier3D::get_primary_negative_damp_threshold); + + ClassDB::bind_method(D_METHOD("set_secondary_limit_angle", "angle"), &LookAtModifier3D::set_secondary_limit_angle); + ClassDB::bind_method(D_METHOD("get_secondary_limit_angle"), &LookAtModifier3D::get_secondary_limit_angle); + ClassDB::bind_method(D_METHOD("set_secondary_damp_threshold", "power"), &LookAtModifier3D::set_secondary_damp_threshold); + ClassDB::bind_method(D_METHOD("get_secondary_damp_threshold"), &LookAtModifier3D::get_secondary_damp_threshold); + + ClassDB::bind_method(D_METHOD("set_secondary_positive_limit_angle", "angle"), &LookAtModifier3D::set_secondary_positive_limit_angle); + ClassDB::bind_method(D_METHOD("get_secondary_positive_limit_angle"), &LookAtModifier3D::get_secondary_positive_limit_angle); + ClassDB::bind_method(D_METHOD("set_secondary_positive_damp_threshold", "power"), &LookAtModifier3D::set_secondary_positive_damp_threshold); + ClassDB::bind_method(D_METHOD("get_secondary_positive_damp_threshold"), &LookAtModifier3D::get_secondary_positive_damp_threshold); + ClassDB::bind_method(D_METHOD("set_secondary_negative_limit_angle", "angle"), &LookAtModifier3D::set_secondary_negative_limit_angle); + ClassDB::bind_method(D_METHOD("get_secondary_negative_limit_angle"), &LookAtModifier3D::get_secondary_negative_limit_angle); + ClassDB::bind_method(D_METHOD("set_secondary_negative_damp_threshold", "power"), &LookAtModifier3D::set_secondary_negative_damp_threshold); + ClassDB::bind_method(D_METHOD("get_secondary_negative_damp_threshold"), &LookAtModifier3D::get_secondary_negative_damp_threshold); + + ClassDB::bind_method(D_METHOD("get_interpolation_remaining"), &LookAtModifier3D::get_interpolation_remaining); + ClassDB::bind_method(D_METHOD("is_interpolating"), &LookAtModifier3D::is_interpolating); + ClassDB::bind_method(D_METHOD("is_target_within_limitation"), &LookAtModifier3D::is_target_within_limitation); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_node", PROPERTY_HINT_NODE_TYPE, "Node3D"), "set_target_node", "get_target_node"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "bone", PROPERTY_HINT_ENUM, ""), "set_bone", "get_bone"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "forward_axis", PROPERTY_HINT_ENUM, "+X,-X,+Y,-Y,+Z,-Z"), "set_forward_axis", "get_forward_axis"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "primary_rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z"), "set_primary_rotation_axis", "get_primary_rotation_axis"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_secondary_rotation"), "set_use_secondary_rotation", "is_using_secondary_rotation"); + + ADD_GROUP("Origin Settings", "origin_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "origin_from", PROPERTY_HINT_ENUM, "Self,SpecificBone,ExternalNode"), "set_origin_from", "get_origin_from"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "origin_bone", PROPERTY_HINT_ENUM, ""), "set_origin_bone", "get_origin_bone"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "origin_external_node", PROPERTY_HINT_NODE_TYPE, "Node3D"), "set_origin_external_node", "get_origin_external_node"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "origin_safe_margin", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater,suffix:m"), "set_origin_safe_margin", "get_origin_safe_margin"); + + ADD_GROUP("Time Based Interpolation", ""); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "duration", PROPERTY_HINT_RANGE, "0,10,0.001,or_greater,suffix:s"), "set_duration", "get_duration"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "transition_type", PROPERTY_HINT_ENUM, "Linear,Sine,Quint,Quart,Quad,Expo,Elastic,Cubic,Circ,Bounce,Back,Spring"), "set_transition_type", "get_transition_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ease_type", PROPERTY_HINT_ENUM, "In,Out,InOut,OutIn"), "set_ease_type", "get_ease_type"); + + ADD_GROUP("Angle Limitation", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_angle_limitation"), "set_use_angle_limitation", "is_using_angle_limitation"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "symmetry_limitation"), "set_symmetry_limitation", "is_limitation_symmetry"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "primary_limit_angle", PROPERTY_HINT_RANGE, "0,360,0.01,radians_as_degrees"), "set_primary_limit_angle", "get_primary_limit_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "primary_damp_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_primary_damp_threshold", "get_primary_damp_threshold"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "primary_positive_limit_angle", PROPERTY_HINT_RANGE, "0,180,0.01,radians_as_degrees"), "set_primary_positive_limit_angle", "get_primary_positive_limit_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "primary_positive_damp_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_primary_positive_damp_threshold", "get_primary_positive_damp_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "primary_negative_limit_angle", PROPERTY_HINT_RANGE, "0,180,0.01,radians_as_degrees"), "set_primary_negative_limit_angle", "get_primary_negative_limit_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "primary_negative_damp_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_primary_negative_damp_threshold", "get_primary_negative_damp_threshold"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "secondary_limit_angle", PROPERTY_HINT_RANGE, "0,360,0.01,radians_as_degrees"), "set_secondary_limit_angle", "get_secondary_limit_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "secondary_damp_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_secondary_damp_threshold", "get_secondary_damp_threshold"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "secondary_positive_limit_angle", PROPERTY_HINT_RANGE, "0,180,0.01,radians_as_degrees"), "set_secondary_positive_limit_angle", "get_secondary_positive_limit_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "secondary_positive_damp_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_secondary_positive_damp_threshold", "get_secondary_positive_damp_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "secondary_negative_limit_angle", PROPERTY_HINT_RANGE, "0,180,0.01,radians_as_degrees"), "set_secondary_negative_limit_angle", "get_secondary_negative_limit_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "secondary_negative_damp_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_secondary_negative_damp_threshold", "get_secondary_negative_damp_threshold"); + + BIND_ENUM_CONSTANT(BONE_AXIS_PLUS_X); + BIND_ENUM_CONSTANT(BONE_AXIS_MINUS_X); + BIND_ENUM_CONSTANT(BONE_AXIS_PLUS_Y); + BIND_ENUM_CONSTANT(BONE_AXIS_MINUS_Y); + BIND_ENUM_CONSTANT(BONE_AXIS_PLUS_Z); + BIND_ENUM_CONSTANT(BONE_AXIS_MINUS_Z); + + BIND_ENUM_CONSTANT(ORIGIN_FROM_SELF); + BIND_ENUM_CONSTANT(ORIGIN_FROM_SPECIFIC_BONE); + BIND_ENUM_CONSTANT(ORIGIN_FROM_EXTERNAL_NODE); +} + +void LookAtModifier3D::_process_modification() { + if (!is_inside_tree()) { + return; + } + + Skeleton3D *skeleton = get_skeleton(); + if (!skeleton || bone < 0 || bone >= skeleton->get_bone_count()) { + return; + } + + // Calculate bone rest space in the world. + Transform3D bone_rest_space; + int parent_bone = skeleton->get_bone_parent(bone); + if (parent_bone < 0) { + bone_rest_space = skeleton->get_global_transform() * skeleton->get_bone_rest(bone); + } else { + bone_rest_space = skeleton->get_global_transform() * skeleton->get_bone_global_pose(parent_bone) * skeleton->get_bone_rest(bone); + } + + // Calculate forward_vector and destination. + is_within_limitations = true; + Vector3 prev_forward_vector = forward_vector; + Quaternion destination; + Node3D *target = Object::cast_to<Node3D>(get_node_or_null(target_node)); + if (!target) { + destination = skeleton->get_bone_pose_rotation(bone); + } else { + Transform3D origin_tr; + if (origin_from == ORIGIN_FROM_SPECIFIC_BONE && origin_bone < skeleton->get_bone_count()) { + origin_tr = skeleton->get_global_transform() * skeleton->get_bone_global_pose(origin_bone); + } else if (origin_from == ORIGIN_FROM_EXTERNAL_NODE) { + Node3D *origin_src = Object::cast_to<Node3D>(get_node_or_null(origin_external_node)); + if (origin_src) { + origin_tr = origin_src->get_global_transform(); + } else { + origin_tr = bone_rest_space; + } + } else { + origin_tr = bone_rest_space; + } + forward_vector = bone_rest_space.basis.xform_inv((target->get_global_position() - origin_tr.translated_local(origin_offset).origin)); + forward_vector_nrm = forward_vector.normalized(); + if (forward_vector_nrm.abs().is_equal_approx(get_vector_from_axis(primary_rotation_axis))) { + destination = skeleton->get_bone_pose_rotation(bone); + forward_vector = Vector3(0, 0, 0); // The zero-vector to be used for checking in the line immediately below to avoid animation glitch. + } else { + destination = look_at_with_axes(skeleton->get_bone_rest(bone)).basis.get_rotation_quaternion(); + } + } + + // Detect flipping. + Vector3::Axis current_forward_axis = get_axis_from_bone_axis(forward_axis); + if (is_intersecting_axis(prev_forward_vector, forward_vector, current_forward_axis, secondary_rotation_axis) || + is_intersecting_axis(prev_forward_vector, forward_vector, primary_rotation_axis, primary_rotation_axis, true) || + is_intersecting_axis(prev_forward_vector, forward_vector, secondary_rotation_axis, current_forward_axis) || + (prev_forward_vector != Vector3(0, 0, 0) && forward_vector == Vector3(0, 0, 0)) || + (prev_forward_vector == Vector3(0, 0, 0) && forward_vector != Vector3(0, 0, 0))) { + init_transition(); + } else if (use_angle_limitation && signbit(prev_forward_vector[secondary_rotation_axis]) != signbit(forward_vector[secondary_rotation_axis])) { + // Flipping by angle_limitation can be detected by sign of secondary rotation axes during forward_vector is rotated more than 90 degree from forward_axis (means dot production is negative). + Vector3 prev_forward_vector_nrm = forward_vector.normalized(); + Vector3 rest_forward_vector = get_vector_from_bone_axis(forward_axis); + if (symmetry_limitation) { + if (!Math::is_equal_approx(primary_limit_angle, (float)Math_TAU) && prev_forward_vector_nrm.dot(rest_forward_vector) < 0 && forward_vector_nrm.dot(rest_forward_vector) < 0) { + init_transition(); + } + } else { + if (!Math::is_equal_approx(primary_positive_limit_angle + primary_negative_limit_angle, (float)Math_TAU) && prev_forward_vector_nrm.dot(rest_forward_vector) < 0 && forward_vector_nrm.dot(rest_forward_vector) < 0) { + init_transition(); + } + } + } + + // Do time-based interpolation. + if (remaining > 0) { + double delta = 0.0; + if (skeleton->get_modifier_callback_mode_process() == Skeleton3D::MODIFIER_CALLBACK_MODE_PROCESS_IDLE) { + delta = get_process_delta_time(); + } else { + delta = get_physics_process_delta_time(); + } + remaining = MAX(0, remaining - time_step * delta); + if (use_angle_limitation) { + // Interpolate through the rest same as AnimationTree blending for preventing to penetrate the bone into the body. + Quaternion rest = skeleton->get_bone_rest(bone).basis.get_rotation_quaternion(); + float weight = Tween::run_equation(transition_type, ease_type, 1 - remaining, 0.0, 1.0, 1.0); + destination = rest * Quaternion().slerp(rest.inverse() * from_q, 1 - weight) * Quaternion().slerp(rest.inverse() * destination, weight); + } else { + destination = from_q.slerp(destination, Tween::run_equation(transition_type, ease_type, 1 - remaining, 0.0, 1.0, 1.0)); + } + } + + skeleton->set_bone_pose_rotation(bone, destination); + prev_q = destination; +} + +bool LookAtModifier3D::is_intersecting_axis(const Vector3 &p_prev, const Vector3 &p_current, Vector3::Axis p_flipping_axis, Vector3::Axis p_check_axis, bool p_check_plane) const { + // Prevent that the angular velocity does not become too large. + // Check that is p_flipping_axis flipped nearby p_check_axis (close than origin_safe_margin) or not. If p_check_plane is true, check two axes of crossed plane. + if (p_check_plane) { + if (get_projection_vector(p_prev, p_check_axis).length() > origin_safe_margin && get_projection_vector(p_current, p_check_axis).length() > origin_safe_margin) { + return false; + } + } else if (Math::abs(p_prev[p_check_axis]) > origin_safe_margin && Math::abs(p_current[p_check_axis]) > origin_safe_margin) { + return false; + } + + return signbit(p_prev[p_flipping_axis]) != signbit(p_current[p_flipping_axis]); +} + +Vector3 LookAtModifier3D::get_basis_vector_from_bone_axis(const Basis &p_basis, LookAtModifier3D::BoneAxis p_axis) const { + Vector3 ret; + switch (p_axis) { + case BONE_AXIS_PLUS_X: { + ret = p_basis.get_column(0); + } break; + case BONE_AXIS_MINUS_X: { + ret = -p_basis.get_column(0); + } break; + case BONE_AXIS_PLUS_Y: { + ret = p_basis.get_column(1); + } break; + case BONE_AXIS_MINUS_Y: { + ret = -p_basis.get_column(1); + } break; + case BONE_AXIS_PLUS_Z: { + ret = p_basis.get_column(2); + } break; + case BONE_AXIS_MINUS_Z: { + ret = -p_basis.get_column(2); + } break; + } + return ret; +} + +Vector3 LookAtModifier3D::get_vector_from_bone_axis(const LookAtModifier3D::BoneAxis &p_axis) const { + Vector3 ret; + switch (p_axis) { + case BONE_AXIS_PLUS_X: { + ret = Vector3(1, 0, 0); + } break; + case BONE_AXIS_MINUS_X: { + ret = Vector3(-1, 0, 0); + } break; + case BONE_AXIS_PLUS_Y: { + ret = Vector3(0, 1, 0); + } break; + case BONE_AXIS_MINUS_Y: { + ret = Vector3(0, -1, 0); + } break; + case BONE_AXIS_PLUS_Z: { + ret = Vector3(0, 0, 1); + } break; + case BONE_AXIS_MINUS_Z: { + ret = Vector3(0, 0, -1); + } break; + } + return ret; +} + +Vector3 LookAtModifier3D::get_vector_from_axis(const Vector3::Axis &p_axis) const { + Vector3 ret; + switch (p_axis) { + case Vector3::AXIS_X: { + ret = Vector3(1, 0, 0); + } break; + case Vector3::AXIS_Y: { + ret = Vector3(0, 1, 0); + } break; + case Vector3::AXIS_Z: { + ret = Vector3(0, 0, 1); + } break; + } + return ret; +} + +Vector3::Axis LookAtModifier3D::get_axis_from_bone_axis(BoneAxis p_axis) const { + Vector3::Axis ret = Vector3::AXIS_X; + switch (p_axis) { + case BONE_AXIS_PLUS_X: + case BONE_AXIS_MINUS_X: { + ret = Vector3::AXIS_X; + } break; + case BONE_AXIS_PLUS_Y: + case BONE_AXIS_MINUS_Y: { + ret = Vector3::AXIS_Y; + } break; + case BONE_AXIS_PLUS_Z: + case BONE_AXIS_MINUS_Z: { + ret = Vector3::AXIS_Z; + } break; + } + return ret; +} + +Vector2 LookAtModifier3D::get_projection_vector(const Vector3 &p_vector, Vector3::Axis p_axis) const { + // NOTE: axis is swapped between 2D and 3D. + Vector2 ret; + switch (p_axis) { + case Vector3::AXIS_X: { + ret = Vector2(p_vector.z, p_vector.y); + } break; + case Vector3::AXIS_Y: { + ret = Vector2(p_vector.x, p_vector.z); + } break; + case Vector3::AXIS_Z: { + ret = Vector2(p_vector.y, p_vector.x); + } break; + } + return ret; +} + +float LookAtModifier3D::remap_damped(float p_from, float p_to, float p_damp_threshold, float p_value) const { + float sign = signbit(p_value) ? -1.0f : 1.0f; + float abs_value = Math::abs(p_value); + + if (Math::is_equal_approx(p_damp_threshold, 1.0f) || Math::is_zero_approx(p_to)) { + return sign * CLAMP(abs_value, p_from, p_to); // Avoid division by zero. + } + + float value = Math::inverse_lerp(p_from, p_to, abs_value); + + if (value <= p_damp_threshold) { + return sign * CLAMP(abs_value, p_from, p_to); + } + + double limit = Math_PI; + double inv_to = 1.0 / p_to; + double end_x = limit * inv_to; + double position = abs_value * inv_to; + Vector2 start = Vector2(p_damp_threshold, p_damp_threshold); + Vector2 mid = Vector2(1.0, 1.0); + Vector2 end = Vector2(end_x, 1.0); + value = get_bspline_y(start, mid, end, position); + + return sign * Math::lerp(p_from, p_to, value); +} + +double LookAtModifier3D::get_bspline_y(const Vector2 &p_from, const Vector2 &p_control, const Vector2 &p_to, double p_x) const { + double a = p_from.x - 2.0 * p_control.x + p_to.x; + double b = -2.0 * p_from.x + 2.0 * p_control.x; + double c = p_from.x - p_x; + double t = 0.0; + if (Math::is_zero_approx(a)) { + t = -c / b; // Almost linear. + } else { + double discriminant = b * b - 4.0 * a * c; + double sqrt_discriminant = Math::sqrt(discriminant); + double e = 1.0 / (2.0 * a); + double t1 = (-b + sqrt_discriminant) * e; + t = (0.0 <= t1 && t1 <= 1.0) ? t1 : (-b - sqrt_discriminant) * e; + } + double u = 1.0 - t; + double y = u * u * p_from.y + 2.0 * u * t * p_control.y + t * t * p_to.y; + return y; +} + +Transform3D LookAtModifier3D::look_at_with_axes(const Transform3D &p_rest) { + // Primary rotation by projection to 2D plane by xform_inv and picking elements. + Vector3 current_vector = get_basis_vector_from_bone_axis(p_rest.basis, forward_axis).normalized(); + Vector2 src_vec2 = get_projection_vector(p_rest.basis.xform_inv(forward_vector_nrm), primary_rotation_axis).normalized(); + Vector2 dst_vec2 = get_projection_vector(p_rest.basis.xform_inv(current_vector), primary_rotation_axis).normalized(); + real_t calculated_angle = src_vec2.angle_to(dst_vec2); + Transform3D primary_result = p_rest.rotated_local(get_vector_from_axis(primary_rotation_axis), calculated_angle); + Transform3D current_result = primary_result; // primary_result will be used by calculation of secondary rotation, current_result is rotated by that. + float limit_angle = 0.0; + float damp_threshold = 0.0; + + if (use_angle_limitation) { + if (symmetry_limitation) { + limit_angle = primary_limit_angle * 0.5f; + damp_threshold = primary_damp_threshold; + } else { + if (signbit(calculated_angle)) { + limit_angle = primary_negative_limit_angle; + damp_threshold = primary_negative_damp_threshold; + } else { + limit_angle = primary_positive_limit_angle; + damp_threshold = primary_positive_damp_threshold; + } + } + if (Math::abs(calculated_angle) > limit_angle) { + is_within_limitations = false; + } + calculated_angle = remap_damped(0, limit_angle, damp_threshold, calculated_angle); + current_result = p_rest.rotated_local(get_vector_from_axis(primary_rotation_axis), calculated_angle); + } + + // Needs for detecting flipping even if use_secondary_rotation is false. + Vector3 secondary_plane = get_vector_from_bone_axis(forward_axis) + get_vector_from_axis(primary_rotation_axis); + secondary_rotation_axis = Math::is_zero_approx(secondary_plane.x) ? Vector3::AXIS_X : (Math::is_zero_approx(secondary_plane.y) ? Vector3::AXIS_Y : Vector3::AXIS_Z); + + if (!use_secondary_rotation) { + return current_result; + } + + // Secondary rotation by projection to 2D plane by xform_inv and picking elements. + current_vector = get_basis_vector_from_bone_axis(primary_result.basis, forward_axis).normalized(); + src_vec2 = get_projection_vector(primary_result.basis.xform_inv(forward_vector_nrm), secondary_rotation_axis).normalized(); + dst_vec2 = get_projection_vector(primary_result.basis.xform_inv(current_vector), secondary_rotation_axis).normalized(); + calculated_angle = src_vec2.angle_to(dst_vec2); + + if (use_angle_limitation) { + if (symmetry_limitation) { + limit_angle = secondary_limit_angle * 0.5f; + damp_threshold = secondary_damp_threshold; + } else { + if (signbit(calculated_angle)) { + limit_angle = secondary_negative_limit_angle; + damp_threshold = secondary_negative_damp_threshold; + } else { + limit_angle = secondary_positive_limit_angle; + damp_threshold = secondary_positive_damp_threshold; + } + } + if (Math::abs(calculated_angle) > limit_angle) { + is_within_limitations = false; + } + calculated_angle = remap_damped(0, limit_angle, damp_threshold, calculated_angle); + } + + current_result = current_result.rotated_local(get_vector_from_axis(secondary_rotation_axis), calculated_angle); + + return current_result; +} + +void LookAtModifier3D::init_transition() { + if (Math::is_zero_approx(duration)) { + return; + } + from_q = prev_q; + remaining = 1.0; +} diff --git a/scene/3d/look_at_modifier_3d.h b/scene/3d/look_at_modifier_3d.h new file mode 100644 index 0000000000..5f3c4e8b1c --- /dev/null +++ b/scene/3d/look_at_modifier_3d.h @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* look_at_modifier_3d.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef LOOK_AT_MODIFIER_3D_H +#define LOOK_AT_MODIFIER_3D_H + +#include "scene/3d/skeleton_modifier_3d.h" +#include "scene/animation/tween.h" + +class LookAtModifier3D : public SkeletonModifier3D { + GDCLASS(LookAtModifier3D, SkeletonModifier3D); + +public: + enum BoneAxis { + BONE_AXIS_PLUS_X, + BONE_AXIS_MINUS_X, + BONE_AXIS_PLUS_Y, + BONE_AXIS_MINUS_Y, + BONE_AXIS_PLUS_Z, + BONE_AXIS_MINUS_Z, + }; + + enum OriginFrom { + ORIGIN_FROM_SELF, + ORIGIN_FROM_SPECIFIC_BONE, + ORIGIN_FROM_EXTERNAL_NODE, + }; + +private: + int bone = 0; + + Vector3 forward_vector; + Vector3 forward_vector_nrm; + BoneAxis forward_axis = BONE_AXIS_PLUS_Z; + Vector3::Axis primary_rotation_axis = Vector3::AXIS_Y; + Vector3::Axis secondary_rotation_axis = Vector3::AXIS_X; + bool use_secondary_rotation = true; + + OriginFrom origin_from = ORIGIN_FROM_SELF; + int origin_bone = -1; + NodePath origin_external_node; + + Vector3 origin_offset; + float origin_safe_margin = 0.1; + + NodePath target_node; + + float duration = 0; + Tween::TransitionType transition_type = Tween::TRANS_LINEAR; + Tween::EaseType ease_type = Tween::EASE_IN; + + bool use_angle_limitation = false; + bool symmetry_limitation = true; + + float primary_limit_angle = Math_TAU; + float primary_damp_threshold = 1.0f; + float primary_positive_limit_angle = Math_PI; + float primary_positive_damp_threshold = 1.0f; + float primary_negative_limit_angle = Math_PI; + float primary_negative_damp_threshold = 1.0f; + + float secondary_limit_angle = Math_TAU; + float secondary_damp_threshold = 1.0f; + float secondary_positive_limit_angle = Math_PI; + float secondary_positive_damp_threshold = 1.0f; + float secondary_negative_limit_angle = Math_PI; + float secondary_negative_damp_threshold = 1.0f; + + bool is_within_limitations = false; + + // For time-based interpolation. + Quaternion from_q; + Quaternion prev_q; + + float remaining = 0; + float time_step = 1.0; + + Vector3 get_basis_vector_from_bone_axis(const Basis &p_basis, BoneAxis p_axis) const; + Vector3 get_vector_from_bone_axis(const BoneAxis &p_axis) const; + Vector3 get_vector_from_axis(const Vector3::Axis &p_axis) const; + Vector3::Axis get_axis_from_bone_axis(BoneAxis p_axis) const; + Vector2 get_projection_vector(const Vector3 &p_vector, Vector3::Axis p_axis) const; + float remap_damped(float p_from, float p_to, float p_damp_threshold, float p_value) const; + double get_bspline_y(const Vector2 &p_from, const Vector2 &p_control, const Vector2 &p_to, double p_x) const; + bool is_intersecting_axis(const Vector3 &p_prev, const Vector3 &p_current, Vector3::Axis p_flipping_axis, Vector3::Axis p_check_axis, bool p_check_plane = false) const; + + Transform3D look_at_with_axes(const Transform3D &p_rest); + void init_transition(); + +protected: + virtual PackedStringArray get_configuration_warnings() const override; + void _validate_property(PropertyInfo &p_property) const; + + static void _bind_methods(); + + virtual void _process_modification() override; + +public: + void set_bone(int p_bone); + int get_bone() const; + + void set_forward_axis(BoneAxis p_axis); + BoneAxis get_forward_axis() const; + void set_primary_rotation_axis(Vector3::Axis p_axis); + Vector3::Axis get_primary_rotation_axis() const; + void set_use_secondary_rotation(bool p_enabled); + bool is_using_secondary_rotation() const; + + void set_origin_from(OriginFrom p_origin_from); + OriginFrom get_origin_from() const; + void set_origin_bone(int p_bone); + int get_origin_bone() const; + void set_origin_external_node(const NodePath &p_external_node); + NodePath get_origin_external_node() const; + + void set_origin_offset(const Vector3 &p_offset); + Vector3 get_origin_offset() const; + void set_origin_safe_margin(float p_margin); + float get_origin_safe_margin() const; + + void set_target_node(const NodePath &p_target_node); + NodePath get_target_node() const; + + void set_duration(float p_duration); + float get_duration() const; + void set_transition_type(Tween::TransitionType p_transition_type); + Tween::TransitionType get_transition_type() const; + void set_ease_type(Tween::EaseType p_ease_type); + Tween::EaseType get_ease_type() const; + + void set_use_angle_limitation(bool p_enabled); + bool is_using_angle_limitation() const; + void set_symmetry_limitation(bool p_enabled); + bool is_limitation_symmetry() const; + + void set_primary_limit_angle(float p_angle); + float get_primary_limit_angle() const; + void set_primary_damp_threshold(float p_power); + float get_primary_damp_threshold() const; + + void set_primary_positive_limit_angle(float p_angle); + float get_primary_positive_limit_angle() const; + void set_primary_positive_damp_threshold(float p_power); + float get_primary_positive_damp_threshold() const; + void set_primary_negative_limit_angle(float p_angle); + float get_primary_negative_limit_angle() const; + void set_primary_negative_damp_threshold(float p_power); + float get_primary_negative_damp_threshold() const; + + void set_secondary_limit_angle(float p_angle); + float get_secondary_limit_angle() const; + void set_secondary_damp_threshold(float p_power); + float get_secondary_damp_threshold() const; + + void set_secondary_positive_limit_angle(float p_angle); + float get_secondary_positive_limit_angle() const; + void set_secondary_positive_damp_threshold(float p_power); + float get_secondary_positive_damp_threshold() const; + void set_secondary_negative_limit_angle(float p_angle); + float get_secondary_negative_limit_angle() const; + void set_secondary_negative_damp_threshold(float p_power); + float get_secondary_negative_damp_threshold() const; + + float get_interpolation_remaining() const; + bool is_interpolating() const; + bool is_target_within_limitation() const; +}; + +VARIANT_ENUM_CAST(LookAtModifier3D::BoneAxis); +VARIANT_ENUM_CAST(LookAtModifier3D::OriginFrom); + +#endif // LOOK_AT_MODIFIER_3D_H diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index f551cb401c..14bc22a217 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -87,17 +87,9 @@ bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const { } void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const { - List<String> ls; - for (const KeyValue<StringName, int> &E : blend_shape_properties) { - ls.push_back(E.key); - } - - ls.sort(); - - for (const String &E : ls) { - p_list->push_back(PropertyInfo(Variant::FLOAT, E, PROPERTY_HINT_RANGE, "-1,1,0.00001")); + for (uint32_t i = 0; i < blend_shape_tracks.size(); i++) { + p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("blend_shapes/%s", String(mesh->get_blend_shape_name(i))), PROPERTY_HINT_RANGE, "-1,1,0.00001")); } - if (mesh.is_valid()) { for (int i = 0; i < mesh->get_surface_count(); i++) { p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("%s/%d", PNAME("surface_material_override"), i), PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT)); @@ -142,6 +134,7 @@ int MeshInstance3D::get_blend_shape_count() const { } return mesh->get_blend_shape_count(); } + int MeshInstance3D::find_blend_shape_by_name(const StringName &p_name) { if (mesh.is_null()) { return -1; @@ -153,11 +146,13 @@ int MeshInstance3D::find_blend_shape_by_name(const StringName &p_name) { } return -1; } + float MeshInstance3D::get_blend_shape_value(int p_blend_shape) const { ERR_FAIL_COND_V(mesh.is_null(), 0.0); ERR_FAIL_INDEX_V(p_blend_shape, (int)blend_shape_tracks.size(), 0); return blend_shape_tracks[p_blend_shape]; } + void MeshInstance3D::set_blend_shape_value(int p_blend_shape, float p_value) { ERR_FAIL_COND(mesh.is_null()); ERR_FAIL_INDEX(p_blend_shape, (int)blend_shape_tracks.size()); diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 5bbb724e2f..faf138896a 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -272,12 +272,20 @@ void NavigationAgent3D::_notification(int p_what) { #endif // DEBUG_ENABLED } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (agent_parent) { NavigationServer3D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process()); } } break; + case NOTIFICATION_UNSUSPENDED: { + if (get_tree()->is_paused()) { + break; + } + [[fallthrough]]; + } + case NOTIFICATION_UNPAUSED: { if (agent_parent) { NavigationServer3D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process()); @@ -1073,8 +1081,8 @@ void NavigationAgent3D::_update_debug_path() { debug_path_instance = RenderingServer::get_singleton()->instance_create(); } - if (!debug_path_mesh.is_valid()) { - debug_path_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (debug_path_mesh.is_null()) { + debug_path_mesh.instantiate(); } debug_path_mesh->clear_surfaces(); diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp index 0cce21b9d0..9e29384fc9 100644 --- a/scene/3d/navigation_link_3d.cpp +++ b/scene/3d/navigation_link_3d.cpp @@ -56,8 +56,8 @@ void NavigationLink3D::_update_debug_mesh() { debug_instance = RenderingServer::get_singleton()->instance_create(); } - if (!debug_mesh.is_valid()) { - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (debug_mesh.is_null()) { + debug_mesh.instantiate(); } RID nav_map = get_world_3d()->get_navigation_map(); diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index f2ac8f789c..7be01589f4 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -92,33 +92,30 @@ void NavigationObstacle3D::_notification(int p_what) { } else { _update_map(RID()); } - previous_transform = get_global_transform(); // need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents NavigationServer3D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); - _update_position(get_global_transform().origin); + _update_transform(); set_physics_process_internal(true); #ifdef DEBUG_ENABLED - if ((NavigationServer3D::get_singleton()->get_debug_avoidance_enabled()) && - (NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_radius())) { - _update_fake_agent_radius_debug(); - _update_static_obstacle_debug(); - } + _update_debug(); #endif // DEBUG_ENABLED } break; +#ifdef TOOLS_ENABLED + case NOTIFICATION_TRANSFORM_CHANGED: { + update_gizmos(); + } break; +#endif // TOOLS_ENABLED + case NOTIFICATION_EXIT_TREE: { set_physics_process_internal(false); _update_map(RID()); #ifdef DEBUG_ENABLED - if (fake_agent_radius_debug_instance.is_valid()) { - RS::get_singleton()->instance_set_visible(fake_agent_radius_debug_instance, false); - } - if (static_obstacle_debug_instance.is_valid()) { - RS::get_singleton()->instance_set_visible(static_obstacle_debug_instance, false); - } + _update_debug(); #endif // DEBUG_ENABLED } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (!can_process()) { map_before_pause = map_current; @@ -130,6 +127,13 @@ void NavigationObstacle3D::_notification(int p_what) { NavigationServer3D::get_singleton()->obstacle_set_paused(obstacle, !can_process()); } break; + case NOTIFICATION_UNSUSPENDED: { + if (get_tree()->is_paused()) { + break; + } + [[fallthrough]]; + } + case NOTIFICATION_UNPAUSED: { if (!can_process()) { map_before_pause = map_current; @@ -143,20 +147,13 @@ void NavigationObstacle3D::_notification(int p_what) { #ifdef DEBUG_ENABLED case NOTIFICATION_VISIBILITY_CHANGED: { - if (is_inside_tree()) { - if (fake_agent_radius_debug_instance.is_valid()) { - RS::get_singleton()->instance_set_visible(fake_agent_radius_debug_instance, is_visible_in_tree()); - } - if (static_obstacle_debug_instance.is_valid()) { - RS::get_singleton()->instance_set_visible(static_obstacle_debug_instance, is_visible_in_tree()); - } - } + _update_debug(); } break; #endif // DEBUG_ENABLED case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (is_inside_tree()) { - _update_position(get_global_transform().origin); + _update_transform(); if (velocity_submitted) { velocity_submitted = false; @@ -167,15 +164,23 @@ void NavigationObstacle3D::_notification(int p_what) { previous_velocity = velocity; } #ifdef DEBUG_ENABLED - if (fake_agent_radius_debug_instance.is_valid() && radius > 0.0) { - Transform3D debug_transform; - debug_transform.origin = get_global_position(); - RS::get_singleton()->instance_set_transform(fake_agent_radius_debug_instance, debug_transform); + if (fake_agent_radius_debug_instance_rid.is_valid() && radius > 0.0) { + // Prevent non-positive scaling. + const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001); + // Agent radius is a scalar value and does not support non-uniform scaling, choose the largest axis. + const float scaling_max_value = safe_scale[safe_scale.max_axis_index()]; + const Vector3 uniform_max_scale = Vector3(scaling_max_value, scaling_max_value, scaling_max_value); + const Transform3D debug_transform = Transform3D(Basis().scaled(uniform_max_scale), get_global_position()); + + RS::get_singleton()->instance_set_transform(fake_agent_radius_debug_instance_rid, debug_transform); } - if (static_obstacle_debug_instance.is_valid() && get_vertices().size() > 0) { - Transform3D debug_transform; - debug_transform.origin = get_global_position(); - RS::get_singleton()->instance_set_transform(static_obstacle_debug_instance, debug_transform); + if (static_obstacle_debug_instance_rid.is_valid() && get_vertices().size() > 0) { + // Prevent non-positive scaling. + const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001); + // Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account. + const Transform3D debug_transform = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), get_global_rotation().y), get_global_position()); + + RS::get_singleton()->instance_set_transform(static_obstacle_debug_instance_rid, debug_transform); } #endif // DEBUG_ENABLED } @@ -184,53 +189,83 @@ void NavigationObstacle3D::_notification(int p_what) { } NavigationObstacle3D::NavigationObstacle3D() { - obstacle = NavigationServer3D::get_singleton()->obstacle_create(); + NavigationServer3D *ns3d = NavigationServer3D::get_singleton(); - NavigationServer3D::get_singleton()->obstacle_set_height(obstacle, height); - NavigationServer3D::get_singleton()->obstacle_set_radius(obstacle, radius); - NavigationServer3D::get_singleton()->obstacle_set_vertices(obstacle, vertices); - NavigationServer3D::get_singleton()->obstacle_set_avoidance_layers(obstacle, avoidance_layers); - NavigationServer3D::get_singleton()->obstacle_set_use_3d_avoidance(obstacle, use_3d_avoidance); - NavigationServer3D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); + obstacle = ns3d->obstacle_create(); + + ns3d->obstacle_set_height(obstacle, height); + ns3d->obstacle_set_radius(obstacle, radius); + ns3d->obstacle_set_vertices(obstacle, vertices); + ns3d->obstacle_set_avoidance_layers(obstacle, avoidance_layers); + ns3d->obstacle_set_use_3d_avoidance(obstacle, use_3d_avoidance); + ns3d->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); #ifdef DEBUG_ENABLED - NavigationServer3D::get_singleton()->connect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_fake_agent_radius_debug)); - NavigationServer3D::get_singleton()->connect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_static_obstacle_debug)); + RenderingServer *rs = RenderingServer::get_singleton(); + + fake_agent_radius_debug_mesh_rid = rs->mesh_create(); + static_obstacle_debug_mesh_rid = rs->mesh_create(); + + fake_agent_radius_debug_instance_rid = rs->instance_create(); + static_obstacle_debug_instance_rid = rs->instance_create(); + + rs->instance_set_base(fake_agent_radius_debug_instance_rid, fake_agent_radius_debug_mesh_rid); + rs->instance_set_base(static_obstacle_debug_instance_rid, static_obstacle_debug_mesh_rid); + + ns3d->connect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_fake_agent_radius_debug)); + ns3d->connect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_static_obstacle_debug)); _update_fake_agent_radius_debug(); _update_static_obstacle_debug(); #endif // DEBUG_ENABLED + +#ifdef TOOLS_ENABLED + set_notify_transform(true); +#endif // TOOLS_ENABLED } NavigationObstacle3D::~NavigationObstacle3D() { - ERR_FAIL_NULL(NavigationServer3D::get_singleton()); + NavigationServer3D *ns3d = NavigationServer3D::get_singleton(); + ERR_FAIL_NULL(ns3d); - NavigationServer3D::get_singleton()->free(obstacle); + ns3d->free(obstacle); obstacle = RID(); #ifdef DEBUG_ENABLED - NavigationServer3D::get_singleton()->disconnect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_fake_agent_radius_debug)); - NavigationServer3D::get_singleton()->disconnect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_static_obstacle_debug)); - if (fake_agent_radius_debug_instance.is_valid()) { - RenderingServer::get_singleton()->free(fake_agent_radius_debug_instance); + ns3d->disconnect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_fake_agent_radius_debug)); + ns3d->disconnect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_static_obstacle_debug)); + + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + if (fake_agent_radius_debug_instance_rid.is_valid()) { + rs->free(fake_agent_radius_debug_instance_rid); + fake_agent_radius_debug_instance_rid = RID(); } - if (fake_agent_radius_debug_mesh.is_valid()) { - RenderingServer::get_singleton()->free(fake_agent_radius_debug_mesh->get_rid()); + if (fake_agent_radius_debug_mesh_rid.is_valid()) { + rs->free(fake_agent_radius_debug_mesh_rid); + fake_agent_radius_debug_mesh_rid = RID(); } - - if (static_obstacle_debug_instance.is_valid()) { - RenderingServer::get_singleton()->free(static_obstacle_debug_instance); + if (static_obstacle_debug_instance_rid.is_valid()) { + rs->free(static_obstacle_debug_instance_rid); + static_obstacle_debug_instance_rid = RID(); } - if (static_obstacle_debug_mesh.is_valid()) { - RenderingServer::get_singleton()->free(static_obstacle_debug_mesh->get_rid()); + if (static_obstacle_debug_mesh_rid.is_valid()) { + rs->free(static_obstacle_debug_mesh_rid); + static_obstacle_debug_mesh_rid = RID(); } #endif // DEBUG_ENABLED } void NavigationObstacle3D::set_vertices(const Vector<Vector3> &p_vertices) { vertices = p_vertices; - NavigationServer3D::get_singleton()->obstacle_set_vertices(obstacle, vertices); + + const Basis basis = is_inside_tree() ? get_global_basis() : get_basis(); + const float rotation_y = is_inside_tree() ? get_global_rotation().y : get_rotation().y; + const Vector3 safe_scale = basis.get_scale().abs().maxf(0.001); + const Transform3D safe_transform = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), rotation_y), Vector3()); + NavigationServer3D::get_singleton()->obstacle_set_vertices(obstacle, safe_transform.xform(vertices)); #ifdef DEBUG_ENABLED _update_static_obstacle_debug(); + update_gizmos(); #endif // DEBUG_ENABLED } @@ -258,10 +293,14 @@ void NavigationObstacle3D::set_radius(real_t p_radius) { } radius = p_radius; - NavigationServer3D::get_singleton()->obstacle_set_radius(obstacle, radius); + + // Prevent non-positive or non-uniform scaling of dynamic obstacle radius. + const Vector3 safe_scale = (is_inside_tree() ? get_global_basis() : get_basis()).get_scale().abs().maxf(0.001); + NavigationServer3D::get_singleton()->obstacle_set_radius(obstacle, safe_scale[safe_scale.max_axis_index()] * radius); #ifdef DEBUG_ENABLED _update_fake_agent_radius_debug(); + update_gizmos(); #endif // DEBUG_ENABLED } @@ -272,10 +311,12 @@ void NavigationObstacle3D::set_height(real_t p_height) { } height = p_height; - NavigationServer3D::get_singleton()->obstacle_set_height(obstacle, height); + const float scale_factor = MAX(Math::abs((is_inside_tree() ? get_global_basis() : get_basis()).get_scale().y), 0.001); + NavigationServer3D::get_singleton()->obstacle_set_height(obstacle, scale_factor * height); #ifdef DEBUG_ENABLED _update_static_obstacle_debug(); + update_gizmos(); #endif // DEBUG_ENABLED } @@ -346,6 +387,25 @@ bool NavigationObstacle3D::get_carve_navigation_mesh() const { return carve_navigation_mesh; } +PackedStringArray NavigationObstacle3D::get_configuration_warnings() const { + PackedStringArray warnings = Node3D::get_configuration_warnings(); + + if (get_global_rotation().x != 0.0 || get_global_rotation().z != 0.0) { + warnings.push_back(RTR("NavigationObstacle3D only takes global rotation around the y-axis into account. Rotations around the x-axis or z-axis might lead to unexpected results.")); + } + + const Vector3 global_scale = get_global_basis().get_scale(); + if (global_scale.x < 0.001 || global_scale.y < 0.001 || global_scale.z < 0.001) { + warnings.push_back(RTR("NavigationObstacle3D does not support negative or zero scaling.")); + } + + if (radius > 0.0 && !get_global_basis().is_conformal()) { + warnings.push_back(RTR("The agent radius can only be scaled uniformly. The largest scale value along the three axes will be used.")); + } + + return warnings; +} + void NavigationObstacle3D::_update_map(RID p_map) { NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, p_map); map_current = p_map; @@ -355,36 +415,63 @@ void NavigationObstacle3D::_update_position(const Vector3 p_position) { NavigationServer3D::get_singleton()->obstacle_set_position(obstacle, p_position); } +void NavigationObstacle3D::_update_transform() { + _update_position(get_global_position()); + + // Prevent non-positive or non-uniform scaling of dynamic obstacle radius. + const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001); + const float scaling_max_value = safe_scale[safe_scale.max_axis_index()]; + NavigationServer3D::get_singleton()->obstacle_set_radius(obstacle, scaling_max_value * radius); + + // Apply modified node transform which only takes y-axis rotation into account to vertices. + const Transform3D safe_transform = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), get_global_rotation().y), Vector3()); + NavigationServer3D::get_singleton()->obstacle_set_vertices(obstacle, safe_transform.xform(vertices)); + NavigationServer3D::get_singleton()->obstacle_set_height(obstacle, safe_scale.y * height); +} + void NavigationObstacle3D::_update_use_3d_avoidance(bool p_use_3d_avoidance) { NavigationServer3D::get_singleton()->obstacle_set_use_3d_avoidance(obstacle, use_3d_avoidance); _update_map(map_current); } #ifdef DEBUG_ENABLED +void NavigationObstacle3D::_update_debug() { + RenderingServer *rs = RenderingServer::get_singleton(); + if (is_inside_tree()) { + rs->instance_set_visible(fake_agent_radius_debug_instance_rid, is_visible_in_tree()); + rs->instance_set_visible(static_obstacle_debug_instance_rid, is_visible_in_tree()); + rs->instance_set_scenario(fake_agent_radius_debug_instance_rid, get_world_3d()->get_scenario()); + rs->instance_set_scenario(static_obstacle_debug_instance_rid, get_world_3d()->get_scenario()); + rs->instance_set_transform(fake_agent_radius_debug_instance_rid, Transform3D(Basis(), get_global_position())); + rs->instance_set_transform(static_obstacle_debug_instance_rid, Transform3D(Basis(), get_global_position())); + _update_fake_agent_radius_debug(); + _update_static_obstacle_debug(); + } else { + rs->mesh_clear(fake_agent_radius_debug_mesh_rid); + rs->mesh_clear(static_obstacle_debug_mesh_rid); + rs->instance_set_scenario(fake_agent_radius_debug_instance_rid, RID()); + rs->instance_set_scenario(static_obstacle_debug_instance_rid, RID()); + } +} + void NavigationObstacle3D::_update_fake_agent_radius_debug() { + NavigationServer3D *ns3d = NavigationServer3D::get_singleton(); + RenderingServer *rs = RenderingServer::get_singleton(); + bool is_debug_enabled = false; if (Engine::get_singleton()->is_editor_hint()) { is_debug_enabled = true; - } else if (NavigationServer3D::get_singleton()->get_debug_enabled() && - NavigationServer3D::get_singleton()->get_debug_avoidance_enabled() && - NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_radius()) { + } else if (ns3d->get_debug_enabled() && + ns3d->get_debug_avoidance_enabled() && + ns3d->get_debug_navigation_avoidance_enable_obstacles_radius()) { is_debug_enabled = true; } - if (is_debug_enabled == false) { - if (fake_agent_radius_debug_instance.is_valid()) { - RS::get_singleton()->instance_set_visible(fake_agent_radius_debug_instance, false); - } - return; - } + rs->mesh_clear(fake_agent_radius_debug_mesh_rid); - if (!fake_agent_radius_debug_instance.is_valid()) { - fake_agent_radius_debug_instance = RenderingServer::get_singleton()->instance_create(); - } - if (!fake_agent_radius_debug_mesh.is_valid()) { - fake_agent_radius_debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (!is_debug_enabled) { + return; } - fake_agent_radius_debug_mesh->clear_surfaces(); Vector<Vector3> face_vertex_array; Vector<int> face_indices_array; @@ -439,147 +526,106 @@ void NavigationObstacle3D::_update_fake_agent_radius_debug() { face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array; face_mesh_array[Mesh::ARRAY_INDEX] = face_indices_array; - fake_agent_radius_debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array); - Ref<StandardMaterial3D> face_material = NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_obstacles_radius_material(); - fake_agent_radius_debug_mesh->surface_set_material(0, face_material); + rs->mesh_add_surface_from_arrays(fake_agent_radius_debug_mesh_rid, RS::PRIMITIVE_TRIANGLES, face_mesh_array); + + Ref<StandardMaterial3D> face_material = ns3d->get_debug_navigation_avoidance_obstacles_radius_material(); + rs->instance_set_surface_override_material(fake_agent_radius_debug_instance_rid, 0, face_material->get_rid()); - RS::get_singleton()->instance_set_base(fake_agent_radius_debug_instance, fake_agent_radius_debug_mesh->get_rid()); if (is_inside_tree()) { - RS::get_singleton()->instance_set_scenario(fake_agent_radius_debug_instance, get_world_3d()->get_scenario()); - RS::get_singleton()->instance_set_visible(fake_agent_radius_debug_instance, is_visible_in_tree()); + rs->instance_set_scenario(fake_agent_radius_debug_instance_rid, get_world_3d()->get_scenario()); + rs->instance_set_visible(fake_agent_radius_debug_instance_rid, is_visible_in_tree()); } } #endif // DEBUG_ENABLED #ifdef DEBUG_ENABLED void NavigationObstacle3D::_update_static_obstacle_debug() { - bool is_debug_enabled = false; if (Engine::get_singleton()->is_editor_hint()) { - is_debug_enabled = true; - } else if (NavigationServer3D::get_singleton()->get_debug_enabled() && - NavigationServer3D::get_singleton()->get_debug_avoidance_enabled() && - NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_static()) { - is_debug_enabled = true; - } - - if (is_debug_enabled == false) { - if (static_obstacle_debug_instance.is_valid()) { - RS::get_singleton()->instance_set_visible(static_obstacle_debug_instance, false); - } + // Don't update inside Editor as Node3D gizmo takes care of this. return; } - if (vertices.size() < 3) { - if (static_obstacle_debug_instance.is_valid()) { - RS::get_singleton()->instance_set_visible(static_obstacle_debug_instance, false); - } - return; - } + NavigationServer3D *ns3d = NavigationServer3D::get_singleton(); + RenderingServer *rs = RenderingServer::get_singleton(); - if (!static_obstacle_debug_instance.is_valid()) { - static_obstacle_debug_instance = RenderingServer::get_singleton()->instance_create(); - } - if (!static_obstacle_debug_mesh.is_valid()) { - static_obstacle_debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - } - static_obstacle_debug_mesh->clear_surfaces(); - - Vector<Vector2> polygon_2d_vertices; - polygon_2d_vertices.resize(vertices.size()); - Vector2 *polygon_2d_vertices_ptr = polygon_2d_vertices.ptrw(); - - for (int i = 0; i < vertices.size(); ++i) { - Vector3 obstacle_vertex = vertices[i]; - Vector2 obstacle_vertex_2d = Vector2(obstacle_vertex.x, obstacle_vertex.z); - polygon_2d_vertices_ptr[i] = obstacle_vertex_2d; + bool is_debug_enabled = false; + if (ns3d->get_debug_enabled() && + ns3d->get_debug_avoidance_enabled() && + ns3d->get_debug_navigation_avoidance_enable_obstacles_static()) { + is_debug_enabled = true; } - Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(polygon_2d_vertices); + rs->mesh_clear(static_obstacle_debug_mesh_rid); - if (triangulated_polygon_2d_indices.is_empty()) { - // failed triangulation + if (!is_debug_enabled) { return; } - bool obstacle_pushes_inward = Geometry2D::is_polygon_clockwise(polygon_2d_vertices); - - Vector<Vector3> face_vertex_array; - Vector<int> face_indices_array; - - face_vertex_array.resize(polygon_2d_vertices.size()); - face_indices_array.resize(triangulated_polygon_2d_indices.size()); + const int vertex_count = vertices.size(); - Vector3 *face_vertex_array_ptr = face_vertex_array.ptrw(); - int *face_indices_array_ptr = face_indices_array.ptrw(); - - for (int i = 0; i < triangulated_polygon_2d_indices.size(); ++i) { - int vertex_index = triangulated_polygon_2d_indices[i]; - const Vector2 &vertex_2d = polygon_2d_vertices[vertex_index]; - Vector3 vertex_3d = Vector3(vertex_2d.x, 0.0, vertex_2d.y); - face_vertex_array_ptr[vertex_index] = vertex_3d; - face_indices_array_ptr[i] = vertex_index; + if (vertex_count < 3) { + if (static_obstacle_debug_instance_rid.is_valid()) { + rs->instance_set_visible(static_obstacle_debug_instance_rid, false); + } + return; } - Array face_mesh_array; - face_mesh_array.resize(Mesh::ARRAY_MAX); - face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array; - face_mesh_array[Mesh::ARRAY_INDEX] = face_indices_array; - - static_obstacle_debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array); - Vector<Vector3> edge_vertex_array; + edge_vertex_array.resize(vertex_count * 8); - for (int i = 0; i < polygon_2d_vertices.size(); ++i) { - int from_index = i - 1; - int to_index = i; + Vector3 *edge_vertex_array_ptrw = edge_vertex_array.ptrw(); - if (i == 0) { - from_index = polygon_2d_vertices.size() - 1; - } + int vertex_index = 0; - const Vector2 &vertex_2d_from = polygon_2d_vertices[from_index]; - const Vector2 &vertex_2d_to = polygon_2d_vertices[to_index]; + for (int i = 0; i < vertex_count; i++) { + Vector3 point = vertices[i]; + Vector3 next_point = vertices[(i + 1) % vertex_count]; - Vector3 vertex_3d_ground_from = Vector3(vertex_2d_from.x, 0.0, vertex_2d_from.y); - Vector3 vertex_3d_ground_to = Vector3(vertex_2d_to.x, 0.0, vertex_2d_to.y); + Vector3 direction = next_point.direction_to(point); + Vector3 arrow_dir = direction.cross(Vector3(0.0, 1.0, 0.0)); + Vector3 edge_middle = point + ((next_point - point) * 0.5); - edge_vertex_array.push_back(vertex_3d_ground_from); - edge_vertex_array.push_back(vertex_3d_ground_to); + edge_vertex_array_ptrw[vertex_index++] = edge_middle; + edge_vertex_array_ptrw[vertex_index++] = edge_middle + (arrow_dir * 0.5); - Vector3 vertex_3d_height_from = Vector3(vertex_2d_from.x, height, vertex_2d_from.y); - Vector3 vertex_3d_height_to = Vector3(vertex_2d_to.x, height, vertex_2d_to.y); + edge_vertex_array_ptrw[vertex_index++] = point; + edge_vertex_array_ptrw[vertex_index++] = next_point; - edge_vertex_array.push_back(vertex_3d_height_from); - edge_vertex_array.push_back(vertex_3d_height_to); + edge_vertex_array_ptrw[vertex_index++] = Vector3(point.x, height, point.z); + edge_vertex_array_ptrw[vertex_index++] = Vector3(next_point.x, height, next_point.z); - edge_vertex_array.push_back(vertex_3d_ground_from); - edge_vertex_array.push_back(vertex_3d_height_from); + edge_vertex_array_ptrw[vertex_index++] = point; + edge_vertex_array_ptrw[vertex_index++] = Vector3(point.x, height, point.z); } Array edge_mesh_array; edge_mesh_array.resize(Mesh::ARRAY_MAX); edge_mesh_array[Mesh::ARRAY_VERTEX] = edge_vertex_array; - static_obstacle_debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, edge_mesh_array); + rs->mesh_add_surface_from_arrays(static_obstacle_debug_mesh_rid, RS::PRIMITIVE_LINES, edge_mesh_array); + + Vector<Vector2> polygon_2d_vertices; + polygon_2d_vertices.resize(vertex_count); + for (int i = 0; i < vertex_count; i++) { + const Vector3 &vert = vertices[i]; + polygon_2d_vertices.write[i] = Vector2(vert.x, vert.z); + } + + Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(polygon_2d_vertices); - Ref<StandardMaterial3D> face_material; Ref<StandardMaterial3D> edge_material; - if (obstacle_pushes_inward) { - face_material = NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushin_face_material(); - edge_material = NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material(); + if (triangulated_polygon_2d_indices.is_empty()) { + edge_material = ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material(); } else { - face_material = NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushout_face_material(); - edge_material = NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushout_edge_material(); + edge_material = ns3d->get_debug_navigation_avoidance_static_obstacle_pushout_edge_material(); } - static_obstacle_debug_mesh->surface_set_material(0, face_material); - static_obstacle_debug_mesh->surface_set_material(1, edge_material); + rs->instance_set_surface_override_material(static_obstacle_debug_instance_rid, 0, edge_material->get_rid()); - RS::get_singleton()->instance_set_base(static_obstacle_debug_instance, static_obstacle_debug_mesh->get_rid()); if (is_inside_tree()) { - RS::get_singleton()->instance_set_scenario(static_obstacle_debug_instance, get_world_3d()->get_scenario()); - RS::get_singleton()->instance_set_visible(static_obstacle_debug_instance, is_visible_in_tree()); + rs->instance_set_scenario(static_obstacle_debug_instance_rid, get_world_3d()->get_scenario()); + rs->instance_set_visible(static_obstacle_debug_instance_rid, is_visible_in_tree()); } } #endif // DEBUG_ENABLED diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h index e9a4669fa2..25f376e68b 100644 --- a/scene/3d/navigation_obstacle_3d.h +++ b/scene/3d/navigation_obstacle_3d.h @@ -51,8 +51,6 @@ class NavigationObstacle3D : public Node3D { bool use_3d_avoidance = false; - Transform3D previous_transform; - Vector3 velocity; Vector3 previous_velocity; bool velocity_submitted = false; @@ -61,13 +59,14 @@ class NavigationObstacle3D : public Node3D { bool carve_navigation_mesh = false; #ifdef DEBUG_ENABLED - RID fake_agent_radius_debug_instance; - Ref<ArrayMesh> fake_agent_radius_debug_mesh; + RID fake_agent_radius_debug_instance_rid; + RID fake_agent_radius_debug_mesh_rid; - RID static_obstacle_debug_instance; - Ref<ArrayMesh> static_obstacle_debug_mesh; + RID static_obstacle_debug_instance_rid; + RID static_obstacle_debug_mesh_rid; private: + void _update_debug(); void _update_fake_agent_radius_debug(); void _update_static_obstacle_debug(); #endif // DEBUG_ENABLED @@ -95,7 +94,7 @@ public: real_t get_height() const { return height; } void set_vertices(const Vector<Vector3> &p_vertices); - const Vector<Vector3> &get_vertices() const { return vertices; }; + const Vector<Vector3> &get_vertices() const { return vertices; } void set_avoidance_layers(uint32_t p_layers); uint32_t get_avoidance_layers() const; @@ -107,7 +106,7 @@ public: bool get_use_3d_avoidance() const { return use_3d_avoidance; } void set_velocity(const Vector3 p_velocity); - Vector3 get_velocity() const { return velocity; }; + Vector3 get_velocity() const { return velocity; } void _avoidance_done(Vector3 p_new_velocity); // Dummy @@ -117,9 +116,12 @@ public: void set_carve_navigation_mesh(bool p_enabled); bool get_carve_navigation_mesh() const; + PackedStringArray get_configuration_warnings() const override; + private: void _update_map(RID p_map); void _update_position(const Vector3 p_position); + void _update_transform(); void _update_use_3d_avoidance(bool p_use_3d_avoidance); }; diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index c0c254e7ed..2d67e4334e 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -492,8 +492,8 @@ void NavigationRegion3D::_update_debug_mesh() { debug_instance = RenderingServer::get_singleton()->instance_create(); } - if (!debug_mesh.is_valid()) { - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (debug_mesh.is_null()) { + debug_mesh.instantiate(); } debug_mesh->clear_surfaces(); @@ -669,8 +669,8 @@ void NavigationRegion3D::_update_debug_edge_connections_mesh() { debug_edge_connections_instance = RenderingServer::get_singleton()->instance_create(); } - if (!debug_edge_connections_mesh.is_valid()) { - debug_edge_connections_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (debug_edge_connections_mesh.is_null()) { + debug_edge_connections_mesh.instantiate(); } debug_edge_connections_mesh->clear_surfaces(); diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 217ee28cf1..20288fad3a 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -233,8 +233,8 @@ public: #ifdef TOOLS_ENABLED virtual Transform3D get_global_gizmo_transform() const; virtual Transform3D get_local_gizmo_transform() const; - virtual void set_transform_gizmo_visible(bool p_enabled) { data.transform_gizmo_visible = p_enabled; }; - virtual bool is_transform_gizmo_visible() const { return data.transform_gizmo_visible; }; + virtual void set_transform_gizmo_visible(bool p_enabled) { data.transform_gizmo_visible = p_enabled; } + virtual bool is_transform_gizmo_visible() const { return data.transform_gizmo_visible; } #endif virtual void reparent(Node *p_parent, bool p_keep_global_transform = true) override; diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index 64259a24b0..00c83101b9 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -88,8 +88,8 @@ void Path3D::_update_debug_mesh() { return; } - if (!debug_mesh.is_valid()) { - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (debug_mesh.is_null()) { + debug_mesh.instantiate(); } if (!(curve.is_valid())) { diff --git a/scene/3d/physics/ray_cast_3d.cpp b/scene/3d/physics/ray_cast_3d.cpp index a9272388c1..b9159f072b 100644 --- a/scene/3d/physics/ray_cast_3d.cpp +++ b/scene/3d/physics/ray_cast_3d.cpp @@ -464,7 +464,7 @@ void RayCast3D::_create_debug_shape() { } if (debug_mesh.is_null()) { - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + debug_mesh.instantiate(); } } diff --git a/scene/3d/physics/rigid_body_3d.cpp b/scene/3d/physics/rigid_body_3d.cpp index 275e8cd7a9..6c8cea1ac3 100644 --- a/scene/3d/physics/rigid_body_3d.cpp +++ b/scene/3d/physics/rigid_body_3d.cpp @@ -659,7 +659,7 @@ void RigidBody3D::_reload_physics_characteristics() { } PackedStringArray RigidBody3D::get_configuration_warnings() const { - PackedStringArray warnings = CollisionObject3D::get_configuration_warnings(); + PackedStringArray warnings = PhysicsBody3D::get_configuration_warnings(); Vector3 scale = get_transform().get_basis().get_scale(); if (ABS(scale.x - 1.0) > 0.05 || ABS(scale.y - 1.0) > 0.05 || ABS(scale.z - 1.0) > 0.05) { diff --git a/scene/3d/physics/shape_cast_3d.cpp b/scene/3d/physics/shape_cast_3d.cpp index 8ad651fdf5..19c74bc925 100644 --- a/scene/3d/physics/shape_cast_3d.cpp +++ b/scene/3d/physics/shape_cast_3d.cpp @@ -546,7 +546,7 @@ void ShapeCast3D::_create_debug_shape() { } if (debug_mesh.is_null()) { - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + debug_mesh.instantiate(); } } diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index c1c992588b..b51d8a3438 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -183,17 +183,17 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const { void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const { for (uint32_t i = 0; i < bones.size(); i++) { - const String prep = vformat("%s/%d/", PNAME("bones"), i); - p_list->push_back(PropertyInfo(Variant::STRING, prep + PNAME("name"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, prep + PNAME("parent"), PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + PNAME("rest"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, prep + PNAME("enabled"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + PNAME("position"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + PNAME("rotation"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + PNAME("scale"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + const String prep = vformat("%s/%d/", "bones", i); + p_list->push_back(PropertyInfo(Variant::STRING, prep + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); for (const KeyValue<StringName, Variant> &K : bones[i].metadata) { - PropertyInfo pi = PropertyInfo(bones[i].metadata[K.key].get_type(), prep + PNAME("bone_meta/") + K.key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); + PropertyInfo pi = PropertyInfo(bones[i].metadata[K.key].get_type(), prep + "bone_meta/" + K.key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); p_list->push_back(pi); } } @@ -1032,6 +1032,10 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { return skin_ref; } +void Skeleton3D::force_update_deferred() { + _make_dirty(); +} + void Skeleton3D::force_update_all_dirty_bones() { if (!dirty) { return; diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 0db12600c3..6c51c172af 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -31,6 +31,7 @@ #ifndef SKELETON_3D_H #define SKELETON_3D_H +#include "core/templates/a_hash_map.h" #include "scene/3d/node_3d.h" #include "scene/resources/3d/skin.h" @@ -159,9 +160,9 @@ private: bool process_order_dirty = false; Vector<int> parentless_bones; - HashMap<String, int> name_to_bone_index; + AHashMap<String, int> name_to_bone_index; - mutable StringName concatenated_bone_names = StringName(); + mutable StringName concatenated_bone_names; void _update_bone_names() const; void _make_dirty(); @@ -283,6 +284,7 @@ public: void force_update_all_dirty_bones(); void force_update_all_bone_transforms(); void force_update_bone_children_transforms(int bone_idx); + void force_update_deferred(); void set_modifier_callback_mode_process(ModifierCallbackModeProcess p_mode); ModifierCallbackModeProcess get_modifier_callback_mode_process() const; diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h index 5d6020194e..94145a6915 100644 --- a/scene/3d/skeleton_ik_3d.h +++ b/scene/3d/skeleton_ik_3d.h @@ -131,7 +131,7 @@ class SkeletonIK3D : public SkeletonModifier3D { real_t min_distance = 0.01; int max_iterations = 10; - Variant target_node_override_ref = Variant(); + Variant target_node_override_ref; FabrikInverseKinematic::Task *task = nullptr; #ifndef DISABLE_DEPRECATED diff --git a/scene/3d/skeleton_modifier_3d.cpp b/scene/3d/skeleton_modifier_3d.cpp index d5c603112e..e8a8e517a2 100644 --- a/scene/3d/skeleton_modifier_3d.cpp +++ b/scene/3d/skeleton_modifier_3d.cpp @@ -75,6 +75,17 @@ void SkeletonModifier3D::_skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) // } +void SkeletonModifier3D::_force_update_skeleton_skin() { + if (!is_inside_tree()) { + return; + } + Skeleton3D *skeleton = get_skeleton(); + if (!skeleton) { + return; + } + skeleton->force_update_deferred(); +} + /* Process */ void SkeletonModifier3D::set_active(bool p_active) { @@ -83,6 +94,7 @@ void SkeletonModifier3D::set_active(bool p_active) { } active = p_active; _set_active(active); + _force_update_skeleton_skin(); } bool SkeletonModifier3D::is_active() const { @@ -119,6 +131,10 @@ void SkeletonModifier3D::_notification(int p_what) { case NOTIFICATION_PARENTED: { _update_skeleton(); } break; + case NOTIFICATION_EXIT_TREE: + case NOTIFICATION_UNPARENTED: { + _force_update_skeleton_skin(); + } break; } } diff --git a/scene/3d/skeleton_modifier_3d.h b/scene/3d/skeleton_modifier_3d.h index d00a1e94a9..728b000ff5 100644 --- a/scene/3d/skeleton_modifier_3d.h +++ b/scene/3d/skeleton_modifier_3d.h @@ -50,6 +50,7 @@ protected: void _update_skeleton(); void _update_skeleton_path(); + void _force_update_skeleton_skin(); virtual void _skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 42460eec4c..6e3ada83ad 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -470,7 +470,7 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const { facesw[j] = vtx; } - triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh.instantiate(); triangle_mesh->create(faces); return triangle_mesh; diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index a59754c8cc..2c7a004dd0 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -454,14 +454,48 @@ AABB GeometryInstance3D::get_custom_aabb() const { return custom_aabb; } +void GeometryInstance3D::set_lightmap_texel_scale(float p_scale) { + lightmap_texel_scale = p_scale; +} + +float GeometryInstance3D::get_lightmap_texel_scale() const { + return lightmap_texel_scale; +} + +#ifndef DISABLE_DEPRECATED void GeometryInstance3D::set_lightmap_scale(LightmapScale p_scale) { ERR_FAIL_INDEX(p_scale, LIGHTMAP_SCALE_MAX); - lightmap_scale = p_scale; + switch (p_scale) { + case GeometryInstance3D::LIGHTMAP_SCALE_1X: + lightmap_texel_scale = 1.0f; + break; + case GeometryInstance3D::LIGHTMAP_SCALE_2X: + lightmap_texel_scale = 2.0f; + break; + case GeometryInstance3D::LIGHTMAP_SCALE_4X: + lightmap_texel_scale = 4.0f; + break; + case GeometryInstance3D::LIGHTMAP_SCALE_8X: + lightmap_texel_scale = 8.0f; + break; + case GeometryInstance3D::LIGHTMAP_SCALE_MAX: + break; // Can't happen, but silences warning. + } } GeometryInstance3D::LightmapScale GeometryInstance3D::get_lightmap_scale() const { - return lightmap_scale; + // Return closest approximation. + if (lightmap_texel_scale < 1.5f) { + return GeometryInstance3D::LIGHTMAP_SCALE_1X; + } else if (lightmap_texel_scale < 3.0f) { + return GeometryInstance3D::LIGHTMAP_SCALE_2X; + } else if (lightmap_texel_scale < 6.0f) { + return GeometryInstance3D::LIGHTMAP_SCALE_4X; + } + + return GeometryInstance3D::LIGHTMAP_SCALE_8X; } +#endif // DISABLE_DEPRECATED void GeometryInstance3D::set_gi_mode(GIMode p_mode) { switch (p_mode) { @@ -565,8 +599,13 @@ void GeometryInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance3D::set_extra_cull_margin); ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance3D::get_extra_cull_margin); + ClassDB::bind_method(D_METHOD("set_lightmap_texel_scale", "scale"), &GeometryInstance3D::set_lightmap_texel_scale); + ClassDB::bind_method(D_METHOD("get_lightmap_texel_scale"), &GeometryInstance3D::get_lightmap_texel_scale); + +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_lightmap_scale", "scale"), &GeometryInstance3D::set_lightmap_scale); ClassDB::bind_method(D_METHOD("get_lightmap_scale"), &GeometryInstance3D::get_lightmap_scale); +#endif // DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_gi_mode", "mode"), &GeometryInstance3D::set_gi_mode); ClassDB::bind_method(D_METHOD("get_gi_mode"), &GeometryInstance3D::get_gi_mode); @@ -591,7 +630,10 @@ void GeometryInstance3D::_bind_methods() { ADD_GROUP("Global Illumination", "gi_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Static,Dynamic"), "set_gi_mode", "get_gi_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×")), "set_lightmap_scale", "get_lightmap_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gi_lightmap_texel_scale", PROPERTY_HINT_RANGE, "0.01,10,0.0001,or_greater"), "set_lightmap_texel_scale", "get_lightmap_texel_scale"); +#ifndef DISABLE_DEPRECATED + ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×"), PROPERTY_USAGE_NONE), "set_lightmap_scale", "get_lightmap_scale"); +#endif // DISABLE_DEPRECATED ADD_GROUP("Visibility Range", "visibility_range_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_begin", "get_visibility_range_begin"); diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index 9b02c928b7..073fa74573 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -134,7 +134,7 @@ private: float extra_cull_margin = 0.0; AABB custom_aabb; - LightmapScale lightmap_scale = LIGHTMAP_SCALE_1X; + float lightmap_texel_scale = 1.0f; GIMode gi_mode = GI_MODE_STATIC; bool ignore_occlusion_culling = false; @@ -185,8 +185,13 @@ public: void set_gi_mode(GIMode p_mode); GIMode get_gi_mode() const; - void set_lightmap_scale(LightmapScale p_scale); + void set_lightmap_texel_scale(float p_scale); + float get_lightmap_texel_scale() const; + +#ifndef DISABLE_DEPRECATED + void set_lightmap_scale(GeometryInstance3D::LightmapScale p_scale); LightmapScale get_lightmap_scale() const; +#endif // DISABLE_DEPRECATED void set_instance_shader_parameter(const StringName &p_name, const Variant &p_value); Variant get_instance_shader_parameter(const StringName &p_name) const; @@ -203,8 +208,8 @@ public: }; VARIANT_ENUM_CAST(GeometryInstance3D::ShadowCastingSetting); -VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale); VARIANT_ENUM_CAST(GeometryInstance3D::GIMode); +VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale); VARIANT_ENUM_CAST(GeometryInstance3D::VisibilityRangeFadeMode); #endif // VISUAL_INSTANCE_3D_H diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 214c1f77ca..9869b241d3 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -89,7 +89,7 @@ PackedStringArray XRCamera3D::get_configuration_warnings() const { } return warnings; -}; +} Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const { // get our XRServer @@ -114,7 +114,7 @@ Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const { ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -get_near()).normalized(); return ray; -}; +} Point2 XRCamera3D::unproject_position(const Vector3 &p_pos) const { // get our XRServer @@ -144,7 +144,7 @@ Point2 XRCamera3D::unproject_position(const Vector3 &p_pos) const { res.y = (-p.normal.y * 0.5 + 0.5) * viewport_size.y; return res; -}; +} Vector3 XRCamera3D::project_position(const Point2 &p_point, real_t p_z_depth) const { // get our XRServer @@ -174,7 +174,7 @@ Vector3 XRCamera3D::project_position(const Point2 &p_point, real_t p_z_depth) co Vector3 p(point.x, point.y, -p_z_depth); return get_camera_transform().xform(p); -}; +} Vector<Plane> XRCamera3D::get_frustum() const { // get our XRServer @@ -193,7 +193,7 @@ Vector<Plane> XRCamera3D::get_frustum() const { // TODO Just use the first view for now, this is mostly for debugging so we may look into using our combined projection here. Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); return cm.get_projection_planes(get_camera_transform()); -}; +} XRCamera3D::XRCamera3D() { XRServer *xr_server = XRServer::get_singleton(); @@ -240,7 +240,7 @@ void XRNode3D::_bind_methods() { ClassDB::bind_method(D_METHOD("trigger_haptic_pulse", "action_name", "frequency", "amplitude", "duration_sec", "delay_sec"), &XRNode3D::trigger_haptic_pulse); ADD_SIGNAL(MethodInfo("tracking_changed", PropertyInfo(Variant::BOOL, "tracking"))); -}; +} void XRNode3D::_validate_property(PropertyInfo &p_property) const { XRServer *xr_server = XRServer::get_singleton(); @@ -499,7 +499,7 @@ void XRController3D::_bind_methods() { ADD_SIGNAL(MethodInfo("input_float_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value"))); ADD_SIGNAL(MethodInfo("input_vector2_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "value"))); ADD_SIGNAL(MethodInfo("profile_changed", PropertyInfo(Variant::STRING, "role"))); -}; +} void XRController3D::_bind_tracker() { XRNode3D::_bind_tracker(); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index a2aef60417..d0773fc83f 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -93,7 +93,9 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::process(const AnimationMixer AnimationMixer::PlaybackInfo pi = p_playback_info; if (p_playback_info.seeked) { - pi.delta = get_node_time_info().position - p_playback_info.time; + if (p_playback_info.is_external_seeking) { + pi.delta = get_node_time_info().position - p_playback_info.time; + } } else { pi.time = get_node_time_info().position + (backward ? -p_playback_info.delta : p_playback_info.delta); } @@ -140,6 +142,12 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe // 1. Progress for AnimationNode. bool will_end = Animation::is_greater_or_equal_approx(cur_time + cur_delta, cur_len); + bool is_started = p_seek && !p_is_external_seeking && Math::is_zero_approx(cur_time); + + // 1. Progress for AnimationNode. + if (is_started && advance_on_start) { + cur_time = cur_delta; + } if (cur_loop_mode != Animation::LOOP_NONE) { if (cur_loop_mode == Animation::LOOP_LINEAR) { if (!Math::is_zero_approx(cur_len)) { @@ -232,7 +240,7 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe // We should use call_deferred since the track keys are still being processed. if (process_state->tree && !p_test_only) { // AnimationTree uses seek to 0 "internally" to process the first key of the animation, which is used as the start detection. - if (p_seek && !p_is_external_seeking && Math::is_zero_approx(cur_playback_time)) { + if (is_started) { process_state->tree->call_deferred(SNAME("emit_signal"), SceneStringName(animation_started), animation); } // Finished. @@ -282,6 +290,14 @@ bool AnimationNodeAnimation::is_backward() const { return backward; } +void AnimationNodeAnimation::set_advance_on_start(bool p_advance_on_start) { + advance_on_start = p_advance_on_start; +} + +bool AnimationNodeAnimation::is_advance_on_start() const { + return advance_on_start; +} + void AnimationNodeAnimation::set_use_custom_timeline(bool p_use_custom_timeline) { use_custom_timeline = p_use_custom_timeline; notify_property_list_changed(); @@ -331,6 +347,9 @@ void AnimationNodeAnimation::_bind_methods() { ClassDB::bind_method(D_METHOD("set_play_mode", "mode"), &AnimationNodeAnimation::set_play_mode); ClassDB::bind_method(D_METHOD("get_play_mode"), &AnimationNodeAnimation::get_play_mode); + ClassDB::bind_method(D_METHOD("set_advance_on_start", "advance_on_start"), &AnimationNodeAnimation::set_advance_on_start); + ClassDB::bind_method(D_METHOD("is_advance_on_start"), &AnimationNodeAnimation::is_advance_on_start); + ClassDB::bind_method(D_METHOD("set_use_custom_timeline", "use_custom_timeline"), &AnimationNodeAnimation::set_use_custom_timeline); ClassDB::bind_method(D_METHOD("is_using_custom_timeline"), &AnimationNodeAnimation::is_using_custom_timeline); @@ -348,6 +367,7 @@ void AnimationNodeAnimation::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation"); ADD_PROPERTY(PropertyInfo(Variant::INT, "play_mode", PROPERTY_HINT_ENUM, "Forward,Backward"), "set_play_mode", "get_play_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "advance_on_start"), "set_advance_on_start", "is_advance_on_start"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_custom_timeline"), "set_use_custom_timeline", "is_using_custom_timeline"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "timeline_length", PROPERTY_HINT_RANGE, "0.001,60,0.001,or_greater,or_less,hide_slider,suffix:s"), "set_timeline_length", "get_timeline_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stretch_time_scale"), "set_stretch_time_scale", "is_stretching_time_scale"); @@ -983,6 +1003,14 @@ String AnimationNodeTimeSeek::get_caption() const { return "TimeSeek"; } +void AnimationNodeTimeSeek::set_explicit_elapse(bool p_enable) { + explicit_elapse = p_enable; +} + +bool AnimationNodeTimeSeek::is_explicit_elapse() const { + return explicit_elapse; +} + AnimationNode::NodeTimeInfo AnimationNodeTimeSeek::_process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { double cur_seek_pos = get_parameter(seek_pos_request); @@ -991,7 +1019,7 @@ AnimationNode::NodeTimeInfo AnimationNodeTimeSeek::_process(const AnimationMixer if (Animation::is_greater_or_equal_approx(cur_seek_pos, 0)) { pi.time = cur_seek_pos; pi.seeked = true; - pi.is_external_seeking = true; + pi.is_external_seeking = explicit_elapse; set_parameter(seek_pos_request, -1.0); // Reset. } @@ -1002,6 +1030,12 @@ AnimationNodeTimeSeek::AnimationNodeTimeSeek() { add_input("in"); } +void AnimationNodeTimeSeek::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_explicit_elapse", "enable"), &AnimationNodeTimeSeek::set_explicit_elapse); + ClassDB::bind_method(D_METHOD("is_explicit_elapse"), &AnimationNodeTimeSeek::is_explicit_elapse); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "explicit_elapse"), "set_explicit_elapse", "is_explicit_elapse"); +} + ///////////////////////////////////////////////// bool AnimationNodeTransition::_set(const StringName &p_path, const Variant &p_value) { diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 2add35d009..c48d799eea 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -38,6 +38,8 @@ class AnimationNodeAnimation : public AnimationRootNode { StringName animation; + bool advance_on_start = false; + bool use_custom_timeline = false; double timeline_length = 1.0; Animation::LoopMode loop_mode = Animation::LOOP_NONE; @@ -72,6 +74,9 @@ public: void set_backward(bool p_backward); bool is_backward() const; + void set_advance_on_start(bool p_advance_on_start); + bool is_advance_on_start() const; + void set_use_custom_timeline(bool p_use_custom_timeline); bool is_using_custom_timeline() const; @@ -297,6 +302,10 @@ class AnimationNodeTimeSeek : public AnimationNode { GDCLASS(AnimationNodeTimeSeek, AnimationNode); StringName seek_pos_request = PNAME("seek_request"); + bool explicit_elapse = true; + +protected: + static void _bind_methods(); public: virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; @@ -306,6 +315,9 @@ public: virtual NodeTimeInfo _process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only = false) override; + void set_explicit_elapse(bool p_enable); + bool is_explicit_elapse() const; + AnimationNodeTimeSeek(); }; diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp index eb8bc8c382..3e09e425b0 100644 --- a/scene/animation/animation_mixer.cpp +++ b/scene/animation/animation_mixer.cpp @@ -33,6 +33,8 @@ #include "core/config/engine.h" #include "core/config/project_settings.h" +#include "core/string/print_string.h" +#include "core/string/string_name.h" #include "scene/2d/audio_stream_player_2d.h" #include "scene/animation/animation_player.h" #include "scene/audio/audio_stream_player.h" @@ -127,6 +129,9 @@ void AnimationMixer::_validate_property(PropertyInfo &p_property) const { p_property.usage |= PROPERTY_USAGE_READ_ONLY; } #endif // TOOLS_ENABLED + if (root_motion_track.is_empty() && p_property.name == "root_motion_local") { + p_property.usage = PROPERTY_USAGE_NONE; + } } /* -------------------------------------------- */ @@ -267,6 +272,16 @@ bool AnimationMixer::has_animation_library(const StringName &p_name) const { return false; } +StringName AnimationMixer::get_animation_library_name(const Ref<AnimationLibrary> &p_animation_library) const { + ERR_FAIL_COND_V(p_animation_library.is_null(), StringName()); + for (const AnimationLibraryData &lib : animation_libraries) { + if (lib.library == p_animation_library) { + return lib.name; + } + } + return StringName(); +} + StringName AnimationMixer::find_animation_library(const Ref<Animation> &p_animation) const { for (const KeyValue<StringName, AnimationData> &E : animation_set) { if (E.value.animation == p_animation) { @@ -563,6 +578,7 @@ void AnimationMixer::_clear_caches() { memdelete(K.value); } track_cache.clear(); + animation_track_num_to_track_cashe.clear(); cache_valid = false; capture_cache.clear(); @@ -599,6 +615,22 @@ void AnimationMixer::_init_root_motion_cache() { root_motion_scale_accumulator = Vector3(1, 1, 1); } +void AnimationMixer::_create_track_num_to_track_cashe_for_animation(Ref<Animation> &p_animation) { + ERR_FAIL_COND(animation_track_num_to_track_cashe.has(p_animation)); + LocalVector<TrackCache *> &track_num_to_track_cashe = animation_track_num_to_track_cashe.insert_new(p_animation, LocalVector<TrackCache *>())->value; + const Vector<Animation::Track *> &tracks = p_animation->get_tracks(); + + track_num_to_track_cashe.resize(tracks.size()); + for (int i = 0; i < tracks.size(); i++) { + TrackCache **track_ptr = track_cache.getptr(tracks[i]->thash); + if (track_ptr == nullptr) { + track_num_to_track_cashe[i] = nullptr; + } else { + track_num_to_track_cashe[i] = *track_ptr; + } + } +} + bool AnimationMixer::_update_caches() { setup_pass++; @@ -716,6 +748,15 @@ bool AnimationMixer::_update_caches() { } } + if (is_value && callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS) { + if (child) { + PropertyInfo prop_info; + ClassDB::get_property_info(child->get_class_name(), path.get_concatenated_subnames(), &prop_info); + if (prop_info.hint == PROPERTY_HINT_ONESHOT) { + WARN_PRINT_ED(vformat("%s: '%s', Value Track: '%s' is oneshot property, but will be continuously updated. Consider setting a value other than ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS to AnimationMixer.callback_mode_dominant.", mixer_name, String(E), String(path))); + } + } + } } break; case Animation::TYPE_POSITION_3D: case Animation::TYPE_ROTATION_3D: @@ -922,6 +963,16 @@ bool AnimationMixer::_update_caches() { idx++; } + for (KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) { + K.value->blend_idx = track_map[K.value->path]; + } + + animation_track_num_to_track_cashe.clear(); + for (const StringName &E : sname_list) { + Ref<Animation> anim = get_animation(E); + _create_track_num_to_track_cashe_for_animation(anim); + } + track_count = idx; cache_valid = true; @@ -946,7 +997,7 @@ void AnimationMixer::_process_animation(double p_delta, bool p_update_only) { clear_animation_instances(); } -Variant AnimationMixer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx) { +Variant AnimationMixer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant &p_value, ObjectID p_object_id, int p_object_sub_idx) { #ifndef _3D_DISABLED switch (p_anim->track_get_type(p_track)) { case Animation::TYPE_POSITION_3D: { @@ -1033,7 +1084,7 @@ void AnimationMixer::_blend_init() { } } -bool AnimationMixer::_blend_pre_process(double p_delta, int p_track_count, const HashMap<NodePath, int> &p_track_map) { +bool AnimationMixer::_blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) { return true; } @@ -1052,6 +1103,9 @@ void AnimationMixer::blend_capture(double p_delta) { capture_cache.remain -= p_delta * capture_cache.step; if (Animation::is_less_or_equal_approx(capture_cache.remain, 0)) { + if (capture_cache.animation.is_valid()) { + animation_track_num_to_track_cashe.erase(capture_cache.animation); + } capture_cache.clear(); return; } @@ -1084,26 +1138,30 @@ void AnimationMixer::_blend_calc_total_weight() { real_t weight = ai.playback_info.weight; const real_t *track_weights_ptr = ai.playback_info.track_weights.ptr(); int track_weights_count = ai.playback_info.track_weights.size(); - static LocalVector<Animation::TypeHash> processed_hashes; + ERR_CONTINUE_EDMSG(!animation_track_num_to_track_cashe.has(a), "No animation in cache."); + LocalVector<TrackCache *> &track_num_to_track_cashe = animation_track_num_to_track_cashe[a]; + thread_local HashSet<Animation::TypeHash, HashHasher> processed_hashes; processed_hashes.clear(); const Vector<Animation::Track *> tracks = a->get_tracks(); - for (const Animation::Track *animation_track : tracks) { + Animation::Track *const *tracks_ptr = tracks.ptr(); + int count = tracks.size(); + for (int i = 0; i < count; i++) { + Animation::Track *animation_track = tracks_ptr[i]; if (!animation_track->enabled) { continue; } Animation::TypeHash thash = animation_track->thash; - TrackCache **track_ptr = track_cache.getptr(thash); - if (track_ptr == nullptr || processed_hashes.has(thash)) { + TrackCache *track = track_num_to_track_cashe[i]; + if (track == nullptr || processed_hashes.has(thash)) { // No path, but avoid error spamming. // Or, there is the case different track type with same path; These can be distinguished by hash. So don't add the weight doubly. continue; } - TrackCache *track = *track_ptr; - int blend_idx = track_map[track->path]; + int blend_idx = track->blend_idx; ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count); real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight; track->total_weight += blend; - processed_hashes.push_back(thash); + processed_hashes.insert(thash); } } } @@ -1130,6 +1188,8 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { #ifndef _3D_DISABLED bool calc_root = !seeked || is_external_seeking; #endif // _3D_DISABLED + ERR_CONTINUE_EDMSG(!animation_track_num_to_track_cashe.has(a), "No animation in cache."); + LocalVector<TrackCache *> &track_num_to_track_cashe = animation_track_num_to_track_cashe[a]; const Vector<Animation::Track *> tracks = a->get_tracks(); Animation::Track *const *tracks_ptr = tracks.ptr(); real_t a_length = a->get_length(); @@ -1139,15 +1199,11 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (!animation_track->enabled) { continue; } - Animation::TypeHash thash = animation_track->thash; - TrackCache **track_ptr = track_cache.getptr(thash); - if (track_ptr == nullptr) { + TrackCache *track = track_num_to_track_cashe[i]; + if (track == nullptr) { continue; // No path, but avoid error spamming. } - TrackCache *track = *track_ptr; - int *blend_idx_ptr = track_map.getptr(track->path); - ERR_CONTINUE(blend_idx_ptr == nullptr); - int blend_idx = *blend_idx_ptr; + int blend_idx = track->blend_idx; ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count); real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight; if (!deterministic) { @@ -1168,6 +1224,10 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); if (track->root_motion && calc_root) { + int rot_track = -1; + if (root_motion_local) { + rot_track = a->find_track(a->track_get_path(i), Animation::TYPE_ROTATION_3D); + } double prev_time = time - delta; if (!backward) { if (Animation::is_less_approx(prev_time, start)) { @@ -1202,41 +1262,92 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } } } - Vector3 loc[2]; - if (!backward) { - if (Animation::is_greater_approx(prev_time, time)) { - Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); - if (err != OK) { - continue; + if (rot_track >= 0) { + Vector3 loc[2]; + Quaternion rot; + if (!backward) { + if (Animation::is_greater_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, end, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + + a->try_rotation_track_interpolate(rot_track, end, &rot); + rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx); + + root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend; + prev_time = start; } - loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); - a->try_position_track_interpolate(i, end, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); - root_motion_cache.loc += (loc[1] - loc[0]) * blend; - prev_time = start; + } else { + if (Animation::is_less_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, start, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + + a->try_rotation_track_interpolate(rot_track, start, &rot); + rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx); + + root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend; + prev_time = end; + } + } + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, time, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + + a->try_rotation_track_interpolate(rot_track, time, &rot); + rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx); + + root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend; + prev_time = !backward ? start : end; } else { - if (Animation::is_less_approx(prev_time, time)) { - Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); - if (err != OK) { - continue; + Vector3 loc[2]; + if (!backward) { + if (Animation::is_greater_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, end, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + root_motion_cache.loc += (loc[1] - loc[0]) * blend; + prev_time = start; + } + } else { + if (Animation::is_less_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, start, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + root_motion_cache.loc += (loc[1] - loc[0]) * blend; + prev_time = end; } - loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); - a->try_position_track_interpolate(i, start, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); - root_motion_cache.loc += (loc[1] - loc[0]) * blend; - prev_time = end; } + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, time, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + root_motion_cache.loc += (loc[1] - loc[0]) * blend; + prev_time = !backward ? start : end; } - Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); - if (err != OK) { - continue; - } - loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); - a->try_position_track_interpolate(i, time, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); - root_motion_cache.loc += (loc[1] - loc[0]) * blend; - prev_time = !backward ? start : end; } { Vector3 loc; @@ -1311,6 +1422,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx); a->try_rotation_track_interpolate(i, start, &rot[1]); + rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx); root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = end; } @@ -1386,8 +1498,8 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx); a->try_scale_track_interpolate(i, end, &scale[1]); - root_motion_cache.scale += (scale[1] - scale[0]) * blend; scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx); + root_motion_cache.scale += (scale[1] - scale[0]) * blend; prev_time = start; } } else { @@ -1581,7 +1693,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { track_info.loop = a->get_loop_mode() != Animation::LOOP_NONE; track_info.backward = backward; track_info.use_blend = a->audio_track_is_use_blend(i); - HashMap<int, PlayingAudioStreamInfo> &map = track_info.stream_info; + AHashMap<int, PlayingAudioStreamInfo> &map = track_info.stream_info; // Main process to fire key is started from here. if (p_update_only) { @@ -1850,7 +1962,7 @@ void AnimationMixer::_blend_apply() { PlayingAudioTrackInfo &track_info = L.value; float db = Math::linear_to_db(track_info.use_blend ? track_info.volume : 1.0); LocalVector<int> erase_streams; - HashMap<int, PlayingAudioStreamInfo> &map = track_info.stream_info; + AHashMap<int, PlayingAudioStreamInfo> &map = track_info.stream_info; for (const KeyValue<int, PlayingAudioStreamInfo> &M : map) { PlayingAudioStreamInfo pasi = M.value; @@ -1958,12 +2070,21 @@ void AnimationMixer::clear_caches() { void AnimationMixer::set_root_motion_track(const NodePath &p_track) { root_motion_track = p_track; + notify_property_list_changed(); } NodePath AnimationMixer::get_root_motion_track() const { return root_motion_track; } +void AnimationMixer::set_root_motion_local(bool p_enabled) { + root_motion_local = p_enabled; +} + +bool AnimationMixer::is_root_motion_local() const { + return root_motion_local; +} + Vector3 AnimationMixer::get_root_motion_position() const { return root_motion_position; } @@ -2134,7 +2255,7 @@ void AnimationMixer::restore(const Ref<AnimatedValuesBackup> &p_backup) { ERR_FAIL_COND(p_backup.is_null()); track_cache = p_backup->get_data(); _blend_apply(); - track_cache = HashMap<Animation::TypeHash, AnimationMixer::TrackCache *>(); + track_cache = AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher>(); cache_valid = false; } @@ -2181,6 +2302,9 @@ void AnimationMixer::capture(const StringName &p_name, double p_duration, Tween: capture_cache.step = 1.0 / p_duration; capture_cache.trans_type = p_trans_type; capture_cache.ease_type = p_ease_type; + if (capture_cache.animation.is_valid()) { + animation_track_num_to_track_cashe.erase(capture_cache.animation); + } capture_cache.animation.instantiate(); bool is_valid = false; @@ -2204,6 +2328,8 @@ void AnimationMixer::capture(const StringName &p_name, double p_duration, Tween: } if (!is_valid) { capture_cache.clear(); + } else { + _create_track_num_to_track_cashe_for_animation(capture_cache.animation); } } @@ -2304,6 +2430,8 @@ void AnimationMixer::_bind_methods() { /* ---- Root motion accumulator for Skeleton3D ---- */ ClassDB::bind_method(D_METHOD("set_root_motion_track", "path"), &AnimationMixer::set_root_motion_track); ClassDB::bind_method(D_METHOD("get_root_motion_track"), &AnimationMixer::get_root_motion_track); + ClassDB::bind_method(D_METHOD("set_root_motion_local", "enabled"), &AnimationMixer::set_root_motion_local); + ClassDB::bind_method(D_METHOD("is_root_motion_local"), &AnimationMixer::is_root_motion_local); ClassDB::bind_method(D_METHOD("get_root_motion_position"), &AnimationMixer::get_root_motion_position); ClassDB::bind_method(D_METHOD("get_root_motion_rotation"), &AnimationMixer::get_root_motion_rotation); @@ -2331,6 +2459,7 @@ void AnimationMixer::_bind_methods() { ADD_GROUP("Root Motion", "root_motion_"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_motion_track"), "set_root_motion_track", "get_root_motion_track"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "root_motion_local"), "set_root_motion_local", "is_root_motion_local"); ADD_GROUP("Audio", "audio_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "audio_max_polyphony", PROPERTY_HINT_RANGE, "1,127,1"), "set_audio_max_polyphony", "get_audio_max_polyphony"); @@ -2370,7 +2499,7 @@ AnimationMixer::AnimationMixer() { AnimationMixer::~AnimationMixer() { } -void AnimatedValuesBackup::set_data(const HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> p_data) { +void AnimatedValuesBackup::set_data(const AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher> p_data) { clear_data(); for (const KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &E : p_data) { @@ -2383,7 +2512,7 @@ void AnimatedValuesBackup::set_data(const HashMap<Animation::TypeHash, Animation } } -HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> AnimatedValuesBackup::get_data() const { +AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher> AnimatedValuesBackup::get_data() const { HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> ret; for (const KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &E : data) { AnimationMixer::TrackCache *track = get_cache_copy(E.value); diff --git a/scene/animation/animation_mixer.h b/scene/animation/animation_mixer.h index 27c9a00a9c..82deccaa95 100644 --- a/scene/animation/animation_mixer.h +++ b/scene/animation/animation_mixer.h @@ -31,6 +31,7 @@ #ifndef ANIMATION_MIXER_H #define ANIMATION_MIXER_H +#include "core/templates/a_hash_map.h" #include "scene/animation/tween.h" #include "scene/main/node.h" #include "scene/resources/animation.h" @@ -102,7 +103,7 @@ public: protected: /* ---- Data lists ---- */ LocalVector<AnimationLibraryData> animation_libraries; - HashMap<StringName, AnimationData> animation_set; // HashMap<Library name + Animation name, AnimationData> + AHashMap<StringName, AnimationData> animation_set; // HashMap<Library name + Animation name, AnimationData> TypedArray<StringName> _get_animation_library_list() const; Vector<String> _get_animation_list() const { @@ -148,6 +149,7 @@ protected: uint64_t setup_pass = 0; Animation::TrackType type = Animation::TrackType::TYPE_ANIMATION; NodePath path; + int blend_idx = -1; ObjectID object_id; real_t total_weight = 0.0; @@ -269,7 +271,7 @@ protected: // Audio track information for mixng and ending. struct PlayingAudioTrackInfo { - HashMap<int, PlayingAudioStreamInfo> stream_info; + AHashMap<int, PlayingAudioStreamInfo> stream_info; double length = 0.0; double time = 0.0; real_t volume = 0.0; @@ -308,7 +310,8 @@ protected: }; RootMotionCache root_motion_cache; - HashMap<Animation::TypeHash, TrackCache *> track_cache; + AHashMap<Animation::TypeHash, TrackCache *, HashHasher> track_cache; + AHashMap<Ref<Animation>, LocalVector<TrackCache *>> animation_track_num_to_track_cashe; HashSet<TrackCache *> playing_caches; Vector<Node *> playing_audio_stream_players; @@ -318,18 +321,20 @@ protected: void _clear_playing_caches(); void _init_root_motion_cache(); bool _update_caches(); + void _create_track_num_to_track_cashe_for_animation(Ref<Animation> &p_animation); /* ---- Audio ---- */ AudioServer::PlaybackType playback_type; /* ---- Blending processor ---- */ LocalVector<AnimationInstance> animation_instances; - HashMap<NodePath, int> track_map; + AHashMap<NodePath, int> track_map; int track_count = 0; bool deterministic = false; /* ---- Root motion accumulator for Skeleton3D ---- */ NodePath root_motion_track; + bool root_motion_local = false; Vector3 root_motion_position = Vector3(0, 0, 0); Quaternion root_motion_rotation = Quaternion(0, 0, 0, 1); Vector3 root_motion_scale = Vector3(0, 0, 0); @@ -359,12 +364,12 @@ protected: virtual void _process_animation(double p_delta, bool p_update_only = false); // For post process with retrieved key value during blending. - virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx = -1); + virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant &p_value, ObjectID p_object_id, int p_object_sub_idx = -1); Variant post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx = -1); GDVIRTUAL5RC(Variant, _post_process_key_value, Ref<Animation>, int, Variant, ObjectID, int); void _blend_init(); - virtual bool _blend_pre_process(double p_delta, int p_track_count, const HashMap<NodePath, int> &p_track_map); + virtual bool _blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map); virtual void _blend_capture(double p_delta); void _blend_calc_total_weight(); // For undeterministic blending. void _blend_process(double p_delta, bool p_update_only = false); @@ -405,6 +410,7 @@ public: void get_animation_library_list(List<StringName> *p_animations) const; Ref<AnimationLibrary> get_animation_library(const StringName &p_name) const; bool has_animation_library(const StringName &p_name) const; + StringName get_animation_library_name(const Ref<AnimationLibrary> &p_animation_library) const; StringName find_animation_library(const Ref<Animation> &p_animation) const; Error add_animation_library(const StringName &p_name, const Ref<AnimationLibrary> &p_animation_library); void remove_animation_library(const StringName &p_name); @@ -442,6 +448,9 @@ public: void set_root_motion_track(const NodePath &p_track); NodePath get_root_motion_track() const; + void set_root_motion_local(bool p_enabled); + bool is_root_motion_local() const; + Vector3 get_root_motion_position() const; Quaternion get_root_motion_rotation() const; Vector3 get_root_motion_scale() const; @@ -485,11 +494,11 @@ public: class AnimatedValuesBackup : public RefCounted { GDCLASS(AnimatedValuesBackup, RefCounted); - HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> data; + AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher> data; public: - void set_data(const HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> p_data); - HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> get_data() const; + void set_data(const AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher> p_data); + AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher> get_data() const; void clear_data(); AnimationMixer::TrackCache *get_cache_copy(AnimationMixer::TrackCache *p_cache) const; diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index c3c5399a6b..5cc204100c 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -1619,7 +1619,7 @@ AnimationNode::NodeTimeInfo AnimationNodeStateMachine::_process(const AnimationM playback_new = playback_new->duplicate(); // Don't process original when testing. } - return playback_new->process(node_state.base_path, this, p_playback_info, p_test_only); + return playback_new->process(node_state.get_base_path(), this, p_playback_info, p_test_only); } String AnimationNodeStateMachine::get_caption() const { diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 8a2ca47920..7d28aead6e 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -133,7 +133,7 @@ void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const { List<PropertyInfo> anim_names; for (const KeyValue<StringName, AnimationData> &E : animation_set) { - HashMap<StringName, StringName>::ConstIterator F = animation_next_set.find(E.key); + AHashMap<StringName, StringName>::ConstIterator F = animation_next_set.find(E.key); if (F && F->value != StringName()) { anim_names.push_back(PropertyInfo(Variant::STRING, "next/" + String(E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } @@ -299,7 +299,7 @@ void AnimationPlayer::_blend_playback_data(double p_delta, bool p_started) { } } -bool AnimationPlayer::_blend_pre_process(double p_delta, int p_track_count, const HashMap<NodePath, int> &p_track_map) { +bool AnimationPlayer::_blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) { if (!playback.current.from) { _set_process(false); return false; @@ -876,6 +876,20 @@ Tween::EaseType AnimationPlayer::get_auto_capture_ease_type() const { return auto_capture_ease_type; } +#ifdef TOOLS_ENABLED +void AnimationPlayer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + const String pf = p_function; + if (p_idx == 0 && (pf == "play" || pf == "play_backwards" || pf == "has_animation" || pf == "queue")) { + List<StringName> al; + get_animation_list(&al); + for (const StringName &name : al) { + r_options->push_back(String(name).quote()); + } + } + AnimationMixer::get_argument_options(p_function, p_idx, r_options); +} +#endif + void AnimationPlayer::_animation_removed(const StringName &p_name, const StringName &p_library) { AnimationMixer::_animation_removed(p_name, p_library); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 3223e2522d..6d7e8aa996 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -52,7 +52,7 @@ public: #endif // DISABLE_DEPRECATED private: - HashMap<StringName, StringName> animation_next_set; // For auto advance. + AHashMap<StringName, StringName> animation_next_set; // For auto advance. float speed_scale = 1.0; double default_blend_time = 0.0; @@ -138,7 +138,7 @@ protected: static void _bind_methods(); // Make animation instances. - virtual bool _blend_pre_process(double p_delta, int p_track_count, const HashMap<NodePath, int> &p_track_map) override; + virtual bool _blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) override; virtual void _blend_capture(double p_delta) override; virtual void _blend_post_process() override; @@ -178,6 +178,10 @@ public: void set_auto_capture_ease_type(Tween::EaseType p_auto_capture_ease_type); Tween::EaseType get_auto_capture_ease_type() const; +#ifdef TOOLS_ENABLED + void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; +#endif + void play(const StringName &p_name = StringName(), double p_custom_blend = -1, float p_custom_scale = 1.0, bool p_from_end = false); void play_section_with_markers(const StringName &p_name = StringName(), const StringName &p_start_marker = StringName(), const StringName &p_end_marker = StringName(), double p_custom_blend = -1, float p_custom_scale = 1.0, bool p_from_end = false); void play_section(const StringName &p_name = StringName(), double p_start_time = -1, double p_end_time = -1, double p_custom_blend = -1, float p_custom_scale = 1.0, bool p_from_end = false); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 19080e61de..f2871cda79 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -75,20 +75,34 @@ void AnimationNode::set_parameter(const StringName &p_name, const Variant &p_val if (process_state->is_testing) { return; } + + const AHashMap<StringName, int>::Iterator it = property_cache.find(p_name); + if (it) { + process_state->tree->property_map.get_by_index(it->value).value.first = p_value; + return; + } + ERR_FAIL_COND(!process_state->tree->property_parent_map.has(node_state.base_path)); ERR_FAIL_COND(!process_state->tree->property_parent_map[node_state.base_path].has(p_name)); StringName path = process_state->tree->property_parent_map[node_state.base_path][p_name]; - - process_state->tree->property_map[path].first = p_value; + int idx = process_state->tree->property_map.get_index(path); + property_cache.insert_new(p_name, idx); + process_state->tree->property_map.get_by_index(idx).value.first = p_value; } Variant AnimationNode::get_parameter(const StringName &p_name) const { ERR_FAIL_NULL_V(process_state, Variant()); + const AHashMap<StringName, int>::ConstIterator it = property_cache.find(p_name); + if (it) { + return process_state->tree->property_map.get_by_index(it->value).value.first; + } ERR_FAIL_COND_V(!process_state->tree->property_parent_map.has(node_state.base_path), Variant()); ERR_FAIL_COND_V(!process_state->tree->property_parent_map[node_state.base_path].has(p_name), Variant()); StringName path = process_state->tree->property_parent_map[node_state.base_path][p_name]; - return process_state->tree->property_map[path].first; + int idx = process_state->tree->property_map.get_index(path); + property_cache.insert_new(p_name, idx); + return process_state->tree->property_map.get_by_index(idx).value.first; } void AnimationNode::set_node_time_info(const NodeTimeInfo &p_node_time_info) { @@ -203,7 +217,7 @@ AnimationNode::NodeTimeInfo AnimationNode::_blend_node(Ref<AnimationNode> p_node } for (const KeyValue<NodePath, bool> &E : filter) { - const HashMap<NodePath, int> &map = *process_state->track_map; + const AHashMap<NodePath, int> &map = *process_state->track_map; if (!map.has(E.key)) { continue; } @@ -292,7 +306,7 @@ AnimationNode::NodeTimeInfo AnimationNode::_blend_node(Ref<AnimationNode> p_node // This process, which depends on p_sync is needed to process sync correctly in the case of // that a synced AnimationNodeSync exists under the un-synced AnimationNodeSync. - p_node->node_state.base_path = new_path; + p_node->set_node_state_base_path(new_path); p_node->node_state.parent = new_parent; if (!p_playback_info.seeked && !p_sync && !any_valid) { p_playback_info.delta = 0.0; @@ -357,7 +371,9 @@ AnimationNode::NodeTimeInfo AnimationNode::process(const AnimationMixer::Playbac AnimationMixer::PlaybackInfo pi = p_playback_info; if (p_playback_info.seeked) { - pi.delta = get_node_time_info().position - p_playback_info.time; + if (p_playback_info.is_external_seeking) { + pi.delta = get_node_time_info().position - p_playback_info.time; + } } else { pi.time = get_node_time_info().position + p_playback_info.delta; } @@ -603,7 +619,7 @@ Ref<AnimationRootNode> AnimationTree::get_root_animation_node() const { return root_animation_node; } -bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const HashMap<NodePath, int> &p_track_map) { +bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) { _update_properties(); // If properties need updating, update them. if (!root_animation_node.is_valid()) { @@ -627,7 +643,7 @@ bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const for (int i = 0; i < p_track_count; i++) { src_blendsw[i] = 1.0; // By default all go to 1 for the root input. } - root_animation_node->node_state.base_path = SNAME(Animation::PARAMETERS_BASE_PATH.ascii().get_data()); + root_animation_node->set_node_state_base_path(SNAME(Animation::PARAMETERS_BASE_PATH.ascii().get_data())); root_animation_node->node_state.parent = nullptr; } @@ -732,7 +748,7 @@ void AnimationTree::_animation_node_removed(const ObjectID &p_oid, const StringN void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<AnimationNode> p_node) { ERR_FAIL_COND(p_node.is_null()); if (!property_parent_map.has(p_base_path)) { - property_parent_map[p_base_path] = HashMap<StringName, StringName>(); + property_parent_map[p_base_path] = AHashMap<StringName, StringName>(); } if (!property_reference_map.has(p_node->get_instance_id())) { property_reference_map[p_node->get_instance_id()] = p_base_path; @@ -767,7 +783,7 @@ void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<A pinfo.name = p_base_path + key; properties.push_back(pinfo); } - + p_node->make_cache_dirty(); List<AnimationNode::ChildNode> children; p_node->get_child_nodes(&children); diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index d4b7bf31c9..5a2a822ff0 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -60,7 +60,7 @@ public: bool closable = false; Vector<Input> inputs; - HashMap<NodePath, bool> filter; + AHashMap<NodePath, bool> filter; bool filter_enabled = false; // To propagate information from upstream for use in estimation of playback progress. @@ -91,28 +91,63 @@ public: if (Math::is_zero_approx(remain)) { return 0; } - return length - position; + return remain; } }; // Temporary state for blending process which needs to be stored in each AnimationNodes. struct NodeState { + friend AnimationNode; + + private: StringName base_path; + + public: AnimationNode *parent = nullptr; Vector<StringName> connections; Vector<real_t> track_weights; + + const StringName get_base_path() const { + return base_path; + } + } node_state; // Temporary state for blending process which needs to be started in the AnimationTree, pass through the AnimationNodes, and then return to the AnimationTree. struct ProcessState { AnimationTree *tree = nullptr; - const HashMap<NodePath, int> *track_map; // TODO: Is there a better way to manage filter/tracks? + const AHashMap<NodePath, int> *track_map; // TODO: Is there a better way to manage filter/tracks? bool is_testing = false; bool valid = false; String invalid_reasons; uint64_t last_pass = 0; } *process_state = nullptr; +private: + mutable AHashMap<StringName, int> property_cache; + +public: + void set_node_state_base_path(const StringName p_base_path) { + if (p_base_path != node_state.base_path) { + node_state.base_path = p_base_path; + make_cache_dirty(); + } + } + + void set_node_state_base_path(const String p_base_path) { + if (p_base_path != node_state.base_path) { + node_state.base_path = p_base_path; + make_cache_dirty(); + } + } + + const StringName get_node_state_base_path() const { + return node_state.get_base_path(); + } + + void make_cache_dirty() { + property_cache.clear(); + } Array _get_filters() const; void _set_filters(const Array &p_filters); friend class AnimationNodeBlendTree; @@ -151,7 +186,7 @@ protected: GDVIRTUAL1RC(Ref<AnimationNode>, _get_child_by_name, StringName) GDVIRTUAL1RC(Variant, _get_parameter_default_value, StringName) GDVIRTUAL1RC(bool, _is_parameter_read_only, StringName) - GDVIRTUAL4RC(double, _process, double, bool, bool, bool) + GDVIRTUAL4R(double, _process, double, bool, bool, bool) GDVIRTUAL0RC(String, _get_caption) GDVIRTUAL0RC(bool, _has_filter) @@ -250,9 +285,9 @@ private: friend class AnimationNode; List<PropertyInfo> properties; - HashMap<StringName, HashMap<StringName, StringName>> property_parent_map; - HashMap<ObjectID, StringName> property_reference_map; - HashMap<StringName, Pair<Variant, bool>> property_map; // Property value and read-only flag. + AHashMap<StringName, AHashMap<StringName, StringName>> property_parent_map; + AHashMap<ObjectID, StringName> property_reference_map; + AHashMap<StringName, Pair<Variant, bool>> property_map; // Property value and read-only flag. bool properties_dirty = true; @@ -286,7 +321,7 @@ private: virtual void _set_active(bool p_active) override; // Make animation instances. - virtual bool _blend_pre_process(double p_delta, int p_track_count, const HashMap<NodePath, int> &p_track_map) override; + virtual bool _blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) override; #ifndef DISABLE_DEPRECATED void _set_process_callback_bind_compat_80813(AnimationProcessCallback p_mode); diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index fd520dadd6..2c0222b3b8 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -94,7 +94,6 @@ void RootMotionView::_notification(int p_what) { if (has_node(path)) { Node *node = get_node(path); - AnimationMixer *mixer = Object::cast_to<AnimationMixer>(node); if (mixer && mixer->is_active() && mixer->get_root_motion_track() != NodePath()) { if (is_processing_internal() && mixer->get_callback_mode_process() == AnimationMixer::ANIMATION_CALLBACK_MODE_PROCESS_PHYSICS) { @@ -106,12 +105,12 @@ void RootMotionView::_notification(int p_what) { set_process_internal(true); set_physics_process_internal(false); } + transform.origin = mixer->get_root_motion_position(); transform.basis = mixer->get_root_motion_rotation(); // Scale is meaningless. - diff = mixer->get_root_motion_rotation_accumulator(); + diff = mixer->is_root_motion_local() ? Quaternion() : mixer->get_root_motion_rotation_accumulator(); } } - if (!first && transform == Transform3D()) { return; } diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index d4b44a8b69..3996ec9b1e 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -262,7 +262,7 @@ void AudioStreamPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,24,suffix:dB"), "set_volume_db", "get_volume_db"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_ONESHOT, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_target", PROPERTY_HINT_ENUM, "Stereo,Surround,Center"), "set_mix_target", "get_mix_target"); diff --git a/scene/audio/audio_stream_player_internal.cpp b/scene/audio/audio_stream_player_internal.cpp index 7d1ed56ca8..621aa31fc6 100644 --- a/scene/audio/audio_stream_player_internal.cpp +++ b/scene/audio/audio_stream_player_internal.cpp @@ -112,6 +112,7 @@ void AudioStreamPlayerInternal::notification(int p_what) { stream_playbacks.clear(); } break; + case Node::NOTIFICATION_SUSPENDED: case Node::NOTIFICATION_PAUSED: { if (!node->can_process()) { // Node can't process so we start fading out to silence @@ -119,6 +120,13 @@ void AudioStreamPlayerInternal::notification(int p_what) { } } break; + case Node::NOTIFICATION_UNSUSPENDED: { + if (node->get_tree()->is_paused()) { + break; + } + [[fallthrough]]; + } + case Node::NOTIFICATION_UNPAUSED: { set_stream_paused(false); } break; diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 22e5238fae..377bc0eefe 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -30,21 +30,36 @@ #include "scene_debugger.h" +#include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" -#include "core/debugger/engine_profiler.h" #include "core/io/marshalls.h" #include "core/object/script_language.h" #include "core/templates/local_vector.h" +#include "scene/2d/physics/collision_object_2d.h" +#include "scene/2d/physics/collision_polygon_2d.h" +#include "scene/2d/physics/collision_shape_2d.h" +#ifndef _3D_DISABLED +#include "scene/3d/label_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/physics/collision_object_3d.h" +#include "scene/3d/physics/collision_shape_3d.h" +#include "scene/3d/sprite_3d.h" +#include "scene/resources/surface_tool.h" +#endif // _3D_DISABLED +#include "scene/gui/popup_menu.h" +#include "scene/main/canvas_layer.h" #include "scene/main/scene_tree.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" - -SceneDebugger *SceneDebugger::singleton = nullptr; +#include "scene/theme/theme_db.h" SceneDebugger::SceneDebugger() { singleton = this; + #ifdef DEBUG_ENABLED LiveEditor::singleton = memnew(LiveEditor); + RuntimeNodeSelect::singleton = memnew(RuntimeNodeSelect); + EngineDebugger::register_message_capture("scene", EngineDebugger::Capture(nullptr, SceneDebugger::parse_message)); #endif } @@ -56,7 +71,13 @@ SceneDebugger::~SceneDebugger() { memdelete(LiveEditor::singleton); LiveEditor::singleton = nullptr; } + + if (RuntimeNodeSelect::singleton) { + memdelete(RuntimeNodeSelect::singleton); + RuntimeNodeSelect::singleton = nullptr; + } #endif + singleton = nullptr; } @@ -73,18 +94,33 @@ void SceneDebugger::deinitialize() { } #ifdef DEBUG_ENABLED +void SceneDebugger::_handle_input(const Ref<InputEvent> &p_event, const Ref<Shortcut> &p_shortcut) { + Ref<InputEventKey> k = p_event; + if (k.is_valid() && k->is_pressed() && !k->is_echo() && p_shortcut->matches_event(k)) { + EngineDebugger::get_singleton()->send_message("request_quit", Array()); + } +} + Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured) { SceneTree *scene_tree = SceneTree::get_singleton(); if (!scene_tree) { return ERR_UNCONFIGURED; } + LiveEditor *live_editor = LiveEditor::get_singleton(); if (!live_editor) { return ERR_UNCONFIGURED; } + RuntimeNodeSelect *runtime_node_select = RuntimeNodeSelect::get_singleton(); + if (!runtime_node_select) { + return ERR_UNCONFIGURED; + } r_captured = true; - if (p_msg == "request_scene_tree") { // Scene tree + if (p_msg == "setup_scene") { + SceneTree::get_singleton()->get_root()->connect(SceneStringName(window_input), callable_mp_static(SceneDebugger::_handle_input).bind(DebuggerMarshalls::deserialize_key_shortcut(p_args))); + + } else if (p_msg == "request_scene_tree") { // Scene tree live_editor->_send_tree(); } else if (p_msg == "save_node") { // Save node. @@ -99,22 +135,33 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra ObjectID id = p_args[0]; _send_object_id(id); - } else if (p_msg == "override_camera_2D:set") { // Camera + } else if (p_msg == "suspend_changed") { ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); - bool enforce = p_args[0]; - scene_tree->get_root()->enable_canvas_transform_override(enforce); + bool suspended = p_args[0]; + scene_tree->set_suspend(suspended); + runtime_node_select->_update_input_state(); - } else if (p_msg == "override_camera_2D:transform") { - ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); - Transform2D transform = p_args[0]; - scene_tree->get_root()->set_canvas_transform_override(transform); -#ifndef _3D_DISABLED - } else if (p_msg == "override_camera_3D:set") { + } else if (p_msg == "next_frame") { + _next_frame(); + + } else if (p_msg == "override_cameras") { // Camera ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); bool enable = p_args[0]; + bool from_editor = p_args[1]; + scene_tree->get_root()->enable_canvas_transform_override(enable); +#ifndef _3D_DISABLED scene_tree->get_root()->enable_camera_3d_override(enable); +#endif // _3D_DISABLED + runtime_node_select->_set_camera_override_enabled(enable && !from_editor); - } else if (p_msg == "override_camera_3D:transform") { + } else if (p_msg == "transform_camera_2d") { + ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); + Transform2D transform = p_args[0]; + scene_tree->get_root()->set_canvas_transform_override(transform); + runtime_node_select->_queue_selection_update(); + +#ifndef _3D_DISABLED + } else if (p_msg == "transform_camera_3d") { ERR_FAIL_COND_V(p_args.size() < 5, ERR_INVALID_DATA); Transform3D transform = p_args[0]; bool is_perspective = p_args[1]; @@ -127,95 +174,148 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra scene_tree->get_root()->set_camera_3d_override_orthogonal(size_or_fov, depth_near, depth_far); } scene_tree->get_root()->set_camera_3d_override_transform(transform); + runtime_node_select->_queue_selection_update(); #endif // _3D_DISABLED + } else if (p_msg == "set_object_property") { ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); _set_object_property(p_args[0], p_args[1], p_args[2]); + runtime_node_select->_queue_selection_update(); - } else if (!p_msg.begins_with("live_")) { // Live edits below. - return ERR_SKIP; - } else if (p_msg == "live_set_root") { - ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); - live_editor->_root_func(p_args[0], p_args[1]); + } else if (p_msg == "reload_cached_files") { + ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); + PackedStringArray files = p_args[0]; + reload_cached_files(files); + + } else if (p_msg.begins_with("live_")) { /// Live Edit + if (p_msg == "live_set_root") { + ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); + live_editor->_root_func(p_args[0], p_args[1]); + + } else if (p_msg == "live_node_path") { + ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); + live_editor->_node_path_func(p_args[0], p_args[1]); + + } else if (p_msg == "live_res_path") { + ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); + live_editor->_res_path_func(p_args[0], p_args[1]); + + } else if (p_msg == "live_node_prop_res") { + ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); + live_editor->_node_set_res_func(p_args[0], p_args[1], p_args[2]); + + } else if (p_msg == "live_node_prop") { + ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); + live_editor->_node_set_func(p_args[0], p_args[1], p_args[2]); + + } else if (p_msg == "live_res_prop_res") { + ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); + live_editor->_res_set_res_func(p_args[0], p_args[1], p_args[2]); + + } else if (p_msg == "live_res_prop") { + ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); + live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]); + + } else if (p_msg == "live_node_call") { + ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); + LocalVector<Variant> args; + LocalVector<Variant *> argptrs; + args.resize(p_args.size() - 2); + argptrs.resize(args.size()); + for (uint32_t i = 0; i < args.size(); i++) { + args[i] = p_args[i + 2]; + argptrs[i] = &args[i]; + } + live_editor->_node_call_func(p_args[0], p_args[1], argptrs.size() ? (const Variant **)argptrs.ptr() : nullptr, argptrs.size()); + + } else if (p_msg == "live_res_call") { + ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); + LocalVector<Variant> args; + LocalVector<Variant *> argptrs; + args.resize(p_args.size() - 2); + argptrs.resize(args.size()); + for (uint32_t i = 0; i < args.size(); i++) { + args[i] = p_args[i + 2]; + argptrs[i] = &args[i]; + } + live_editor->_res_call_func(p_args[0], p_args[1], argptrs.size() ? (const Variant **)argptrs.ptr() : nullptr, argptrs.size()); - } else if (p_msg == "live_node_path") { - ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); - live_editor->_node_path_func(p_args[0], p_args[1]); + } else if (p_msg == "live_create_node") { + ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); + live_editor->_create_node_func(p_args[0], p_args[1], p_args[2]); - } else if (p_msg == "live_res_path") { - ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); - live_editor->_res_path_func(p_args[0], p_args[1]); + } else if (p_msg == "live_instantiate_node") { + ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); + live_editor->_instance_node_func(p_args[0], p_args[1], p_args[2]); - } else if (p_msg == "live_node_prop_res") { - ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); - live_editor->_node_set_res_func(p_args[0], p_args[1], p_args[2]); + } else if (p_msg == "live_remove_node") { + ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); + live_editor->_remove_node_func(p_args[0]); - } else if (p_msg == "live_node_prop") { - ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); - live_editor->_node_set_func(p_args[0], p_args[1], p_args[2]); + if (!runtime_node_select->has_selection) { + runtime_node_select->_clear_selection(); + } - } else if (p_msg == "live_res_prop_res") { - ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); - live_editor->_res_set_res_func(p_args[0], p_args[1], p_args[2]); + } else if (p_msg == "live_remove_and_keep_node") { + ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); + live_editor->_remove_and_keep_node_func(p_args[0], p_args[1]); - } else if (p_msg == "live_res_prop") { - ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); - live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]); + if (!runtime_node_select->has_selection) { + runtime_node_select->_clear_selection(); + } - } else if (p_msg == "live_node_call") { - ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); - LocalVector<Variant> args; - LocalVector<Variant *> argptrs; - args.resize(p_args.size() - 2); - argptrs.resize(args.size()); - for (uint32_t i = 0; i < args.size(); i++) { - args[i] = p_args[i + 2]; - argptrs[i] = &args[i]; - } - live_editor->_node_call_func(p_args[0], p_args[1], argptrs.size() ? (const Variant **)argptrs.ptr() : nullptr, argptrs.size()); + } else if (p_msg == "live_restore_node") { + ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); + live_editor->_restore_node_func(p_args[0], p_args[1], p_args[2]); - } else if (p_msg == "live_res_call") { - ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); - LocalVector<Variant> args; - LocalVector<Variant *> argptrs; - args.resize(p_args.size() - 2); - argptrs.resize(args.size()); - for (uint32_t i = 0; i < args.size(); i++) { - args[i] = p_args[i + 2]; - argptrs[i] = &args[i]; + } else if (p_msg == "live_duplicate_node") { + ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); + live_editor->_duplicate_node_func(p_args[0], p_args[1]); + + } else if (p_msg == "live_reparent_node") { + ERR_FAIL_COND_V(p_args.size() < 4, ERR_INVALID_DATA); + live_editor->_reparent_node_func(p_args[0], p_args[1], p_args[2], p_args[3]); + + } else { + return ERR_SKIP; } - live_editor->_res_call_func(p_args[0], p_args[1], argptrs.size() ? (const Variant **)argptrs.ptr() : nullptr, argptrs.size()); - } else if (p_msg == "live_create_node") { - ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); - live_editor->_create_node_func(p_args[0], p_args[1], p_args[2]); + } else if (p_msg.begins_with("runtime_node_select_")) { /// Runtime Node Selection + if (p_msg == "runtime_node_select_setup") { + ERR_FAIL_COND_V(p_args.is_empty() || p_args[0].get_type() != Variant::DICTIONARY, ERR_INVALID_DATA); + runtime_node_select->_setup(p_args[0]); - } else if (p_msg == "live_instantiate_node") { - ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); - live_editor->_instance_node_func(p_args[0], p_args[1], p_args[2]); + } else if (p_msg == "runtime_node_select_set_type") { + ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); + RuntimeNodeSelect::NodeType type = (RuntimeNodeSelect::NodeType)(int)p_args[0]; + runtime_node_select->_node_set_type(type); - } else if (p_msg == "live_remove_node") { - ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); - live_editor->_remove_node_func(p_args[0]); + } else if (p_msg == "runtime_node_select_set_mode") { + ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); + RuntimeNodeSelect::SelectMode mode = (RuntimeNodeSelect::SelectMode)(int)p_args[0]; + runtime_node_select->_select_set_mode(mode); - } else if (p_msg == "live_remove_and_keep_node") { - ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); - live_editor->_remove_and_keep_node_func(p_args[0], p_args[1]); + } else if (p_msg == "runtime_node_select_set_visible") { + ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); + bool visible = p_args[0]; + runtime_node_select->_set_selection_visible(visible); - } else if (p_msg == "live_restore_node") { - ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); - live_editor->_restore_node_func(p_args[0], p_args[1], p_args[2]); + } else if (p_msg == "runtime_node_select_reset_camera_2d") { + runtime_node_select->_reset_camera_2d(); - } else if (p_msg == "live_duplicate_node") { - ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA); - live_editor->_duplicate_node_func(p_args[0], p_args[1]); +#ifndef _3D_DISABLED + } else if (p_msg == "runtime_node_select_reset_camera_3d") { + runtime_node_select->_reset_camera_3d(); +#endif // _3D_DISABLED + + } else { + return ERR_SKIP; + } - } else if (p_msg == "live_reparent_node") { - ERR_FAIL_COND_V(p_args.size() < 4, ERR_INVALID_DATA); - live_editor->_reparent_node_func(p_args[0], p_args[1], p_args[2], p_args[3]); } else { r_captured = false; } + return OK; } @@ -260,6 +360,9 @@ void SceneDebugger::_send_object_id(ObjectID p_id, int p_max_size) { return; } + Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id)); + RuntimeNodeSelect::get_singleton()->_select_node(node); + Array arr; obj.serialize(arr); EngineDebugger::get_singleton()->send_message("scene:inspect_object", arr); @@ -280,6 +383,16 @@ void SceneDebugger::_set_object_property(ObjectID p_id, const String &p_property obj->set(prop_name, p_value); } +void SceneDebugger::_next_frame() { + SceneTree *scene_tree = SceneTree::get_singleton(); + if (!scene_tree->is_suspended()) { + return; + } + + scene_tree->set_suspend(false); + RenderingServer::get_singleton()->connect("frame_post_draw", callable_mp(scene_tree, &SceneTree::set_suspend).bind(true), Object::CONNECT_ONE_SHOT); +} + void SceneDebugger::add_to_cache(const String &p_filename, Node *p_node) { LiveEditor *debugger = LiveEditor::get_singleton(); if (!debugger) { @@ -316,6 +429,15 @@ void SceneDebugger::remove_from_cache(const String &p_filename, Node *p_node) { } } +void SceneDebugger::reload_cached_files(const PackedStringArray &p_files) { + for (const String &file : p_files) { + Ref<Resource> res = ResourceCache::get_ref(file); + if (res.is_valid()) { + res->reload_from_file(); + } + } +} + /// SceneDebuggerObject SceneDebuggerObject::SceneDebuggerObject(ObjectID p_id) { id = ObjectID(); @@ -580,7 +702,6 @@ void SceneDebuggerTree::deserialize(const Array &p_arr) { } /// LiveEditor -LiveEditor *LiveEditor::singleton = nullptr; LiveEditor *LiveEditor::get_singleton() { return singleton; } @@ -1089,4 +1210,950 @@ void LiveEditor::_reparent_node_func(const NodePath &p_at, const NodePath &p_new } } +/// RuntimeNodeSelect +RuntimeNodeSelect *RuntimeNodeSelect::get_singleton() { + return singleton; +} + +RuntimeNodeSelect::~RuntimeNodeSelect() { + if (selection_list && !selection_list->is_visible()) { + memdelete(selection_list); + } + + if (sbox_2d_canvas.is_valid()) { + RS::get_singleton()->free(sbox_2d_canvas); + RS::get_singleton()->free(sbox_2d_ci); + } + +#ifndef _3D_DISABLED + if (sbox_3d_instance.is_valid()) { + RS::get_singleton()->free(sbox_3d_instance); + RS::get_singleton()->free(sbox_3d_instance_ofs); + RS::get_singleton()->free(sbox_3d_instance_xray); + RS::get_singleton()->free(sbox_3d_instance_xray_ofs); + } +#endif // _3D_DISABLED +} + +void RuntimeNodeSelect::_setup(const Dictionary &p_settings) { + Window *root = SceneTree::get_singleton()->get_root(); + ERR_FAIL_COND(root->is_connected(SceneStringName(window_input), callable_mp(this, &RuntimeNodeSelect::_root_window_input))); + + root->connect(SceneStringName(window_input), callable_mp(this, &RuntimeNodeSelect::_root_window_input)); + root->connect("size_changed", callable_mp(this, &RuntimeNodeSelect::_queue_selection_update), CONNECT_DEFERRED); + + selection_list = memnew(PopupMenu); + selection_list->set_theme(ThemeDB::get_singleton()->get_default_theme()); + selection_list->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); + selection_list->set_force_native(true); + selection_list->connect("index_pressed", callable_mp(this, &RuntimeNodeSelect::_items_popup_index_pressed).bind(selection_list)); + selection_list->connect("popup_hide", callable_mp(Object::cast_to<Node>(root), &Node::remove_child).bind(selection_list)); + + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &RuntimeNodeSelect::_pan_callback), callable_mp(this, &RuntimeNodeSelect::_zoom_callback)); + + ViewPanner::ControlScheme panning_scheme = (ViewPanner::ControlScheme)p_settings.get("editors/panning/2d_editor_panning_scheme", 0).operator int(); + bool simple_panning = p_settings.get("editors/panning/simple_panning", false); + int pan_speed = p_settings.get("editors/panning/2d_editor_pan_speed", 20); + Array keys = p_settings.get("canvas_item_editor/pan_view", Array()).operator Array(); + panner->setup(panning_scheme, DebuggerMarshalls::deserialize_key_shortcut(keys), simple_panning); + panner->set_scroll_speed(pan_speed); + warped_panning = p_settings.get("editors/panning/warped_mouse_panning", false); + + /// 2D Selection Box Generation + + sbox_2d_canvas = RS::get_singleton()->canvas_create(); + sbox_2d_ci = RS::get_singleton()->canvas_item_create(); + RS::get_singleton()->viewport_attach_canvas(root->get_viewport_rid(), sbox_2d_canvas); + RS::get_singleton()->canvas_item_set_parent(sbox_2d_ci, sbox_2d_canvas); + +#ifndef _3D_DISABLED + cursor = Cursor(); + + /// 3D Selection Box Generation + // Copied from the Node3DEditor implementation. + + // Use two AABBs to create the illusion of a slightly thicker line. + AABB aabb(Vector3(), Vector3(1, 1, 1)); + + // Create a x-ray (visible through solid surfaces) and standard version of the selection box. + // Both will be drawn at the same position, but with different opacity. + // This lets the user see where the selection is while still having a sense of depth. + Ref<SurfaceTool> st = memnew(SurfaceTool); + Ref<SurfaceTool> st_xray = memnew(SurfaceTool); + + st->begin(Mesh::PRIMITIVE_LINES); + st_xray->begin(Mesh::PRIMITIVE_LINES); + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + + st->add_vertex(a); + st->add_vertex(b); + st_xray->add_vertex(a); + st_xray->add_vertex(b); + } + + Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D); + mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + // In the original Node3DEditor, this value would be fetched from the "editors/3d/selection_box_color" editor property, + // but since this is not accessible from here, we will just use the default value. + const Color selection_color_3d = Color(1, 0.5, 0); + mat->set_albedo(selection_color_3d); + mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + st->set_material(mat); + sbox_3d_mesh = st->commit(); + + Ref<StandardMaterial3D> mat_xray = memnew(StandardMaterial3D); + mat_xray->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + mat_xray->set_albedo(selection_color_3d * Color(1, 1, 1, 0.15)); + mat_xray->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + st_xray->set_material(mat_xray); + sbox_3d_mesh_xray = st_xray->commit(); +#endif // _3D_DISABLED + + SceneTree::get_singleton()->connect("process_frame", callable_mp(this, &RuntimeNodeSelect::_process_frame)); + SceneTree::get_singleton()->connect("physics_frame", callable_mp(this, &RuntimeNodeSelect::_physics_frame)); + + // This function will be called before the root enters the tree at first when the Game view is passing its settings to + // the debugger, so queue the update for after it enters. + root->connect(SceneStringName(tree_entered), callable_mp(this, &RuntimeNodeSelect::_update_input_state), Object::CONNECT_ONE_SHOT); +} + +void RuntimeNodeSelect::_node_set_type(NodeType p_type) { + node_select_type = p_type; + _update_input_state(); +} + +void RuntimeNodeSelect::_select_set_mode(SelectMode p_mode) { + node_select_mode = p_mode; +} + +void RuntimeNodeSelect::_set_camera_override_enabled(bool p_enabled) { + camera_override = p_enabled; + + if (p_enabled) { + _update_view_2d(); + } + +#ifndef _3D_DISABLED + if (camera_first_override) { + _reset_camera_2d(); + _reset_camera_3d(); + + camera_first_override = false; + } else if (p_enabled) { + _update_view_2d(); + + SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); + SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(CAMERA_BASE_FOV * cursor.fov_scale, CAMERA_ZNEAR, CAMERA_ZFAR); + } +#endif // _3D_DISABLED +} + +void RuntimeNodeSelect::_root_window_input(const Ref<InputEvent> &p_event) { + Window *root = SceneTree::get_singleton()->get_root(); + if (node_select_type == NODE_TYPE_NONE || selection_list->is_visible()) { + // Workaround for platforms that don't allow subwindows. + if (selection_list->is_visible() && selection_list->is_embedded()) { + root->set_disable_input_override(false); + selection_list->push_input(p_event); + callable_mp(root->get_viewport(), &Viewport::set_disable_input_override).call_deferred(true); + } + + return; + } + + if (camera_override) { + if (node_select_type == NODE_TYPE_2D) { + if (panner->gui_input(p_event, warped_panning ? Rect2(Vector2(), root->get_size()) : Rect2())) { + return; + } + } else if (node_select_type == NODE_TYPE_3D) { +#ifndef _3D_DISABLED + if (root->get_camera_3d() && _handle_3d_input(p_event)) { + return; + } +#endif // _3D_DISABLED + } + } + + Ref<InputEventMouseButton> b = p_event; + if (!b.is_valid() || !b->is_pressed()) { + return; + } + + list_shortcut_pressed = node_select_mode == SELECT_MODE_SINGLE && b->get_button_index() == MouseButton::RIGHT && b->is_alt_pressed(); + if (list_shortcut_pressed || b->get_button_index() == MouseButton::LEFT) { + selection_position = b->get_position(); + } +} + +void RuntimeNodeSelect::_items_popup_index_pressed(int p_index, PopupMenu *p_popup) { + Object *obj = p_popup->get_item_metadata(p_index).get_validated_object(); + if (!obj) { + return; + } + + Array message; + message.append(obj->get_instance_id()); + EngineDebugger::get_singleton()->send_message("remote_node_clicked", message); +} + +void RuntimeNodeSelect::_update_input_state() { + SceneTree *scene_tree = SceneTree::get_singleton(); + // This function can be called at the very beginning, when the root hasn't entered the tree yet. + // So check first to avoid a crash. + if (!scene_tree->get_root()->is_inside_tree()) { + return; + } + + bool disable_input = scene_tree->is_suspended() || node_select_type != RuntimeNodeSelect::NODE_TYPE_NONE; + Input::get_singleton()->set_disable_input(disable_input); + Input::get_singleton()->set_mouse_mode_override_enabled(disable_input); + scene_tree->get_root()->set_disable_input_override(disable_input); +} + +void RuntimeNodeSelect::_process_frame() { +#ifndef _3D_DISABLED + if (camera_freelook) { + Transform3D transform = _get_cursor_transform(); + Vector3 forward = transform.basis.xform(Vector3(0, 0, -1)); + const Vector3 right = transform.basis.xform(Vector3(1, 0, 0)); + Vector3 up = transform.basis.xform(Vector3(0, 1, 0)); + + Vector3 direction; + + Input *input = Input::get_singleton(); + bool was_input_disabled = input->is_input_disabled(); + if (was_input_disabled) { + input->set_disable_input(false); + } + + if (input->is_physical_key_pressed(Key::A)) { + direction -= right; + } + if (input->is_physical_key_pressed(Key::D)) { + direction += right; + } + if (input->is_physical_key_pressed(Key::W)) { + direction += forward; + } + if (input->is_physical_key_pressed(Key::S)) { + direction -= forward; + } + if (input->is_physical_key_pressed(Key::E)) { + direction += up; + } + if (input->is_physical_key_pressed(Key::Q)) { + direction -= up; + } + + real_t speed = FREELOOK_BASE_SPEED; + if (input->is_physical_key_pressed(Key::SHIFT)) { + speed *= 3.0; + } + if (input->is_physical_key_pressed(Key::ALT)) { + speed *= 0.333333; + } + + if (was_input_disabled) { + input->set_disable_input(true); + } + + if (direction != Vector3()) { + // Calculate the process time manually, as the time scale is frozen. + const double process_time = (1.0 / Engine::get_singleton()->get_frames_per_second()) * Engine::get_singleton()->get_unfrozen_time_scale(); + const Vector3 motion = direction * speed * process_time; + cursor.pos += motion; + cursor.eye_pos += motion; + + SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); + } + } +#endif // _3D_DISABLED + + if (selection_update_queued || !SceneTree::get_singleton()->is_suspended()) { + selection_update_queued = false; + if (has_selection) { + _update_selection(); + } + } +} + +void RuntimeNodeSelect::_physics_frame() { + if (!Math::is_inf(selection_position.x) || !Math::is_inf(selection_position.y)) { + _click_point(); + selection_position = Point2(INFINITY, INFINITY); + } +} + +void RuntimeNodeSelect::_click_point() { + Window *root = SceneTree::get_singleton()->get_root(); + Point2 pos = root->get_screen_transform().affine_inverse().xform(selection_position); + Vector<SelectResult> items; + + if (node_select_type == NODE_TYPE_2D) { + for (int i = 0; i < root->get_child_count(); i++) { + _find_canvas_items_at_pos(pos, root->get_child(i), items); + } + + // Remove possible duplicates. + for (int i = 0; i < items.size(); i++) { + Node *item = items[i].item; + for (int j = 0; j < i; j++) { + if (items[j].item == item) { + items.remove_at(i); + i--; + + break; + } + } + } + } else if (node_select_type == NODE_TYPE_3D) { +#ifndef _3D_DISABLED + _find_3d_items_at_pos(pos, items); +#endif // _3D_DISABLED + } + + if (items.is_empty()) { + return; + } + + items.sort(); + + if ((!list_shortcut_pressed && node_select_mode == SELECT_MODE_SINGLE) || items.size() == 1) { + Array message; + message.append(items[0].item->get_instance_id()); + EngineDebugger::get_singleton()->send_message("remote_node_clicked", message); + } else if (list_shortcut_pressed || node_select_mode == SELECT_MODE_LIST) { + if (!selection_list->is_inside_tree()) { + root->add_child(selection_list); + } + + selection_list->clear(); + for (const SelectResult &I : items) { + selection_list->add_item(I.item->get_name()); + selection_list->set_item_metadata(-1, I.item); + } + + selection_list->set_position(selection_list->is_embedded() ? pos : selection_position + root->get_position()); + selection_list->reset_size(); + selection_list->popup(); + // FIXME: Ugly hack that stops the popup from hiding when the button is released. + selection_list->call_deferred(SNAME("set_position"), selection_list->get_position() + Point2(1, 0)); + } +} + +void RuntimeNodeSelect::_select_node(Node *p_node) { + if (p_node == selected_node) { + return; + } + + _clear_selection(); + + CanvasItem *ci = Object::cast_to<CanvasItem>(p_node); + if (ci) { + selected_node = p_node; + } else { +#ifndef _3D_DISABLED + Node3D *node_3d = Object::cast_to<Node3D>(p_node); + if (node_3d) { + if (!node_3d->is_inside_world()) { + return; + } + + selected_node = p_node; + + sbox_3d_instance = RS::get_singleton()->instance_create2(sbox_3d_mesh->get_rid(), node_3d->get_world_3d()->get_scenario()); + sbox_3d_instance_ofs = RS::get_singleton()->instance_create2(sbox_3d_mesh->get_rid(), node_3d->get_world_3d()->get_scenario()); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sbox_3d_instance, RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sbox_3d_instance_ofs, RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance_ofs, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance_ofs, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); + + sbox_3d_instance_xray = RS::get_singleton()->instance_create2(sbox_3d_mesh_xray->get_rid(), node_3d->get_world_3d()->get_scenario()); + sbox_3d_instance_xray_ofs = RS::get_singleton()->instance_create2(sbox_3d_mesh_xray->get_rid(), node_3d->get_world_3d()->get_scenario()); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sbox_3d_instance_xray, RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sbox_3d_instance_xray_ofs, RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance_xray, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance_xray, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance_xray_ofs, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); + RS::get_singleton()->instance_geometry_set_flag(sbox_3d_instance_xray_ofs, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); + } +#endif // _3D_DISABLED + } + + has_selection = selected_node; + _queue_selection_update(); +} + +void RuntimeNodeSelect::_queue_selection_update() { + if (has_selection && selection_visible) { + if (SceneTree::get_singleton()->is_suspended()) { + _update_selection(); + } else { + selection_update_queued = true; + } + } +} + +void RuntimeNodeSelect::_update_selection() { + if (has_selection && (!selected_node || !selected_node->is_inside_tree())) { + _clear_selection(); + return; + } + + CanvasItem *ci = Object::cast_to<CanvasItem>(selected_node); + if (ci) { + Window *root = SceneTree::get_singleton()->get_root(); + Transform2D xform; + if (root->is_canvas_transform_override_enabled() && !ci->get_canvas_layer_node()) { + RS::get_singleton()->canvas_item_set_transform(sbox_2d_ci, (root->get_canvas_transform_override())); + xform = ci->get_global_transform(); + } else { + RS::get_singleton()->canvas_item_set_transform(sbox_2d_ci, Transform2D()); + xform = ci->get_global_transform_with_canvas(); + } + + // Fallback. + Rect2 rect = Rect2(Vector2(), Vector2(10, 10)); + + if (ci->_edit_use_rect()) { + rect = ci->_edit_get_rect(); + } else { + CollisionShape2D *collision_shape = Object::cast_to<CollisionShape2D>(ci); + if (collision_shape) { + Ref<Shape2D> shape = collision_shape->get_shape(); + if (shape.is_valid()) { + rect = shape->get_rect(); + } + } + } + + RS::get_singleton()->canvas_item_set_visible(sbox_2d_ci, selection_visible); + + if (xform == sbox_2d_xform && rect == sbox_2d_rect) { + return; // Nothing changed. + } + sbox_2d_xform = xform; + sbox_2d_rect = rect; + + RS::get_singleton()->canvas_item_clear(sbox_2d_ci); + + const Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; + + const Color selection_color_2d = Color(1, 0.6, 0.4, 0.7); + for (int i = 0; i < 4; i++) { + RS::get_singleton()->canvas_item_add_line(sbox_2d_ci, endpoints[i], endpoints[(i + 1) % 4], selection_color_2d, Math::round(2.f)); + } + } else { +#ifndef _3D_DISABLED + Node3D *node_3d = Object::cast_to<Node3D>(selected_node); + + // Fallback. + AABB bounds(Vector3(-0.5, -0.5, -0.5), Vector3(1, 1, 1)); + + VisualInstance3D *visual_instance = Object::cast_to<VisualInstance3D>(node_3d); + if (visual_instance) { + bounds = visual_instance->get_aabb(); + } else { + CollisionShape3D *collision_shape = Object::cast_to<CollisionShape3D>(node_3d); + if (collision_shape) { + Ref<Shape3D> shape = collision_shape->get_shape(); + if (shape.is_valid()) { + bounds = shape->get_debug_mesh()->get_aabb(); + } + } + } + + RS::get_singleton()->instance_set_visible(sbox_3d_instance, selection_visible); + RS::get_singleton()->instance_set_visible(sbox_3d_instance_ofs, selection_visible); + RS::get_singleton()->instance_set_visible(sbox_3d_instance_xray, selection_visible); + RS::get_singleton()->instance_set_visible(sbox_3d_instance_xray_ofs, selection_visible); + + Transform3D xform_to_top_level_parent_space = node_3d->get_global_transform().affine_inverse() * node_3d->get_global_transform(); + bounds = xform_to_top_level_parent_space.xform(bounds); + Transform3D t = node_3d->get_global_transform(); + + if (t == sbox_3d_xform && bounds == sbox_3d_bounds) { + return; // Nothing changed. + } + sbox_3d_xform = t; + sbox_3d_bounds = bounds; + + Transform3D t_offset = t; + + // Apply AABB scaling before item's global transform. + { + const Vector3 offset(0.005, 0.005, 0.005); + Basis aabb_s; + aabb_s.scale(bounds.size + offset); + t.translate_local(bounds.position - offset / 2); + t.basis = t.basis * aabb_s; + } + { + const Vector3 offset(0.01, 0.01, 0.01); + Basis aabb_s; + aabb_s.scale(bounds.size + offset); + t_offset.translate_local(bounds.position - offset / 2); + t_offset.basis = t_offset.basis * aabb_s; + } + + RS::get_singleton()->instance_set_transform(sbox_3d_instance, t); + RS::get_singleton()->instance_set_transform(sbox_3d_instance_ofs, t_offset); + RS::get_singleton()->instance_set_transform(sbox_3d_instance_xray, t); + RS::get_singleton()->instance_set_transform(sbox_3d_instance_xray_ofs, t_offset); +#endif // _3D_DISABLED + } +} + +void RuntimeNodeSelect::_clear_selection() { + selected_node = nullptr; + has_selection = false; + + if (sbox_2d_canvas.is_valid()) { + RS::get_singleton()->canvas_item_clear(sbox_2d_ci); + } + +#ifndef _3D_DISABLED + if (sbox_3d_instance.is_valid()) { + RS::get_singleton()->free(sbox_3d_instance); + RS::get_singleton()->free(sbox_3d_instance_ofs); + RS::get_singleton()->free(sbox_3d_instance_xray); + RS::get_singleton()->free(sbox_3d_instance_xray_ofs); + } +#endif // _3D_DISABLED +} + +void RuntimeNodeSelect::_set_selection_visible(bool p_visible) { + selection_visible = p_visible; + + if (has_selection) { + _update_selection(); + } +} + +// Copied and trimmed from the CanvasItemEditor implementation. +void RuntimeNodeSelect::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<SelectResult> &r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { + if (!p_node || Object::cast_to<Viewport>(p_node)) { + return; + } + + // In the original CanvasItemEditor, this value would be fetched from the "editors/polygon_editor/point_grab_radius" editor property, + // but since this is not accessible from here, we will just use the default value. + const real_t grab_distance = 8; + CanvasItem *ci = Object::cast_to<CanvasItem>(p_node); + + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + if (ci) { + if (!ci->is_set_as_top_level()) { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_parent_xform * ci->get_transform(), p_canvas_xform); + } else { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, ci->get_transform(), p_canvas_xform); + } + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); + } + } + + if (ci && ci->is_visible_in_tree()) { + Transform2D xform = p_canvas_xform; + if (!ci->is_set_as_top_level()) { + xform *= p_parent_xform; + } + + Vector2 pos; + // Cameras (overridden or not) don't affect `CanvasLayer`s. + if (!ci->get_canvas_layer_node()) { + Window *root = SceneTree::get_singleton()->get_root(); + pos = (root->is_canvas_transform_override_enabled() ? root->get_canvas_transform_override() : root->get_canvas_transform()).affine_inverse().xform(p_pos); + } else { + pos = p_pos; + } + + xform = (xform * ci->get_transform()).affine_inverse(); + const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length() / view_2d_zoom; + if (ci->_edit_is_selected_on_click(xform.xform(pos), local_grab_distance)) { + SelectResult res; + res.item = ci; + res.order = ci->get_effective_z_index() + ci->get_canvas_layer(); + r_items.push_back(res); + + // If it's a shape, get the collision object it's from. + // FIXME: If the collision object has multiple shapes, only the topmost will be above it in the list. + if (Object::cast_to<CollisionShape2D>(ci) || Object::cast_to<CollisionPolygon2D>(ci)) { + CollisionObject2D *collision_object = Object::cast_to<CollisionObject2D>(ci->get_parent()); + if (collision_object) { + SelectResult res_col; + res_col.item = ci->get_parent(); + res_col.order = collision_object->get_z_index() + ci->get_canvas_layer(); + r_items.push_back(res_col); + } + } + } + } +} + +void RuntimeNodeSelect::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) { + view_2d_offset.x -= p_scroll_vec.x / view_2d_zoom; + view_2d_offset.y -= p_scroll_vec.y / view_2d_zoom; + + _update_view_2d(); +} + +// A very shallow copy of the same function inside CanvasItemEditor. +void RuntimeNodeSelect::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) { + real_t prev_zoom = view_2d_zoom; + view_2d_zoom = CLAMP(view_2d_zoom * p_zoom_factor, VIEW_2D_MIN_ZOOM, VIEW_2D_MAX_ZOOM); + + Vector2 pos = SceneTree::get_singleton()->get_root()->get_screen_transform().affine_inverse().xform(p_origin); + view_2d_offset += pos / prev_zoom - pos / view_2d_zoom; + + // We want to align in-scene pixels to screen pixels, this prevents blurry rendering + // of small details (texts, lines). + // This correction adds a jitter movement when zooming, so we correct only when the + // zoom factor is an integer. (in the other cases, all pixels won't be aligned anyway) + const real_t closest_zoom_factor = Math::round(view_2d_zoom); + if (Math::is_zero_approx(view_2d_zoom - closest_zoom_factor)) { + // Make sure scene pixel at view_offset is aligned on a screen pixel. + Vector2 view_offset_int = view_2d_offset.floor(); + Vector2 view_offset_frac = view_2d_offset - view_offset_int; + view_2d_offset = view_offset_int + (view_offset_frac * closest_zoom_factor).round() / closest_zoom_factor; + } + + _update_view_2d(); +} + +void RuntimeNodeSelect::_reset_camera_2d() { + view_2d_offset = -SceneTree::get_singleton()->get_root()->get_canvas_transform().get_origin(); + view_2d_zoom = 1; + + _update_view_2d(); +} + +void RuntimeNodeSelect::_update_view_2d() { + Transform2D transform = Transform2D(); + transform.scale_basis(Size2(view_2d_zoom, view_2d_zoom)); + transform.columns[2] = -view_2d_offset * view_2d_zoom; + + SceneTree::get_singleton()->get_root()->set_canvas_transform_override(transform); + + _queue_selection_update(); +} + +#ifndef _3D_DISABLED +void RuntimeNodeSelect::_find_3d_items_at_pos(const Point2 &p_pos, Vector<SelectResult> &r_items) { + Window *root = SceneTree::get_singleton()->get_root(); + Camera3D *camera = root->get_viewport()->get_camera_3d(); + if (!camera) { + return; + } + + Vector3 ray, pos, to; + if (root->get_viewport()->is_camera_3d_override_enabled()) { + Viewport *vp = root->get_viewport(); + ray = vp->camera_3d_override_project_ray_normal(p_pos); + pos = vp->camera_3d_override_project_ray_origin(p_pos); + to = pos + ray * vp->get_camera_3d_override_properties()["z_far"]; + } else { + ray = camera->project_ray_normal(p_pos); + pos = camera->project_ray_origin(p_pos); + to = pos + ray * camera->get_far(); + } + + // Start with physical objects. + PhysicsDirectSpaceState3D *ss = root->get_world_3d()->get_direct_space_state(); + PhysicsDirectSpaceState3D::RayResult result; + HashSet<RID> excluded; + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = pos; + ray_params.to = to; + ray_params.collide_with_areas = true; + while (true) { + ray_params.exclude = excluded; + if (ss->intersect_ray(ray_params, result)) { + SelectResult res; + res.item = Object::cast_to<Node>(result.collider); + res.order = -pos.distance_to(Object::cast_to<Node3D>(res.item)->get_global_transform().xform(result.position)); + + // Fetch collision shapes. + CollisionObject3D *collision = Object::cast_to<CollisionObject3D>(result.collider); + if (collision) { + List<uint32_t> owners; + collision->get_shape_owners(&owners); + for (const uint32_t &I : owners) { + SelectResult res_shape; + res_shape.item = Object::cast_to<Node>(collision->shape_owner_get_owner(I)); + res_shape.order = res.order; + r_items.push_back(res_shape); + } + } + + r_items.push_back(res); + + excluded.insert(result.rid); + } else { + break; + } + } + + // Then go for the meshes. + Vector<ObjectID> items = RS::get_singleton()->instances_cull_ray(pos, to, root->get_world_3d()->get_scenario()); + for (int i = 0; i < items.size(); i++) { + Object *obj = ObjectDB::get_instance(items[i]); + GeometryInstance3D *geo_instance = nullptr; + Ref<TriangleMesh> mesh_collision; + + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(obj); + if (mesh_instance) { + if (mesh_instance->get_mesh().is_valid()) { + geo_instance = mesh_instance; + mesh_collision = mesh_instance->get_mesh()->generate_triangle_mesh(); + } + } else { + Label3D *label = Object::cast_to<Label3D>(obj); + if (label) { + geo_instance = label; + mesh_collision = label->generate_triangle_mesh(); + } else { + Sprite3D *sprite = Object::cast_to<Sprite3D>(obj); + if (sprite) { + geo_instance = sprite; + mesh_collision = sprite->generate_triangle_mesh(); + } + } + } + + if (mesh_collision.is_valid()) { + Transform3D gt = geo_instance->get_global_transform(); + Transform3D ai = gt.affine_inverse(); + Vector3 point, normal; + if (mesh_collision->intersect_ray(ai.xform(pos), ai.basis.xform(ray).normalized(), point, normal)) { + SelectResult res; + res.item = Object::cast_to<Node>(obj); + res.order = -pos.distance_to(gt.xform(point)); + r_items.push_back(res); + + continue; + } + } + + items.remove_at(i); + i--; + } +} + +bool RuntimeNodeSelect::_handle_3d_input(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; + + if (b.is_valid()) { + const real_t zoom_factor = 1.08 * b->get_factor(); + switch (b->get_button_index()) { + case MouseButton::WHEEL_UP: { + if (!camera_freelook) { + _cursor_scale_distance(1.0 / zoom_factor); + } + + return true; + } break; + case MouseButton::WHEEL_DOWN: { + if (!camera_freelook) { + _cursor_scale_distance(zoom_factor); + } + + return true; + } break; + case MouseButton::RIGHT: { + _set_camera_freelook_enabled(b->is_pressed()); + return true; + } break; + default: { + } + } + } + + Ref<InputEventMouseMotion> m = p_event; + + if (m.is_valid()) { + if (camera_freelook) { + _cursor_look(m); + } else if (m->get_button_mask().has_flag(MouseButtonMask::MIDDLE)) { + if (m->is_shift_pressed()) { + _cursor_pan(m); + } else { + _cursor_orbit(m); + } + } + + return true; + } + + Ref<InputEventKey> k = p_event; + + if (k.is_valid()) { + if (k->get_physical_keycode() == Key::ESCAPE) { + _set_camera_freelook_enabled(false); + return true; + } else if (k->is_ctrl_pressed()) { + switch (k->get_physical_keycode()) { + case Key::EQUAL: { + cursor.fov_scale = CLAMP(cursor.fov_scale - 0.05, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE); + SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(CAMERA_BASE_FOV * cursor.fov_scale, CAMERA_ZNEAR, CAMERA_ZFAR); + + return true; + } break; + case Key::MINUS: { + cursor.fov_scale = CLAMP(cursor.fov_scale + 0.05, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE); + SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(CAMERA_BASE_FOV * cursor.fov_scale, CAMERA_ZNEAR, CAMERA_ZFAR); + + return true; + } break; + case Key::KEY_0: { + cursor.fov_scale = 1; + SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(CAMERA_BASE_FOV, CAMERA_ZNEAR, CAMERA_ZFAR); + + return true; + } break; + default: { + } + } + } + } + + // TODO: Handle magnify and pan input gestures. + + return false; +} + +void RuntimeNodeSelect::_set_camera_freelook_enabled(bool p_enabled) { + camera_freelook = p_enabled; + + if (p_enabled) { + // Make sure eye_pos is synced, because freelook referential is eye pos rather than orbit pos + Vector3 forward = _get_cursor_transform().basis.xform(Vector3(0, 0, -1)); + cursor.eye_pos = cursor.pos - cursor.distance * forward; + + previous_mouse_position = SceneTree::get_singleton()->get_root()->get_mouse_position(); + + // Hide mouse like in an FPS (warping doesn't work). + Input::get_singleton()->set_mouse_mode_override(Input::MOUSE_MODE_CAPTURED); + + } else { + // Restore mouse. + Input::get_singleton()->set_mouse_mode_override(Input::MOUSE_MODE_VISIBLE); + + // Restore the previous mouse position when leaving freelook mode. + // This is done because leaving `Input.MOUSE_MODE_CAPTURED` will center the cursor + // due to OS limitations. + Input::get_singleton()->warp_mouse(previous_mouse_position); + } +} + +void RuntimeNodeSelect::_cursor_scale_distance(real_t p_scale) { + real_t min_distance = MAX(CAMERA_ZNEAR * 4, VIEW_3D_MIN_ZOOM); + real_t max_distance = MIN(CAMERA_ZFAR / 4, VIEW_3D_MAX_ZOOM); + cursor.distance = CLAMP(cursor.distance * p_scale, min_distance, max_distance); + + SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); +} + +void RuntimeNodeSelect::_cursor_look(Ref<InputEventWithModifiers> p_event) { + Window *root = SceneTree::get_singleton()->get_root(); + const Vector2 relative = Input::get_singleton()->warp_mouse_motion(p_event, Rect2(Vector2(), root->get_size())); + const Transform3D prev_camera_transform = _get_cursor_transform(); + + cursor.x_rot += relative.y * RADS_PER_PIXEL; + // Clamp the Y rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented. + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); + + cursor.y_rot += relative.x * RADS_PER_PIXEL; + + // Look is like the opposite of Orbit: the focus point rotates around the camera. + Transform3D camera_transform = _get_cursor_transform(); + Vector3 pos = camera_transform.xform(Vector3(0, 0, 0)); + Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0)); + Vector3 diff = prev_pos - pos; + cursor.pos += diff; + + SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); +} + +void RuntimeNodeSelect::_cursor_pan(Ref<InputEventWithModifiers> p_event) { + Window *root = SceneTree::get_singleton()->get_root(); + // Reduce all sides of the area by 1, so warping works when windows are maximized/fullscreen. + const Vector2 relative = Input::get_singleton()->warp_mouse_motion(p_event, Rect2(Vector2(1, 1), root->get_size() - Vector2(2, 2))); + const real_t pan_speed = 1 / 150.0; + + Transform3D camera_transform; + camera_transform.translate_local(cursor.pos); + camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot); + camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot); + + Vector3 translation(1 * -relative.x * pan_speed, relative.y * pan_speed, 0); + translation *= cursor.distance / 4; + camera_transform.translate_local(translation); + cursor.pos = camera_transform.origin; + + SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); +} + +void RuntimeNodeSelect::_cursor_orbit(Ref<InputEventWithModifiers> p_event) { + Window *root = SceneTree::get_singleton()->get_root(); + // Reduce all sides of the area by 1, so warping works when windows are maximized/fullscreen. + const Vector2 relative = Input::get_singleton()->warp_mouse_motion(p_event, Rect2(Vector2(1, 1), root->get_size() - Vector2(2, 2))); + + cursor.x_rot += relative.y * RADS_PER_PIXEL; + // Clamp the Y rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented. + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); + + cursor.y_rot += relative.x * RADS_PER_PIXEL; + + SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); +} + +Transform3D RuntimeNodeSelect::_get_cursor_transform() { + Transform3D camera_transform; + camera_transform.translate_local(cursor.pos); + camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot); + camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot); + camera_transform.translate_local(0, 0, cursor.distance); + + return camera_transform; +} + +void RuntimeNodeSelect::_reset_camera_3d() { + camera_first_override = true; + + Window *root = SceneTree::get_singleton()->get_root(); + Camera3D *camera = root->get_camera_3d(); + if (!camera) { + return; + } + + cursor = Cursor(); + Transform3D transform = camera->get_global_transform(); + transform.translate_local(0, 0, -cursor.distance); + cursor.pos = transform.origin; + + cursor.x_rot = -camera->get_global_rotation().x; + cursor.y_rot = -camera->get_global_rotation().y; + + cursor.fov_scale = CLAMP(camera->get_fov() / CAMERA_BASE_FOV, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE); + + SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); + SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(CAMERA_BASE_FOV * cursor.fov_scale, CAMERA_ZNEAR, CAMERA_ZFAR); +} +#endif // _3D_DISABLED #endif diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index 0c28ca2a0c..90c8000eb4 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -31,19 +31,21 @@ #ifndef SCENE_DEBUGGER_H #define SCENE_DEBUGGER_H -#include "core/object/class_db.h" +#include "core/input/shortcut.h" #include "core/object/ref_counted.h" #include "core/string/ustring.h" #include "core/templates/pair.h" #include "core/variant/array.h" +#include "scene/gui/view_panner.h" +#include "scene/resources/mesh.h" +class PopupMenu; class Script; class Node; class SceneDebugger { -public: private: - static SceneDebugger *singleton; + inline static SceneDebugger *singleton = nullptr; SceneDebugger(); @@ -55,15 +57,19 @@ public: #ifdef DEBUG_ENABLED private: + static void _handle_input(const Ref<InputEvent> &p_event, const Ref<Shortcut> &p_shortcut); + static void _save_node(ObjectID id, const String &p_path); static void _set_node_owner_recursive(Node *p_node, Node *p_owner); static void _set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value); static void _send_object_id(ObjectID p_id, int p_max_size = 1 << 20); + static void _next_frame(); public: static Error parse_message(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured); static void add_to_cache(const String &p_filename, Node *p_node); static void remove_from_cache(const String &p_filename, Node *p_node); + static void reload_cached_files(const PackedStringArray &p_files); #endif }; @@ -158,13 +164,164 @@ private: LiveEditor() { singleton = this; live_edit_root = NodePath("/root"); - }; + } - static LiveEditor *singleton; + inline static LiveEditor *singleton = nullptr; public: static LiveEditor *get_singleton(); }; + +class RuntimeNodeSelect : public Object { + GDCLASS(RuntimeNodeSelect, Object); + +public: + enum NodeType { + NODE_TYPE_NONE, + NODE_TYPE_2D, + NODE_TYPE_3D, + NODE_TYPE_MAX + }; + + enum SelectMode { + SELECT_MODE_SINGLE, + SELECT_MODE_LIST, + SELECT_MODE_MAX + }; + +private: + friend class SceneDebugger; + + struct SelectResult { + Node *item = nullptr; + real_t order = 0; + _FORCE_INLINE_ bool operator<(const SelectResult &p_rr) const { return p_rr.order < order; } + }; + + bool has_selection = false; + Node *selected_node = nullptr; + PopupMenu *selection_list = nullptr; + bool selection_visible = true; + bool selection_update_queued = false; + bool warped_panning = false; + + bool camera_override = false; + + // Values taken from EditorZoomWidget. + const float VIEW_2D_MIN_ZOOM = 1.0 / 128; + const float VIEW_2D_MAX_ZOOM = 128; + + Ref<ViewPanner> panner; + Vector2 view_2d_offset; + real_t view_2d_zoom = 1.0; + + RID sbox_2d_canvas; + RID sbox_2d_ci; + Transform2D sbox_2d_xform; + Rect2 sbox_2d_rect; + +#ifndef _3D_DISABLED + struct Cursor { + Vector3 pos; + real_t x_rot, y_rot, distance, fov_scale; + Vector3 eye_pos; // Used in freelook mode. + + Cursor() { + // These rotations place the camera in +X +Y +Z, aka south east, facing north west. + x_rot = 0.5; + y_rot = -0.5; + distance = 4; + fov_scale = 1.0; + } + }; + Cursor cursor; + + // Values taken from Node3DEditor. + const float VIEW_3D_MIN_ZOOM = 0.01; +#ifdef REAL_T_IS_DOUBLE + const double VIEW_3D_MAX_ZOOM = 1'000'000'000'000; +#else + const float VIEW_3D_MAX_ZOOM = 10'000; +#endif + const float CAMERA_ZNEAR = 0.05; + const float CAMERA_ZFAR = 4'000; + + const float CAMERA_BASE_FOV = 75; + const float CAMERA_MIN_FOV_SCALE = 0.1; + const float CAMERA_MAX_FOV_SCALE = 2.5; + + const float FREELOOK_BASE_SPEED = 4; + const float RADS_PER_PIXEL = 0.004; + + bool camera_first_override = true; + bool camera_freelook = false; + + Vector2 previous_mouse_position; + + Ref<ArrayMesh> sbox_3d_mesh; + Ref<ArrayMesh> sbox_3d_mesh_xray; + RID sbox_3d_instance; + RID sbox_3d_instance_ofs; + RID sbox_3d_instance_xray; + RID sbox_3d_instance_xray_ofs; + Transform3D sbox_3d_xform; + AABB sbox_3d_bounds; +#endif + + Point2 selection_position = Point2(INFINITY, INFINITY); + bool list_shortcut_pressed = false; + + NodeType node_select_type = NODE_TYPE_2D; + SelectMode node_select_mode = SELECT_MODE_SINGLE; + + void _setup(const Dictionary &p_settings); + + void _node_set_type(NodeType p_type); + void _select_set_mode(SelectMode p_mode); + + void _set_camera_override_enabled(bool p_enabled); + + void _root_window_input(const Ref<InputEvent> &p_event); + void _items_popup_index_pressed(int p_index, PopupMenu *p_popup); + void _update_input_state(); + + void _process_frame(); + void _physics_frame(); + + void _click_point(); + void _select_node(Node *p_node); + void _queue_selection_update(); + void _update_selection(); + void _clear_selection(); + void _set_selection_visible(bool p_visible); + + void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<SelectResult> &r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event); + void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event); + void _reset_camera_2d(); + void _update_view_2d(); + +#ifndef _3D_DISABLED + void _find_3d_items_at_pos(const Point2 &p_pos, Vector<SelectResult> &r_items); + bool _handle_3d_input(const Ref<InputEvent> &p_event); + void _set_camera_freelook_enabled(bool p_enabled); + void _cursor_scale_distance(real_t p_scale); + void _cursor_look(Ref<InputEventWithModifiers> p_event); + void _cursor_pan(Ref<InputEventWithModifiers> p_event); + void _cursor_orbit(Ref<InputEventWithModifiers> p_event); + Transform3D _get_cursor_transform(); + void _reset_camera_3d(); +#endif + + RuntimeNodeSelect() { singleton = this; } + + inline static RuntimeNodeSelect *singleton = nullptr; + +public: + static RuntimeNodeSelect *get_singleton(); + + ~RuntimeNodeSelect(); +}; #endif #endif // SCENE_DEBUGGER_H diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 34f5095493..bd4770bcc3 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -205,6 +205,7 @@ void BaseButton::set_disabled(bool p_disabled) { status.pressing_inside = false; } queue_redraw(); + update_minimum_size(); } bool BaseButton::is_disabled() const { diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 0a5f2ec6c7..3e593a8372 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -296,19 +296,12 @@ void Button::_notification(int p_what) { } } break; case DRAW_HOVER_PRESSED: { - // Edge case for CheckButton and CheckBox. - if (has_theme_stylebox("hover_pressed")) { - if (has_theme_color(SNAME("font_hover_pressed_color"))) { - font_color = theme_cache.font_hover_pressed_color; - } - if (has_theme_color(SNAME("icon_hover_pressed_color"))) { - icon_modulate_color = theme_cache.icon_hover_pressed_color; - } - - break; + font_color = theme_cache.font_hover_pressed_color; + if (has_theme_color(SNAME("icon_hover_pressed_color"))) { + icon_modulate_color = theme_cache.icon_hover_pressed_color; } - } - [[fallthrough]]; + + } break; case DRAW_PRESSED: { if (has_theme_color(SNAME("font_pressed_color"))) { font_color = theme_cache.font_pressed_color; @@ -568,6 +561,7 @@ void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) { } autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; p_paragraph->set_break_flags(autowrap_flags); + p_paragraph->set_line_spacing(theme_cache.line_spacing); if (text_direction == Control::TEXT_DIRECTION_INHERITED) { p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); @@ -649,7 +643,7 @@ String Button::get_language() const { return language; } -void Button::set_icon(const Ref<Texture2D> &p_icon) { +void Button::set_button_icon(const Ref<Texture2D> &p_icon) { if (icon == p_icon) { return; } @@ -673,7 +667,7 @@ void Button::_texture_changed() { update_minimum_size(); } -Ref<Texture2D> Button::get_icon() const { +Ref<Texture2D> Button::get_button_icon() const { return icon; } @@ -769,8 +763,8 @@ void Button::_bind_methods() { ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction); ClassDB::bind_method(D_METHOD("set_language", "language"), &Button::set_language); ClassDB::bind_method(D_METHOD("get_language"), &Button::get_language); - ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon); - ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_icon); + ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_button_icon); + ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_button_icon); ClassDB::bind_method(D_METHOD("set_flat", "enabled"), &Button::set_flat); ClassDB::bind_method(D_METHOD("is_flat"), &Button::is_flat); ClassDB::bind_method(D_METHOD("set_clip_text", "enabled"), &Button::set_clip_text); @@ -840,6 +834,7 @@ void Button::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, icon_max_width); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, align_to_largest_stylebox); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, line_spacing); } Button::Button(const String &p_text) { diff --git a/scene/gui/button.h b/scene/gui/button.h index 5f4429bc1d..686d4806db 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -100,6 +100,7 @@ private: int h_separation = 0; int icon_max_width = 0; + int line_spacing = 0; } theme_cache; void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = ""); @@ -137,8 +138,8 @@ public: void set_language(const String &p_language); String get_language() const; - void set_icon(const Ref<Texture2D> &p_icon); - Ref<Texture2D> get_icon() const; + void set_button_icon(const Ref<Texture2D> &p_icon); + Ref<Texture2D> get_button_icon() const; void set_expand_icon(bool p_enabled); bool is_expand_icon() const; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 7346c9dcd3..89f1564775 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -1481,7 +1481,7 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 if (E) { text_rid = E->value; } else { - String fc = String::num(p_line + 1).lpad(line_number_digits, line_number_padding); + String fc = String::num_int64(p_line + 1).lpad(line_number_digits, line_number_padding); if (is_localizing_numeral_system()) { fc = TS->format_number(fc); } @@ -1498,9 +1498,9 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 ofs.y += TS->shaped_text_get_ascent(text_rid); if (rtl) { - ofs.x = p_region.position.x; - } else { ofs.x = p_region.get_end().x - text_size.width; + } else { + ofs.x = p_region.position.x; } Color number_color = get_line_gutter_item_color(p_line, line_number_gutter); diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index ab443e95e1..2cd34ec99f 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -251,13 +251,13 @@ private: Ref<Texture2D> completion_color_bg; Color breakpoint_color = Color(1, 1, 1); - Ref<Texture2D> breakpoint_icon = Ref<Texture2D>(); + Ref<Texture2D> breakpoint_icon; Color bookmark_color = Color(1, 1, 1); - Ref<Texture2D> bookmark_icon = Ref<Texture2D>(); + Ref<Texture2D> bookmark_icon; Color executing_line_color = Color(1, 1, 1); - Ref<Texture2D> executing_line_icon = Ref<Texture2D>(); + Ref<Texture2D> executing_line_icon; Color line_number_color = Color(1, 1, 1); diff --git a/scene/gui/color_mode.h b/scene/gui/color_mode.h index 94193ccf74..0abc90bb44 100644 --- a/scene/gui/color_mode.h +++ b/scene/gui/color_mode.h @@ -41,9 +41,9 @@ public: virtual String get_name() const = 0; - virtual int get_slider_count() const { return 3; }; + virtual int get_slider_count() const { return 3; } virtual float get_slider_step() const = 0; - virtual float get_spinbox_arrow_step() const { return get_slider_step(); }; + virtual float get_spinbox_arrow_step() const { return get_slider_step(); } virtual String get_slider_label(int idx) const = 0; virtual float get_slider_max(int idx) const = 0; virtual float get_slider_value(int idx) const = 0; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index fe4c91cb56..06dff67172 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -80,10 +80,10 @@ void ColorPicker::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - btn_pick->set_icon(theme_cache.screen_picker); + btn_pick->set_button_icon(theme_cache.screen_picker); _update_drop_down_arrow(btn_preset->is_pressed(), btn_preset); _update_drop_down_arrow(btn_recent_preset->is_pressed(), btn_recent_preset); - btn_add_preset->set_icon(theme_cache.add_preset); + btn_add_preset->set_button_icon(theme_cache.add_preset); btn_pick->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); btn_shape->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); @@ -116,7 +116,7 @@ void ColorPicker::_notification(int p_what) { shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_OKHSL_CIRCLE), theme_cache.shape_circle); if (current_shape != SHAPE_NONE) { - btn_shape->set_icon(shape_popup->get_item_icon(current_shape)); + btn_shape->set_button_icon(shape_popup->get_item_icon(current_shape)); } internal_margin->begin_bulk_theme_override(); @@ -217,14 +217,14 @@ void fragment() { circle_ok_color_shader->set_code(OK_COLOR_SHADER + R"( // ColorPicker ok color hsv circle shader. -uniform float v = 1.0; +uniform float ok_hsl_l = 1.0; void fragment() { float x = UV.x - 0.5; float y = UV.y - 0.5; float h = atan(y, x) / (2.0 * M_PI); float s = sqrt(x * x + y * y) * 2.0; - vec3 col = okhsl_to_srgb(vec3(h, s, v)); + vec3 col = okhsl_to_srgb(vec3(h, s, ok_hsl_l)); x += 0.001; y += 0.001; float b = float(sqrt(x * x + y * y) < 0.5); @@ -245,21 +245,7 @@ void ColorPicker::finish_shaders() { } void ColorPicker::set_focus_on_line_edit() { - bool has_hardware_keyboard = true; -#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED) - has_hardware_keyboard = DisplayServer::get_singleton()->has_hardware_keyboard(); -#endif // ANDROID_ENABLED || IOS_ENABLED - if (has_hardware_keyboard) { - callable_mp((Control *)c_text, &Control::grab_focus).call_deferred(); - } else { - // A hack to avoid showing the virtual keyboard when the ColorPicker window popups and - // no hardware keyboard is detected on Android and IOS. - // This will only focus the LineEdit without editing, the virtual keyboard will only be visible when - // we touch the LineEdit to enter edit mode. - callable_mp(c_text, &LineEdit::set_editable).call_deferred(false); - callable_mp((Control *)c_text, &Control::grab_focus).call_deferred(); - callable_mp(c_text, &LineEdit::set_editable).call_deferred(true); - } + callable_mp((Control *)c_text, &Control::grab_focus).call_deferred(); } void ColorPicker::_update_controls() { @@ -401,10 +387,21 @@ void ColorPicker::_slider_value_changed() { color = modes[current_mode]->get_color(); modes[current_mode]->_value_changed(); - if (current_mode == MODE_HSV || current_mode == MODE_OKHSL) { + if (current_mode == MODE_HSV) { h = sliders[0]->get_value() / 360.0; s = sliders[1]->get_value() / 100.0; v = sliders[2]->get_value() / 100.0; + ok_hsl_h = color.get_ok_hsl_h(); + ok_hsl_s = color.get_ok_hsl_s(); + ok_hsl_l = color.get_ok_hsl_l(); + last_color = color; + } else if (current_mode == MODE_OKHSL) { + ok_hsl_h = sliders[0]->get_value() / 360.0; + ok_hsl_s = sliders[1]->get_value() / 100.0; + ok_hsl_l = sliders[2]->get_value() / 100.0; + h = color.get_h(); + s = color.get_s(); + v = color.get_v(); last_color = color; } @@ -518,20 +515,17 @@ Vector<float> ColorPicker::get_active_slider_values() { } void ColorPicker::_copy_color_to_hsv() { - if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { - h = color.get_ok_hsl_h(); - s = color.get_ok_hsl_s(); - v = color.get_ok_hsl_l(); - } else { - h = color.get_h(); - s = color.get_s(); - v = color.get_v(); - } + ok_hsl_h = color.get_ok_hsl_h(); + ok_hsl_s = color.get_ok_hsl_s(); + ok_hsl_l = color.get_ok_hsl_l(); + h = color.get_h(); + s = color.get_s(); + v = color.get_v(); } void ColorPicker::_copy_hsv_to_color() { if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { - color.set_ok_hsl(h, s, v, color.a); + color.set_ok_hsl(ok_hsl_h, ok_hsl_s, ok_hsl_l, color.a); } else { color.set_hsv(h, s, v, color.a); } @@ -719,14 +713,14 @@ void ColorPicker::_text_type_toggled() { if (text_is_constructor) { text_type->set_text(""); #ifdef TOOLS_ENABLED - text_type->set_icon(get_editor_theme_icon(SNAME("Script"))); + text_type->set_button_icon(get_editor_theme_icon(SNAME("Script"))); #endif c_text->set_editable(false); c_text->set_tooltip_text(RTR("Copy this constructor in a script.")); } else { text_type->set_text("#"); - text_type->set_icon(nullptr); + text_type->set_button_icon(nullptr); c_text->set_editable(true); c_text->set_tooltip_text(ETR("Enter a hex code (\"#ff0000\") or named color (\"red\").")); @@ -752,7 +746,7 @@ void ColorPicker::set_picker_shape(PickerShapeType p_shape) { } if (p_shape != SHAPE_NONE) { shape_popup->set_item_checked(p_shape, true); - btn_shape->set_icon(shape_popup->get_item_icon(p_shape)); + btn_shape->set_button_icon(shape_popup->get_item_icon(p_shape)); } current_shape = p_shape; @@ -808,9 +802,9 @@ void ColorPicker::_show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_ void ColorPicker::_update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset) { if (p_is_btn_pressed) { - p_btn_preset->set_icon(theme_cache.expanded_arrow); + p_btn_preset->set_button_icon(theme_cache.expanded_arrow); } else { - p_btn_preset->set_icon(theme_cache.folded_arrow); + p_btn_preset->set_button_icon(theme_cache.folded_arrow); } } @@ -1215,8 +1209,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { int x; int y; if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { - x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2); - y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2); + x = center.x + (center.x * Math::cos((actual_shape == SHAPE_OKHSL_CIRCLE ? ok_hsl_h : h) * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2); + y = center.y + (center.y * Math::sin((actual_shape == SHAPE_OKHSL_CIRCLE ? ok_hsl_h : h) * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2); } else { real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; @@ -1252,11 +1246,11 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { Vector<Point2> points; Vector<Color> colors; Color col; - col.set_ok_hsl(h, s, 1); + col.set_ok_hsl(ok_hsl_h, ok_hsl_s, 1); Color col2; - col2.set_ok_hsl(h, s, 0.5); + col2.set_ok_hsl(ok_hsl_h, ok_hsl_s, 0.5); Color col3; - col3.set_ok_hsl(h, s, 0); + col3.set_ok_hsl(ok_hsl_h, ok_hsl_s, 0); points.resize(6); colors.resize(6); points.set(0, Vector2(c->get_size().x, 0)); @@ -1272,8 +1266,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { colors.set(4, col2); colors.set(5, col); c->draw_polygon(points, colors); - int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1); - col.set_ok_hsl(h, 1, v); + int y = c->get_size().y - c->get_size().y * CLAMP(ok_hsl_l, 0, 1); + col.set_ok_hsl(ok_hsl_h, 1, ok_hsl_l); c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); } else if (actual_shape == SHAPE_VHS_CIRCLE) { Vector<Point2> points; @@ -1297,8 +1291,10 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { } } else if (p_which == 2) { c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1)); - if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { + if (actual_shape == SHAPE_VHS_CIRCLE) { circle_mat->set_shader_parameter("v", v); + } else if (actual_shape == SHAPE_OKHSL_CIRCLE) { + circle_mat->set_shader_parameter("ok_hsl_l", ok_hsl_l); } } } @@ -1322,6 +1318,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { real_t rad = center.angle_to_point(bev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; s = CLAMP(dist / center.x, 0, 1); + ok_hsl_h = h; + ok_hsl_s = s; } else { return; } @@ -1389,6 +1387,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { real_t rad = center.angle_to_point(mev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; s = CLAMP(dist / center.x, 0, 1); + ok_hsl_h = h; + ok_hsl_s = s; } else { if (spinning) { real_t rad = center.angle_to_point(mev->get_position()); @@ -1426,6 +1426,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { v = 1.0 - (y / w_edit->get_size().height); + ok_hsl_l = v; } else { h = y / w_edit->get_size().height; } @@ -1454,6 +1455,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height); if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { v = 1.0 - (y / w_edit->get_size().height); + ok_hsl_l = v; } else { h = y / w_edit->get_size().height; } @@ -1567,23 +1569,21 @@ void ColorPicker::_pick_button_pressed_legacy() { picker_texture_rect = memnew(TextureRect); picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT); + picker_texture_rect->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE); picker_window->add_child(picker_texture_rect); picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND); picker_texture_rect->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_picker_texture_input)); - picker_preview = memnew(Panel); - picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); - picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_window->add_child(picker_preview); - picker_preview_label = memnew(Label); - picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview_label->set_anchors_preset(Control::PRESET_CENTER_TOP); picker_preview_label->set_text(ETR("Color Picking active")); - picker_preview->add_child(picker_preview_label); - picker_preview_style_box = (Ref<StyleBoxFlat>)memnew(StyleBoxFlat); + picker_preview_style_box.instantiate(); picker_preview_style_box->set_bg_color(Color(1.0, 1.0, 1.0)); - picker_preview->add_theme_style_override(SceneStringName(panel), picker_preview_style_box); + picker_preview_style_box->set_content_margin_all(4.0); + picker_preview_label->add_theme_style_override(CoreStringName(normal), picker_preview_style_box); + + picker_window->add_child(picker_preview_label); } Rect2i screen_rect; @@ -1625,7 +1625,7 @@ void ColorPicker::_pick_button_pressed_legacy() { } picker_window->set_size(screen_rect.size); - picker_preview->set_size(screen_rect.size / 10.0); // 10% of size in each axis. + picker_preview_label->set_custom_minimum_size(screen_rect.size / 10); // 10% of size in each axis. picker_window->popup(); } @@ -1648,7 +1648,7 @@ void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) { Vector2 ofs = mev->get_position(); picker_color = img->get_pixel(ofs.x, ofs.y); picker_preview_style_box->set_bg_color(picker_color); - picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); + picker_preview_label->add_theme_color_override(SceneStringName(font_color), picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); } } } @@ -2103,7 +2103,9 @@ void ColorPickerButton::pressed() { float v_offset = show_above ? -minsize.y : get_size().y; popup->set_position(get_screen_position() + Vector2(h_offset, v_offset)); popup->popup(); - picker->set_focus_on_line_edit(); + if (DisplayServer::get_singleton()->has_hardware_keyboard()) { + picker->set_focus_on_line_edit(); + } } void ColorPickerButton::_notification(int p_what) { diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index ad028584b1..aedf4aef16 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -130,7 +130,6 @@ private: Popup *picker_window = nullptr; // Legacy color picking. TextureRect *picker_texture_rect = nullptr; - Panel *picker_preview = nullptr; Label *picker_preview_label = nullptr; Ref<StyleBoxFlat> picker_preview_style_box; Color picker_color; @@ -212,6 +211,11 @@ private: float h = 0.0; float s = 0.0; float v = 0.0; + + float ok_hsl_h = 0.0; + float ok_hsl_s = 0.0; + float ok_hsl_l = 0.0; + Color last_color; struct ThemeCache { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index c1d197ea9b..4a3f7f2414 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -44,7 +44,7 @@ #ifdef TOOLS_ENABLED #include "editor/plugins/control_editor_plugin.h" -#endif +#endif // TOOLS_ENABLED // Editor plugin interoperability. @@ -120,11 +120,11 @@ void Control::_edit_set_state(const Dictionary &p_state) { void Control::_edit_set_position(const Point2 &p_position) { ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); set_position(p_position, ControlEditorToolbar::get_singleton()->is_anchors_mode_enabled() && get_parent_control()); -}; +} Point2 Control::_edit_get_position() const { return get_position(); -}; +} void Control::_edit_set_scale(const Size2 &p_scale) { set_scale(p_scale); @@ -140,14 +140,6 @@ void Control::_edit_set_rect(const Rect2 &p_edit_rect) { set_size(p_edit_rect.size.snappedf(1), ControlEditorToolbar::get_singleton()->is_anchors_mode_enabled()); } -Rect2 Control::_edit_get_rect() const { - return Rect2(Point2(), get_size()); -} - -bool Control::_edit_use_rect() const { - return true; -} - void Control::_edit_set_rotation(real_t p_rotation) { set_rotation(p_rotation); } @@ -178,7 +170,17 @@ bool Control::_edit_use_pivot() const { Size2 Control::_edit_get_minimum_size() const { return get_combined_minimum_size(); } -#endif +#endif // TOOLS_ENABLED + +#ifdef DEBUG_ENABLED +Rect2 Control::_edit_get_rect() const { + return Rect2(Point2(), get_size()); +} + +bool Control::_edit_use_rect() const { + return true; +} +#endif // DEBUG_ENABLED void Control::reparent(Node *p_parent, bool p_keep_global_transform) { ERR_MAIN_THREAD_GUARD; @@ -239,7 +241,7 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List } CanvasItem::get_argument_options(p_function, p_idx, r_options); } -#endif +#endif // TOOLS_ENABLED PackedStringArray Control::get_configuration_warnings() const { ERR_READ_THREAD_GUARD_V(PackedStringArray()); @@ -663,7 +665,7 @@ Rect2 Control::get_parent_anchorable_rect() const { #else parent_rect = get_viewport()->get_visible_rect(); -#endif +#endif // TOOLS_ENABLED } return parent_rect; @@ -1396,7 +1398,7 @@ void Control::set_position(const Point2 &p_point, bool p_keep_offsets) { data.pos_cache = p_point; return; } -#endif +#endif // TOOLS_ENABLED if (p_keep_offsets) { _compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor); @@ -1440,7 +1442,7 @@ void Control::_set_size(const Size2 &p_size) { if (data.size_warning && (data.anchor[SIDE_LEFT] != data.anchor[SIDE_RIGHT] || data.anchor[SIDE_TOP] != data.anchor[SIDE_BOTTOM])) { WARN_PRINT("Nodes with non-equal opposite anchors will have their size overridden after _ready(). \nIf you want to set size, change the anchors or consider using set_deferred()."); } -#endif +#endif // DEBUG_ENABLED set_size(p_size); } @@ -1462,7 +1464,7 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) { data.size_cache = new_size; return; } -#endif +#endif // TOOLS_ENABLED if (p_keep_offsets) { _compute_anchors(Rect2(data.pos_cache, new_size), data.offset, data.anchor); @@ -2745,7 +2747,7 @@ Variant Control::get_theme_item(Theme::DataType p_data_type, const StringName &p Ref<Texture2D> Control::get_editor_theme_icon(const StringName &p_name) const { return get_theme_icon(p_name, SNAME("EditorIcons")); } -#endif +#endif // TOOLS_ENABLED bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); @@ -3042,7 +3044,7 @@ void Control::set_layout_direction(Control::LayoutDirection p_direction) { if (data.layout_dir == p_direction) { return; } - ERR_FAIL_INDEX((int)p_direction, 4); + ERR_FAIL_INDEX(p_direction, LAYOUT_DIRECTION_MAX); data.layout_dir = p_direction; @@ -3087,7 +3089,7 @@ bool Control::is_layout_rtl() const { const_cast<Control *>(this)->data.is_rtl = true; return data.is_rtl; } -#endif +#endif // TOOLS_ENABLED Node *parent_node = get_parent(); while (parent_node) { Control *parent_control = Object::cast_to<Control>(parent_node); @@ -3115,13 +3117,20 @@ bool Control::is_layout_rtl() const { String locale = TranslationServer::get_singleton()->get_tool_locale(); const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale); } - } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) { + } else if (data.layout_dir == LAYOUT_DIRECTION_APPLICATION_LOCALE) { if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { const_cast<Control *>(this)->data.is_rtl = true; } else { String locale = TranslationServer::get_singleton()->get_tool_locale(); const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale); } + } else if (data.layout_dir == LAYOUT_DIRECTION_SYSTEM_LOCALE) { + if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { + const_cast<Control *>(this)->data.is_rtl = true; + } else { + String locale = OS::get_singleton()->get_locale(); + const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale); + } } else { const_cast<Control *>(this)->data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL); } @@ -3155,7 +3164,7 @@ bool Control::is_auto_translating() const { ERR_READ_THREAD_GUARD_V(false); return can_auto_translate(); } -#endif +#endif // DISABLE_DEPRECATED void Control::set_tooltip_auto_translate_mode(AutoTranslateMode p_mode) { ERR_MAIN_THREAD_GUARD; @@ -3208,7 +3217,7 @@ void Control::_notification(int p_notification) { case NOTIFICATION_EDITOR_POST_SAVE: { saving = false; } break; -#endif +#endif // TOOLS_ENABLED case NOTIFICATION_POSTINITIALIZE: { data.initialized = true; @@ -3254,7 +3263,7 @@ void Control::_notification(int p_notification) { case NOTIFICATION_READY: { #ifdef DEBUG_ENABLED connect(SceneStringName(ready), callable_mp(this, &Control::_clear_size_warning), CONNECT_DEFERRED | CONNECT_ONE_SHOT); -#endif +#endif // DEBUG_ENABLED } break; case NOTIFICATION_ENTER_CANVAS: { @@ -3566,7 +3575,7 @@ void Control::_bind_methods() { #ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_auto_translate", "enable"), &Control::set_auto_translate); ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating); -#endif +#endif // DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_localize_numeral_system", "enable"), &Control::set_localize_numeral_system); ClassDB::bind_method(D_METHOD("is_localizing_numeral_system"), &Control::is_localizing_numeral_system); @@ -3574,7 +3583,7 @@ void Control::_bind_methods() { ADD_GROUP("Layout", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "custom_minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Based on Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Based on Application Locale,Left-to-Right,Right-to-Left,Based on System Locale"), "set_layout_direction", "get_layout_direction"); ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode"); ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION); @@ -3621,7 +3630,7 @@ void Control::_bind_methods() { #ifndef DISABLE_DEPRECATED ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_auto_translate", "is_auto_translating"); -#endif +#endif // DISABLE_DEPRECATED ADD_GROUP("Tooltip", "tooltip_"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip_text", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip_text", "get_tooltip_text"); @@ -3723,9 +3732,14 @@ void Control::_bind_methods() { BIND_ENUM_CONSTANT(ANCHOR_END); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED); - BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE); + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_APPLICATION_LOCALE); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_RTL); + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_SYSTEM_LOCALE); + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_MAX); +#ifndef DISABLE_DEPRECATED + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE); +#endif // DISABLE_DEPRECATED BIND_ENUM_CONSTANT(TEXT_DIRECTION_INHERITED); BIND_ENUM_CONSTANT(TEXT_DIRECTION_AUTO); diff --git a/scene/gui/control.h b/scene/gui/control.h index 6e1621ce58..ac386659ec 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -48,7 +48,7 @@ class Control : public CanvasItem { #ifdef TOOLS_ENABLED bool saving = false; -#endif +#endif //TOOLS_ENABLED public: enum Anchor { @@ -140,9 +140,14 @@ public: enum LayoutDirection { LAYOUT_DIRECTION_INHERITED, - LAYOUT_DIRECTION_LOCALE, + LAYOUT_DIRECTION_APPLICATION_LOCALE, LAYOUT_DIRECTION_LTR, - LAYOUT_DIRECTION_RTL + LAYOUT_DIRECTION_RTL, + LAYOUT_DIRECTION_SYSTEM_LOCALE, + LAYOUT_DIRECTION_MAX, +#ifndef DISABLE_DEPRECATED + LAYOUT_DIRECTION_LOCALE = LAYOUT_DIRECTION_APPLICATION_LOCALE, +#endif // DISABLE_DEPRECATED }; enum TextDirection { @@ -391,8 +396,6 @@ public: virtual Size2 _edit_get_scale() const override; virtual void _edit_set_rect(const Rect2 &p_edit_rect) override; - virtual Rect2 _edit_get_rect() const override; - virtual bool _edit_use_rect() const override; virtual void _edit_set_rotation(real_t p_rotation) override; virtual real_t _edit_get_rotation() const override; @@ -403,7 +406,13 @@ public: virtual bool _edit_use_pivot() const override; virtual Size2 _edit_get_minimum_size() const override; -#endif +#endif //TOOLS_ENABLED + +#ifdef DEBUG_ENABLED + virtual Rect2 _edit_get_rect() const override; + virtual bool _edit_use_rect() const override; +#endif // DEBUG_ENABLED + virtual void reparent(Node *p_parent, bool p_keep_global_transform = true) override; // Editor integration. @@ -413,7 +422,7 @@ public: PackedStringArray get_configuration_warnings() const override; #ifdef TOOLS_ENABLED virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; -#endif +#endif //TOOLS_ENABLED virtual bool is_text_field() const; @@ -600,7 +609,7 @@ public: Variant get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type = StringName()) const; #ifdef TOOLS_ENABLED Ref<Texture2D> get_editor_theme_icon(const StringName &p_name) const; -#endif +#endif //TOOLS_ENABLED bool has_theme_icon_override(const StringName &p_name) const; bool has_theme_stylebox_override(const StringName &p_name) const; @@ -632,7 +641,7 @@ public: #ifndef DISABLE_DEPRECATED void set_auto_translate(bool p_enable); bool is_auto_translating() const; -#endif +#endif //DISABLE_DEPRECATED void set_tooltip_auto_translate_mode(AutoTranslateMode p_mode); AutoTranslateMode get_tooltip_auto_translate_mode() const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index d8e9d1bcc0..e601f16843 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -50,7 +50,7 @@ void FileDialog::popup_file_dialog() { } void FileDialog::_focus_file_text() { - int lp = file->get_text().rfind("."); + int lp = file->get_text().rfind_char('.'); if (lp != -1) { file->select(0, lp); if (file->is_inside_tree() && !is_part_of_edited_scene()) { @@ -67,7 +67,18 @@ void FileDialog::_native_popup() { } else if (access == ACCESS_USERDATA) { root = OS::get_singleton()->get_user_data_dir(); } - DisplayServer::get_singleton()->file_dialog_with_options_show(get_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), filters, _get_options(), callable_mp(this, &FileDialog::_native_dialog_cb)); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE_EXTRA)) { + DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &FileDialog::_native_dialog_cb_with_options)); + } else { + DisplayServer::get_singleton()->file_dialog_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, callable_mp(this, &FileDialog::_native_dialog_cb)); + } +} + +bool FileDialog::_can_use_native_popup() { + if (access == ACCESS_RESOURCES || access == ACCESS_USERDATA || options.size() > 0) { + return DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE_EXTRA); + } + return DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE); } void FileDialog::popup(const Rect2i &p_rect) { @@ -80,7 +91,7 @@ void FileDialog::popup(const Rect2i &p_rect) { } #endif - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (_can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { _native_popup(); } else { ConfirmationDialog::popup(p_rect); @@ -99,7 +110,7 @@ void FileDialog::set_visible(bool p_visible) { } #endif - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (_can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { if (p_visible) { _native_popup(); } @@ -108,7 +119,11 @@ void FileDialog::set_visible(bool p_visible) { } } -void FileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options) { +void FileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter) { + _native_dialog_cb_with_options(p_ok, p_files, p_filter, Dictionary()); +} + +void FileDialog::_native_dialog_cb_with_options(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options) { if (!p_ok) { file->set_text(""); emit_signal(SNAME("canceled")); @@ -182,7 +197,7 @@ void FileDialog::_notification(int p_what) { #endif // Replace the built-in dialog with the native one if it started visible. - if (is_visible() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (is_visible() && _can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { ConfirmationDialog::set_visible(false); _native_popup(); } @@ -197,18 +212,18 @@ void FileDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - dir_up->set_icon(theme_cache.parent_folder); + dir_up->set_button_icon(theme_cache.parent_folder); if (vbox->is_layout_rtl()) { - dir_prev->set_icon(theme_cache.forward_folder); - dir_next->set_icon(theme_cache.back_folder); + dir_prev->set_button_icon(theme_cache.forward_folder); + dir_next->set_button_icon(theme_cache.back_folder); } else { - dir_prev->set_icon(theme_cache.back_folder); - dir_next->set_icon(theme_cache.forward_folder); + dir_prev->set_button_icon(theme_cache.back_folder); + dir_next->set_button_icon(theme_cache.forward_folder); } - refresh->set_icon(theme_cache.reload); - show_hidden->set_icon(theme_cache.toggle_hidden); - makedir->set_icon(theme_cache.create_folder); - show_filename_filter_button->set_icon(theme_cache.toggle_filename_filter); + refresh->set_button_icon(theme_cache.reload); + show_hidden->set_button_icon(theme_cache.toggle_hidden); + makedir->set_button_icon(theme_cache.create_folder); + show_filename_filter_button->set_button_icon(theme_cache.toggle_filename_filter); dir_up->begin_bulk_theme_override(); dir_up->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color); @@ -836,37 +851,54 @@ void FileDialog::_filename_filter_selected() { void FileDialog::update_filters() { filter->clear(); + processed_filters.clear(); if (filters.size() > 1) { String all_filters; + String all_filters_full; const int max_filters = 5; for (int i = 0; i < MIN(max_filters, filters.size()); i++) { - String flt = filters[i].get_slice(";", 0).strip_edges(); + String flt = filters[i].get_slicec(';', 0).strip_edges(); if (i > 0) { all_filters += ", "; } all_filters += flt; } + for (int i = 0; i < filters.size(); i++) { + String flt = filters[i].get_slicec(';', 0).strip_edges(); + if (i > 0) { + all_filters_full += ","; + } + all_filters_full += flt; + } if (max_filters < filters.size()) { all_filters += ", ..."; } - filter->add_item(atr(ETR("All Recognized")) + " (" + all_filters + ")"); + String f = atr(ETR("All Recognized")) + " (" + all_filters + ")"; + filter->add_item(f); + processed_filters.push_back(all_filters_full + ";" + f); } for (int i = 0; i < filters.size(); i++) { - String flt = filters[i].get_slice(";", 0).strip_edges(); + String flt = filters[i].get_slicec(';', 0).strip_edges(); String desc = filters[i].get_slice(";", 1).strip_edges(); if (desc.length()) { - filter->add_item(String(tr(desc)) + " (" + flt + ")"); + String f = atr(desc) + " (" + flt + ")"; + filter->add_item(f); + processed_filters.push_back(flt + ";" + f); } else { - filter->add_item("(" + flt + ")"); + String f = "(" + flt + ")"; + filter->add_item(f); + processed_filters.push_back(flt + ";" + f); } } - filter->add_item(atr(ETR("All Files")) + " (*)"); + String f = atr(ETR("All Files")) + " (*)"; + filter->add_item(f); + processed_filters.push_back("*.*;" + f); } void FileDialog::clear_filename_filter() { @@ -969,7 +1001,7 @@ void FileDialog::set_current_path(const String &p_path) { if (!p_path.size()) { return; } - int pos = MAX(p_path.rfind("/"), p_path.rfind("\\")); + int pos = MAX(p_path.rfind_char('/'), p_path.rfind_char('\\')); if (pos == -1) { set_current_file(p_path); } else { @@ -1487,7 +1519,7 @@ void FileDialog::set_use_native_dialog(bool p_native) { #endif // Replace the built-in dialog with the native one if it's currently visible. - if (is_inside_tree() && is_visible() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (is_inside_tree() && is_visible() && _can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { ConfirmationDialog::set_visible(false); _native_popup(); } @@ -1571,6 +1603,7 @@ FileDialog::FileDialog() { vbox->add_child(hbc); tree = memnew(Tree); + tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tree->set_hide_root(true); vbox->add_margin_child(ETR("Directories & Files:"), tree, true); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 6ef60a0f4f..82067ac534 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -101,6 +101,7 @@ private: Button *show_filename_filter_button = nullptr; Vector<String> filters; + Vector<String> processed_filters; String file_name_filter; bool show_filename_filter = false; @@ -188,8 +189,10 @@ private: virtual void shortcut_input(const Ref<InputEvent> &p_event) override; + bool _can_use_native_popup(); void _native_popup(); - void _native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options); + void _native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter); + void _native_dialog_cb_with_options(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options); bool _is_open_should_be_disabled(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 646757008a..7e07f4a202 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -317,7 +317,7 @@ bool GraphEdit::is_node_connected(const StringName &p_from, int p_from_port, con void GraphEdit::disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port) { ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); - for (const List<Ref<Connection>>::Element *E = connections.front(); E; E = E->next()) { + for (List<Ref<Connection>>::Element *E = connections.front(); E; E = E->next()) { if (E->get()->from_node == p_from && E->get()->from_port == p_from_port && E->get()->to_node == p_to && E->get()->to_port == p_to_port) { connection_map[p_from].erase(E->get()); connection_map[p_to].erase(E->get()); @@ -733,14 +733,14 @@ void GraphEdit::_update_theme_item_cache() { void GraphEdit::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - zoom_minus_button->set_icon(theme_cache.zoom_out); - zoom_reset_button->set_icon(theme_cache.zoom_reset); - zoom_plus_button->set_icon(theme_cache.zoom_in); + zoom_minus_button->set_button_icon(theme_cache.zoom_out); + zoom_reset_button->set_button_icon(theme_cache.zoom_reset); + zoom_plus_button->set_button_icon(theme_cache.zoom_in); - toggle_snapping_button->set_icon(theme_cache.snapping_toggle); - toggle_grid_button->set_icon(theme_cache.grid_toggle); - minimap_button->set_icon(theme_cache.minimap_toggle); - arrange_button->set_icon(theme_cache.layout); + toggle_snapping_button->set_button_icon(theme_cache.snapping_toggle); + toggle_grid_button->set_button_icon(theme_cache.grid_toggle); + minimap_button->set_button_icon(theme_cache.minimap_toggle); + arrange_button->set_button_icon(theme_cache.layout); zoom_label->set_custom_minimum_size(Size2(48, 0) * theme_cache.base_scale); @@ -3001,5 +3001,5 @@ GraphEdit::GraphEdit() { set_clip_contents(true); - arranger = Ref<GraphEditArranger>(memnew(GraphEditArranger(this))); + arranger.instantiate(this); } diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 42b4e56b48..7a0e5b8867 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -335,6 +335,121 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col } } +void Label::_ensure_shaped() const { + if (dirty || font_dirty || lines_dirty) { + const_cast<Label *>(this)->_shape(); + } +} + +RID Label::get_line_rid(int p_line) const { + return lines_rid[p_line]; +} + +Rect2 Label::get_line_rect(int p_line) const { + // Returns a rect providing the line's horizontal offset and total size. To determine the vertical + // offset, use r_offset and r_line_spacing from get_layout_data. + bool rtl = TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL; + bool rtl_layout = is_layout_rtl(); + Ref<StyleBox> style = theme_cache.normal_style; + Size2 size = get_size(); + Size2 line_size = TS->shaped_text_get_size(lines_rid[p_line]); + Vector2 offset; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_FILL: + if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) { + offset.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); + } else { + offset.x = style->get_offset().x; + } + break; + case HORIZONTAL_ALIGNMENT_LEFT: { + if (rtl_layout) { + offset.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); + } else { + offset.x = style->get_offset().x; + } + } break; + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = int(size.width - line_size.width) / 2; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + if (rtl_layout) { + offset.x = style->get_offset().x; + } else { + offset.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); + } + } break; + } + + return Rect2(offset, line_size); +} + +void Label::get_layout_data(Vector2 &r_offset, int &r_line_limit, int &r_line_spacing) const { + // Computes several common parameters involved in laying out and rendering text set to this label. + // Only vertical margin is considered in r_offset: use get_line_rect to get the horizontal offset + // for a given line of text. + Size2 size = get_size(); + Ref<StyleBox> style = theme_cache.normal_style; + int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing; + + float total_h = 0.0; + int lines_visible = 0; + + // Get number of lines to fit to the height. + for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { + total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { + break; + } + lines_visible++; + } + + if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { + lines_visible = max_lines_visible; + } + + r_line_limit = MIN(lines_rid.size(), lines_visible + lines_skipped); + + // Get real total height. + total_h = 0; + for (int64_t i = lines_skipped; i < r_line_limit; i++) { + total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + } + total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); + + int vbegin = 0, vsep = 0; + if (lines_visible > 0) { + switch (vertical_alignment) { + case VERTICAL_ALIGNMENT_TOP: { + // Nothing. + } break; + case VERTICAL_ALIGNMENT_CENTER: { + vbegin = (size.y - (total_h - line_spacing)) / 2; + vsep = 0; + + } break; + case VERTICAL_ALIGNMENT_BOTTOM: { + vbegin = size.y - (total_h - line_spacing); + vsep = 0; + + } break; + case VERTICAL_ALIGNMENT_FILL: { + vbegin = 0; + if (lines_visible > 1) { + vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1); + } else { + vsep = 0; + } + + } break; + } + } + + r_offset = { 0, style->get_offset().y + vbegin }; + r_line_spacing = line_spacing + vsep; +} + PackedStringArray Label::get_configuration_warnings() const { PackedStringArray warnings = Control::get_configuration_warnings(); @@ -361,10 +476,7 @@ PackedStringArray Label::get_configuration_warnings() const { } if (font.is_valid()) { - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - + _ensure_shaped(); const Glyph *glyph = TS->shaped_text_get_glyphs(text_rid); int64_t glyph_count = TS->shaped_text_get_glyph_count(text_rid); for (int64_t i = 0; i < glyph_count; i++) { @@ -416,22 +528,17 @@ void Label::_notification(int p_what) { } } - if (dirty || font_dirty || lines_dirty) { - _shape(); - } + _ensure_shaped(); RID ci = get_canvas_item(); bool has_settings = settings.is_valid(); Size2 string_size; - Size2 size = get_size(); Ref<StyleBox> style = theme_cache.normal_style; - Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font; Color font_color = has_settings ? settings->get_font_color() : theme_cache.font_color; Color font_shadow_color = has_settings ? settings->get_shadow_color() : theme_cache.font_shadow_color; Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : theme_cache.font_shadow_offset; - int line_spacing = has_settings ? settings->get_line_spacing() : theme_cache.line_spacing; Color font_outline_color = has_settings ? settings->get_outline_color() : theme_cache.font_outline_color; int outline_size = has_settings ? settings->get_outline_size() : theme_cache.font_outline_size; int shadow_outline_size = has_settings ? settings->get_shadow_size() : theme_cache.font_shadow_outline_size; @@ -440,98 +547,28 @@ void Label::_notification(int p_what) { style->draw(ci, Rect2(Point2(0, 0), get_size())); - float total_h = 0.0; - int lines_visible = 0; - - // Get number of lines to fit to the height. - for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; - if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { - break; - } - lines_visible++; - } - - if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { - lines_visible = max_lines_visible; - } - - int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped); bool trim_chars = (visible_chars >= 0) && (visible_chars_behavior == TextServer::VC_CHARS_AFTER_SHAPING); bool trim_glyphs_ltr = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !rtl_layout)); bool trim_glyphs_rtl = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && rtl_layout)); - // Get real total height. + Vector2 ofs; + int line_limit; + int line_spacing; + get_layout_data(ofs, line_limit, line_spacing); + + int processed_glyphs = 0; int total_glyphs = 0; - total_h = 0; - for (int64_t i = lines_skipped; i < last_line; i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + + for (int64_t i = lines_skipped; i < line_limit; i++) { total_glyphs += TS->shaped_text_get_glyph_count(lines_rid[i]) + TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]); } - int visible_glyphs = total_glyphs * visible_ratio; - int processed_glyphs = 0; - total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); - - int vbegin = 0, vsep = 0; - if (lines_visible > 0) { - switch (vertical_alignment) { - case VERTICAL_ALIGNMENT_TOP: { - // Nothing. - } break; - case VERTICAL_ALIGNMENT_CENTER: { - vbegin = (size.y - (total_h - line_spacing)) / 2; - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_BOTTOM: { - vbegin = size.y - (total_h - line_spacing); - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_FILL: { - vbegin = 0; - if (lines_visible > 1) { - vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1); - } else { - vsep = 0; - } - } break; - } - } + int visible_glyphs = total_glyphs * visible_ratio; - Vector2 ofs; - ofs.y = style->get_offset().y + vbegin; - for (int i = lines_skipped; i < last_line; i++) { - Size2 line_size = TS->shaped_text_get_size(lines_rid[i]); - ofs.x = 0; + for (int i = lines_skipped; i < line_limit; i++) { + Vector2 line_offset = get_line_rect(i).position; + ofs.x = line_offset.x; ofs.y += TS->shaped_text_get_ascent(lines_rid[i]); - switch (horizontal_alignment) { - case HORIZONTAL_ALIGNMENT_FILL: - if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - break; - case HORIZONTAL_ALIGNMENT_LEFT: { - if (rtl_layout) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - } break; - case HORIZONTAL_ALIGNMENT_CENTER: { - ofs.x = int(size.width - line_size.width) / 2; - } break; - case HORIZONTAL_ALIGNMENT_RIGHT: { - if (rtl_layout) { - ofs.x = style->get_offset().x; - } else { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } - } break; - } const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]); @@ -621,7 +658,7 @@ void Label::_notification(int p_what) { } } } - ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing; + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } break; @@ -637,102 +674,16 @@ void Label::_notification(int p_what) { } Rect2 Label::get_character_bounds(int p_pos) const { - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - - bool has_settings = settings.is_valid(); - Size2 size = get_size(); - Ref<StyleBox> style = theme_cache.normal_style; - int line_spacing = has_settings ? settings->get_line_spacing() : theme_cache.line_spacing; - bool rtl = (TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL); - bool rtl_layout = is_layout_rtl(); - - float total_h = 0.0; - int lines_visible = 0; - - // Get number of lines to fit to the height. - for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; - if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { - break; - } - lines_visible++; - } - - if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { - lines_visible = max_lines_visible; - } - - int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped); - - // Get real total height. - total_h = 0; - for (int64_t i = lines_skipped; i < last_line; i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; - } - - total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); - - int vbegin = 0, vsep = 0; - if (lines_visible > 0) { - switch (vertical_alignment) { - case VERTICAL_ALIGNMENT_TOP: { - // Nothing. - } break; - case VERTICAL_ALIGNMENT_CENTER: { - vbegin = (size.y - (total_h - line_spacing)) / 2; - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_BOTTOM: { - vbegin = size.y - (total_h - line_spacing); - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_FILL: { - vbegin = 0; - if (lines_visible > 1) { - vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1); - } else { - vsep = 0; - } - - } break; - } - } + _ensure_shaped(); Vector2 ofs; - ofs.y = style->get_offset().y + vbegin; - for (int i = lines_skipped; i < last_line; i++) { - Size2 line_size = TS->shaped_text_get_size(lines_rid[i]); - ofs.x = 0; - switch (horizontal_alignment) { - case HORIZONTAL_ALIGNMENT_FILL: - if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - break; - case HORIZONTAL_ALIGNMENT_LEFT: { - if (rtl_layout) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - } break; - case HORIZONTAL_ALIGNMENT_CENTER: { - ofs.x = int(size.width - line_size.width) / 2; - } break; - case HORIZONTAL_ALIGNMENT_RIGHT: { - if (rtl_layout) { - ofs.x = style->get_offset().x; - } else { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } - } break; - } + int line_limit; + int line_spacing; + get_layout_data(ofs, line_limit, line_spacing); + + for (int i = lines_skipped; i < line_limit; i++) { + Rect2 line_rect = get_line_rect(i); + ofs.x = line_rect.position.x; int v_size = TS->shaped_text_get_glyph_count(lines_rid[i]); const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); @@ -746,22 +697,19 @@ Rect2 Label::get_character_bounds(int p_pos) const { } Rect2 rect; rect.position = ofs + Vector2(gl_off, 0); - rect.size = Vector2(advance, TS->shaped_text_get_size(lines_rid[i]).y); + rect.size = Vector2(advance, line_rect.size.y); return rect; } } gl_off += glyphs[j].advance * glyphs[j].repeat; } - ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing; + ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } return Rect2(); } Size2 Label::get_minimum_size() const { - // don't want to mutable everything - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } + _ensure_shaped(); Size2 min_size = minsize; @@ -798,10 +746,7 @@ int Label::get_line_count() const { if (!is_inside_tree()) { return 1; } - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - + _ensure_shaped(); return lines_rid.size(); } @@ -1104,10 +1049,7 @@ int Label::get_max_lines_visible() const { } int Label::get_total_character_count() const { - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - + _ensure_shaped(); return xl_text.length(); } diff --git a/scene/gui/label.h b/scene/gui/label.h index e0ebca944a..2576d21c33 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -91,11 +91,16 @@ private: int font_shadow_outline_size; } theme_cache; + void _ensure_shaped() const; void _update_visible(); void _shape(); void _invalidate(); protected: + RID get_line_rid(int p_line) const; + Rect2 get_line_rect(int p_line) const; + void get_layout_data(Vector2 &r_offset, int &r_line_limit, int &r_line_spacing) const; + void _notification(int p_what); static void _bind_methods(); #ifndef DISABLE_DEPRECATED diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 9967805134..b7c7326172 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -128,6 +128,7 @@ bool LineEdit::has_ime_text() const { void LineEdit::cancel_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } ime_text = String(); @@ -140,6 +141,7 @@ void LineEdit::cancel_ime() { void LineEdit::apply_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } @@ -1450,13 +1452,12 @@ void LineEdit::undo() { return; } + if (!has_undo()) { + return; + } + if (undo_stack_pos == nullptr) { - if (undo_stack.size() <= 1) { - return; - } undo_stack_pos = undo_stack.back(); - } else if (undo_stack_pos == undo_stack.front()) { - return; } deselect(); @@ -1477,10 +1478,7 @@ void LineEdit::redo() { return; } - if (undo_stack_pos == nullptr) { - return; - } - if (undo_stack_pos == undo_stack.back()) { + if (!has_redo()) { return; } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 5432058f7b..26d164a62d 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -178,7 +178,7 @@ bool OptionButton::_set(const StringName &p_name, const Variant &p_value) { } void OptionButton::_focused(int p_which) { - emit_signal(SNAME("item_focused"), p_which); + emit_signal(SNAME("item_focused"), popup->get_item_index(p_which)); } void OptionButton::_selected(int p_which) { @@ -225,7 +225,7 @@ void OptionButton::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { popup->set_item_icon(p_idx, p_icon); if (current == p_idx) { - set_icon(p_icon); + set_button_icon(p_icon); } _queue_update_size_cache(); } @@ -381,7 +381,7 @@ void OptionButton::_select(int p_which, bool p_emit) { current = NONE_SELECTED; set_text(""); - set_icon(nullptr); + set_button_icon(nullptr); } else { ERR_FAIL_INDEX(p_which, popup->get_item_count()); @@ -391,7 +391,7 @@ void OptionButton::_select(int p_which, bool p_emit) { current = p_which; set_text(popup->get_item_text(current)); - set_icon(popup->get_item_icon(current)); + set_button_icon(popup->get_item_icon(current)); } if (is_inside_tree() && p_emit) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 3c04094526..f6ebcc854c 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -474,7 +474,7 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) { for (int i = search_from; i < items.size(); i++) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); set_input_as_handled(); @@ -488,7 +488,7 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) { for (int i = 0; i < search_from; i++) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); set_input_as_handled(); @@ -512,7 +512,7 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) { for (int i = search_from; i >= 0; i--) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); set_input_as_handled(); @@ -526,7 +526,7 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) { for (int i = items.size() - 1; i >= search_from; i--) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); set_input_as_handled(); @@ -692,7 +692,7 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) { if (items[i].text.findn(search_string) == 0) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); set_input_as_handled(); @@ -1091,7 +1091,7 @@ void PopupMenu::_notification(int p_what) { for (int i = search_from; i < items.size(); i++) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); match_found = true; @@ -1104,7 +1104,7 @@ void PopupMenu::_notification(int p_what) { for (int i = 0; i < search_from; i++) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); break; @@ -1124,7 +1124,7 @@ void PopupMenu::_notification(int p_what) { for (int i = search_from; i >= 0; i--) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); match_found = true; @@ -1137,7 +1137,7 @@ void PopupMenu::_notification(int p_what) { for (int i = items.size() - 1; i >= search_from; i--) { if (!items[i].separator && !items[i].disabled) { mouse_over = i; - emit_signal(SNAME("id_focused"), i); + emit_signal(SNAME("id_focused"), items[i].id); scroll_to_item(i); control->queue_redraw(); break; diff --git a/scene/gui/range.h b/scene/gui/range.h index b1c2446ded..710fed8645 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -64,7 +64,7 @@ class Range : public Control { protected: virtual void _value_changed(double p_value); - void _notify_shared_value_changed() { shared->emit_value_changed(); }; + void _notify_shared_value_changed() { shared->emit_value_changed(); } static void _bind_methods(); diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h index 681f068fb2..94e1bd4f04 100644 --- a/scene/gui/rich_text_effect.h +++ b/scene/gui/rich_text_effect.h @@ -79,20 +79,20 @@ public: Color get_color() { return color; } void set_color(Color p_color) { color = p_color; } - uint32_t get_glyph_index() const { return glyph_index; }; - void set_glyph_index(uint32_t p_glyph_index) { glyph_index = p_glyph_index; }; + uint32_t get_glyph_index() const { return glyph_index; } + void set_glyph_index(uint32_t p_glyph_index) { glyph_index = p_glyph_index; } - uint16_t get_glyph_flags() const { return glyph_flags; }; - void set_glyph_flags(uint16_t p_glyph_flags) { glyph_flags = p_glyph_flags; }; + uint16_t get_glyph_flags() const { return glyph_flags; } + void set_glyph_flags(uint16_t p_glyph_flags) { glyph_flags = p_glyph_flags; } - uint8_t get_glyph_count() const { return glyph_count; }; - void set_glyph_count(uint8_t p_glyph_count) { glyph_count = p_glyph_count; }; + uint8_t get_glyph_count() const { return glyph_count; } + void set_glyph_count(uint8_t p_glyph_count) { glyph_count = p_glyph_count; } - int32_t get_relative_index() const { return relative_index; }; - void set_relative_index(int32_t p_relative_index) { relative_index = p_relative_index; }; + int32_t get_relative_index() const { return relative_index; } + void set_relative_index(int32_t p_relative_index) { relative_index = p_relative_index; } - RID get_font() const { return font; }; - void set_font(RID p_font) { font = p_font; }; + RID get_font() const { return font; } + void set_font(RID p_font) { font = p_font; } Dictionary get_environment() { return environment; } void set_environment(Dictionary p_environment) { environment = p_environment; } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 26141663c1..b0886a95d7 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1833,8 +1833,7 @@ void RichTextLabel::_notification(int p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { - // If `text` is empty, it could mean that the tag stack is being used instead. Leave it be. - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } @@ -3109,6 +3108,10 @@ void RichTextLabel::add_text(const String &p_text) { } void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline) { + if (!internal_stack_editing) { + stack_externally_modified = true; + } + p_item->parent = current; p_item->E = current->subitems.push_back(p_item); p_item->index = current_idx++; @@ -3382,6 +3385,8 @@ bool RichTextLabel::remove_paragraph(int p_paragraph, bool p_no_invalidate) { return false; } + stack_externally_modified = true; + if (main->lines.size() == 1) { // Clear all. main->_clear_children(); @@ -4016,6 +4021,8 @@ void RichTextLabel::clear() { set_process_internal(false); MutexLock data_lock(data_mutex); + stack_externally_modified = false; + main->_clear_children(); current = main; current_frame = main; @@ -4845,7 +4852,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { String tooltip; bool size_in_percent = false; if (!bbcode_value.is_empty()) { - int sep = bbcode_value.find("x"); + int sep = bbcode_value.find_char('x'); if (sep == -1) { width = bbcode_value.to_int(); } else { @@ -5818,11 +5825,19 @@ void RichTextLabel::set_text(const String &p_bbcode) { return; } + stack_externally_modified = false; + text = p_bbcode; _apply_translation(); } void RichTextLabel::_apply_translation() { + if (text.is_empty()) { + return; + } + + internal_stack_editing = true; + String xl_text = atr(text); if (use_bbcode) { parse_bbcode(xl_text); @@ -5830,6 +5845,8 @@ void RichTextLabel::_apply_translation() { clear(); add_text(xl_text); } + + internal_stack_editing = false; } String RichTextLabel::get_text() const { @@ -5843,8 +5860,7 @@ void RichTextLabel::set_use_bbcode(bool p_enable) { use_bbcode = p_enable; notify_property_list_changed(); - // If `text` is empty, it could mean that the tag stack is being used instead. Leave it be. - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } } @@ -5854,7 +5870,7 @@ bool RichTextLabel::is_using_bbcode() const { } String RichTextLabel::get_parsed_text() const { - String txt = ""; + String txt; Item *it = main; while (it) { if (it->type == ITEM_DROPCAP) { @@ -5881,7 +5897,7 @@ void RichTextLabel::set_text_direction(Control::TextDirection p_text_direction) if (text_direction != p_text_direction) { text_direction = p_text_direction; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5901,7 +5917,7 @@ void RichTextLabel::set_horizontal_alignment(HorizontalAlignment p_alignment) { if (default_alignment != p_alignment) { default_alignment = p_alignment; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5920,7 +5936,7 @@ void RichTextLabel::set_justification_flags(BitField<TextServer::JustificationFl if (default_jst_flags != p_flags) { default_jst_flags = p_flags; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5939,7 +5955,7 @@ void RichTextLabel::set_tab_stops(const PackedFloat32Array &p_tab_stops) { if (default_tab_stops != p_tab_stops) { default_tab_stops = p_tab_stops; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5958,7 +5974,7 @@ void RichTextLabel::set_structured_text_bidi_override(TextServer::StructuredText _stop_thread(); st_parser = p_parser; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5992,7 +6008,7 @@ void RichTextLabel::set_language(const String &p_language) { _stop_thread(); language = p_language; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -6050,7 +6066,7 @@ float RichTextLabel::get_visible_ratio() const { void RichTextLabel::set_effects(Array p_effects) { custom_effects = p_effects; - if ((!text.is_empty()) && use_bbcode) { + if (!stack_externally_modified && use_bbcode) { parse_bbcode(atr(text)); } } @@ -6065,7 +6081,7 @@ void RichTextLabel::install_effect(const Variant effect) { ERR_FAIL_COND_MSG(rteffect.is_null(), "Invalid RichTextEffect resource."); custom_effects.push_back(effect); - if ((!text.is_empty()) && use_bbcode) { + if (!stack_externally_modified && use_bbcode) { parse_bbcode(atr(text)); } } diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index a01da02b27..ef4d17b8aa 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -626,6 +626,9 @@ private: String text; void _apply_translation(); + bool internal_stack_editing = false; + bool stack_externally_modified = false; + bool fit_content = false; struct ThemeCache { diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 1ac0e8b59f..312b538a99 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -461,7 +461,7 @@ void ScrollContainer::update_scrollbars() { void ScrollContainer::_scroll_moved(float) { queue_sort(); -}; +} void ScrollContainer::set_h_scroll(int p_pos) { h_scroll->set_value(p_pos); @@ -625,7 +625,7 @@ void ScrollContainer::_bind_methods() { BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollContainer, panel_style, "panel"); GLOBAL_DEF("gui/common/default_scroll_deadzone", 0); -}; +} ScrollContainer::ScrollContainer() { h_scroll = memnew(HScrollBar); @@ -641,4 +641,4 @@ ScrollContainer::ScrollContainer() { deadzone = GLOBAL_GET("gui/common/default_scroll_deadzone"); set_clip_contents(true); -}; +} diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 01c2b9bffe..2928794551 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -41,7 +41,11 @@ Size2 SpinBox::get_minimum_size() const { } void SpinBox::_update_text(bool p_keep_line_edit) { - String value = String::num(get_value(), Math::range_step_decimals(get_step())); + double step = get_step(); + if (use_custom_arrow_step && custom_arrow_step != 0.0) { + step = custom_arrow_step; + } + String value = String::num(get_value(), Math::range_step_decimals(step)); if (is_localizing_numeral_system()) { value = TS->format_number(value); } @@ -75,6 +79,9 @@ void SpinBox::_text_submitted(const String &p_string) { text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix); Error err = expr->parse(text); + + use_custom_arrow_step = false; + if (err != OK) { // If the expression failed try without converting commas to dots - they might have been for parameter separation. text = p_string; @@ -114,8 +121,13 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) { void SpinBox::_range_click_timeout() { if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { bool up = get_local_mouse_position().y < (get_size().height / 2); - double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); - set_value(get_value() + (up ? step : -step)); + double step = get_step(); + // Arrow button is being pressed, so we also need to set the step to the same value as custom_arrow_step if its not 0. + double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); + _set_step_no_signal(temp_step); + set_value(get_value() + (up ? temp_step : -temp_step)); + _set_step_no_signal(step); + use_custom_arrow_step = true; if (range_click_timer->is_one_shot()) { range_click_timer->set_wait_time(0.075); @@ -156,8 +168,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; Ref<InputEventMouseMotion> mm = p_event; - double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); - + double step = get_step(); Vector2 mpos; bool mouse_on_up_button = false; bool mouse_on_down_button = false; @@ -177,7 +188,12 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { line_edit->grab_focus(); if (mouse_on_up_button || mouse_on_down_button) { - set_value(get_value() + (mouse_on_up_button ? step : -step)); + // Arrow button is being pressed, so step is being changed temporarily. + double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); + _set_step_no_signal(temp_step); + set_value(get_value() + (mouse_on_up_button ? temp_step : -temp_step)); + _set_step_no_signal(step); + use_custom_arrow_step = true; } state_cache.up_button_pressed = mouse_on_up_button; state_cache.down_button_pressed = mouse_on_down_button; @@ -193,17 +209,20 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { case MouseButton::RIGHT: { line_edit->grab_focus(); if (mouse_on_up_button || mouse_on_down_button) { + use_custom_arrow_step = false; set_value(mouse_on_up_button ? get_max() : get_min()); } } break; case MouseButton::WHEEL_UP: { if (line_edit->is_editing()) { + use_custom_arrow_step = false; set_value(get_value() + step * mb->get_factor()); accept_event(); } } break; case MouseButton::WHEEL_DOWN: { if (line_edit->is_editing()) { + use_custom_arrow_step = false; set_value(get_value() - step * mb->get_factor()); accept_event(); } @@ -243,6 +262,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { if (drag.enabled) { drag.diff_y += mm->get_relative().y; double diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8) * SIGN(drag.diff_y); + use_custom_arrow_step = false; set_value(CLAMP(drag.base_val + step * diff_y, get_min(), get_max())); } else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); @@ -519,6 +539,18 @@ void SpinBox::_update_buttons_state_for_current_value() { } } +void SpinBox::_set_step_no_signal(double p_step) { + set_block_signals(true); + set_step(p_step); + set_block_signals(false); +} + +void SpinBox::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "exp_edit") { + p_property.usage = PROPERTY_USAGE_NONE; + } +} + void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &SpinBox::set_horizontal_alignment); ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &SpinBox::get_horizontal_alignment); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 294dc3e5d5..564294649c 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -66,6 +66,7 @@ class SpinBox : public Range { String suffix; String last_updated_text; double custom_arrow_step = 0.0; + bool use_custom_arrow_step = false; void _line_edit_input(const Ref<InputEvent> &p_event); @@ -133,10 +134,12 @@ class SpinBox : public Range { void _mouse_exited(); void _update_buttons_state_for_current_value(); + void _set_step_no_signal(double p_step); protected: virtual void gui_input(const Ref<InputEvent> &p_event) override; void _value_changed(double p_value) override; + void _validate_property(PropertyInfo &p_property) const; void _notification(int p_what); static void _bind_methods(); diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index a443ae9abf..775db65c3f 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -246,6 +246,14 @@ bool SubViewportContainer::_is_propagated_in_gui_input(const Ref<InputEvent> &p_ return false; } +void SubViewportContainer::set_consume_drag_and_drop(bool p_enable) { + consume_drag_and_drop = p_enable; +} + +bool SubViewportContainer::is_consume_drag_and_drop_enabled() { + return consume_drag_and_drop; +} + void SubViewportContainer::add_child_notify(Node *p_child) { if (Object::cast_to<SubViewport>(p_child)) { queue_redraw(); @@ -286,8 +294,12 @@ void SubViewportContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stretch_shrink", "amount"), &SubViewportContainer::set_stretch_shrink); ClassDB::bind_method(D_METHOD("get_stretch_shrink"), &SubViewportContainer::get_stretch_shrink); + ClassDB::bind_method(D_METHOD("set_consume_drag_and_drop", "amount"), &SubViewportContainer::set_consume_drag_and_drop); + ClassDB::bind_method(D_METHOD("is_consume_drag_and_drop_enabled"), &SubViewportContainer::is_consume_drag_and_drop_enabled); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stretch"), "set_stretch", "is_stretch_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_shrink", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), "set_stretch_shrink", "get_stretch_shrink"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "consume_drag_and_drop"), "set_consume_drag_and_drop", "is_consume_drag_and_drop_enabled"); GDVIRTUAL_BIND(_propagate_input_event, "event"); } diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h index 06420de730..7230615771 100644 --- a/scene/gui/subviewport_container.h +++ b/scene/gui/subviewport_container.h @@ -38,6 +38,8 @@ class SubViewportContainer : public Container { bool stretch = false; int shrink = 1; + bool consume_drag_and_drop = false; + void _notify_viewports(int p_notification); bool _is_propagated_in_gui_input(const Ref<InputEvent> &p_event); void _send_event_to_viewports(const Ref<InputEvent> &p_event); @@ -63,6 +65,9 @@ public: int get_stretch_shrink() const; void recalc_force_viewport_sizes(); + void set_consume_drag_and_drop(bool p_enable); + bool is_consume_drag_and_drop_enabled(); + virtual Size2 get_minimum_size() const override; virtual Vector<int> get_allowed_size_flags_horizontal() const override; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 6b5ff23436..b8bb17eb2a 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -332,6 +332,7 @@ void TextEdit::Text::clear() { max_line_width_dirty = true; max_line_height_dirty = true; + total_visible_line_count = 0; Line line; line.gutters.resize(gutter_count); @@ -421,6 +422,10 @@ void TextEdit::Text::remove_range(int p_from_line, int p_to_line) { for (int i = p_from_line; i < p_to_line; i++) { const Line &text_line = text[i]; + if (text_line.hidden) { + continue; + } + if (text_line.height == max_line_height) { max_line_height_dirty = true; } @@ -435,6 +440,8 @@ void TextEdit::Text::remove_range(int p_from_line, int p_to_line) { text.write[(i - diff) + 1] = text[i + 1]; } text.resize(text.size() - diff); + + ERR_FAIL_COND(total_visible_line_count < 0); // BUG } void TextEdit::Text::add_gutter(int p_at) { @@ -3169,6 +3176,7 @@ bool TextEdit::has_ime_text() const { void TextEdit::cancel_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } ime_text = String(); @@ -3181,6 +3189,7 @@ void TextEdit::cancel_ime() { void TextEdit::apply_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } @@ -4166,7 +4175,7 @@ void TextEdit::redo() { } _push_current_op(); - if (undo_stack_pos == nullptr) { + if (!has_redo()) { return; // Nothing to do. } @@ -5069,7 +5078,7 @@ bool TextEdit::multicaret_edit_ignore_caret(int p_caret) const { } bool TextEdit::is_caret_visible(int p_caret) const { - ERR_FAIL_INDEX_V(p_caret, carets.size(), 0); + ERR_FAIL_INDEX_V(p_caret, carets.size(), false); return carets[p_caret].visible; } @@ -5736,7 +5745,7 @@ TextServer::AutowrapMode TextEdit::get_autowrap_mode() const { } bool TextEdit::is_line_wrapped(int p_line) const { - ERR_FAIL_INDEX_V(p_line, text.size(), 0); + ERR_FAIL_INDEX_V(p_line, text.size(), false); if (get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) { return false; } @@ -7301,6 +7310,10 @@ void TextEdit::_paste_internal(int p_caret) { } String clipboard = DisplayServer::get_singleton()->clipboard_get(); + if (clipboard.is_empty()) { + // Nothing to paste. + return; + } // Paste a full line. Ignore '\r' characters that may have been added to the clipboard by the OS. if (get_caret_count() == 1 && !has_selection(0) && !cut_copy_line.is_empty() && cut_copy_line == clipboard.replace("\r", "")) { diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 94b105d486..6b137581f2 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -139,7 +139,7 @@ private: Variant metadata; bool clickable = false; - Ref<Texture2D> icon = Ref<Texture2D>(); + Ref<Texture2D> icon; String text = ""; Color color = Color(1, 1, 1); }; @@ -693,9 +693,9 @@ protected: void _set_symbol_lookup_word(const String &p_symbol); // Theme items. - virtual Color _get_brace_mismatch_color() const { return Color(); }; - virtual Color _get_code_folding_color() const { return Color(); }; - virtual Ref<Texture2D> _get_folded_eol_icon() const { return Ref<Texture2D>(); }; + virtual Color _get_brace_mismatch_color() const { return Color(); } + virtual Color _get_code_folding_color() const { return Color(); } + virtual Ref<Texture2D> _get_folded_eol_icon() const { return Ref<Texture2D>(); } /* Text manipulation */ diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index c267ff93c6..47bb0643b3 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -340,11 +340,11 @@ Ref<BitMap> TextureButton::get_click_mask() const { Ref<Texture2D> TextureButton::get_texture_focused() const { return focused; -}; +} void TextureButton::set_texture_focused(const Ref<Texture2D> &p_focused) { focused = p_focused; -}; +} void TextureButton::_set_texture(Ref<Texture2D> *p_destination, const Ref<Texture2D> &p_texture) { DEV_ASSERT(p_destination); diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp index 4ad56d21d3..24c68e0188 100644 --- a/scene/gui/texture_progress_bar.cpp +++ b/scene/gui/texture_progress_bar.cpp @@ -608,11 +608,10 @@ int TextureProgressBar::get_fill_mode() { } void TextureProgressBar::set_radial_initial_angle(float p_angle) { - while (p_angle > 360) { - p_angle -= 360; - } - while (p_angle < 0) { - p_angle += 360; + ERR_FAIL_COND_MSG(!Math::is_finite(p_angle), "Angle is non-finite."); + + if (p_angle < 0.0 || p_angle > 360.0) { + p_angle = Math::fposmodp(p_angle, 360.0f); } if (rad_init_angle == p_angle) { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 646cd9c70e..f6e05f5796 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -961,19 +961,17 @@ TreeItem *TreeItem::_get_prev_in_tree(bool p_wrap, bool p_include_invisible) { if (!prev_item) { current = current->parent; - if (current == tree->root && tree->hide_root) { - return nullptr; - } else if (!current) { - if (p_wrap) { - current = this; - TreeItem *temp = get_next_visible(); - while (temp) { - current = temp; - temp = temp->get_next_visible(); - } - } else { + if (!current || (current == tree->root && tree->hide_root)) { + if (!p_wrap) { return nullptr; } + // Wrap around to the last visible item. + current = this; + TreeItem *temp = get_next_visible(); + while (temp) { + current = temp; + temp = temp->get_next_visible(); + } } } else { current = prev_item; @@ -1101,7 +1099,7 @@ void TreeItem::clear_children() { first_child = nullptr; last_child = nullptr; children_cache.clear(); -}; +} int TreeItem::get_index() { int idx = 0; @@ -1576,7 +1574,7 @@ Size2 TreeItem::get_minimum_size(int p_column) { const TreeItem::Cell &cell = cells[p_column]; - if (cell.cached_minimum_size_dirty) { + if (cell.cached_minimum_size_dirty || cell.text_buf->is_dirty() || cell.dirty) { Size2 size = Size2( parent_tree->theme_cache.inner_item_margin_left + parent_tree->theme_cache.inner_item_margin_right, parent_tree->theme_cache.inner_item_margin_top + parent_tree->theme_cache.inner_item_margin_bottom); @@ -1595,7 +1593,9 @@ Size2 TreeItem::get_minimum_size(int p_column) { // Icon. if (cell.mode == CELL_MODE_CHECK) { - size.width += parent_tree->theme_cache.checked->get_width() + parent_tree->theme_cache.h_separation; + Size2i check_size = parent_tree->theme_cache.checked->get_size(); + size.width += check_size.width + parent_tree->theme_cache.h_separation; + size.height = MAX(size.height, check_size.height); } if (cell.icon.is_valid()) { Size2i icon_size = parent_tree->_get_cell_icon_size(cell); @@ -1607,7 +1607,8 @@ Size2 TreeItem::get_minimum_size(int p_column) { for (int i = 0; i < cell.buttons.size(); i++) { Ref<Texture2D> texture = cell.buttons[i].texture; if (texture.is_valid()) { - Size2 button_size = texture->get_size() + parent_tree->theme_cache.button_pressed->get_minimum_size(); + Size2 button_size = texture->get_size(); + button_size.width += parent_tree->theme_cache.button_pressed->get_minimum_size().width; size.width += button_size.width + parent_tree->theme_cache.button_margin; size.height = MAX(size.height, button_size.height); } @@ -1891,44 +1892,7 @@ int Tree::compute_item_height(TreeItem *p_item) const { int height = 0; for (int i = 0; i < columns.size(); i++) { - if (p_item->cells[i].dirty) { - const_cast<Tree *>(this)->update_item_cell(p_item, i); - } - height = MAX(height, p_item->cells[i].text_buf->get_size().y); - for (int j = 0; j < p_item->cells[i].buttons.size(); j++) { - Size2i s; // = cache.button_pressed->get_minimum_size(); - s += p_item->cells[i].buttons[j].texture->get_size(); - if (s.height > height) { - height = s.height; - } - } - - switch (p_item->cells[i].mode) { - case TreeItem::CELL_MODE_CHECK: { - int check_icon_h = theme_cache.checked->get_height(); - if (height < check_icon_h) { - height = check_icon_h; - } - [[fallthrough]]; - } - case TreeItem::CELL_MODE_STRING: - case TreeItem::CELL_MODE_CUSTOM: - case TreeItem::CELL_MODE_ICON: { - Ref<Texture2D> icon = p_item->cells[i].icon; - if (!icon.is_null()) { - Size2i s = _get_cell_icon_size(p_item->cells[i]); - if (s.height > height) { - height = s.height; - } - } - if (p_item->cells[i].mode == TreeItem::CELL_MODE_CUSTOM && p_item->cells[i].custom_button) { - height += theme_cache.custom_button->get_minimum_size().height; - } - - } break; - default: { - } - } + height = MAX(height, p_item->get_minimum_size(i).y); } int item_min_height = MAX(theme_cache.font->get_height(theme_cache.font_size), p_item->get_custom_minimum_height()); if (height < item_min_height) { @@ -2165,12 +2129,18 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin); int skip2 = 0; + + bool is_row_hovered = (!cache.hover_header_row && cache.hover_item == p_item); + for (int i = 0; i < columns.size(); i++) { if (skip2) { skip2--; continue; } + bool is_col_hovered = cache.hover_column == i; + bool is_cell_hovered = is_row_hovered && is_col_hovered; + bool is_cell_button_hovered = is_cell_hovered && cache.hover_button_index_in_column != -1; int item_width = get_column_width(i); if (i == 0) { @@ -2203,6 +2173,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int total_ofs = ofs - theme_cache.offset.x; + // If part of the column is beyond the right side of the control due to scrolling, clamp the label width + // so that all buttons attached to the cell remain within view. if (total_ofs + item_width > p_draw_size.width) { item_width = MAX(buttons_width, p_draw_size.width - total_ofs); } @@ -2247,17 +2219,42 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(r.position.x, r.position.y + r.size.height), r.position + r.size, theme_cache.guide_color, 1); } - if (i == 0) { - if (p_item->cells[0].selected && select_mode == SELECT_ROW) { + if (i == 0 && select_mode == SELECT_ROW) { + if (p_item->cells[0].selected || is_row_hovered) { const Rect2 content_rect = _get_content_rect(); Rect2i row_rect = Rect2i(Point2i(content_rect.position.x, item_rect.position.y), Size2i(content_rect.size.x, item_rect.size.y)); if (rtl) { row_rect.position.x = get_size().width - row_rect.position.x - row_rect.size.x; } - if (has_focus()) { - theme_cache.selected_focus->draw(ci, row_rect); + + if (p_item->cells[0].selected) { + if (has_focus()) { + theme_cache.selected_focus->draw(ci, row_rect); + } else { + theme_cache.selected->draw(ci, row_rect); + } + } else if (!drop_mode_flags) { + if (is_cell_button_hovered) { + theme_cache.hovered_dimmed->draw(ci, row_rect); + } else { + theme_cache.hovered->draw(ci, row_rect); + } + } + } + } + + if (select_mode != SELECT_ROW) { + Rect2i r = cell_rect; + if (rtl) { + r.position.x = get_size().width - r.position.x - r.size.x; + } + + // Cell hover. + if (is_cell_hovered && !p_item->cells[i].selected && !drop_mode_flags) { + if (is_cell_button_hovered) { + theme_cache.hovered_dimmed->draw(ci, r); } else { - theme_cache.selected->draw(ci, row_rect); + theme_cache.hovered->draw(ci, r); } } } @@ -2335,7 +2332,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (p_item->cells[i].custom_color) { cell_color = p_item->cells[i].color; } else { - cell_color = p_item->cells[i].selected ? theme_cache.font_selected_color : theme_cache.font_color; + bool draw_as_hover = !drop_mode_flags && (select_mode == SELECT_ROW ? is_row_hovered : is_cell_hovered); + bool draw_as_hover_dim = draw_as_hover && is_cell_button_hovered; + cell_color = p_item->cells[i].selected ? theme_cache.font_selected_color : (draw_as_hover_dim ? theme_cache.font_hovered_dimmed_color : (draw_as_hover ? theme_cache.font_hovered_color : theme_cache.font_color)); } Color font_outline_color = theme_cache.font_outline_color; @@ -2487,7 +2486,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 ir.size.width -= downarrow->get_width(); if (p_item->cells[i].custom_button) { - if (cache.hover_item == p_item && cache.hover_cell == i) { + if (cache.hover_item == p_item && cache.hover_column == i) { if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { draw_style_box(theme_cache.custom_button_pressed, ir); } else { @@ -2508,19 +2507,26 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } break; } + // Draw the buttons inside the cell. for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) { Ref<Texture2D> button_texture = p_item->cells[i].buttons[j].texture; Size2 button_size = button_texture->get_size() + theme_cache.button_pressed->get_minimum_size(); Point2i button_ofs = Point2i(ofs + item_width_with_buttons - button_size.width, p_pos.y) - theme_cache.offset + p_draw_ofs; - if (cache.click_type == Cache::CLICK_BUTTON && cache.click_item == p_item && cache.click_column == i && cache.click_index == j && !p_item->cells[i].buttons[j].disabled) { - // Being pressed. + bool should_draw_pressed = cache.click_type == Cache::CLICK_BUTTON && cache.click_item == p_item && cache.click_column == i && cache.click_index == j && !p_item->cells[i].buttons[j].disabled; + bool should_draw_hovered = !should_draw_pressed && !drop_mode_flags && cache.hover_item == p_item && cache.hover_column == i && cache.hover_button_index_in_column == j && !p_item->cells[i].buttons[j].disabled; + + if (should_draw_pressed || should_draw_hovered) { Point2 od = button_ofs; if (rtl) { od.x = get_size().width - od.x - button_size.x; } - theme_cache.button_pressed->draw(get_canvas_item(), Rect2(od.x, od.y, button_size.width, MAX(button_size.height, label_h))); + if (should_draw_pressed) { + theme_cache.button_pressed->draw(get_canvas_item(), Rect2(od.x, od.y, button_size.width, MAX(button_size.height, label_h))); + } else { + theme_cache.button_hover->draw(get_canvas_item(), Rect2(od.x, od.y, button_size.width, MAX(button_size.height, label_h))); + } } button_ofs.y += (label_h - button_size.height) / 2; @@ -2551,6 +2557,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } } + // Draw the folding arrow. if (!p_item->disable_folding && !hide_folding && p_item->first_child && p_item->get_visible_child_count() != 0) { //has visible children, draw the guide box Ref<Texture2D> arrow; @@ -2966,6 +2973,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int col_width = MAX(button_w, MIN(limit_w, col_width)); } + // Cell button detection code. for (int j = c.buttons.size() - 1; j >= 0; j--) { Ref<Texture2D> b = c.buttons[j].texture; int w = b->get_size().width + theme_cache.button_pressed->get_minimum_size().width; @@ -2978,7 +2986,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int } // Make sure the click is correct. - Point2 click_pos = get_global_mouse_position() - get_global_position(); + const Point2 click_pos = get_local_mouse_position(); if (!get_item_at_position(click_pos)) { pressed_button = -1; cache.click_type = Cache::CLICK_NONE; @@ -3485,7 +3493,11 @@ bool Tree::_scroll(bool p_horizontal, float p_pages) { double prev_value = scroll->get_value(); scroll->set_value(scroll->get_value() + scroll->get_page() * p_pages); - return scroll->get_value() != prev_value; + bool scroll_happened = scroll->get_value() != prev_value; + if (scroll_happened) { + _determine_hovered_item(); + } + return scroll_happened; } Rect2 Tree::_get_scrollbar_layout_rect() const { @@ -3710,92 +3722,10 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { - Ref<StyleBox> bg = theme_cache.panel_style; - bool rtl = is_layout_rtl(); - - Point2 pos = mm->get_position(); - if (rtl) { - pos.x = get_size().width - pos.x; - } - pos -= theme_cache.panel_style->get_offset(); - - Cache::ClickType old_hover = cache.hover_type; - int old_index = cache.hover_index; - - cache.hover_type = Cache::CLICK_NONE; - cache.hover_index = 0; - if (show_column_titles) { - pos.y -= _get_title_button_height(); - if (pos.y < 0) { - pos.x += theme_cache.offset.x; - int len = 0; - for (int i = 0; i < columns.size(); i++) { - len += get_column_width(i); - if (pos.x < len) { - cache.hover_type = Cache::CLICK_TITLE; - cache.hover_index = i; - break; - } - } - } - } - - if (root) { - Point2 mpos = mm->get_position(); - if (rtl) { - mpos.x = get_size().width - mpos.x; - } - mpos -= theme_cache.panel_style->get_offset(); - mpos.y -= _get_title_button_height(); - if (mpos.y >= 0) { - if (h_scroll->is_visible_in_tree()) { - mpos.x += h_scroll->get_value(); - } - if (v_scroll->is_visible_in_tree()) { - mpos.y += v_scroll->get_value(); - } - - TreeItem *old_it = cache.hover_item; - int old_col = cache.hover_cell; - - int col, h, section; - TreeItem *it = _find_item_at_pos(root, mpos, col, h, section); - - if (drop_mode_flags) { - if (it != drop_mode_over) { - drop_mode_over = it; - queue_redraw(); - } - if (it && section != drop_mode_section) { - drop_mode_section = section; - queue_redraw(); - } - } - - cache.hover_item = it; - cache.hover_cell = col; - - if (it != old_it || col != old_col) { - if (old_it && old_col >= old_it->cells.size()) { - // Columns may have changed since last redraw(). - queue_redraw(); - } else { - // Only need to update if mouse enters/exits a button - bool was_over_button = old_it && old_it->cells[old_col].custom_button; - bool is_over_button = it && it->cells[col].custom_button; - if (was_over_button || is_over_button) { - queue_redraw(); - } - } - } - } - } - - // Update if mouse enters/exits columns - if (cache.hover_type != old_hover || cache.hover_index != old_index) { - queue_redraw(); - } + hovered_pos = mm->get_position(); + _determine_hovered_item(); + bool rtl = is_layout_rtl(); if (pressing_for_editor && popup_pressing_edited_item && (popup_pressing_edited_item->get_cell_mode(popup_pressing_edited_item_column) == TreeItem::CELL_MODE_RANGE)) { /* This needs to happen now, because the popup can be closed when pressing another item, and must remain the popup edited item until it actually closes */ popup_edited_item = popup_pressing_edited_item; @@ -4080,6 +4010,174 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } } +void Tree::_determine_hovered_item() { + Ref<StyleBox> bg = theme_cache.panel_style; + bool rtl = is_layout_rtl(); + + Point2 pos = hovered_pos; + if (rtl) { + pos.x = get_size().width - pos.x; + } + pos -= theme_cache.panel_style->get_offset(); + + bool old_header_row = cache.hover_header_row; + int old_header_column = cache.hover_header_column; + TreeItem *old_item = cache.hover_item; + int old_column = cache.hover_column; + int old_button_index_in_column = cache.hover_button_index_in_column; + + // Determine hover on column headers. + cache.hover_header_row = false; + cache.hover_header_column = 0; + if (show_column_titles && is_mouse_hovering) { + pos.y -= _get_title_button_height(); + if (pos.y < 0) { + pos.x += theme_cache.offset.x; + int len = 0; + for (int i = 0; i < columns.size(); i++) { + len += get_column_width(i); + if (pos.x < len) { + cache.hover_header_row = true; + cache.hover_header_column = i; + cache.hover_button_index_in_column = -1; + break; + } + } + } + } + + // Determine hover on rows and items. + if (root && is_mouse_hovering) { + Point2 mpos = hovered_pos; + if (rtl) { + mpos.x = get_size().width - mpos.x; + } + mpos -= theme_cache.panel_style->get_offset(); + mpos.y -= _get_title_button_height(); + if (mpos.y >= 0) { + if (h_scroll->is_visible_in_tree()) { + mpos.x += h_scroll->get_value(); + } + if (v_scroll->is_visible_in_tree()) { + mpos.y += v_scroll->get_value(); + } + + int col, h, section; + TreeItem *it = _find_item_at_pos(root, mpos, col, h, section); + + // Find possible hovered button in cell. + int col_button_index = -1; + + Point2 cpos = mpos; + + if (it) { + const TreeItem::Cell &c = it->cells[col]; + int col_width = get_column_width(col); + + // In the first column, tree nesting indent impacts the leftmost possible buttons position + // and the clickable area of the folding arrow. + int col_indent = 0; + if (col == 0) { + col_indent = _get_item_h_offset(it); + } + + // Compute total width of buttons block including spacings. + int buttons_width = 0; + for (int j = c.buttons.size() - 1; j >= 0; j--) { + Ref<Texture2D> b = c.buttons[j].texture; + Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size(); + buttons_width += size.width + theme_cache.button_margin; + } + + // Adjust when buttons are shifted left into view so that they remain visible even + // if part of the cell is beyond the right border due to horizontal scrolling and + // a long string in one of the items. This matches the drawing & click handling algorithms + // that are based on recursion. + int clamped_column_offset = 0; + int col_left = 0; + + for (int i = 0; i < col; i++) { + int i_col_w = get_column_width(i); + cpos.x -= i_col_w; + col_left += i_col_w; + } + col_left -= theme_cache.offset.x; + + // Compute buttons offset that makes them visible, in comparison to what would be their + // natural position that would cut them off. + if (!rtl) { + const Rect2 content_rect = _get_content_rect(); + int cw = content_rect.size.width; + int col_right = col_left + col_width; + if (col_right > cw) { + clamped_column_offset = col_right - cw - theme_cache.scrollbar_h_separation; + int max_clamp_offset = col_width - col_indent - buttons_width; + if (clamped_column_offset > max_clamp_offset) { + clamped_column_offset = max_clamp_offset; + } + } + } + col_width -= clamped_column_offset; + + // Find the actual button under coordinates. + for (int j = c.buttons.size() - 1; j >= 0; j--) { + Ref<Texture2D> b = c.buttons[j].texture; + Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size(); + if (cpos.x > col_width - size.width && col_button_index == -1) { + col_button_index = j; + } + col_width -= size.width + theme_cache.button_margin; + } + } + + if (drop_mode_flags) { + if (it != drop_mode_over) { + drop_mode_over = it; + queue_redraw(); + } + if (it && section != drop_mode_section) { + drop_mode_section = section; + queue_redraw(); + } + } + + cache.hover_item = it; + cache.hover_column = col; + cache.hover_button_index_in_column = col_button_index; + + if (it != old_item || col != old_column) { + if (old_item && old_column >= old_item->cells.size()) { + // Columns may have changed since last redraw(). + queue_redraw(); + } else { + // Only need to update if mouse enters/exits a button. + bool was_over_button = old_item && old_item->cells[old_column].custom_button; + bool is_over_button = it && it->cells[col].custom_button; + if (was_over_button || is_over_button) { + queue_redraw(); + } + } + } + } + } + + // Reduce useless redraw calls. + + bool hovered_cell_button_changed = (cache.hover_button_index_in_column != old_button_index_in_column); + bool hovered_column_changed = (cache.hover_column != old_column); + + // Mouse has moved from row to row, or from cell to cell within same row unless selection mode is full row which saves a useless redraw. + bool item_hover_needs_redraw = !cache.hover_header_row && (cache.hover_item != old_item || hovered_cell_button_changed || (select_mode != SELECT_ROW && hovered_column_changed)); + // Mouse has moved between two different column header sections. + bool header_hover_needs_redraw = cache.hover_header_row && cache.hover_header_column != old_header_column; + // Mouse has moved between header and "main" areas. + bool whole_needs_redraw = cache.hover_header_row != old_header_row; + + if (whole_needs_redraw || header_hover_needs_redraw || item_hover_needs_redraw) { + queue_redraw(); + } +} + bool Tree::edit_selected(bool p_force_edit) { TreeItem *s = get_selected(); ERR_FAIL_NULL_V_MSG(s, false, "No item selected."); @@ -4304,9 +4402,20 @@ void Tree::_notification(int p_what) { } } break; + case NOTIFICATION_MOUSE_ENTER: { + is_mouse_hovering = true; + _determine_hovered_item(); + } break; + case NOTIFICATION_MOUSE_EXIT: { - if (cache.hover_type != Cache::CLICK_NONE) { - cache.hover_type = Cache::CLICK_NONE; + is_mouse_hovering = false; + // Clear hovered item cache. + if (cache.hover_header_row || cache.hover_item != nullptr) { + cache.hover_header_row = false; + cache.hover_header_column = -1; + cache.hover_item = nullptr; + cache.hover_column = -1; + cache.hover_button_index_in_column = -1; queue_redraw(); } } break; @@ -4420,7 +4529,7 @@ void Tree::_notification(int p_what) { //title buttons int ofs2 = theme_cache.panel_style->get_margin(SIDE_LEFT); for (int i = 0; i < columns.size(); i++) { - Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? theme_cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? theme_cache.title_button_hover : theme_cache.title_button); + Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? theme_cache.title_button_pressed : ((cache.hover_header_row && cache.hover_header_column == i) ? theme_cache.title_button_hover : theme_cache.title_button); Rect2 tbrect = Rect2(ofs2 - theme_cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh); if (cache.rtl) { tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x; @@ -4536,6 +4645,8 @@ TreeItem *Tree::create_item(TreeItem *p_parent, int p_index) { } } + _determine_hovered_item(); + return ti; } @@ -4557,6 +4668,7 @@ void Tree::item_edited(int p_column, TreeItem *p_item, MouseButton p_custom_mous edited_col = p_column; if (p_item != nullptr && p_column >= 0 && p_column < p_item->cells.size()) { edited_item->cells.write[p_column].dirty = true; + edited_item->cells.write[p_column].cached_minimum_size_dirty = true; } emit_signal(SNAME("item_edited")); if (p_custom_mouse_index != MouseButton::NONE) { @@ -4679,8 +4791,10 @@ void Tree::clear() { popup_edited_item = nullptr; popup_pressing_edited_item = nullptr; + _determine_hovered_item(); + queue_redraw(); -}; +} void Tree::set_hide_root(bool p_enabled) { if (hide_root == p_enabled) { @@ -4931,6 +5045,7 @@ int Tree::get_columns() const { } void Tree::_scroll_moved(float) { + _determine_hovered_item(); queue_redraw(); } @@ -4972,7 +5087,47 @@ int Tree::get_item_offset(TreeItem *p_item) const { } } - return -1; //not found + return -1; // Not found. +} + +int Tree::_get_item_h_offset(TreeItem *p_item) const { + TreeItem *it = root; + int nesting_level = 0; + if (!it) { + return 0; + } + + while (true) { + if (it == p_item) { + if (!hide_root) { + nesting_level += 1; + } + if (hide_folding) { + nesting_level -= 1; + } + return nesting_level * theme_cache.item_margin; + } + + if (it->first_child && !it->collapsed) { + it = it->first_child; + nesting_level += 1; + + } else if (it->next) { + it = it->next; + } else { + while (!it->next) { + it = it->parent; + nesting_level -= 1; + if (it == nullptr) { + return 0; + } + } + + it = it->next; + } + } + + return -1; // Not found. } void Tree::ensure_cursor_is_visible() { @@ -5174,14 +5329,16 @@ void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) { int y_offset = get_item_offset(p_item); if (y_offset != -1) { - const int tbh = _get_title_button_height(); - y_offset -= tbh; + const int title_button_height = _get_title_button_height(); + y_offset -= title_button_height; const int cell_h = compute_item_height(p_item) + theme_cache.v_separation; - int screen_h = area_size.height - tbh; + int screen_h = area_size.height - title_button_height; if (p_center_on_item) { - v_scroll->set_value(y_offset - (screen_h - cell_h) / 2.0f); + // This makes sure that centering the offset doesn't overflow. + const double v_scroll_value = y_offset - MAX((screen_h - cell_h) / 2.0, 0.0); + v_scroll->set_value(v_scroll_value); } else { if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet. v_scroll->set_value(y_offset); @@ -5803,10 +5960,13 @@ void Tree::_bind_methods() { BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT, Tree, tb_font, "title_button_font"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT_SIZE, Tree, tb_font_size, "title_button_font_size"); + BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, hovered); + BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, hovered_dimmed); BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, selected); BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, selected_focus); BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, cursor); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Tree, cursor_unfocus, "cursor_unfocused"); + BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, button_hover); BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, button_pressed); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, checked); @@ -5827,6 +5987,8 @@ void Tree::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, custom_button_font_highlight); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_hovered_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_hovered_dimmed_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_selected_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_disabled_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, drop_position_color); diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 86efdfec52..b417b7ee31 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -450,6 +450,9 @@ private: Vector2 pressing_pos; Rect2 pressing_item_rect; + Vector2 hovered_pos; + bool is_mouse_hovering = false; + float range_drag_base = 0.0; bool range_drag_enabled = false; Vector2 range_drag_capture_pos; @@ -545,10 +548,13 @@ private: int font_size = 0; int tb_font_size = 0; + Ref<StyleBox> hovered; + Ref<StyleBox> hovered_dimmed; Ref<StyleBox> selected; Ref<StyleBox> selected_focus; Ref<StyleBox> cursor; Ref<StyleBox> cursor_unfocus; + Ref<StyleBox> button_hover; Ref<StyleBox> button_pressed; Ref<StyleBox> title_button; Ref<StyleBox> title_button_hover; @@ -572,6 +578,8 @@ private: Ref<Texture2D> updown; Color font_color; + Color font_hovered_color; + Color font_hovered_dimmed_color; Color font_selected_color; Color font_disabled_color; Color guide_color; @@ -623,16 +631,17 @@ private: }; ClickType click_type = Cache::CLICK_NONE; - ClickType hover_type = Cache::CLICK_NONE; int click_index = -1; int click_id = -1; TreeItem *click_item = nullptr; int click_column = 0; - int hover_index = -1; + int hover_header_column = -1; + bool hover_header_row = false; Point2 click_pos; TreeItem *hover_item = nullptr; - int hover_cell = -1; + int hover_column = -1; + int hover_button_index_in_column = -1; bool rtl = false; } cache; @@ -660,6 +669,7 @@ private: TreeItem *_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards = false); TreeItem *_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_column, int &h, int §ion) const; + int _get_item_h_offset(TreeItem *p_item) const; void _find_button_at_pos(const Point2 &p_pos, TreeItem *&r_item, int &r_column, int &r_index) const; @@ -689,6 +699,8 @@ private: bool enable_recursive_folding = true; + void _determine_hovered_item(); + int _count_selected_items(TreeItem *p_from) const; bool _is_branch_selected(TreeItem *p_from) const; bool _is_sibling_branch_selected(TreeItem *p_from) const; diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 0b521f926d..878bceccbc 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -178,6 +178,7 @@ void VideoStreamPlayer::_notification(int p_notification) { draw_texture_rect(texture, Rect2(Point2(), s), false); } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (is_playing() && !is_paused()) { paused_from_tree = true; @@ -189,6 +190,13 @@ void VideoStreamPlayer::_notification(int p_notification) { } } break; + case NOTIFICATION_UNSUSPENDED: { + if (get_tree()->is_paused()) { + break; + } + [[fallthrough]]; + } + case NOTIFICATION_UNPAUSED: { if (paused_from_tree) { paused_from_tree = false; diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index c0386b056f..f87dad1889 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -44,7 +44,7 @@ #define ERR_DRAW_GUARD \ ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside this node's `_draw()`, functions connected to its `draw` signal, or when it receives NOTIFICATION_DRAW.") -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { if (_edit_use_rect()) { return _edit_get_rect().has_point(p_point); @@ -52,11 +52,13 @@ bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tole return p_point.length() < p_tolerance; } } +#endif // DEBUG_ENABLED +#ifdef TOOLS_ENABLED Transform2D CanvasItem::_edit_get_transform() const { return Transform2D(_edit_get_rotation(), _edit_get_position() + _edit_get_pivot()); } -#endif +#endif //TOOLS_ENABLED bool CanvasItem::is_visible_in_tree() const { ERR_READ_THREAD_GUARD_V(false); @@ -1158,7 +1160,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_edit_get_pivot"), &CanvasItem::_edit_get_pivot); ClassDB::bind_method(D_METHOD("_edit_use_pivot"), &CanvasItem::_edit_use_pivot); ClassDB::bind_method(D_METHOD("_edit_get_transform"), &CanvasItem::_edit_get_transform); -#endif +#endif //TOOLS_ENABLED ClassDB::bind_method(D_METHOD("get_canvas_item"), &CanvasItem::get_canvas_item); @@ -1253,7 +1255,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("force_update_transform"), &CanvasItem::force_update_transform); - ClassDB::bind_method(D_METHOD("make_canvas_position_local", "screen_point"), &CanvasItem::make_canvas_position_local); + ClassDB::bind_method(D_METHOD("make_canvas_position_local", "viewport_point"), &CanvasItem::make_canvas_position_local); ClassDB::bind_method(D_METHOD("make_input_local", "event"), &CanvasItem::make_input_local); ClassDB::bind_method(D_METHOD("set_visibility_layer", "layer"), &CanvasItem::set_visibility_layer); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 028c2cb2cf..c74f8238e3 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -174,7 +174,7 @@ protected: void _draw_multiline_bind_compat_84523(const Vector<Point2> &p_points, const Color &p_color, real_t p_width); void _draw_multiline_colors_bind_compat_84523(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width); static void _bind_compatibility_methods(); -#endif +#endif // DISABLE_DEPRECATED void _validate_property(PropertyInfo &p_property) const; @@ -193,11 +193,9 @@ public: NOTIFICATION_WORLD_2D_CHANGED = 36, }; - /* EDITOR */ -#ifdef TOOLS_ENABLED - // Select the node - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + /* EDITOR AND DEBUGGING */ +#ifdef TOOLS_ENABLED // Save and restore a CanvasItem state virtual void _edit_set_state(const Dictionary &p_state) {} virtual Dictionary _edit_get_state() const { return Dictionary(); } @@ -211,23 +209,32 @@ public: virtual Size2 _edit_get_scale() const = 0; // Used to rotate the node - virtual bool _edit_use_rotation() const { return false; }; + virtual bool _edit_use_rotation() const { return false; } virtual void _edit_set_rotation(real_t p_rotation) {} - virtual real_t _edit_get_rotation() const { return 0.0; }; + virtual real_t _edit_get_rotation() const { return 0.0; } // Used to resize/move the node - virtual bool _edit_use_rect() const { return false; }; // MAYBE REPLACE BY A _edit_get_editmode() virtual void _edit_set_rect(const Rect2 &p_rect) {} - virtual Rect2 _edit_get_rect() const { return Rect2(0, 0, 0, 0); }; - virtual Size2 _edit_get_minimum_size() const { return Size2(-1, -1); }; // LOOKS WEIRD + virtual Size2 _edit_get_minimum_size() const { return Size2(-1, -1); } // LOOKS WEIRD // Used to set a pivot - virtual bool _edit_use_pivot() const { return false; }; + virtual bool _edit_use_pivot() const { return false; } virtual void _edit_set_pivot(const Point2 &p_pivot) {} - virtual Point2 _edit_get_pivot() const { return Point2(); }; + virtual Point2 _edit_get_pivot() const { return Point2(); } virtual Transform2D _edit_get_transform() const; -#endif +#endif // TOOLS_ENABLED + +#ifdef DEBUG_ENABLED + // Those need to be available in debug runtime, to allow for node selection. + + // Select the node. + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + + // Used to resize/move the node. + virtual bool _edit_use_rect() const { return false; } // Maybe replace with _edit_get_editmode(). + virtual Rect2 _edit_get_rect() const { return Rect2(0, 0, 0, 0); } +#endif // DEBUG_ENABLED void update_draw_order(); @@ -375,7 +382,7 @@ public: TextureRepeat get_texture_repeat_in_tree() const; // Used by control nodes to retrieve the parent's anchorable area - virtual Rect2 get_anchorable_rect() const { return Rect2(0, 0, 0, 0); }; + virtual Rect2 get_anchorable_rect() const { return Rect2(0, 0, 0, 0); } int get_canvas_layer() const; CanvasLayer *get_canvas_layer_node() const; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 8526611093..986bd87af2 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -87,7 +87,7 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S String lowwer_case_header_name = p_header_name.to_lower(); for (int i = 0; i < p_headers.size(); i++) { - if (p_headers[i].find(":") > 0) { + if (p_headers[i].find_char(':') > 0) { Vector<String> parts = p_headers[i].split(":", false, 1); if (parts.size() > 1 && parts[0].strip_edges().to_lower() == lowwer_case_header_name) { value = parts[1].strip_edges(); diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp index 29166f3d92..9222ce6df3 100644 --- a/scene/main/instance_placeholder.cpp +++ b/scene/main/instance_placeholder.cpp @@ -245,7 +245,7 @@ Dictionary InstancePlaceholder::get_stored_values(bool p_with_order) { } return ret; -}; +} void InstancePlaceholder::_bind_methods() { ClassDB::bind_method(D_METHOD("get_stored_values", "with_order"), &InstancePlaceholder::get_stored_values, DEFVAL(false)); diff --git a/scene/main/missing_node.cpp b/scene/main/missing_node.cpp index 83672ae5e0..d5a183eab1 100644 --- a/scene/main/missing_node.cpp +++ b/scene/main/missing_node.cpp @@ -84,17 +84,17 @@ bool MissingNode::is_recording_properties() const { PackedStringArray MissingNode::get_configuration_warnings() const { // The mere existence of this node is warning. - PackedStringArray ret; + PackedStringArray warnings = Node::get_configuration_warnings(); if (!original_scene.is_empty()) { - ret.push_back(vformat(RTR("This node was an instance of scene '%s', which was no longer available when this scene was loaded."), original_scene)); - ret.push_back(vformat(RTR("Saving current scene will discard instance and all its properties, including editable children edits (if existing)."))); + warnings.push_back(vformat(RTR("This node was an instance of scene '%s', which was no longer available when this scene was loaded."), original_scene)); + warnings.push_back(vformat(RTR("Saving current scene will discard instance and all its properties, including editable children edits (if existing)."))); } else if (!original_class.is_empty()) { - ret.push_back(vformat(RTR("This node was saved as class type '%s', which was no longer available when this scene was loaded."), original_class)); - ret.push_back(RTR("Data from the original node is kept as a placeholder until this type of node is available again. It can hence be safely re-saved without risk of data loss.")); + warnings.push_back(vformat(RTR("This node was saved as class type '%s', which was no longer available when this scene was loaded."), original_class)); + warnings.push_back(RTR("Data from the original node is kept as a placeholder until this type of node is available again. It can hence be safely re-saved without risk of data loss.")); } else { - ret.push_back(RTR("Unrecognized missing node. Check scene dependency errors for details.")); + warnings.push_back(RTR("Unrecognized missing node. Check scene dependency errors for details.")); } - return ret; + return warnings; } void MissingNode::_bind_methods() { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index d921cc5b67..5063f0d6d0 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -184,6 +184,7 @@ void Node::_notification(int p_notification) { } } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (is_physics_interpolated_and_enabled() && is_inside_tree()) { reset_physics_interpolation(); @@ -695,6 +696,16 @@ void Node::_propagate_pause_notification(bool p_enable) { data.blocked--; } +void Node::_propagate_suspend_notification(bool p_enable) { + notification(p_enable ? NOTIFICATION_SUSPENDED : NOTIFICATION_UNSUSPENDED); + + data.blocked++; + for (KeyValue<StringName, Node *> &KV : data.children) { + KV.value->_propagate_suspend_notification(p_enable); + } + data.blocked--; +} + Node::ProcessMode Node::get_process_mode() const { return data.process_mode; } @@ -850,7 +861,7 @@ bool Node::can_process_notification(int p_what) const { bool Node::can_process() const { ERR_FAIL_COND_V(!is_inside_tree(), false); - return _can_process(get_tree()->is_paused()); + return !get_tree()->is_suspended() && _can_process(get_tree()->is_paused()); } bool Node::_can_process(bool p_paused) const { @@ -3044,11 +3055,12 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { if (copy && copytarget && E.callable.get_method() != StringName()) { Callable copy_callable = Callable(copytarget, E.callable.get_method()); if (!copy->is_connected(E.signal.get_name(), copy_callable)) { - int arg_count = E.callable.get_bound_arguments_count(); - if (arg_count > 0) { + int unbound_arg_count = E.callable.get_unbound_arguments_count(); + if (unbound_arg_count > 0) { + copy_callable = copy_callable.unbind(unbound_arg_count); + } + if (E.callable.get_bound_arguments_count() > 0) { copy_callable = copy_callable.bindv(E.callable.get_bound_arguments()); - } else if (arg_count < 0) { - copy_callable = copy_callable.unbind(-arg_count); } copy->connect(E.signal.get_name(), copy_callable, E.flags); } diff --git a/scene/main/node.h b/scene/main/node.h index 799478fa35..e2f3ce9b78 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -300,6 +300,7 @@ private: void _set_tree(SceneTree *p_tree); void _propagate_pause_notification(bool p_enable); + void _propagate_suspend_notification(bool p_enable); _FORCE_INLINE_ bool _can_process(bool p_paused) const; _FORCE_INLINE_ bool _is_enabled() const; @@ -439,6 +440,8 @@ public: // Editor specific node notifications NOTIFICATION_EDITOR_PRE_SAVE = 9001, NOTIFICATION_EDITOR_POST_SAVE = 9002, + NOTIFICATION_SUSPENDED = 9003, + NOTIFICATION_UNSUSPENDED = 9004 }; /* NODE/TREE */ diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 71d91b970e..16b41c8f9b 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -899,7 +899,7 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { return debug_contact_mesh; } - debug_contact_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + debug_contact_mesh.instantiate(); Ref<StandardMaterial3D> mat = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); @@ -954,11 +954,14 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { void SceneTree::set_pause(bool p_enabled) { ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Pause can only be set from the main thread."); + ERR_FAIL_COND_MSG(suspended, "Pause state cannot be modified while suspended."); if (p_enabled == paused) { return; } + paused = p_enabled; + #ifndef _3D_DISABLED PhysicsServer3D::get_singleton()->set_active(!p_enabled); #endif // _3D_DISABLED @@ -972,6 +975,30 @@ bool SceneTree::is_paused() const { return paused; } +void SceneTree::set_suspend(bool p_enabled) { + ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Suspend can only be set from the main thread."); + + if (p_enabled == suspended) { + return; + } + + suspended = p_enabled; + + Engine::get_singleton()->set_freeze_time_scale(p_enabled); + +#ifndef _3D_DISABLED + PhysicsServer3D::get_singleton()->set_active(!p_enabled && !paused); +#endif // _3D_DISABLED + PhysicsServer2D::get_singleton()->set_active(!p_enabled && !paused); + if (get_root()) { + get_root()->_propagate_suspend_notification(p_enabled); + } +} + +bool SceneTree::is_suspended() const { + return suspended; +} + void SceneTree::_process_group(ProcessGroup *p_group, bool p_physics) { // When reading this function, keep in mind that this code must work in a way where // if any node is removed, this needs to continue working. diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 7e44541105..291e4a5a0c 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -143,6 +143,7 @@ private: bool debug_navigation_hint = false; #endif bool paused = false; + bool suspended = false; HashMap<StringName, Group> group_map; bool _quit = false; @@ -343,6 +344,8 @@ public: void set_pause(bool p_enabled); bool is_paused() const; + void set_suspend(bool p_enabled); + bool is_suspended() const; #ifdef DEBUG_ENABLED void set_debug_collisions_hint(bool p_enabled); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 0cdb23618f..a0f39462a0 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -330,7 +330,7 @@ void Viewport::_sub_window_update(Window *p_window) { int close_h_ofs = p_window->theme_cache.close_h_offset; int close_v_ofs = p_window->theme_cache.close_v_offset; - TextLine title_text = TextLine(p_window->atr(p_window->get_title()), title_font, font_size); + TextLine title_text = TextLine(p_window->get_translated_title(), title_font, font_size); title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs); title_text.set_direction(p_window->is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); int x = (r.size.width - title_text.get_size().x) / 2; @@ -1213,7 +1213,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) { } } else { WARN_PRINT("Invalid world_2d"); - world_2d = Ref<World2D>(memnew(World2D)); + world_2d.instantiate(); } world_2d->register_viewport(this); @@ -1478,12 +1478,12 @@ void Viewport::_gui_show_tooltip() { gui.tooltip_label = memnew(Label); gui.tooltip_label->set_theme_type_variation(SNAME("TooltipLabel")); gui.tooltip_label->set_text(gui.tooltip_text); + gui.tooltip_label->set_auto_translate_mode(tooltip_owner->get_tooltip_auto_translate_mode()); base_tooltip = gui.tooltip_label; panel->connect(SceneStringName(mouse_entered), callable_mp(this, &Viewport::_gui_cancel_tooltip)); } base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - base_tooltip->set_auto_translate_mode(tooltip_owner->get_tooltip_auto_translate_mode()); panel->set_transient(true); panel->set_flag(Window::FLAG_NO_FOCUS, true); @@ -1921,7 +1921,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_global_transform_with_canvas().affine_inverse().xform(mpos)); tooltip = tooltip.strip_edges(); - if (tooltip.is_empty() || tooltip != gui.tooltip_text) { + if (tooltip != gui.tooltip_text) { _gui_cancel_tooltip(); } else { is_tooltip_shown = true; @@ -1931,21 +1931,19 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } } - // If the tooltip timer isn't running, start it. - // Otherwise, only reset the timer if the mouse has moved more than 5 pixels. - if (!is_tooltip_shown && over->can_process() && - (gui.tooltip_timer.is_null() || - Math::is_zero_approx(gui.tooltip_timer->get_time_left()) || - mm->get_relative().length() > 5.0)) { - if (gui.tooltip_timer.is_valid()) { - gui.tooltip_timer->release_connections(); - gui.tooltip_timer = Ref<SceneTreeTimer>(); + // Reset the timer if the mouse has moved more than 5 pixels or has entered a new control. + if (!is_tooltip_shown && over->can_process()) { + Vector2 new_tooltip_pos = over->get_screen_transform().xform(pos); + if (over != gui.tooltip_control || gui.tooltip_pos.distance_squared_to(new_tooltip_pos) > 25) { + if (gui.tooltip_timer.is_valid()) { + gui.tooltip_timer->release_connections(); + } + gui.tooltip_control = over; + gui.tooltip_pos = new_tooltip_pos; + gui.tooltip_timer = get_tree()->create_timer(gui.tooltip_delay); + gui.tooltip_timer->set_ignore_time_scale(true); + gui.tooltip_timer->connect("timeout", callable_mp(this, &Viewport::_gui_show_tooltip)); } - gui.tooltip_control = over; - gui.tooltip_pos = over->get_screen_transform().xform(pos); - gui.tooltip_timer = get_tree()->create_timer(gui.tooltip_delay); - gui.tooltip_timer->set_ignore_time_scale(true); - gui.tooltip_timer->connect("timeout", callable_mp(this, &Viewport::_gui_show_tooltip)); } } @@ -3062,6 +3060,14 @@ void Viewport::_update_mouse_over(Vector2 p_pos) { } v->_update_mouse_over(v->get_final_transform().affine_inverse().xform(pos)); } + + Viewport *section_root = get_section_root_viewport(); + if (section_root && c->is_consume_drag_and_drop_enabled()) { + // Evaluating `consume_drag_and_drop` and adjusting target_control needs to happen + // after `_update_mouse_over` in the SubViewports, because otherwise physics picking + // would not work inside SubViewports. + section_root->gui.target_control = over; + } } } @@ -3123,7 +3129,7 @@ void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) { ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(p_event.is_null()); - if (disable_input) { + if (disable_input || disable_input_override) { return; } @@ -3195,7 +3201,7 @@ void Viewport::push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local local_input_handled = false; - if (disable_input || !_can_consume_input_events()) { + if (disable_input || disable_input_override || !_can_consume_input_events()) { return; } @@ -3298,7 +3304,7 @@ void Viewport::set_disable_input(bool p_disable) { if (p_disable == disable_input) { return; } - if (p_disable) { + if (p_disable && !disable_input_override) { _drop_mouse_focus(); _mouse_leave_viewport(); _gui_cancel_tooltip(); @@ -3311,6 +3317,19 @@ bool Viewport::is_input_disabled() const { return disable_input; } +void Viewport::set_disable_input_override(bool p_disable) { + ERR_MAIN_THREAD_GUARD; + if (p_disable == disable_input_override) { + return; + } + if (p_disable && !disable_input) { + _drop_mouse_focus(); + _mouse_leave_viewport(); + _gui_cancel_tooltip(); + } + disable_input_override = p_disable; +} + Variant Viewport::gui_get_drag_data() const { ERR_READ_THREAD_GUARD_V(Variant()); return get_section_root_viewport()->gui.drag_data; @@ -4237,6 +4256,22 @@ void Viewport::set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, } } +HashMap<StringName, real_t> Viewport::get_camera_3d_override_properties() const { + HashMap<StringName, real_t> props; + + props["size"] = 0; + props["fov"] = 0; + props["z_near"] = 0; + props["z_far"] = 0; + ERR_READ_THREAD_GUARD_V(props); + + props["size"] = camera_3d_override.size; + props["fov"] = camera_3d_override.fov; + props["z_near"] = camera_3d_override.z_near; + props["z_far"] = camera_3d_override.z_far; + return props; +} + void Viewport::set_disable_3d(bool p_disable) { ERR_MAIN_THREAD_GUARD; disable_3d = p_disable; @@ -4270,6 +4305,54 @@ Transform3D Viewport::get_camera_3d_override_transform() const { return Transform3D(); } +Vector3 Viewport::camera_3d_override_project_ray_normal(const Point2 &p_pos) const { + ERR_READ_THREAD_GUARD_V(Vector3()); + Vector3 ray = camera_3d_override_project_local_ray_normal(p_pos); + return camera_3d_override.transform.basis.xform(ray).normalized(); +} + +Vector3 Viewport::camera_3d_override_project_local_ray_normal(const Point2 &p_pos) const { + ERR_READ_THREAD_GUARD_V(Vector3()); + Size2 viewport_size = get_camera_rect_size(); + Vector2 cpos = get_camera_coords(p_pos); + Vector3 ray; + + if (camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) { + ray = Vector3(0, 0, -1); + } else { + Projection cm; + cm.set_perspective(camera_3d_override.fov, get_visible_rect().size.aspect(), camera_3d_override.z_near, camera_3d_override.z_far, false); + + Vector2 screen_he = cm.get_viewport_half_extents(); + ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -camera_3d_override.z_near).normalized(); + } + + return ray; +} + +Vector3 Viewport::camera_3d_override_project_ray_origin(const Point2 &p_pos) const { + ERR_READ_THREAD_GUARD_V(Vector3()); + Size2 viewport_size = get_camera_rect_size(); + Vector2 cpos = get_camera_coords(p_pos); + ERR_FAIL_COND_V(viewport_size.y == 0, Vector3()); + + if (camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) { + Vector2 pos = cpos / viewport_size; + real_t vsize, hsize; + hsize = camera_3d_override.size * viewport_size.aspect(); + vsize = camera_3d_override.size; + + Vector3 ray; + ray.x = pos.x * (hsize)-hsize / 2; + ray.y = (1.0 - pos.y) * (vsize)-vsize / 2; + ray.z = -camera_3d_override.z_near; + ray = camera_3d_override.transform.xform(ray); + return ray; + } else { + return camera_3d_override.transform.origin; + }; +} + Ref<World3D> Viewport::get_world_3d() const { ERR_READ_THREAD_GUARD_V(Ref<World3D>()); return world_3d; @@ -4309,7 +4392,7 @@ void Viewport::set_world_3d(const Ref<World3D> &p_world_3d) { own_world_3d = world_3d->duplicate(); world_3d->connect_changed(callable_mp(this, &Viewport::_own_world_3d_changed)); } else { - own_world_3d = Ref<World3D>(memnew(World3D)); + own_world_3d.instantiate(); } } @@ -4360,7 +4443,7 @@ void Viewport::set_use_own_world_3d(bool p_use_own_world_3d) { own_world_3d = world_3d->duplicate(); world_3d->connect_changed(callable_mp(this, &Viewport::_own_world_3d_changed)); } else { - own_world_3d = Ref<World3D>(memnew(World3D)); + own_world_3d.instantiate(); } } else { own_world_3d = Ref<World3D>(); @@ -4886,7 +4969,7 @@ void Viewport::_validate_property(PropertyInfo &p_property) const { } Viewport::Viewport() { - world_2d = Ref<World2D>(memnew(World2D)); + world_2d.instantiate(); world_2d->register_viewport(this); viewport = RenderingServer::get_singleton()->viewport_create(); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index a18dc1f6f0..92691ccbec 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -401,6 +401,7 @@ private: DefaultCanvasItemTextureRepeat default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; bool disable_input = false; + bool disable_input_override = false; void _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input); void _gui_call_notification(Control *p_control, int p_what); @@ -580,6 +581,8 @@ public: void set_disable_input(bool p_disable); bool is_input_disabled() const; + void set_disable_input_override(bool p_disable); + Vector2 get_mouse_position() const; void warp_mouse(const Vector2 &p_position); virtual void update_mouse_cursor_state(); @@ -770,6 +773,11 @@ public: void set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far); void set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far); + HashMap<StringName, real_t> get_camera_3d_override_properties() const; + + Vector3 camera_3d_override_project_ray_normal(const Point2 &p_pos) const; + Vector3 camera_3d_override_project_ray_origin(const Point2 &p_pos) const; + Vector3 camera_3d_override_project_local_ray_normal(const Point2 &p_pos) const; void set_disable_3d(bool p_disable); bool is_3d_disabled() const; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 803ce89bc9..05904fa8f9 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -31,10 +31,8 @@ #include "window.h" #include "core/config/project_settings.h" -#include "core/debugger/engine_debugger.h" #include "core/input/shortcut.h" #include "core/string/translation_server.h" -#include "core/variant/variant_parser.h" #include "scene/gui/control.h" #include "scene/theme/theme_db.h" #include "scene/theme/theme_owner.h" @@ -305,6 +303,11 @@ String Window::get_title() const { return title; } +String Window::get_translated_title() const { + ERR_READ_THREAD_GUARD_V(String()); + return tr_title; +} + void Window::_settings_changed() { if (visible && initial_position != WINDOW_INITIAL_POSITION_ABSOLUTE && is_in_edited_scene_root()) { Size2 screen_size = Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height")); @@ -1631,35 +1634,6 @@ bool Window::_can_consume_input_events() const { void Window::_window_input(const Ref<InputEvent> &p_ev) { ERR_MAIN_THREAD_GUARD; - if (EngineDebugger::is_active()) { - // Quit from game window using the stop shortcut (F8 by default). - // The custom shortcut is provided via environment variable when running from the editor. - if (debugger_stop_shortcut.is_null()) { - String shortcut_str = OS::get_singleton()->get_environment("__GODOT_EDITOR_STOP_SHORTCUT__"); - if (!shortcut_str.is_empty()) { - Variant shortcut_var; - - VariantParser::StreamString ss; - ss.s = shortcut_str; - - String errs; - int line; - VariantParser::parse(&ss, shortcut_var, errs, line); - debugger_stop_shortcut = shortcut_var; - } - - if (debugger_stop_shortcut.is_null()) { - // Define a default shortcut if it wasn't provided or is invalid. - debugger_stop_shortcut.instantiate(); - debugger_stop_shortcut->set_events({ (Variant)InputEventKey::create_reference(Key::F8) }); - } - } - - Ref<InputEventKey> k = p_ev; - if (k.is_valid() && k->is_pressed() && !k->is_echo() && debugger_stop_shortcut->matches_event(k)) { - EngineDebugger::get_singleton()->send_message("request_quit", Array()); - } - } if (exclusive_child != nullptr) { if (!is_embedding_subwindows()) { // Not embedding, no need for event. @@ -2635,7 +2609,7 @@ void Window::set_unparent_when_invisible(bool p_unparent) { void Window::set_layout_direction(Window::LayoutDirection p_direction) { ERR_MAIN_THREAD_GUARD; - ERR_FAIL_INDEX((int)p_direction, 4); + ERR_FAIL_INDEX(p_direction, LAYOUT_DIRECTION_MAX); layout_dir = p_direction; propagate_notification(Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED); @@ -2700,13 +2674,20 @@ bool Window::is_layout_rtl() const { String locale = TranslationServer::get_singleton()->get_tool_locale(); return TS->is_locale_right_to_left(locale); } - } else if (layout_dir == LAYOUT_DIRECTION_LOCALE) { + } else if (layout_dir == LAYOUT_DIRECTION_APPLICATION_LOCALE) { if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { return true; } else { String locale = TranslationServer::get_singleton()->get_tool_locale(); return TS->is_locale_right_to_left(locale); } + } else if (layout_dir == LAYOUT_DIRECTION_SYSTEM_LOCALE) { + if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { + return true; + } else { + String locale = OS::get_singleton()->get_locale(); + return TS->is_locale_right_to_left(locale); + } } else { return (layout_dir == LAYOUT_DIRECTION_RTL); } @@ -3001,6 +2982,7 @@ void Window::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_window"), "set_flag", "get_flag", FLAG_POPUP); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "extend_to_title"), "set_flag", "get_flag", FLAG_EXTEND_TO_TITLE); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "mouse_passthrough"), "set_flag", "get_flag", FLAG_MOUSE_PASSTHROUGH); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "sharp_corners"), "set_flag", "get_flag", FLAG_SHARP_CORNERS); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_native"), "set_force_native", "get_force_native"); ADD_GROUP("Limits", ""); @@ -3054,6 +3036,7 @@ void Window::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_POPUP); BIND_ENUM_CONSTANT(FLAG_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(FLAG_MOUSE_PASSTHROUGH); + BIND_ENUM_CONSTANT(FLAG_SHARP_CORNERS); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED); @@ -3070,9 +3053,14 @@ void Window::_bind_methods() { BIND_ENUM_CONSTANT(CONTENT_SCALE_STRETCH_INTEGER); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED); - BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE); + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_APPLICATION_LOCALE); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_RTL); + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_SYSTEM_LOCALE); + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_MAX); +#ifndef DISABLE_DEPRECATED + BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE); +#endif // DISABLE_DEPRECATED BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_ABSOLUTE); BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_PRIMARY_SCREEN); diff --git a/scene/main/window.h b/scene/main/window.h index 47aaf73728..a1d95ab91f 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -62,6 +62,7 @@ public: FLAG_POPUP = DisplayServer::WINDOW_FLAG_POPUP, FLAG_EXTEND_TO_TITLE = DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE, FLAG_MOUSE_PASSTHROUGH = DisplayServer::WINDOW_FLAG_MOUSE_PASSTHROUGH, + FLAG_SHARP_CORNERS = DisplayServer::WINDOW_FLAG_SHARP_CORNERS, FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX, }; @@ -86,9 +87,14 @@ public: enum LayoutDirection { LAYOUT_DIRECTION_INHERITED, - LAYOUT_DIRECTION_LOCALE, + LAYOUT_DIRECTION_APPLICATION_LOCALE, LAYOUT_DIRECTION_LTR, - LAYOUT_DIRECTION_RTL + LAYOUT_DIRECTION_RTL, + LAYOUT_DIRECTION_SYSTEM_LOCALE, + LAYOUT_DIRECTION_MAX, +#ifndef DISABLE_DEPRECATED + LAYOUT_DIRECTION_LOCALE = LAYOUT_DIRECTION_APPLICATION_LOCALE, +#endif // DISABLE_DEPRECATED }; enum { @@ -268,6 +274,7 @@ public: void set_title(const String &p_title); String get_title() const; + String get_translated_title() const; void set_initial_position(WindowInitialPosition p_initial_position); WindowInitialPosition get_initial_position() const; @@ -368,7 +375,7 @@ public: bool is_wrapping_controls() const; void child_controls_changed(); - Window *get_exclusive_child() const { return exclusive_child; }; + Window *get_exclusive_child() const { return exclusive_child; } Window *get_parent_visible_window() const; Viewport *get_parent_viewport() const; diff --git a/scene/property_utils.cpp b/scene/property_utils.cpp index 94a037bd9b..9cae7d2a3a 100644 --- a/scene/property_utils.cpp +++ b/scene/property_utils.cpp @@ -89,6 +89,16 @@ Variant PropertyUtils::get_property_default_value(const Object *p_object, const *r_is_valid = false; } + // Handle special case "script" property, where the default value is either null or the custom type script. + // Do this only if there's no states stack cache to trace for default values. + if (!p_states_stack_cache && p_property == CoreStringName(script) && p_object->has_meta(SceneStringName(_custom_type_script))) { + Ref<Script> ct_scr = p_object->get_meta(SceneStringName(_custom_type_script)); + if (r_is_valid) { + *r_is_valid = true; + } + return ct_scr; + } + Ref<Script> topmost_script; if (const Node *node = Object::cast_to<Node>(p_object)) { @@ -172,7 +182,7 @@ Variant PropertyUtils::get_property_default_value(const Object *p_object, const // Heuristically check if this is a synthetic property (whatever/0, whatever/1, etc.) // because they are not in the class DB yet must have a default (null). String prop_str = String(p_property); - int p = prop_str.rfind("/"); + int p = prop_str.rfind_char('/'); if (p != -1 && p < prop_str.length() - 1) { bool all_digits = true; for (int i = p + 1; i < prop_str.length(); i++) { diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 6b1ce2b4ca..8a048e9cc3 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -243,6 +243,7 @@ #include "scene/3d/light_3d.h" #include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_probe.h" +#include "scene/3d/look_at_modifier_3d.h" #include "scene/3d/marker_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/multimesh_instance_3d.h" @@ -512,6 +513,9 @@ void register_scene_types() { GDREGISTER_CLASS(AnimationNodeStateMachine); GDREGISTER_CLASS(AnimationNodeStateMachinePlayback); + GDREGISTER_INTERNAL_CLASS(AnimationNodeStartState); + GDREGISTER_INTERNAL_CLASS(AnimationNodeEndState); + GDREGISTER_CLASS(AnimationNodeSync); GDREGISTER_CLASS(AnimationNodeStateMachineTransition); GDREGISTER_CLASS(AnimationNodeOutput); @@ -608,6 +612,7 @@ void register_scene_types() { GDREGISTER_CLASS(SkeletonIK3D); GDREGISTER_CLASS(BoneAttachment3D); + GDREGISTER_CLASS(LookAtModifier3D); GDREGISTER_CLASS(VehicleBody3D); GDREGISTER_CLASS(VehicleWheel3D); diff --git a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp index e3f14539a8..07e9caa713 100644 --- a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp +++ b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp @@ -43,7 +43,7 @@ void NavigationMeshSourceGeometryData2D::clear() { bool NavigationMeshSourceGeometryData2D::has_data() { RWLockRead read_lock(geometry_rwlock); return traversable_outlines.size(); -}; +} void NavigationMeshSourceGeometryData2D::clear_projected_obstructions() { RWLockWrite write_lock(geometry_rwlock); diff --git a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h index b29c106fb5..2812925770 100644 --- a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h +++ b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h @@ -36,6 +36,8 @@ #include "scene/resources/2d/navigation_polygon.h" class NavigationMeshSourceGeometryData2D : public Resource { + friend class NavMeshGenerator2D; + GDCLASS(NavigationMeshSourceGeometryData2D, Resource); RWLock geometry_rwlock; diff --git a/scene/resources/2d/navigation_polygon.cpp b/scene/resources/2d/navigation_polygon.cpp index 3dfa906e3b..37240e8038 100644 --- a/scene/resources/2d/navigation_polygon.cpp +++ b/scene/resources/2d/navigation_polygon.cpp @@ -36,7 +36,7 @@ #include "thirdparty/misc/polypartition.h" -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 NavigationPolygon::_edit_get_rect() const { RWLockRead read_lock(rwlock); if (rect_cache_dirty) { @@ -79,7 +79,7 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double } return false; } -#endif +#endif // DEBUG_ENABLED void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) { RWLockWrite write_lock(rwlock); diff --git a/scene/resources/2d/navigation_polygon.h b/scene/resources/2d/navigation_polygon.h index ed2c606c55..59e5eeed68 100644 --- a/scene/resources/2d/navigation_polygon.h +++ b/scene/resources/2d/navigation_polygon.h @@ -68,10 +68,11 @@ protected: TypedArray<Vector<Vector2>> _get_outlines() const; public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 _edit_get_rect() const; bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; -#endif +#endif // DEBUG_ENABLED + enum SamplePartitionType { SAMPLE_PARTITION_CONVEX_PARTITION = 0, SAMPLE_PARTITION_TRIANGULATE, diff --git a/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h b/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h index 0732153997..d1e50cb702 100644 --- a/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h +++ b/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h @@ -64,7 +64,7 @@ public: execution_mode_physics_process }; - Vector<Ref<SkeletonModification2D>> modifications = Vector<Ref<SkeletonModification2D>>(); + Vector<Ref<SkeletonModification2D>> modifications; void setup(); void execute(float p_delta, int p_execution_mode); diff --git a/scene/resources/2d/tile_set.cpp b/scene/resources/2d/tile_set.cpp index 229e18be23..5ecfc32622 100644 --- a/scene/resources/2d/tile_set.cpp +++ b/scene/resources/2d/tile_set.cpp @@ -174,13 +174,13 @@ void TileMapPattern::set_size(const Size2i &p_size) { bool TileMapPattern::is_empty() const { return pattern.is_empty(); -}; +} void TileMapPattern::clear() { size = Size2i(); pattern.clear(); emit_changed(); -}; +} bool TileMapPattern::_set(const StringName &p_name, const Variant &p_value) { if (p_name == "tile_data") { @@ -571,11 +571,11 @@ void TileSet::set_uv_clipping(bool p_uv_clipping) { bool TileSet::is_uv_clipping() const { return uv_clipping; -}; +} int TileSet::get_occlusion_layers_count() const { return occlusion_layers.size(); -}; +} void TileSet::add_occlusion_layer(int p_index) { if (p_index < 0) { @@ -699,6 +699,17 @@ uint32_t TileSet::get_physics_layer_collision_mask(int p_layer_index) const { return physics_layers[p_layer_index].collision_mask; } +void TileSet::set_physics_layer_collision_priority(int p_layer_index, real_t p_priority) { + ERR_FAIL_INDEX(p_layer_index, physics_layers.size()); + physics_layers.write[p_layer_index].collision_priority = p_priority; + emit_changed(); +} + +real_t TileSet::get_physics_layer_collision_priority(int p_layer_index) const { + ERR_FAIL_INDEX_V(p_layer_index, physics_layers.size(), 0); + return physics_layers[p_layer_index].collision_priority; +} + void TileSet::set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material) { ERR_FAIL_INDEX(p_layer_index, physics_layers.size()); physics_layers.write[p_layer_index].physics_material = p_physics_material; @@ -3691,7 +3702,7 @@ Array TileSet::compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool return cannot_convert_array; break; } -}; +} #endif // DISABLE_DEPRECATED @@ -3900,6 +3911,13 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } set_physics_layer_collision_mask(index, p_value); return true; + } else if (components[1] == "collision_priority") { + ERR_FAIL_COND_V(p_value.get_type() != Variant::FLOAT, false); + while (index >= physics_layers.size()) { + add_physics_layer(); + } + set_physics_layer_collision_priority(index, p_value); + return true; } else if (components[1] == "physics_material") { Ref<PhysicsMaterial> physics_material = p_value; while (index >= physics_layers.size()) { @@ -4051,6 +4069,9 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { } else if (components[1] == "collision_mask") { r_ret = get_physics_layer_collision_mask(index); return true; + } else if (components[1] == "collision_priority") { + r_ret = get_physics_layer_collision_priority(index); + return true; } else if (components[1] == "physics_material") { r_ret = get_physics_layer_physics_material(index); return true; @@ -4176,6 +4197,13 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } p_list->push_back(property_info); + // physics_layer_%d/collision_priority + property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/collision_priority", i)); + if (physics_layers[i].collision_priority == 1.0) { + property_info.usage ^= PROPERTY_USAGE_STORAGE; + } + p_list->push_back(property_info); + // physics_layer_%d/physics_material property_info = PropertyInfo(Variant::OBJECT, vformat("physics_layer_%d/physics_material", i), PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"); if (!physics_layers[i].physics_material.is_valid()) { @@ -4220,10 +4248,10 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { // Tile Proxies. // Note: proxies need to be set after sources are set. - p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Tile Proxies", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/source_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/coords_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/alternative_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Patterns. for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) { @@ -4287,6 +4315,8 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("get_physics_layer_collision_layer", "layer_index"), &TileSet::get_physics_layer_collision_layer); ClassDB::bind_method(D_METHOD("set_physics_layer_collision_mask", "layer_index", "mask"), &TileSet::set_physics_layer_collision_mask); ClassDB::bind_method(D_METHOD("get_physics_layer_collision_mask", "layer_index"), &TileSet::get_physics_layer_collision_mask); + ClassDB::bind_method(D_METHOD("set_physics_layer_collision_priority", "layer_index", "priority"), &TileSet::set_physics_layer_collision_priority); + ClassDB::bind_method(D_METHOD("get_physics_layer_collision_priority", "layer_index"), &TileSet::get_physics_layer_collision_priority); ClassDB::bind_method(D_METHOD("set_physics_layer_physics_material", "layer_index", "physics_material"), &TileSet::set_physics_layer_physics_material); ClassDB::bind_method(D_METHOD("get_physics_layer_physics_material", "layer_index"), &TileSet::get_physics_layer_physics_material); @@ -4432,7 +4462,7 @@ TileSet *TileSetSource::get_tile_set() const { void TileSetSource::reset_state() { tile_set = nullptr; -}; +} void TileSetSource::_bind_methods() { // Base tiles @@ -4931,10 +4961,13 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { } for (const KeyValue<int, TileData *> &E_alternative : E_tile.value.alternatives) { + const String formatted_key = itos(E_alternative.key); + // Add a dummy property to show the alternative exists. - tile_property_list.push_back(PropertyInfo(Variant::INT, vformat("%d", E_alternative.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + tile_property_list.push_back(PropertyInfo(Variant::INT, formatted_key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Get the alternative tile's properties and append them to the list of properties. + const String alternative_property_info_prefix = formatted_key + '/'; List<PropertyInfo> alternative_property_list; E_alternative.value->get_property_list(&alternative_property_list); for (PropertyInfo &alternative_property_info : alternative_property_list) { @@ -4943,14 +4976,15 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value))) { alternative_property_info.usage ^= PROPERTY_USAGE_STORAGE; } - alternative_property_info.name = vformat("%s/%s", vformat("%d", E_alternative.key), alternative_property_info.name); + alternative_property_info.name = alternative_property_info_prefix + alternative_property_info.name; tile_property_list.push_back(alternative_property_info); } } // Add all alternative. + const String property_info_prefix = vformat("%d:%d/", E_tile.key.x, E_tile.key.y); for (PropertyInfo &tile_property_info : tile_property_list) { - tile_property_info.name = vformat("%s/%s", vformat("%d:%d", E_tile.key.x, E_tile.key.y), tile_property_info.name); + tile_property_info.name = property_info_prefix + tile_property_info.name; p_list->push_back(tile_property_info); } } @@ -6480,9 +6514,9 @@ int TileData::get_terrain_set() const { } void TileData::set_terrain(int p_terrain) { - ERR_FAIL_COND(terrain_set < 0); ERR_FAIL_COND(p_terrain < -1); - if (tile_set) { + ERR_FAIL_COND(terrain_set < 0 && p_terrain != -1); + if (tile_set && terrain_set >= 0) { ERR_FAIL_COND(p_terrain >= tile_set->get_terrains_count(terrain_set)); } terrain = p_terrain; @@ -6495,9 +6529,9 @@ int TileData::get_terrain() const { void TileData::set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) { ERR_FAIL_INDEX(p_peering_bit, TileSet::CellNeighbor::CELL_NEIGHBOR_MAX); - ERR_FAIL_COND(terrain_set < 0); ERR_FAIL_COND(p_terrain_index < -1); - if (tile_set) { + ERR_FAIL_COND(terrain_set < 0 && p_terrain_index != -1); + if (tile_set && terrain_set >= 0) { ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set)); ERR_FAIL_COND(!is_valid_terrain_peering_bit(p_peering_bit)); } diff --git a/scene/resources/2d/tile_set.h b/scene/resources/2d/tile_set.h index 15e1a16359..6d3ccd1d2d 100644 --- a/scene/resources/2d/tile_set.h +++ b/scene/resources/2d/tile_set.h @@ -278,7 +278,7 @@ public: bool operator==(const TerrainsPattern &p_terrains_pattern) const; bool operator!=(const TerrainsPattern &p_terrains_pattern) const { return !operator==(p_terrains_pattern); - }; + } void set_terrain(int p_terrain); int get_terrain() const; @@ -327,6 +327,7 @@ private: struct PhysicsLayer { uint32_t collision_layer = 1; uint32_t collision_mask = 1; + real_t collision_priority = 1.0; Ref<PhysicsMaterial> physics_material; }; Vector<PhysicsLayer> physics_layers; @@ -448,6 +449,8 @@ public: uint32_t get_physics_layer_collision_layer(int p_layer_index) const; void set_physics_layer_collision_mask(int p_layer_index, uint32_t p_mask); uint32_t get_physics_layer_collision_mask(int p_layer_index) const; + void set_physics_layer_collision_priority(int p_layer_index, real_t p_priority); + real_t get_physics_layer_collision_priority(int p_layer_index) const; void set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material); Ref<PhysicsMaterial> get_physics_layer_physics_material(int p_layer_index) const; @@ -812,8 +815,8 @@ public: // Scenes accessors. Lot are similar to "Alternative tiles". int get_scene_tiles_count() { return get_alternative_tiles_count(Vector2i()); } - int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); }; - bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); }; + int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); } + bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); } int create_scene_tile(Ref<PackedScene> p_packed_scene = Ref<PackedScene>(), int p_id_override = -1); void set_scene_tile_id(int p_id, int p_new_id); void set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene); @@ -836,7 +839,7 @@ private: bool flip_v = false; bool transpose = false; Vector2i texture_origin; - Ref<Material> material = Ref<Material>(); + Ref<Material> material; Color modulate = Color(1.0, 1.0, 1.0, 1.0); int z_index = 0; int y_sort_origin = 0; diff --git a/scene/resources/3d/convex_polygon_shape_3d.cpp b/scene/resources/3d/convex_polygon_shape_3d.cpp index 3bfeeca461..586d5f4678 100644 --- a/scene/resources/3d/convex_polygon_shape_3d.cpp +++ b/scene/resources/3d/convex_polygon_shape_3d.cpp @@ -35,7 +35,7 @@ Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() const { Vector<Vector3> poly_points = get_points(); - if (poly_points.size() > 3) { + if (poly_points.size() > 1) { // Need at least 2 points for a line. Vector<Vector3> varr = Variant(poly_points); Geometry3D::MeshData md; Error err = ConvexHullComputer::convex_hull(varr, md); diff --git a/scene/resources/3d/importer_mesh.cpp b/scene/resources/3d/importer_mesh.cpp index 47cd64f19a..f040f04cd8 100644 --- a/scene/resources/3d/importer_mesh.cpp +++ b/scene/resources/3d/importer_mesh.cpp @@ -33,108 +33,10 @@ #include "core/io/marshalls.h" #include "core/math/convex_hull.h" #include "core/math/random_pcg.h" -#include "core/math/static_raycaster.h" -#include "scene/resources/animation_library.h" #include "scene/resources/surface_tool.h" #include <cstdint> -void ImporterMesh::Surface::split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) { - _split_normals(arrays, p_indices, p_normals); - - for (BlendShape &blend_shape : blend_shape_data) { - _split_normals(blend_shape.arrays, p_indices, p_normals); - } -} - -void ImporterMesh::Surface::_split_normals(Array &r_arrays, const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) { - ERR_FAIL_COND(r_arrays.size() != RS::ARRAY_MAX); - - const PackedVector3Array &vertices = r_arrays[RS::ARRAY_VERTEX]; - int current_vertex_count = vertices.size(); - int new_vertex_count = p_indices.size(); - int final_vertex_count = current_vertex_count + new_vertex_count; - const int *indices_ptr = p_indices.ptr(); - - for (int i = 0; i < r_arrays.size(); i++) { - if (i == RS::ARRAY_INDEX) { - continue; - } - - if (r_arrays[i].get_type() == Variant::NIL) { - continue; - } - - switch (r_arrays[i].get_type()) { - case Variant::PACKED_VECTOR3_ARRAY: { - PackedVector3Array data = r_arrays[i]; - data.resize(final_vertex_count); - Vector3 *data_ptr = data.ptrw(); - if (i == RS::ARRAY_NORMAL) { - const Vector3 *normals_ptr = p_normals.ptr(); - memcpy(&data_ptr[current_vertex_count], normals_ptr, sizeof(Vector3) * new_vertex_count); - } else { - for (int j = 0; j < new_vertex_count; j++) { - data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; - } - } - r_arrays[i] = data; - } break; - case Variant::PACKED_VECTOR2_ARRAY: { - PackedVector2Array data = r_arrays[i]; - data.resize(final_vertex_count); - Vector2 *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; - } - r_arrays[i] = data; - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - PackedFloat32Array data = r_arrays[i]; - int elements = data.size() / current_vertex_count; - data.resize(final_vertex_count * elements); - float *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(float) * elements); - } - r_arrays[i] = data; - } break; - case Variant::PACKED_INT32_ARRAY: { - PackedInt32Array data = r_arrays[i]; - int elements = data.size() / current_vertex_count; - data.resize(final_vertex_count * elements); - int32_t *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(int32_t) * elements); - } - r_arrays[i] = data; - } break; - case Variant::PACKED_BYTE_ARRAY: { - PackedByteArray data = r_arrays[i]; - int elements = data.size() / current_vertex_count; - data.resize(final_vertex_count * elements); - uint8_t *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(uint8_t) * elements); - } - r_arrays[i] = data; - } break; - case Variant::PACKED_COLOR_ARRAY: { - PackedColorArray data = r_arrays[i]; - data.resize(final_vertex_count); - Color *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; - } - r_arrays[i] = data; - } break; - default: { - ERR_FAIL_MSG("Unhandled array type."); - } break; - } - } -} - String ImporterMesh::validate_blend_shape_name(const String &p_name) { String name = p_name; const char *characters = ":"; @@ -266,10 +168,56 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma mesh.unref(); } -void ImporterMesh::optimize_indices_for_cache() { +template <typename T> +static Vector<T> _remap_array(Vector<T> p_array, const Vector<uint32_t> &p_remap, uint32_t p_vertex_count) { + ERR_FAIL_COND_V(p_array.size() % p_remap.size() != 0, p_array); + int num_elements = p_array.size() / p_remap.size(); + T *data = p_array.ptrw(); + SurfaceTool::remap_vertex_func(data, data, p_remap.size(), sizeof(T) * num_elements, p_remap.ptr()); + p_array.resize(p_vertex_count * num_elements); + return p_array; +} + +static void _remap_arrays(Array &r_arrays, const Vector<uint32_t> &p_remap, uint32_t p_vertex_count) { + for (int i = 0; i < r_arrays.size(); i++) { + if (i == RS::ARRAY_INDEX) { + continue; + } + + switch (r_arrays[i].get_type()) { + case Variant::NIL: + break; + case Variant::PACKED_VECTOR3_ARRAY: + r_arrays[i] = _remap_array<Vector3>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_VECTOR2_ARRAY: + r_arrays[i] = _remap_array<Vector2>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_FLOAT32_ARRAY: + r_arrays[i] = _remap_array<float>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_INT32_ARRAY: + r_arrays[i] = _remap_array<int32_t>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_BYTE_ARRAY: + r_arrays[i] = _remap_array<uint8_t>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_COLOR_ARRAY: + r_arrays[i] = _remap_array<Color>(r_arrays[i], p_remap, p_vertex_count); + break; + default: + ERR_FAIL_MSG("Unhandled array type."); + } + } +} + +void ImporterMesh::optimize_indices() { if (!SurfaceTool::optimize_vertex_cache_func) { return; } + if (!SurfaceTool::optimize_vertex_fetch_remap_func || !SurfaceTool::remap_vertex_func || !SurfaceTool::remap_index_func) { + return; + } for (int i = 0; i < surfaces.size(); i++) { if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) { @@ -286,10 +234,48 @@ void ImporterMesh::optimize_indices_for_cache() { continue; } + // Optimize indices for vertex cache to establish final triangle order. int *indices_ptr = indices.ptrw(); SurfaceTool::optimize_vertex_cache_func((unsigned int *)indices_ptr, (const unsigned int *)indices_ptr, index_count, vertex_count); + surfaces.write[i].arrays[RS::ARRAY_INDEX] = indices; + + for (int j = 0; j < surfaces[i].lods.size(); ++j) { + Surface::LOD &lod = surfaces.write[i].lods.write[j]; + int *lod_indices_ptr = lod.indices.ptrw(); + SurfaceTool::optimize_vertex_cache_func((unsigned int *)lod_indices_ptr, (const unsigned int *)lod_indices_ptr, lod.indices.size(), vertex_count); + } + // Concatenate indices for all LODs in the order of coarse->fine; this establishes the effective order of vertices, + // and is important to optimize for vertex fetch (all GPUs) and shading (Mali GPUs) + PackedInt32Array merged_indices; + for (int j = surfaces[i].lods.size() - 1; j >= 0; --j) { + merged_indices.append_array(surfaces[i].lods[j].indices); + } + merged_indices.append_array(indices); + + // Generate remap array that establishes optimal vertex order according to the order of indices above. + Vector<uint32_t> remap; + remap.resize(vertex_count); + unsigned int new_vertex_count = SurfaceTool::optimize_vertex_fetch_remap_func(remap.ptrw(), (const unsigned int *)merged_indices.ptr(), merged_indices.size(), vertex_count); + + // We need to remap all vertex and index arrays in lockstep according to the remap. + SurfaceTool::remap_index_func((unsigned int *)indices_ptr, (const unsigned int *)indices_ptr, index_count, remap.ptr()); surfaces.write[i].arrays[RS::ARRAY_INDEX] = indices; + + for (int j = 0; j < surfaces[i].lods.size(); ++j) { + Surface::LOD &lod = surfaces.write[i].lods.write[j]; + int *lod_indices_ptr = lod.indices.ptrw(); + SurfaceTool::remap_index_func((unsigned int *)lod_indices_ptr, (const unsigned int *)lod_indices_ptr, lod.indices.size(), remap.ptr()); + } + + _remap_arrays(surfaces.write[i].arrays, remap, new_vertex_count); + for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) { + _remap_arrays(surfaces.write[i].blend_shape_data.write[j].arrays, remap, new_vertex_count); + } + } + + if (shadow_mesh.is_valid()) { + shadow_mesh->optimize_indices(); } } @@ -306,16 +292,13 @@ void ImporterMesh::optimize_indices_for_cache() { } \ write_array[vert_idx] = transformed_vert; -void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_bone_transform_array, bool p_raycast_normals) { +void ImporterMesh::generate_lods(float p_normal_merge_angle, Array p_bone_transform_array) { if (!SurfaceTool::simplify_scale_func) { return; } if (!SurfaceTool::simplify_with_attrib_func) { return; } - if (!SurfaceTool::optimize_vertex_cache_func) { - return; - } LocalVector<Transform3D> bone_transform_vector; for (int i = 0; i < p_bone_transform_array.size(); i++) { @@ -379,8 +362,6 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } float normal_merge_threshold = Math::cos(Math::deg_to_rad(p_normal_merge_angle)); - float normal_pre_split_threshold = Math::cos(Math::deg_to_rad(MIN(180.0f, p_normal_split_angle * 2.0f))); - float normal_split_threshold = Math::cos(Math::deg_to_rad(p_normal_split_angle)); const Vector3 *normals_ptr = normals.ptr(); HashMap<Vector3, LocalVector<Pair<int, int>>> unique_vertices; @@ -469,22 +450,6 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli unsigned int index_target = 12; // Start with the smallest target, 4 triangles unsigned int last_index_count = 0; - // Only used for normal raycasting - int split_vertex_count = vertex_count; - LocalVector<Vector3> split_vertex_normals; - LocalVector<int> split_vertex_indices; - split_vertex_normals.reserve(index_count / 3); - split_vertex_indices.reserve(index_count / 3); - - RandomPCG pcg; - pcg.seed(123456789); // Keep seed constant across imports - - Ref<StaticRaycaster> raycaster = p_raycast_normals ? StaticRaycaster::create() : Ref<StaticRaycaster>(); - if (raycaster.is_valid()) { - raycaster->add_mesh(vertices, indices, 0); - raycaster->commit(); - } - const float max_mesh_error = FLT_MAX; // We don't want to limit by error, just by index target float mesh_error = 0.0f; @@ -503,6 +468,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli merged_normals_f32.ptr(), sizeof(float) * 3, // Attribute stride normal_weights, 3, + nullptr, // Vertex lock index_target, max_mesh_error, simplify_options, @@ -533,173 +499,6 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } - if (raycaster.is_valid()) { - LocalVector<LocalVector<int>> vertex_corners; - vertex_corners.resize(vertex_count); - - int *ptrw = new_indices.ptrw(); - for (unsigned int j = 0; j < new_index_count; j++) { - vertex_corners[ptrw[j]].push_back(j); - } - - float error_factor = 1.0f / (scale * MAX(mesh_error, 0.15)); - const float ray_bias = 0.05; - float ray_length = ray_bias + mesh_error * scale * 3.0f; - - Vector<StaticRaycaster::Ray> rays; - LocalVector<Vector2> ray_uvs; - - int32_t *new_indices_ptr = new_indices.ptrw(); - - int current_ray_count = 0; - for (unsigned int j = 0; j < new_index_count; j += 3) { - const Vector3 &v0 = vertices_ptr[new_indices_ptr[j + 0]]; - const Vector3 &v1 = vertices_ptr[new_indices_ptr[j + 1]]; - const Vector3 &v2 = vertices_ptr[new_indices_ptr[j + 2]]; - Vector3 face_normal = vec3_cross(v0 - v2, v0 - v1); - float face_area = face_normal.length(); // Actually twice the face area, since it's the same error_factor on all faces, we don't care - if (!Math::is_finite(face_area) || face_area == 0) { - WARN_PRINT_ONCE("Ignoring face with non-finite normal in LOD generation."); - continue; - } - - Vector3 dir = face_normal / face_area; - int ray_count = CLAMP(5.0 * face_area * error_factor, 16, 64); - - rays.resize(current_ray_count + ray_count); - StaticRaycaster::Ray *rays_ptr = rays.ptrw(); - - ray_uvs.resize(current_ray_count + ray_count); - Vector2 *ray_uvs_ptr = ray_uvs.ptr(); - - for (int k = 0; k < ray_count; k++) { - float u = pcg.randf(); - float v = pcg.randf(); - - if (u + v >= 1.0f) { - u = 1.0f - u; - v = 1.0f - v; - } - - u = 0.9f * u + 0.05f / 3.0f; // Give barycentric coordinates some padding, we don't want to sample right on the edge - v = 0.9f * v + 0.05f / 3.0f; // v = (v - one_third) * 0.95f + one_third; - float w = 1.0f - u - v; - - Vector3 org = v0 * w + v1 * u + v2 * v; - org -= dir * ray_bias; - rays_ptr[current_ray_count + k] = StaticRaycaster::Ray(org, dir, 0.0f, ray_length); - rays_ptr[current_ray_count + k].id = j / 3; - ray_uvs_ptr[current_ray_count + k] = Vector2(u, v); - } - - current_ray_count += ray_count; - } - - raycaster->intersect(rays); - - LocalVector<Vector3> ray_normals; - LocalVector<real_t> ray_normal_weights; - - ray_normals.resize(new_index_count); - ray_normal_weights.resize(new_index_count); - - for (unsigned int j = 0; j < new_index_count; j++) { - ray_normal_weights[j] = 0.0f; - } - - const StaticRaycaster::Ray *rp = rays.ptr(); - for (int j = 0; j < rays.size(); j++) { - if (rp[j].geomID != 0) { // Ray missed - continue; - } - - if (rp[j].normal.normalized().dot(rp[j].dir) > 0.0f) { // Hit a back face. - continue; - } - - const float &u = rp[j].u; - const float &v = rp[j].v; - const float w = 1.0f - u - v; - - const unsigned int &hit_tri_id = rp[j].primID; - const unsigned int &orig_tri_id = rp[j].id; - - const Vector3 &n0 = normals_ptr[indices_ptr[hit_tri_id * 3 + 0]]; - const Vector3 &n1 = normals_ptr[indices_ptr[hit_tri_id * 3 + 1]]; - const Vector3 &n2 = normals_ptr[indices_ptr[hit_tri_id * 3 + 2]]; - Vector3 normal = n0 * w + n1 * u + n2 * v; - - Vector2 orig_uv = ray_uvs[j]; - const real_t orig_bary[3] = { 1.0f - orig_uv.x - orig_uv.y, orig_uv.x, orig_uv.y }; - for (int k = 0; k < 3; k++) { - int idx = orig_tri_id * 3 + k; - real_t weight = orig_bary[k]; - ray_normals[idx] += normal * weight; - ray_normal_weights[idx] += weight; - } - } - - for (unsigned int j = 0; j < new_index_count; j++) { - if (ray_normal_weights[j] < 1.0f) { // Not enough data, the new normal would be just a bad guess - ray_normals[j] = Vector3(); - } else { - ray_normals[j] /= ray_normal_weights[j]; - } - } - - LocalVector<LocalVector<int>> normal_group_indices; - LocalVector<Vector3> normal_group_averages; - normal_group_indices.reserve(24); - normal_group_averages.reserve(24); - - for (unsigned int j = 0; j < vertex_count; j++) { - const LocalVector<int> &corners = vertex_corners[j]; - const Vector3 &vertex_normal = normals_ptr[j]; - - for (const int &corner_idx : corners) { - const Vector3 &ray_normal = ray_normals[corner_idx]; - - if (ray_normal.length_squared() < CMP_EPSILON2) { - continue; - } - - bool found = false; - for (unsigned int l = 0; l < normal_group_indices.size(); l++) { - LocalVector<int> &group_indices = normal_group_indices[l]; - Vector3 n = normal_group_averages[l] / group_indices.size(); - if (n.dot(ray_normal) > normal_pre_split_threshold) { - found = true; - group_indices.push_back(corner_idx); - normal_group_averages[l] += ray_normal; - break; - } - } - - if (!found) { - normal_group_indices.push_back({ corner_idx }); - normal_group_averages.push_back(ray_normal); - } - } - - for (unsigned int k = 0; k < normal_group_indices.size(); k++) { - LocalVector<int> &group_indices = normal_group_indices[k]; - Vector3 n = normal_group_averages[k] / group_indices.size(); - - if (vertex_normal.dot(n) < normal_split_threshold) { - split_vertex_indices.push_back(j); - split_vertex_normals.push_back(n); - int new_idx = split_vertex_count++; - for (const int &index : group_indices) { - new_indices_ptr[index] = new_idx; - } - } - } - - normal_group_indices.clear(); - normal_group_averages.clear(); - } - } - Surface::LOD lod; lod.distance = MAX(mesh_error * scale, CMP_EPSILON2); lod.indices = new_indices; @@ -712,22 +511,13 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } - if (raycaster.is_valid()) { - surfaces.write[i].split_normals(split_vertex_indices, split_vertex_normals); - } - surfaces.write[i].lods.sort_custom<Surface::LODComparator>(); - - for (int j = 0; j < surfaces.write[i].lods.size(); j++) { - Surface::LOD &lod = surfaces.write[i].lods.write[j]; - unsigned int *lod_indices_ptr = (unsigned int *)lod.indices.ptrw(); - SurfaceTool::optimize_vertex_cache_func(lod_indices_ptr, lod_indices_ptr, lod.indices.size(), split_vertex_count); - } } } void ImporterMesh::_generate_lods_bind(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array) { - generate_lods(p_normal_merge_angle, p_normal_split_angle, p_skin_pose_transform_array); + // p_normal_split_angle is unused, but kept for compatibility + generate_lods(p_normal_merge_angle, p_skin_pose_transform_array); } bool ImporterMesh::has_mesh() const { @@ -859,10 +649,6 @@ void ImporterMesh::create_shadow_mesh() { index_wptr[j] = vertex_remap[index]; } - if (SurfaceTool::optimize_vertex_cache_func && surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) { - SurfaceTool::optimize_vertex_cache_func((unsigned int *)index_wptr, (const unsigned int *)index_wptr, index_count, new_vertices.size()); - } - new_surface[RS::ARRAY_INDEX] = new_indices; // Make sure the same LODs as the full version are used. @@ -881,10 +667,6 @@ void ImporterMesh::create_shadow_mesh() { index_wptr[k] = vertex_remap[index]; } - if (SurfaceTool::optimize_vertex_cache_func && surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) { - SurfaceTool::optimize_vertex_cache_func((unsigned int *)index_wptr, (const unsigned int *)index_wptr, index_count, new_vertices.size()); - } - lods[surfaces[i].lods[j].distance] = new_indices; } } diff --git a/scene/resources/3d/importer_mesh.h b/scene/resources/3d/importer_mesh.h index c7e3a059d6..2bdf759da6 100644 --- a/scene/resources/3d/importer_mesh.h +++ b/scene/resources/3d/importer_mesh.h @@ -68,9 +68,6 @@ class ImporterMesh : public Resource { return l.distance < r.distance; } }; - - void split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals); - static void _split_normals(Array &r_arrays, const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals); }; Vector<Surface> surfaces; Vector<String> blend_shapes; @@ -116,9 +113,9 @@ public: void set_surface_material(int p_surface, const Ref<Material> &p_material); - void optimize_indices_for_cache(); + void optimize_indices(); - void generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array, bool p_raycast_normals = false); + void generate_lods(float p_normal_merge_angle, Array p_skin_pose_transform_array); void create_shadow_mesh(); Ref<ImporterMesh> get_shadow_mesh() const; diff --git a/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp b/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp index 59366592ce..74dca88423 100644 --- a/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp +++ b/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp @@ -71,7 +71,7 @@ void NavigationMeshSourceGeometryData3D::append_arrays(const Vector<float> &p_ve bool NavigationMeshSourceGeometryData3D::has_data() { RWLockRead read_lock(geometry_rwlock); return vertices.size() && indices.size(); -}; +} void NavigationMeshSourceGeometryData3D::clear() { RWLockWrite write_lock(geometry_rwlock); diff --git a/scene/resources/3d/primitive_meshes.cpp b/scene/resources/3d/primitive_meshes.cpp index ceeb73d0ef..4d04ae77b1 100644 --- a/scene/resources/3d/primitive_meshes.cpp +++ b/scene/resources/3d/primitive_meshes.cpp @@ -31,6 +31,7 @@ #include "primitive_meshes.h" #include "core/config/project_settings.h" +#include "core/math/math_funcs.h" #include "scene/resources/theme.h" #include "scene/theme/theme_db.h" #include "servers/rendering_server.h" @@ -261,6 +262,9 @@ void PrimitiveMesh::_bind_methods() { } void PrimitiveMesh::set_material(const Ref<Material> &p_material) { + if (p_material == material) { + return; + } material = p_material; if (!pending_request) { // just apply it, else it'll happen when _update is called. @@ -279,6 +283,9 @@ Array PrimitiveMesh::get_mesh_arrays() const { } void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) { + if (p_custom.is_equal_approx(custom_aabb)) { + return; + } custom_aabb = p_custom; RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); @@ -289,6 +296,9 @@ AABB PrimitiveMesh::get_custom_aabb() const { } void PrimitiveMesh::set_flip_faces(bool p_enable) { + if (p_enable == flip_faces) { + return; + } flip_faces = p_enable; request_update(); } @@ -298,12 +308,18 @@ bool PrimitiveMesh::get_flip_faces() const { } void PrimitiveMesh::set_add_uv2(bool p_enable) { + if (p_enable == add_uv2) { + return; + } add_uv2 = p_enable; _update_lightmap_size(); request_update(); } void PrimitiveMesh::set_uv2_padding(float p_padding) { + if (Math::is_equal_approx(p_padding, uv2_padding)) { + return; + } uv2_padding = p_padding; _update_lightmap_size(); request_update(); @@ -578,6 +594,10 @@ void CapsuleMesh::_bind_methods() { } void CapsuleMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(radius, p_radius)) { + return; + } + radius = p_radius; if (radius > height * 0.5) { height = radius * 2.0; @@ -591,6 +611,10 @@ float CapsuleMesh::get_radius() const { } void CapsuleMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } + height = p_height; if (radius > height * 0.5) { radius = height * 0.5; @@ -604,6 +628,10 @@ float CapsuleMesh::get_height() const { } void CapsuleMesh::set_radial_segments(const int p_segments) { + if (radial_segments == p_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -613,6 +641,10 @@ int CapsuleMesh::get_radial_segments() const { } void CapsuleMesh::set_rings(const int p_rings) { + if (rings == p_rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -908,6 +940,10 @@ void BoxMesh::_bind_methods() { } void BoxMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } + size = p_size; _update_lightmap_size(); request_update(); @@ -918,6 +954,10 @@ Vector3 BoxMesh::get_size() const { } void BoxMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w) { + return; + } + subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -927,6 +967,10 @@ int BoxMesh::get_subdivide_width() const { } void BoxMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h) { + return; + } + subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -936,6 +980,10 @@ int BoxMesh::get_subdivide_height() const { } void BoxMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d) { + return; + } + subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1183,6 +1231,10 @@ void CylinderMesh::_bind_methods() { } void CylinderMesh::set_top_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, top_radius)) { + return; + } + top_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1193,6 +1245,10 @@ float CylinderMesh::get_top_radius() const { } void CylinderMesh::set_bottom_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, bottom_radius)) { + return; + } + bottom_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1203,6 +1259,10 @@ float CylinderMesh::get_bottom_radius() const { } void CylinderMesh::set_height(const float p_height) { + if (Math::is_equal_approx(p_height, height)) { + return; + } + height = p_height; _update_lightmap_size(); request_update(); @@ -1213,6 +1273,10 @@ float CylinderMesh::get_height() const { } void CylinderMesh::set_radial_segments(const int p_segments) { + if (p_segments == radial_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -1222,6 +1286,10 @@ int CylinderMesh::get_radial_segments() const { } void CylinderMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -1232,6 +1300,10 @@ int CylinderMesh::get_rings() const { } void CylinderMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } + cap_top = p_cap_top; request_update(); } @@ -1241,6 +1313,10 @@ bool CylinderMesh::is_cap_top() const { } void CylinderMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } + cap_bottom = p_cap_bottom; request_update(); } @@ -1375,6 +1451,9 @@ void PlaneMesh::_bind_methods() { } void PlaneMesh::set_size(const Size2 &p_size) { + if (p_size == size) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1385,6 +1464,9 @@ Size2 PlaneMesh::get_size() const { } void PlaneMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (subdivide_w == 0 && p_divisions < 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1394,6 +1476,9 @@ int PlaneMesh::get_subdivide_width() const { } void PlaneMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (subdivide_d == 0 && p_divisions < 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1403,6 +1488,9 @@ int PlaneMesh::get_subdivide_depth() const { } void PlaneMesh::set_center_offset(const Vector3 p_offset) { + if (p_offset.is_equal_approx(center_offset)) { + return; + } center_offset = p_offset; request_update(); } @@ -1412,6 +1500,9 @@ Vector3 PlaneMesh::get_center_offset() const { } void PlaneMesh::set_orientation(const Orientation p_orientation) { + if (p_orientation == orientation) { + return; + } orientation = p_orientation; request_update(); } @@ -1719,6 +1810,9 @@ void PrismMesh::_bind_methods() { } void PrismMesh::set_left_to_right(const float p_left_to_right) { + if (Math::is_equal_approx(p_left_to_right, left_to_right)) { + return; + } left_to_right = p_left_to_right; request_update(); } @@ -1728,6 +1822,9 @@ float PrismMesh::get_left_to_right() const { } void PrismMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1738,6 +1835,9 @@ Vector3 PrismMesh::get_size() const { } void PrismMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (p_divisions < 0 && subdivide_w == 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1747,6 +1847,9 @@ int PrismMesh::get_subdivide_width() const { } void PrismMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h || (p_divisions < 0 && subdivide_h == 0)) { + return; + } subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1756,6 +1859,9 @@ int PrismMesh::get_subdivide_height() const { } void PrismMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (p_divisions < 0 && subdivide_d == 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1902,6 +2008,9 @@ void SphereMesh::_bind_methods() { } void SphereMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; _update_lightmap_size(); request_update(); @@ -1912,6 +2021,9 @@ float SphereMesh::get_radius() const { } void SphereMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } height = p_height; _update_lightmap_size(); request_update(); @@ -1922,6 +2034,9 @@ float SphereMesh::get_height() const { } void SphereMesh::set_radial_segments(const int p_radial_segments) { + if (p_radial_segments == radial_segments || (radial_segments == 4 && p_radial_segments < 4)) { + return; + } radial_segments = p_radial_segments > 4 ? p_radial_segments : 4; request_update(); } @@ -1931,6 +2046,9 @@ int SphereMesh::get_radial_segments() const { } void SphereMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 1); rings = p_rings; request_update(); @@ -1941,6 +2059,9 @@ int SphereMesh::get_rings() const { } void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) { + if (p_is_hemisphere == is_hemisphere) { + return; + } is_hemisphere = p_is_hemisphere; _update_lightmap_size(); request_update(); @@ -2086,6 +2207,9 @@ void TorusMesh::_bind_methods() { } void TorusMesh::set_inner_radius(const float p_inner_radius) { + if (Math::is_equal_approx(p_inner_radius, inner_radius)) { + return; + } inner_radius = p_inner_radius; request_update(); } @@ -2095,6 +2219,9 @@ float TorusMesh::get_inner_radius() const { } void TorusMesh::set_outer_radius(const float p_outer_radius) { + if (Math::is_equal_approx(p_outer_radius, outer_radius)) { + return; + } outer_radius = p_outer_radius; request_update(); } @@ -2104,6 +2231,9 @@ float TorusMesh::get_outer_radius() const { } void TorusMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 3); rings = p_rings; request_update(); @@ -2114,6 +2244,9 @@ int TorusMesh::get_rings() const { } void TorusMesh::set_ring_segments(const int p_ring_segments) { + if (p_ring_segments == ring_segments) { + return; + } ERR_FAIL_COND(p_ring_segments < 3); ring_segments = p_ring_segments; request_update(); @@ -2143,6 +2276,9 @@ PointMesh::PointMesh() { // TUBE TRAIL void TubeTrailMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; request_update(); } @@ -2151,6 +2287,9 @@ float TubeTrailMesh::get_radius() const { } void TubeTrailMesh::set_radial_steps(const int p_radial_steps) { + if (p_radial_steps == radial_steps) { + return; + } ERR_FAIL_COND(p_radial_steps < 3 || p_radial_steps > 128); radial_steps = p_radial_steps; request_update(); @@ -2160,6 +2299,9 @@ int TubeTrailMesh::get_radial_steps() const { } void TubeTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2169,6 +2311,9 @@ int TubeTrailMesh::get_sections() const { } void TubeTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2177,6 +2322,9 @@ float TubeTrailMesh::get_section_length() const { } void TubeTrailMesh::set_section_rings(const int p_section_rings) { + if (p_section_rings == section_rings) { + return; + } ERR_FAIL_COND(p_section_rings < 1 || p_section_rings > 1024); section_rings = p_section_rings; request_update(); @@ -2186,6 +2334,9 @@ int TubeTrailMesh::get_section_rings() const { } void TubeTrailMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } cap_top = p_cap_top; request_update(); } @@ -2195,6 +2346,9 @@ bool TubeTrailMesh::is_cap_top() const { } void TubeTrailMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } cap_bottom = p_cap_bottom; request_update(); } @@ -2501,6 +2655,9 @@ TubeTrailMesh::TubeTrailMesh() { // RIBBON TRAIL void RibbonTrailMesh::set_shape(Shape p_shape) { + if (p_shape == shape) { + return; + } shape = p_shape; request_update(); } @@ -2509,6 +2666,9 @@ RibbonTrailMesh::Shape RibbonTrailMesh::get_shape() const { } void RibbonTrailMesh::set_size(const float p_size) { + if (Math::is_equal_approx(p_size, size)) { + return; + } size = p_size; request_update(); } @@ -2517,6 +2677,9 @@ float RibbonTrailMesh::get_size() const { } void RibbonTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2526,6 +2689,9 @@ int RibbonTrailMesh::get_sections() const { } void RibbonTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2534,6 +2700,9 @@ float RibbonTrailMesh::get_section_length() const { } void RibbonTrailMesh::set_section_segments(const int p_section_segments) { + if (p_section_segments == section_segments) { + return; + } ERR_FAIL_COND(p_section_segments < 1 || p_section_segments > 1024); section_segments = p_section_segments; request_update(); diff --git a/scene/resources/3d/primitive_meshes.h b/scene/resources/3d/primitive_meshes.h index 85f46a482a..e68ac7fb26 100644 --- a/scene/resources/3d/primitive_meshes.h +++ b/scene/resources/3d/primitive_meshes.h @@ -545,7 +545,7 @@ private: ContourPoint(const Vector2 &p_pt, bool p_sharp) { point = p_pt; sharp = p_sharp; - }; + } }; struct ContourInfo { diff --git a/scene/resources/3d/shape_3d.cpp b/scene/resources/3d/shape_3d.cpp index 5a79392ba5..259d82b7a0 100644 --- a/scene/resources/3d/shape_3d.cpp +++ b/scene/resources/3d/shape_3d.cpp @@ -73,7 +73,7 @@ Ref<ArrayMesh> Shape3D::get_debug_mesh() { Vector<Vector3> lines = get_debug_mesh_lines(); - debug_mesh_cache = Ref<ArrayMesh>(memnew(ArrayMesh)); + debug_mesh_cache.instantiate(); if (!lines.is_empty()) { //make mesh diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 57a4e35f7a..f0b182503a 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1048,7 +1048,7 @@ int Animation::find_track(const NodePath &p_path, const TrackType p_type) const } }; return -1; -}; +} Animation::TrackType Animation::get_cache_type(TrackType p_type) { if (p_type == Animation::TYPE_BEZIER) { diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index f9787dde2e..539001bf25 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -624,7 +624,7 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) { } String file_path = p_path; - if (!(file_path.substr(file_path.length() - 4, 4) == ".wav")) { + if (file_path.substr(file_path.length() - 4, 4).to_lower() != ".wav") { file_path += ".wav"; } diff --git a/scene/resources/camera_attributes.cpp b/scene/resources/camera_attributes.cpp index 3a021720c6..3a0c207a5d 100644 --- a/scene/resources/camera_attributes.cpp +++ b/scene/resources/camera_attributes.cpp @@ -487,7 +487,7 @@ void CameraAttributesPhysical::_bind_methods() { ADD_GROUP("Auto Exposure", "auto_exposure_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_min_exposure_value", "get_auto_exposure_min_exposure_value"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_max_exposure_value", "get_auto_exposure_max_exposure_value"); -}; +} CameraAttributesPhysical::CameraAttributesPhysical() { _update_exposure(); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 8926eb1d51..91d3757590 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -479,6 +479,9 @@ void Curve::set_bake_resolution(int p_resolution) { } real_t Curve::sample_baked(real_t p_offset) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), 0, "Offset is non-finite"); + if (_baked_cache_dirty) { // Last-second bake if not done already const_cast<Curve *>(this)->bake(); @@ -981,6 +984,9 @@ Transform2D Curve2D::_sample_posture(Interval p_interval) const { } Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Vector2(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1000,6 +1006,9 @@ Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const { } Transform2D Curve2D::sample_baked_with_rotation(real_t p_offset, bool p_cubic) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Transform2D(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1454,6 +1463,9 @@ void Curve3D::_remove_point(int p_index) { void Curve3D::remove_point(int p_index) { _remove_point(p_index); + if (closed && points.size() < 2) { + set_closed(false); + } notify_property_list_changed(); } @@ -1470,15 +1482,25 @@ Vector3 Curve3D::sample(int p_index, real_t p_offset) const { ERR_FAIL_COND_V(pc == 0, Vector3()); if (p_index >= pc - 1) { - return points[pc - 1].position; + if (!closed) { + return points[pc - 1].position; + } else { + p_index = pc - 1; + } } else if (p_index < 0) { return points[0].position; } Vector3 p0 = points[p_index].position; Vector3 p1 = p0 + points[p_index].out; - Vector3 p3 = points[p_index + 1].position; - Vector3 p2 = p3 + points[p_index + 1].in; + Vector3 p3, p2; + if (!closed || p_index < pc - 1) { + p3 = points[p_index + 1].position; + p2 = p3 + points[p_index + 1].in; + } else { + p3 = points[0].position; + p2 = p3 + points[0].in; + } return p0.bezier_interpolate(p1, p2, p3, p_offset); } @@ -1596,13 +1618,16 @@ void Curve3D::_bake() const { { Vector<RBMap<real_t, Vector3>> midpoints = _tessellate_even_length(10, bake_interval); + const int num_intervals = closed ? points.size() : points.size() - 1; + #ifdef TOOLS_ENABLED - points_in_cache.resize(points.size()); + points_in_cache.resize(closed ? (points.size() + 1) : points.size()); points_in_cache.set(0, 0); #endif + // Point Count: Begins at 1 to account for the last point. int pc = 1; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { pc++; pc += midpoints[i].size(); #ifdef TOOLS_ENABLED @@ -1625,18 +1650,29 @@ void Curve3D::_bake() const { btw[0] = points[0].tilt; int pidx = 0; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; - bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key); - btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key); + if (!closed || i < num_intervals - 1) { + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key); + btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key); + } else { + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[0].position + points[0].in, points[0].position, E.key); + btw[pidx] = Math::lerp(points[i].tilt, points[0].tilt, E.key); + } } pidx++; - bpw[pidx] = points[i + 1].position; - bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0); - btw[pidx] = points[i + 1].tilt; + if (!closed || i < num_intervals - 1) { + bpw[pidx] = points[i + 1].position; + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0); + btw[pidx] = points[i + 1].tilt; + } else { + bpw[pidx] = points[0].position; + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[0].position + points[0].in, points[0].position, 1.0); + btw[pidx] = points[0].tilt; + } } // Recalculate the baked distances. @@ -1881,6 +1917,9 @@ Basis Curve3D::get_point_baked_posture(int p_index, bool p_apply_tilt) const { #endif Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Vector3(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1900,6 +1939,9 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const { } Transform3D Curve3D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, bool p_apply_tilt) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Transform3D(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1929,6 +1971,9 @@ Transform3D Curve3D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, b } real_t Curve3D::sample_baked_tilt(real_t p_offset) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), 0, "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1948,6 +1993,9 @@ real_t Curve3D::sample_baked_tilt(real_t p_offset) const { } Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Vector3(0, 1, 0), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -2075,6 +2123,20 @@ real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const { return nearest; } +void Curve3D::set_closed(bool p_closed) { + if (closed == p_closed) { + return; + } + + closed = p_closed; + mark_dirty(); + notify_property_list_changed(); +} + +bool Curve3D::is_closed() const { + return closed; +} + void Curve3D::set_bake_interval(real_t p_tolerance) { bake_interval = p_tolerance; mark_dirty(); @@ -2153,11 +2215,17 @@ PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) con } Vector<RBMap<real_t, Vector3>> midpoints; - midpoints.resize(points.size() - 1); + const int num_intervals = closed ? points.size() : points.size() - 1; + midpoints.resize(num_intervals); + // Point Count: Begins at 1 to account for the last point. int pc = 1; - for (int i = 0; i < points.size() - 1; i++) { - _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance); + for (int i = 0; i < num_intervals; i++) { + if (!closed || i < num_intervals - 1) { + _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance); + } else { + _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[0].position, points[0].in, 0, p_max_stages, p_tolerance); + } pc++; pc += midpoints[i].size(); } @@ -2167,14 +2235,18 @@ PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) con bpw[0] = points[0].position; int pidx = 0; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; } pidx++; - bpw[pidx] = points[i + 1].position; + if (!closed || i < num_intervals - 1) { + bpw[pidx] = points[i + 1].position; + } else { + bpw[pidx] = points[0].position; + } } return tess; @@ -2184,10 +2256,15 @@ Vector<RBMap<real_t, Vector3>> Curve3D::_tessellate_even_length(int p_max_stages Vector<RBMap<real_t, Vector3>> midpoints; ERR_FAIL_COND_V_MSG(points.size() < 2, midpoints, "Curve must have at least 2 control point"); - midpoints.resize(points.size() - 1); + const int num_intervals = closed ? points.size() : points.size() - 1; + midpoints.resize(num_intervals); - for (int i = 0; i < points.size() - 1; i++) { - _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_length); + for (int i = 0; i < num_intervals; i++) { + if (!closed || i < num_intervals - 1) { + _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_length); + } else { + _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[0].position, points[0].in, 0, p_max_stages, p_length); + } } return midpoints; } @@ -2200,8 +2277,10 @@ PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_le return tess; } + const int num_intervals = closed ? points.size() : points.size() - 1; + // Point Count: Begins at 1 to account for the last point. int pc = 1; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { pc++; pc += midpoints[i].size(); } @@ -2211,14 +2290,18 @@ PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_le bpw[0] = points[0].position; int pidx = 0; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; } pidx++; - bpw[pidx] = points[i + 1].position; + if (!closed || i < num_intervals - 1) { + bpw[pidx] = points[i + 1].position; + } else { + bpw[pidx] = points[0].position; + } } return tess; @@ -2274,13 +2357,13 @@ void Curve3D::_get_property_list(List<PropertyInfo> *p_list) const { pi.usage &= ~PROPERTY_USAGE_STORAGE; p_list->push_back(pi); - if (i != 0) { + if (closed || i != 0) { pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/in", i)); pi.usage &= ~PROPERTY_USAGE_STORAGE; p_list->push_back(pi); } - if (i != points.size() - 1) { + if (closed || i != points.size() - 1) { pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/out", i)); pi.usage &= ~PROPERTY_USAGE_STORAGE; p_list->push_back(pi); @@ -2308,6 +2391,8 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_points"), &Curve3D::clear_points); ClassDB::bind_method(D_METHOD("sample", "idx", "t"), &Curve3D::sample); ClassDB::bind_method(D_METHOD("samplef", "fofs"), &Curve3D::samplef); + ClassDB::bind_method(D_METHOD("set_closed", "closed"), &Curve3D::set_closed); + ClassDB::bind_method(D_METHOD("is_closed"), &Curve3D::is_closed); //ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve3D::bake,DEFVAL(10)); ClassDB::bind_method(D_METHOD("set_bake_interval", "distance"), &Curve3D::set_bake_interval); ClassDB::bind_method(D_METHOD("get_bake_interval"), &Curve3D::get_bake_interval); @@ -2329,6 +2414,8 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data); ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve3D::_set_data); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "closed"), "set_closed", "is_closed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_ARRAY_COUNT("Points", "point_count", "set_point_count", "get_point_count", "point_"); diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 6da337a93f..154d91e23b 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -264,6 +264,8 @@ class Curve3D : public Resource { mutable Vector<size_t> points_in_cache; #endif + bool closed = false; + mutable bool baked_cache_dirty = false; mutable PackedVector3Array baked_point_cache; mutable Vector<real_t> baked_tilt_cache; @@ -330,6 +332,8 @@ public: Vector3 sample(int p_index, real_t p_offset) const; Vector3 samplef(real_t p_findex) const; + void set_closed(bool p_closed); + bool is_closed() const; void set_bake_interval(real_t p_tolerance); real_t get_bake_interval() const; void set_up_vector_enabled(bool p_enable); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index f8c70c3002..b5e23e9832 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -130,10 +130,7 @@ int Environment::get_canvas_max_layer() const { void Environment::set_camera_feed_id(int p_id) { bg_camera_feed_id = p_id; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - RS::get_singleton()->environment_set_camera_feed_id(environment, camera_feed_id); -#endif + RS::get_singleton()->environment_set_camera_feed_id(environment, bg_camera_feed_id); } int Environment::get_camera_feed_id() const { diff --git a/scene/resources/external_texture.cpp b/scene/resources/external_texture.cpp index 0552bbd081..c8b714372a 100644 --- a/scene/resources/external_texture.cpp +++ b/scene/resources/external_texture.cpp @@ -39,12 +39,14 @@ void ExternalTexture::_bind_methods() { } uint64_t ExternalTexture::get_external_texture_id() const { + _ensure_created(); return RenderingServer::get_singleton()->texture_get_native_handle(texture); } void ExternalTexture::set_size(const Size2 &p_size) { if (p_size.width > 0 && p_size.height > 0 && p_size != size) { size = p_size; + _ensure_created(); RenderingServer::get_singleton()->texture_external_update(texture, size.width, size.height, external_buffer); emit_changed(); } @@ -57,6 +59,7 @@ Size2 ExternalTexture::get_size() const { void ExternalTexture::set_external_buffer_id(uint64_t p_external_buffer) { if (p_external_buffer != external_buffer) { external_buffer = p_external_buffer; + _ensure_created(); RenderingServer::get_singleton()->texture_external_update(texture, size.width, size.height, external_buffer); } } @@ -74,11 +77,29 @@ bool ExternalTexture::has_alpha() const { } RID ExternalTexture::get_rid() const { + if (!texture.is_valid()) { + texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + using_placeholder = true; + } return texture; } +void ExternalTexture::_ensure_created() const { + if (texture.is_valid() && !using_placeholder) { + return; + } + + RID new_texture = RenderingServer::get_singleton()->texture_external_create(size.width, size.height); + if (using_placeholder) { + DEV_ASSERT(texture.is_valid()); + RenderingServer::get_singleton()->texture_replace(texture, new_texture); + using_placeholder = false; + } else { + texture = new_texture; + } +} + ExternalTexture::ExternalTexture() { - texture = RenderingServer::get_singleton()->texture_external_create(size.width, size.height); } ExternalTexture::~ExternalTexture() { diff --git a/scene/resources/external_texture.h b/scene/resources/external_texture.h index 96bcd8d0fe..cd60bcc030 100644 --- a/scene/resources/external_texture.h +++ b/scene/resources/external_texture.h @@ -38,10 +38,13 @@ class ExternalTexture : public Texture2D { GDCLASS(ExternalTexture, Texture2D); private: - RID texture; + mutable RID texture; + mutable bool using_placeholder = false; Size2 size = Size2(256, 256); uint64_t external_buffer = 0; + void _ensure_created() const; + protected: static void _bind_methods(); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 5e4136f449..ae70443e6a 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -647,13 +647,13 @@ void FontFile::_convert_packed_8bit(Ref<Image> &p_source, int p_page, int p_sz) wa[ofs_dst + 1] = r[ofs_src + 3]; } } - Ref<Image> img_r = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_r)); + Ref<Image> img_r = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_r)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r); - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g); - Ref<Image> img_b = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_b)); + Ref<Image> img_b = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_b)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b); - Ref<Image> img_a = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_a)); + Ref<Image> img_a = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_a)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a); } @@ -738,22 +738,22 @@ void FontFile::_convert_packed_4bit(Ref<Image> &p_source, int p_page, int p_sz) } } } - Ref<Image> img_r = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_r)); + Ref<Image> img_r = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_r)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r); - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g); - Ref<Image> img_b = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_b)); + Ref<Image> img_b = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_b)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b); - Ref<Image> img_a = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_a)); + Ref<Image> img_a = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_a)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a); - Ref<Image> img_ro = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_ro)); + Ref<Image> img_ro = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_ro)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 0, img_ro); - Ref<Image> img_go = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_go)); + Ref<Image> img_go = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_go)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 1, img_go); - Ref<Image> img_bo = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_bo)); + Ref<Image> img_bo = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_bo)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 2, img_bo); - Ref<Image> img_ao = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_ao)); + Ref<Image> img_ao = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_ao)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 3, img_ao); } @@ -806,10 +806,10 @@ void FontFile::_convert_rgba_4bit(Ref<Image> &p_source, int p_page, int p_sz) { } } } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_RGBA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_RGBA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g); - Ref<Image> img_o = memnew(Image(w, h, 0, Image::FORMAT_RGBA8, imgdata_o)); + Ref<Image> img_o = memnew(Image(w, h, false, Image::FORMAT_RGBA8, imgdata_o)); set_texture_image(0, Vector2i(p_sz, 1), p_page, img_o); } @@ -838,7 +838,7 @@ void FontFile::_convert_mono_8bit(Ref<Image> &p_source, int p_page, int p_ch, in wg[ofs_dst + 1] = r[ofs_src + p_ch]; } } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_g); } @@ -878,10 +878,10 @@ void FontFile::_convert_mono_4bit(Ref<Image> &p_source, int p_page, int p_ch, in } } } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g); - Ref<Image> img_o = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_o)); + Ref<Image> img_o = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_o)); set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_o); } @@ -1734,7 +1734,7 @@ Error FontFile::_load_bitmap_font(const String &p_path, List<String> *r_image_fi while (true) { String line = f->get_line(); - int delimiter = line.find(" "); + int delimiter = line.find_char(' '); String type = line.substr(0, delimiter); int pos = delimiter + 1; HashMap<String, String> keys; @@ -1744,7 +1744,7 @@ Error FontFile::_load_bitmap_font(const String &p_path, List<String> *r_image_fi } while (pos < line.size()) { - int eq = line.find("=", pos); + int eq = line.find_char('=', pos); if (eq == -1) { break; } @@ -1752,14 +1752,14 @@ Error FontFile::_load_bitmap_font(const String &p_path, List<String> *r_image_fi int end = -1; String value; if (line[eq + 1] == '"') { - end = line.find("\"", eq + 2); + end = line.find_char('"', eq + 2); if (end == -1) { break; } value = line.substr(eq + 2, end - 1 - eq - 1); pos = end + 1; } else { - end = line.find(" ", eq + 1); + end = line.find_char(' ', eq + 1); if (end == -1) { end = line.size(); } diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 4d1d733f8b..8c0e087902 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -45,23 +45,23 @@ void MeshConvexDecompositionSettings::set_max_concavity(real_t p_max_concavity) real_t MeshConvexDecompositionSettings::get_max_concavity() const { return max_concavity; -}; +} void MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias(real_t p_symmetry_planes_clipping_bias) { symmetry_planes_clipping_bias = CLAMP(p_symmetry_planes_clipping_bias, 0.0, 1.0); -}; +} real_t MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias() const { return symmetry_planes_clipping_bias; -}; +} void MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias(real_t p_revolution_axes_clipping_bias) { revolution_axes_clipping_bias = CLAMP(p_revolution_axes_clipping_bias, 0.0, 1.0); -}; +} real_t MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias() const { return revolution_axes_clipping_bias; -}; +} void MeshConvexDecompositionSettings::set_min_volume_per_convex_hull(real_t p_min_volume_per_convex_hull) { min_volume_per_convex_hull = CLAMP(p_min_volume_per_convex_hull, 0.0001, 0.01); @@ -385,7 +385,7 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { } } - triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh.instantiate(); triangle_mesh->create(faces); return triangle_mesh; @@ -1315,7 +1315,7 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String sname = p_name; if (sname.begins_with("surface_")) { - int sl = sname.find("/"); + int sl = sname.find_char('/'); if (sl == -1) { return false; } @@ -1708,7 +1708,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { String sname = p_name; if (sname.begins_with("surface_")) { - int sl = sname.find("/"); + int sl = sname.find_char('/'); if (sl == -1) { return false; } diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index 67ed65df0d..034d4d6996 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -392,8 +392,8 @@ Ref<ArrayMesh> NavigationMesh::get_debug_mesh() { return debug_mesh; } - if (!debug_mesh.is_valid()) { - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (debug_mesh.is_null()) { + debug_mesh.instantiate(); } else { debug_mesh->clear_surfaces(); } diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index d6fe4385c4..d7036fd6d5 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -786,7 +786,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has Dictionary missing_resource_properties = p_node->get_meta(META_MISSING_RESOURCES, Dictionary()); for (const PropertyInfo &E : plist) { - if (!(E.usage & PROPERTY_USAGE_STORAGE)) { + if (!(E.usage & PROPERTY_USAGE_STORAGE) && !missing_resource_properties.has(E.name)) { continue; } @@ -822,10 +822,10 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has value = missing_resource_properties[E.name]; } } else if (E.type == Variant::ARRAY && E.hint == PROPERTY_HINT_TYPE_STRING) { - int hint_subtype_separator = E.hint_string.find(":"); + int hint_subtype_separator = E.hint_string.find_char(':'); if (hint_subtype_separator >= 0) { String subtype_string = E.hint_string.substr(0, hint_subtype_separator); - int slash_pos = subtype_string.find("/"); + int slash_pos = subtype_string.find_char('/'); PropertyHint subtype_hint = PropertyHint::PROPERTY_HINT_NONE; if (slash_pos >= 0) { subtype_hint = PropertyHint(subtype_string.get_slice("/", 1).to_int()); @@ -851,11 +851,11 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has } } } else if (E.type == Variant::DICTIONARY && E.hint == PROPERTY_HINT_TYPE_STRING) { - int key_value_separator = E.hint_string.find(";"); + int key_value_separator = E.hint_string.find_char(';'); if (key_value_separator >= 0) { - int key_subtype_separator = E.hint_string.find(":"); + int key_subtype_separator = E.hint_string.find_char(':'); String key_subtype_string = E.hint_string.substr(0, key_subtype_separator); - int key_slash_pos = key_subtype_string.find("/"); + int key_slash_pos = key_subtype_string.find_char('/'); PropertyHint key_subtype_hint = PropertyHint::PROPERTY_HINT_NONE; if (key_slash_pos >= 0) { key_subtype_hint = PropertyHint(key_subtype_string.get_slice("/", 1).to_int()); @@ -864,9 +864,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has Variant::Type key_subtype = Variant::Type(key_subtype_string.to_int()); bool convert_key = key_subtype == Variant::OBJECT && key_subtype_hint == PROPERTY_HINT_NODE_TYPE; - int value_subtype_separator = E.hint_string.find(":", key_value_separator) - (key_value_separator + 1); + int value_subtype_separator = E.hint_string.find_char(':', key_value_separator) - (key_value_separator + 1); String value_subtype_string = E.hint_string.substr(key_value_separator + 1, value_subtype_separator); - int value_slash_pos = value_subtype_string.find("/"); + int value_slash_pos = value_subtype_string.find_char('/'); PropertyHint value_subtype_hint = PropertyHint::PROPERTY_HINT_NONE; if (value_slash_pos >= 0) { value_subtype_hint = PropertyHint(value_subtype_string.get_slice("/", 1).to_int()); @@ -2195,7 +2195,7 @@ void PackedScene::replace_state(Ref<SceneState> p_by) { } void PackedScene::recreate_state() { - state = Ref<SceneState>(memnew(SceneState)); + state.instantiate(); state->set_path(get_path()); #ifdef TOOLS_ENABLED state->set_last_modified_time(get_last_modified_time()); @@ -2286,5 +2286,5 @@ void PackedScene::_bind_methods() { } PackedScene::PackedScene() { - state = Ref<SceneState>(memnew(SceneState)); + state.instantiate(); } diff --git a/scene/resources/portable_compressed_texture.cpp b/scene/resources/portable_compressed_texture.cpp index 06b5ec6d5a..55bbed7c47 100644 --- a/scene/resources/portable_compressed_texture.cpp +++ b/scene/resources/portable_compressed_texture.cpp @@ -89,7 +89,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { data_size -= mipsize; } - image = Ref<Image>(memnew(Image(size.width, size.height, mipmaps, format, image_data))); + image.instantiate(size.width, size.height, mipmaps, format, image_data); } break; case COMPRESSION_MODE_BASIS_UNIVERSAL: { @@ -100,7 +100,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { case COMPRESSION_MODE_S3TC: case COMPRESSION_MODE_ETC2: case COMPRESSION_MODE_BPTC: { - image = Ref<Image>(memnew(Image(size.width, size.height, mipmaps, format, p_data.slice(20)))); + image.instantiate(size.width, size.height, mipmaps, format, p_data.slice(20)); } break; } ERR_FAIL_COND(image.is_null()); diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index e234a81c88..03f0e107e4 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -600,7 +600,7 @@ Error ResourceLoaderText::load() { if (do_assign) { bool set_valid = true; - if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) { + if (value.get_type() == Variant::OBJECT && missing_resource == nullptr && ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) { // If the property being set is a missing resource (and the parent is not), // then setting it will most likely not work. // Instead, save it as metadata. @@ -723,24 +723,25 @@ Error ResourceLoaderText::load() { if (error) { if (error != ERR_FILE_EOF) { _printerr(); - } else { - error = OK; - if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { - if (!ResourceCache::has(res_path)) { - resource->set_path(res_path); - } - resource->set_as_translation_remapped(translation_remapped); - } else { - resource->set_path_cache(res_path); + return error; + } + // EOF, Done parsing. + error = OK; + if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { + if (!ResourceCache::has(res_path)) { + resource->set_path(res_path); } + resource->set_as_translation_remapped(translation_remapped); + } else { + resource->set_path_cache(res_path); } - return error; + break; } if (!assign.is_empty()) { bool set_valid = true; - if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) { + if (value.get_type() == Variant::OBJECT && missing_resource == nullptr && ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) { // If the property being set is a missing resource (and the parent is not), // then setting it will most likely not work. // Instead, save it as metadata. @@ -1431,8 +1432,8 @@ void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String & p_extensions->push_back("tscn"); } - // Don't allow .tres for PackedScenes. - if (p_type != "PackedScene") { + // Don't allow .tres for PackedScenes or GDExtension. + if (p_type != "PackedScene" && p_type != "GDExtension") { p_extensions->push_back("tres"); } } @@ -1525,6 +1526,10 @@ ResourceUID::ID ResourceFormatLoaderText::get_resource_uid(const String &p_path) return loader.get_uid(f); } +bool ResourceFormatLoaderText::has_custom_uid_support() const { + return true; +} + void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); if (f.is_null()) { @@ -1777,7 +1782,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso for (KeyValue<Ref<Resource>, String> &E : external_resources) { String cached_id = E.key->get_id_for_path(local_path); if (cached_id.is_empty() || cached_ids_found.has(cached_id)) { - int sep_pos = E.value.find("_"); + int sep_pos = E.value.find_char('_'); if (sep_pos != -1) { E.value = E.value.substr(0, sep_pos + 1); // Keep the order found, for improved thread loading performance. } else { @@ -1900,7 +1905,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso #endif } - Dictionary missing_resource_properties = p_resource->get_meta(META_MISSING_RESOURCES, Dictionary()); + Dictionary missing_resource_properties = res->get_meta(META_MISSING_RESOURCES, Dictionary()); List<PropertyInfo> property_list; res->get_property_list(&property_list); @@ -1912,7 +1917,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso continue; } - if (PE->get().usage & PROPERTY_USAGE_STORAGE) { + if (PE->get().usage & PROPERTY_USAGE_STORAGE || missing_resource_properties.has(PE->get().name)) { String name = PE->get().name; Variant value; if (PE->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h index 8397bc985f..4c0bf3d917 100644 --- a/scene/resources/resource_format_text.h +++ b/scene/resources/resource_format_text.h @@ -155,6 +155,7 @@ public: virtual String get_resource_type(const String &p_path) const override; virtual String get_resource_script_class(const String &p_path) const override; virtual ResourceUID::ID get_resource_uid(const String &p_path) const override; + virtual bool has_custom_uid_support() const override; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override; virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) override; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 24d17108d5..d163a42fa9 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -32,6 +32,7 @@ #include "shader.compat.inc" #include "core/io/file_access.h" +#include "scene/main/scene_tree.h" #include "servers/rendering/shader_language.h" #include "servers/rendering/shader_preprocessor.h" #include "servers/rendering_server.h" @@ -138,6 +139,14 @@ String Shader::get_code() const { return code; } +void Shader::inspect_native_shader_code() { + SceneTree *st = SceneTree::get_singleton(); + RID _shader = get_rid(); + if (st && _shader.is_valid()) { + st->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_native_shader_source_visualizer", "_inspect_shader", _shader); + } +} + void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups) const { _update_shader(); _check_shader_rid(); @@ -267,6 +276,9 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("get_shader_uniform_list", "get_groups"), &Shader::_get_shader_uniform_list, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("inspect_native_shader_code"), &Shader::inspect_native_shader_code); + ClassDB::set_method_flags(get_class_static(), _scs_create("inspect_native_shader_code"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code"); BIND_ENUM_CONSTANT(MODE_SPATIAL); diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 18197419f3..7234d37579 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -88,6 +88,8 @@ public: void set_code(const String &p_code); String get_code() const; + void inspect_native_shader_code(); + void get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups = false) const; void set_default_texture_parameter(const StringName &p_name, const Ref<Texture> &p_texture, int p_index = 0); diff --git a/scene/resources/style_box_flat.cpp b/scene/resources/style_box_flat.cpp index 15816925c1..202ab3615b 100644 --- a/scene/resources/style_box_flat.cpp +++ b/scene/resources/style_box_flat.cpp @@ -596,10 +596,10 @@ void StyleBoxFlat::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "skew"), "set_skew", "get_skew"); ADD_GROUP("Border Width", "border_width_"); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_BOTTOM); ADD_GROUP("Border", "border_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color"); @@ -607,18 +607,18 @@ void StyleBoxFlat::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "border_blend"), "set_border_blend", "get_border_blend"); ADD_GROUP("Corner Radius", "corner_radius_"); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT); ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail", PROPERTY_HINT_RANGE, "1,20,1"), "set_corner_detail", "get_corner_detail"); ADD_GROUP("Expand Margins", "expand_margin_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_BOTTOM); ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color"); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 6921885ee0..c230cf1b70 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -33,10 +33,10 @@ #define EQ_VERTEX_DIST 0.00001 SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr; +SurfaceTool::OptimizeVertexFetchRemapFunc SurfaceTool::optimize_vertex_fetch_remap_func = nullptr; SurfaceTool::SimplifyFunc SurfaceTool::simplify_func = nullptr; SurfaceTool::SimplifyWithAttribFunc SurfaceTool::simplify_with_attrib_func = nullptr; SurfaceTool::SimplifyScaleFunc SurfaceTool::simplify_scale_func = nullptr; -SurfaceTool::SimplifySloppyFunc SurfaceTool::simplify_sloppy_func = nullptr; SurfaceTool::GenerateRemapFunc SurfaceTool::generate_remap_func = nullptr; SurfaceTool::RemapVertexFunc SurfaceTool::remap_vertex_func = nullptr; SurfaceTool::RemapIndexFunc SurfaceTool::remap_index_func = nullptr; diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index a072df5bee..68dc9e7198 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -80,18 +80,24 @@ public: enum { /* Do not move vertices that are located on the topological border (vertices on triangle edges that don't have a paired triangle). Useful for simplifying portions of the larger mesh. */ SIMPLIFY_LOCK_BORDER = 1 << 0, // From meshopt_SimplifyLockBorder + /* Improve simplification performance assuming input indices are a sparse subset of the mesh. Note that error becomes relative to subset extents. */ + SIMPLIFY_SPARSE = 1 << 1, // From meshopt_SimplifySparse + /* Treat error limit and resulting error as absolute instead of relative to mesh extents. */ + SIMPLIFY_ERROR_ABSOLUTE = 1 << 2, // From meshopt_SimplifyErrorAbsolute + /* Remove disconnected parts of the mesh during simplification incrementally, regardless of the topological restrictions inside components. */ + SIMPLIFY_PRUNE = 1 << 3, // From meshopt_SimplifyPrune }; typedef void (*OptimizeVertexCacheFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count); static OptimizeVertexCacheFunc optimize_vertex_cache_func; + typedef size_t (*OptimizeVertexFetchRemapFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count); + static OptimizeVertexFetchRemapFunc optimize_vertex_fetch_remap_func; typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float *r_error); static SimplifyFunc simplify_func; - typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, const float *attributes, size_t attribute_stride, const float *attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float *result_error); + typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, const float *attributes, size_t attribute_stride, const float *attribute_weights, size_t attribute_count, const unsigned char *vertex_lock, size_t target_index_count, float target_error, unsigned int options, float *result_error); static SimplifyWithAttribFunc simplify_with_attrib_func; typedef float (*SimplifyScaleFunc)(const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride); static SimplifyScaleFunc simplify_scale_func; - typedef size_t (*SimplifySloppyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *out_result_error); - static SimplifySloppyFunc simplify_sloppy_func; typedef size_t (*GenerateRemapFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size); static GenerateRemapFunc generate_remap_func; typedef void (*RemapVertexFunc)(void *destination, const void *vertices, size_t vertex_count, size_t vertex_size, const unsigned int *remap); @@ -113,7 +119,7 @@ private: SmoothGroupVertex(const Vertex &p_vertex) { vertex = p_vertex.vertex; smooth_group = p_vertex.smooth_group; - }; + } }; struct SmoothGroupVertexHasher { @@ -216,7 +222,9 @@ public: void clear(); - LocalVector<Vertex> &get_vertex_array() { return vertex_array; } + LocalVector<Vertex> &get_vertex_array() { + return vertex_array; + } void create_from_triangle_arrays(const Array &p_arrays); void create_from_arrays(const Array &p_arrays, Mesh::PrimitiveType p_primitive_type = Mesh::PRIMITIVE_TRIANGLES); diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp index da90ba1ef2..4bc03a049a 100644 --- a/scene/resources/syntax_highlighter.cpp +++ b/scene/resources/syntax_highlighter.cpp @@ -205,7 +205,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) { if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) { if (from + end_key_length > line_length && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { // If it's key length and there is a '\', dont skip to highlight esc chars. - if (str.find("\\", from) >= 0) { + if (str.find_char('\\', from) >= 0) { break; } } @@ -242,7 +242,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) { for (; from < line_length; from++) { if (line_length - from < end_key_length) { // Don't break if '\' to highlight esc chars. - if (!is_string || str.find("\\", from) < 0) { + if (!is_string || str.find_char('\\', from) < 0) { break; } } diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index 29a8541cb0..65c6e40241 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -112,6 +112,11 @@ void TextParagraph::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible"), "set_max_lines_visible", "get_max_lines_visible"); + ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextParagraph::set_line_spacing); + ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextParagraph::get_line_spacing); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing"), "set_line_spacing", "get_line_spacing"); + ClassDB::bind_method(D_METHOD("get_line_objects", "line"), &TextParagraph::get_line_objects); ClassDB::bind_method(D_METHOD("get_line_object_rect", "line", "key"), &TextParagraph::get_line_object_rect); ClassDB::bind_method(D_METHOD("get_line_size", "line"), &TextParagraph::get_line_size); @@ -180,6 +185,7 @@ void TextParagraph::_shape_lines() { for (int i = 0; i < line_breaks.size(); i = i + 2) { RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x; + h += line_spacing; if (!tab_stops.is_empty()) { TS->shaped_text_tab_align(line, tab_stops); } @@ -574,12 +580,18 @@ Size2 TextParagraph::get_size() const { } size.x = MAX(size.x, lsize.x); size.y += lsize.y; + if (i != visible_lines - 1) { + size.y += line_spacing; + } } else { if (h_offset > 0 && i <= dropcap_lines) { lsize.y += h_offset; } size.x += lsize.x; size.y = MAX(size.y, lsize.y); + if (i != visible_lines - 1) { + size.x += line_spacing; + } } } if (h_offset > 0) { @@ -612,6 +624,19 @@ int TextParagraph::get_max_lines_visible() const { return max_lines_visible; } +void TextParagraph::set_line_spacing(float p_spacing) { + _THREAD_SAFE_METHOD_ + + if (line_spacing != p_spacing) { + line_spacing = p_spacing; + lines_dirty = true; + } +} + +float TextParagraph::get_line_spacing() const { + return line_spacing; +} + Array TextParagraph::get_line_objects(int p_line) const { _THREAD_SAFE_METHOD_ @@ -697,10 +722,10 @@ Rect2 TextParagraph::get_line_object_rect(int p_line, Variant p_key) const { if (i != p_line) { if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = 0.f; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = 0.f; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -872,10 +897,10 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo TS->shaped_text_draw(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_color); if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = p_pos.x; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = p_pos.y; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -974,10 +999,10 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli TS->shaped_text_draw_outline(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_outline_size, p_color); if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = p_pos.x; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = p_pos.y; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -1001,17 +1026,21 @@ int TextParagraph::hit_test(const Point2 &p_coords) const { if ((p_coords.y >= ofs.y) && (p_coords.y <= ofs.y + TS->shaped_text_get_size(line_rid).y)) { return TS->shaped_text_hit_test_position(line_rid, p_coords.x); } - ofs.y += TS->shaped_text_get_size(line_rid).y; + ofs.y += TS->shaped_text_get_size(line_rid).y + line_spacing; } else { if ((p_coords.x >= ofs.x) && (p_coords.x <= ofs.x + TS->shaped_text_get_size(line_rid).x)) { return TS->shaped_text_hit_test_position(line_rid, p_coords.y); } - ofs.y += TS->shaped_text_get_size(line_rid).x; + ofs.y += TS->shaped_text_get_size(line_rid).x + line_spacing; } } return TS->shaped_text_get_range(rid).y; } +bool TextParagraph::is_dirty() { + return lines_dirty; +} + void TextParagraph::draw_dropcap(RID p_canvas, const Vector2 &p_pos, const Color &p_color) const { _THREAD_SAFE_METHOD_ diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h index 7512955fb3..966ce556d5 100644 --- a/scene/resources/text_paragraph.h +++ b/scene/resources/text_paragraph.h @@ -51,6 +51,7 @@ private: bool lines_dirty = true; + float line_spacing = 0.0; float width = -1.0; int max_lines_visible = -1; @@ -122,6 +123,9 @@ public: void set_max_lines_visible(int p_lines); int get_max_lines_visible() const; + void set_line_spacing(float p_spacing); + float get_line_spacing() const; + Size2 get_non_wrapped_size() const; Size2 get_size() const; @@ -152,7 +156,9 @@ public: int hit_test(const Point2 &p_coords) const; - Mutex &get_mutex() const { return _thread_safe_; }; + bool is_dirty(); + + Mutex &get_mutex() const { return _thread_safe_; } TextParagraph(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language = "", float p_width = -1.f, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL); TextParagraph(); diff --git a/scene/resources/texture_rd.cpp b/scene/resources/texture_rd.cpp index 531dbcbe7e..8e7eeb0ff4 100644 --- a/scene/resources/texture_rd.cpp +++ b/scene/resources/texture_rd.cpp @@ -197,7 +197,7 @@ void TextureLayeredRD::_set_texture_rd_rid(RID p_texture_rd_rid) { RS::TextureLayeredType rs_layer_type; RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid); - ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D_ARRAY); + ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D_ARRAY && tf.texture_type != RD::TEXTURE_TYPE_CUBE && tf.texture_type != RD::TEXTURE_TYPE_CUBE_ARRAY); ERR_FAIL_COND(tf.depth > 1); switch (layer_type) { case LAYERED_TYPE_2D_ARRAY: { diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index d0e55f4065..7c1adeac96 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1368,7 +1368,7 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por ERR_FAIL_INDEX(p_type, TYPE_MAX); Graph *g = &graph[p_type]; - for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { + for (List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { g->connections.erase(E); g->nodes[p_from_node].next_connected_nodes.erase(p_to_node); @@ -1560,7 +1560,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port shader_code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n"; } break; case VisualShaderNode::PORT_TYPE_VECTOR_4D: { - shader_code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ".xyz;\n"; + shader_code += " COLOR = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n"; } break; default: { shader_code += " COLOR.rgb = vec3(0.0);\n"; @@ -1921,13 +1921,13 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { } for (const KeyValue<String, Varying> &E : varyings) { - p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", PNAME("varyings"), E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", "varyings", E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { for (const KeyValue<String, Variant> &E : preview_params) { - p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", PNAME("preview_params"), E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", "preview_params", E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } } #endif // TOOLS_ENABLED @@ -3167,6 +3167,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection_matrix", "PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "specular", "SPECULAR_LIGHT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 3db1ab9338..5350672a86 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -3243,6 +3243,29 @@ String VisualShaderNodeColorFunc::generate_code(Shader::Mode p_mode, VisualShade code += " " + p_output_vars[0] + " = vec3(r, g, b);\n"; code += " }\n"; break; + case FUNC_LINEAR_TO_SRGB: + code += " {\n"; + if (RenderingServer::get_singleton()->is_low_end()) { + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " " + p_output_vars[0] + " = max(vec3(1.055) * pow(c, vec3(0.416666667)) - vec3(0.055), vec3(0.0));\n"; + } else { + code += " vec3 c = clamp(" + p_input_vars[0] + ", vec3(0.0), vec3(1.0));\n"; + code += " const vec3 a = vec3(0.055f);\n"; + code += " " + p_output_vars[0] + " = mix((vec3(1.0f) + a) * pow(c.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * c.rgb, lessThan(c.rgb, vec3(0.0031308f)));\n"; + } + code += " }\n"; + break; + case FUNC_SRGB_TO_LINEAR: + code += " {\n"; + if (RenderingServer::get_singleton()->is_low_end()) { + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " " + p_output_vars[0] + " = c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);\n"; + } else { + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " " + p_output_vars[0] + " = mix(pow((c.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), c.rgb * (1.0 / 12.92), lessThan(c.rgb, vec3(0.04045)));\n"; + } + code += " }\n"; + break; default: break; } @@ -3273,12 +3296,14 @@ void VisualShaderNodeColorFunc::_bind_methods() { ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeColorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeColorFunc::get_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Grayscale,HSV2RGB,RGB2HSV,Sepia"), "set_function", "get_function"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Grayscale,HSV2RGB,RGB2HSV,Sepia,LinearToSRGB,SRGBToLinear"), "set_function", "get_function"); BIND_ENUM_CONSTANT(FUNC_GRAYSCALE); BIND_ENUM_CONSTANT(FUNC_HSV2RGB); BIND_ENUM_CONSTANT(FUNC_RGB2HSV); BIND_ENUM_CONSTANT(FUNC_SEPIA); + BIND_ENUM_CONSTANT(FUNC_LINEAR_TO_SRGB); + BIND_ENUM_CONSTANT(FUNC_SRGB_TO_LINEAR); BIND_ENUM_CONSTANT(FUNC_MAX); } diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 67dc8f7353..36b9560ced 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1353,6 +1353,8 @@ public: FUNC_HSV2RGB, FUNC_RGB2HSV, FUNC_SEPIA, + FUNC_LINEAR_TO_SRGB, + FUNC_SRGB_TO_LINEAR, FUNC_MAX, }; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 140e588291..31daeb3ae3 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -130,6 +130,8 @@ SceneStringNames::SceneStringNames() { shader_overrides_group = StaticCString::create("_shader_overrides_group_"); shader_overrides_group_active = StaticCString::create("_shader_overrides_group_active_"); + _custom_type_script = StaticCString::create("_custom_type_script"); + pressed = StaticCString::create("pressed"); id_pressed = StaticCString::create("id_pressed"); toggled = StaticCString::create("toggled"); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index fc22be33b2..0a2ebeda7a 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -143,6 +143,8 @@ public: StringName shader_overrides_group; StringName shader_overrides_group_active; + StringName _custom_type_script; + StringName pressed; StringName id_pressed; StringName toggled; diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp index caf44ac392..f5065e8de1 100644 --- a/scene/theme/default_theme.cpp +++ b/scene/theme/default_theme.cpp @@ -30,6 +30,7 @@ #include "default_theme.h" +#include "core/io/image.h" #include "core/os/os.h" #include "default_font.gen.h" #include "default_theme_icons.gen.h" @@ -832,10 +833,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox(SceneStringName(panel), "Tree", make_flat_stylebox(style_normal_color, 4, 4, 4, 5)); theme->set_stylebox("focus", "Tree", focus); + theme->set_stylebox("hovered", "Tree", make_flat_stylebox(Color(1, 1, 1, 0.07))); + theme->set_stylebox("hovered_dimmed", "Tree", make_flat_stylebox(Color(1, 1, 1, 0.03))); theme->set_stylebox("selected", "Tree", make_flat_stylebox(style_selected_color)); theme->set_stylebox("selected_focus", "Tree", make_flat_stylebox(style_selected_color)); theme->set_stylebox("cursor", "Tree", focus); theme->set_stylebox("cursor_unfocused", "Tree", focus); + theme->set_stylebox("button_hover", "Tree", make_flat_stylebox(Color(1, 1, 1, 0.07))); theme->set_stylebox("button_pressed", "Tree", button_pressed); theme->set_stylebox("title_button_normal", "Tree", make_flat_stylebox(style_pressed_color, 4, 4, 4, 4)); theme->set_stylebox("title_button_pressed", "Tree", make_flat_stylebox(style_hover_color, 4, 4, 4, 4)); @@ -863,6 +867,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("title_button_color", "Tree", control_font_color); theme->set_color(SceneStringName(font_color), "Tree", control_font_low_color); + theme->set_color("font_hovered_color", "Tree", control_font_hover_color); + theme->set_color("font_hovered_dimmed_color", "Tree", control_font_color); theme->set_color("font_selected_color", "Tree", control_font_pressed_color); theme->set_color("font_disabled_color", "Tree", control_font_disabled_color); theme->set_color("font_outline_color", "Tree", Color(0, 0, 0)); diff --git a/scu_builders.py b/scu_builders.py index 3c04d66668..e0bfffc320 100644 --- a/scu_builders.py +++ b/scu_builders.py @@ -259,10 +259,6 @@ def process_folder(folders, sought_exceptions=[], includes_per_scu=0, extension= def generate_scu_files(max_includes_per_scu): - print("=============================") - print("Single Compilation Unit Build") - print("=============================") - global _max_includes_per_scu _max_includes_per_scu = max_includes_per_scu @@ -290,11 +286,16 @@ def generate_scu_files(max_includes_per_scu): process_folder(["drivers/unix"]) process_folder(["drivers/png"]) + process_folder(["drivers/gles3/effects"]) + process_folder(["drivers/gles3/storage"]) + process_folder(["editor"], ["file_system_dock", "editor_resource_preview"], 32) process_folder(["editor/debugger"]) process_folder(["editor/debugger/debug_adapter"]) process_folder(["editor/export"]) process_folder(["editor/gui"]) + process_folder(["editor/themes"]) + process_folder(["editor/project_manager"]) process_folder(["editor/import"]) process_folder(["editor/import/3d"]) process_folder(["editor/plugins"]) @@ -308,12 +309,15 @@ def generate_scu_files(max_includes_per_scu): process_folder(["platform/web/export"]) process_folder(["platform/windows/export"]) + process_folder(["modules/lightmapper_rd"]) process_folder(["modules/gltf"]) process_folder(["modules/gltf/structures"]) process_folder(["modules/gltf/editor"]) process_folder(["modules/gltf/extensions"]) process_folder(["modules/gltf/extensions/physics"]) process_folder(["modules/navigation"]) + process_folder(["modules/navigation/2d"]) + process_folder(["modules/navigation/3d"]) process_folder(["modules/webrtc"]) process_folder(["modules/websocket"]) process_folder(["modules/gridmap"]) @@ -322,6 +326,8 @@ def generate_scu_files(max_includes_per_scu): process_folder(["modules/openxr"], ["register_types"]) process_folder(["modules/openxr/action_map"]) process_folder(["modules/openxr/editor"]) + process_folder(["modules/openxr/extensions"]) + process_folder(["modules/openxr/scene"]) process_folder(["modules/godot_physics_2d"]) process_folder(["modules/godot_physics_3d"]) process_folder(["modules/godot_physics_3d/joints"]) @@ -340,19 +346,26 @@ def generate_scu_files(max_includes_per_scu): process_folder(["scene/animation"]) process_folder(["scene/gui"]) process_folder(["scene/main"]) + process_folder(["scene/theme"]) process_folder(["scene/resources"]) process_folder(["scene/resources/2d"]) + process_folder(["scene/resources/2d/skeleton"]) process_folder(["scene/resources/3d"]) process_folder(["servers"]) process_folder(["servers/rendering"]) + process_folder(["servers/rendering/dummy/storage"]) process_folder(["servers/rendering/storage"]) process_folder(["servers/rendering/renderer_rd"]) process_folder(["servers/rendering/renderer_rd/effects"]) process_folder(["servers/rendering/renderer_rd/environment"]) process_folder(["servers/rendering/renderer_rd/storage_rd"]) + process_folder(["servers/rendering/renderer_rd/forward_clustered"]) + process_folder(["servers/rendering/renderer_rd/forward_mobile"]) process_folder(["servers/audio"]) process_folder(["servers/audio/effects"]) + process_folder(["servers/navigation"]) + process_folder(["servers/xr"]) # Finally change back the path to the calling folder os.chdir(curr_folder) diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 823bad1d2e..96f8182732 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -61,7 +61,7 @@ class AudioDriverDummy : public AudioDriver { public: virtual const char *get_name() const override { return "Dummy"; - }; + } virtual Error init() override; virtual void start() override; diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 1886ebe1ac..d5c37c2acc 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -76,6 +76,42 @@ int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_fra return ret; } +PackedVector2Array AudioStreamPlayback::_mix_audio_bind(float p_rate_scale, int p_frames) { + Vector<AudioFrame> frames = mix_audio(p_rate_scale, p_frames); + + PackedVector2Array res; + res.resize(frames.size()); + + Vector2 *res_ptrw = res.ptrw(); + for (int i = 0; i < frames.size(); i++) { + res_ptrw[i] = Vector2(frames[i].left, frames[i].right); + } + + return res; +} + +Vector<AudioFrame> AudioStreamPlayback::mix_audio(float p_rate_scale, int p_frames) { + Vector<AudioFrame> res; + res.resize(p_frames); + + int frames = mix(res.ptrw(), p_rate_scale, p_frames); + res.resize(frames); + + return res; +} + +void AudioStreamPlayback::start_playback(double p_from_pos) { + start(p_from_pos); +} + +void AudioStreamPlayback::stop_playback() { + stop(); +} + +void AudioStreamPlayback::seek_playback(double p_time) { + seek(p_time); +} + void AudioStreamPlayback::tag_used_streams() { GDVIRTUAL_CALL(_tag_used_streams); } @@ -108,6 +144,13 @@ void AudioStreamPlayback::_bind_methods() { ClassDB::bind_method(D_METHOD("set_sample_playback", "playback_sample"), &AudioStreamPlayback::set_sample_playback); ClassDB::bind_method(D_METHOD("get_sample_playback"), &AudioStreamPlayback::get_sample_playback); + ClassDB::bind_method(D_METHOD("mix_audio", "rate_scale", "frames"), &AudioStreamPlayback::_mix_audio_bind); + ClassDB::bind_method(D_METHOD("start", "from_pos"), &AudioStreamPlayback::start_playback, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "time"), &AudioStreamPlayback::seek_playback, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayback::stop_playback); + ClassDB::bind_method(D_METHOD("get_loop_count"), &AudioStreamPlayback::get_loop_count); + ClassDB::bind_method(D_METHOD("get_playback_position"), &AudioStreamPlayback::get_playback_position); + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayback::is_playing); } AudioStreamPlayback::AudioStreamPlayback() {} @@ -238,7 +281,7 @@ double AudioStream::get_bpm() const { } bool AudioStream::has_loop() const { - bool ret = 0; + bool ret = false; GDVIRTUAL_CALL(_has_loop, ret); return ret; } @@ -347,7 +390,7 @@ int AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fra Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer(); unsigned int input_size = AudioDriver::get_singleton()->get_input_size(); - int mix_rate = AudioDriver::get_singleton()->get_mix_rate(); + int mix_rate = AudioDriver::get_singleton()->get_input_mix_rate(); unsigned int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1); #ifdef DEBUG_ENABLED unsigned int input_position = AudioDriver::get_singleton()->get_input_position(); @@ -398,7 +441,7 @@ int AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, } float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() { - return AudioDriver::get_singleton()->get_mix_rate(); + return AudioDriver::get_singleton()->get_input_mix_rate(); } void AudioStreamPlaybackMicrophone::start(double p_from_pos) { diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 3feaa53630..65efccdc28 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -83,6 +83,7 @@ class AudioStreamPlayback : public RefCounted { protected: static void _bind_methods(); + PackedVector2Array _mix_audio_bind(float p_rate_scale, int p_frames); GDVIRTUAL1(_start, double) GDVIRTUAL0(_stop) GDVIRTUAL0RC(bool, _is_playing) @@ -118,6 +119,11 @@ public: AudioStreamPlayback(); ~AudioStreamPlayback(); + + Vector<AudioFrame> mix_audio(float p_rate_scale, int p_frames); + void start_playback(double p_from_pos = 0.0); + void stop_playback(); + void seek_playback(double p_time); }; class AudioStreamPlaybackResampled : public AudioStreamPlayback { diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 70ef88e36d..63b2f28e74 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -371,10 +371,14 @@ void AudioServer::_mix_step() { bus->soloed = false; } } + // This is legacy code from 3.x that allows video players and other audio sources that do not implement AudioStreamPlayback to output audio. for (CallbackItem *ci : mix_callback_list) { ci->callback(ci->userdata); } + // Main mixing loop for audio streams. + // The basic idea here is to copy the samples returned by the AudioStreamPlayback's mix function into the audio buffers, + // while always maintaining a lookahead buffer of size LOOKAHEAD_BUFFER_SIZE to allow fade-outs for sudden stoppages. for (AudioStreamPlaybackListNode *playback : playback_list) { // Paused streams are no-ops. Don't even mix audio from the stream playback. if (playback->state.load() == AudioStreamPlaybackListNode::PAUSED) { @@ -385,22 +389,26 @@ void AudioServer::_mix_step() { continue; } + // If `fading_out` is true, we're in the process of fading out the stream playback. + // TODO: Currently this sets the volume of the stream to 0 which creates a linear interpolation between its previous volume and silence. + // A more punchy option for fading out could be to just use the lookahead buffer. bool fading_out = playback->state.load() == AudioStreamPlaybackListNode::FADE_OUT_TO_DELETION || playback->state.load() == AudioStreamPlaybackListNode::FADE_OUT_TO_PAUSE; AudioFrame *buf = mix_buffer.ptrw(); - // Copy the lookeahead buffer into the mix buffer. + // Copy the old contents of the lookahead buffer into the beginning of the mix buffer. for (int i = 0; i < LOOKAHEAD_BUFFER_SIZE; i++) { buf[i] = playback->lookahead[i]; } - // Mix the audio stream + // Mix the audio stream. unsigned int mixed_frames = playback->stream_playback->mix(&buf[LOOKAHEAD_BUFFER_SIZE], playback->pitch_scale.get(), buffer_size); if (tag_used_audio_streams && playback->stream_playback->is_playing()) { playback->stream_playback->tag_used_streams(); } + // Check to see if the stream has run out of samples. if (mixed_frames != buffer_size) { // We know we have at least the size of our lookahead buffer for fade-out purposes. @@ -416,42 +424,52 @@ void AudioServer::_mix_step() { new_state = AudioStreamPlaybackListNode::AWAITING_DELETION; playback->state.store(new_state); } else { - // Move the last little bit of what we just mixed into our lookahead buffer. + // Move the last little bit of what we just mixed into our lookahead buffer for the next call to _mix_step. for (int i = 0; i < LOOKAHEAD_BUFFER_SIZE; i++) { playback->lookahead[i] = buf[buffer_size + i]; } } - AudioStreamPlaybackBusDetails *ptr = playback->bus_details.load(); - ERR_FAIL_NULL(ptr); - // By putting null into the bus details pointers, we're taking ownership of their memory for the duration of this mix. - AudioStreamPlaybackBusDetails bus_details = *ptr; + // Get the bus details for this playback. This contains information about which buses the playback is assigned to and the volume of the playback on each bus. + AudioStreamPlaybackBusDetails *bus_details_ptr = playback->bus_details.load(); + ERR_FAIL_NULL(bus_details_ptr); + // Make a copy of the bus details so we can modify it without worrying about other threads. + AudioStreamPlaybackBusDetails bus_details = *bus_details_ptr; // Mix to any active buses. for (int idx = 0; idx < MAX_BUSES_PER_PLAYBACK; idx++) { if (!bus_details.bus_active[idx]) { continue; } + // This is the AudioServer-internal index of the bus we're mixing to in this step of the loop. Not to be confused with `idx` which is an index into `AudioStreamPlaybackBusDetails` member var arrays. int bus_idx = thread_find_bus_index(bus_details.bus[idx]); + // It's important to know whether or not this bus was active in the previous mix step of this stream. If it was, we need to perform volume interpolation to avoid pops. int prev_bus_idx = -1; for (int search_idx = 0; search_idx < MAX_BUSES_PER_PLAYBACK; search_idx++) { if (!playback->prev_bus_details->bus_active[search_idx]) { continue; } + // If the StringNames of the buses match, we've found the previous bus index. This indicates that this playback mixed to `prev_bus_details->bus[prev_bus_index]` in the previous mix step, which gives us a way to look up the playback's previous volume. if (playback->prev_bus_details->bus[search_idx].hash() == bus_details.bus[idx].hash()) { prev_bus_idx = search_idx; + break; } } + // It's now time to mix to the bus. We do this by going through each channel of the bus and mixing to it. + // The channels correspond to output channels of the audio device, e.g. stereo or 5.1. To reduce needless nesting, this is done with a helper method named `_mix_step_for_channel`. for (int channel_idx = 0; channel_idx < channel_count; channel_idx++) { AudioFrame *channel_buf = thread_get_channel_mix_buffer(bus_idx, channel_idx); + // TODO: This `fading_out` check could be replaced with with an exponential fadeout of the samples from the lookahead buffer for more punchy results. if (fading_out) { bus_details.volume[idx][channel_idx] = AudioFrame(0, 0); } AudioFrame channel_vol = bus_details.volume[idx][channel_idx]; - AudioFrame prev_channel_vol = AudioFrame(0, 0); + // If this bus was not active in the previous mix step, we want to start playback at the full volume to avoid crushing transients. + AudioFrame prev_channel_vol = channel_vol; + // If this bus was active in the previous mix step, we need to interpolate between the previous volume and the current volume to avoid pops. Set `prev_channel_volume` accordingly. if (prev_bus_idx != -1) { prev_channel_vol = playback->prev_bus_details->volume[prev_bus_idx][channel_idx]; } @@ -480,7 +498,7 @@ void AudioServer::_mix_step() { for (int channel_idx = 0; channel_idx < channel_count; channel_idx++) { AudioFrame *channel_buf = thread_get_channel_mix_buffer(bus_idx, channel_idx); AudioFrame prev_channel_vol = playback->prev_bus_details->volume[idx][channel_idx]; - // Fade out to silence + // Fade out to silence. This could be replaced with an exponential fadeout of the samples from the lookahead buffer for more punchy results. _mix_step_for_channel(channel_buf, buf, prev_channel_vol, AudioFrame(0, 0), playback->attenuation_filter_cutoff_hz.get(), playback->highshelf_gain.get(), &playback->filter_process[channel_idx * 2], &playback->filter_process[channel_idx * 2 + 1]); } } @@ -501,15 +519,12 @@ void AudioServer::_mix_step() { switch (playback->state.load()) { case AudioStreamPlaybackListNode::AWAITING_DELETION: case AudioStreamPlaybackListNode::FADE_OUT_TO_DELETION: + // Remove the playback from the list. _delete_stream_playback_list_node(playback); break; case AudioStreamPlaybackListNode::FADE_OUT_TO_PAUSE: { // Pause the stream. - AudioStreamPlaybackListNode::PlaybackState old_state, new_state; - do { - old_state = playback->state.load(); - new_state = AudioStreamPlaybackListNode::PAUSED; - } while (!playback->state.compare_exchange_strong(/* expected= */ old_state, new_state)); + playback->state.store(AudioStreamPlaybackListNode::PAUSED); } break; case AudioStreamPlaybackListNode::PLAYING: case AudioStreamPlaybackListNode::PAUSED: @@ -518,13 +533,13 @@ void AudioServer::_mix_step() { } } + // Now that all of the buses have their audio sources mixed into them, we can process the effects and bus sends. for (int i = buses.size() - 1; i >= 0; i--) { - //go bus by bus Bus *bus = buses[i]; for (int k = 0; k < bus->channels.size(); k++) { if (bus->channels[k].active && !bus->channels[k].used) { - //buffer was not used, but it's still active, so it must be cleaned + // Buffer was not used, but it's still active, so it must be cleaned. AudioFrame *buf = bus->channels.write[k].buffer.ptrw(); for (uint32_t j = 0; j < buffer_size; j++) { @@ -533,7 +548,7 @@ void AudioServer::_mix_step() { } } - //process effects + // Process effects. if (!bus->bypass) { for (int j = 0; j < bus->effects.size(); j++) { if (!bus->effects[j].enabled) { @@ -551,7 +566,7 @@ void AudioServer::_mix_step() { bus->channels.write[k].effect_instances.write[j]->process(bus->channels[k].buffer.ptr(), temp_buffer.write[k].ptrw(), buffer_size); } - //swap buffers, so internal buffer always has the right data + // Swap buffers, so internal buffer always has the right data. for (int k = 0; k < bus->channels.size(); k++) { if (!(buses[i]->channels[k].active || bus->channels[k].effect_instances[j]->process_silence())) { continue; @@ -565,17 +580,17 @@ void AudioServer::_mix_step() { } } - //process send + // Process send. Bus *send = nullptr; if (i > 0) { - //everything has a send save for master bus + // Everything has a send except for the master bus. if (!bus_map.has(bus->send)) { send = buses[0]; } else { send = bus_map[bus->send]; - if (send->index_cache >= bus->index_cache) { //invalid, send to master + if (send->index_cache >= bus->index_cache) { // Invalid, send to master. send = buses[0]; } } @@ -603,7 +618,7 @@ void AudioServer::_mix_step() { } } - //apply volume and compute peak + // Apply volume and compute peak. for (uint32_t j = 0; j < buffer_size; j++) { buf[j] *= volume; @@ -620,7 +635,7 @@ void AudioServer::_mix_step() { bus->channels.write[k].peak_volume = AudioFrame(Math::linear_to_db(peak.left + AUDIO_PEAK_OFFSET), Math::linear_to_db(peak.right + AUDIO_PEAK_OFFSET)); if (!bus->channels[k].used) { - //see if any audio is contained, because channel was not used + // See if any audio is contained, because channel was not used. if (MAX(peak.right, peak.left) > Math::db_to_linear(channel_disable_threshold_db)) { bus->channels.write[k].last_mix_with_audio = mix_frames; @@ -631,7 +646,7 @@ void AudioServer::_mix_step() { } if (send) { - //if not master bus, send + // If not master bus, send. AudioFrame *target_buf = thread_get_channel_mix_buffer(send->index_cache, k); for (uint32_t j = 0; j < buffer_size; j++) { @@ -646,6 +661,7 @@ void AudioServer::_mix_step() { } void AudioServer::_mix_step_for_channel(AudioFrame *p_out_buf, AudioFrame *p_source_buf, AudioFrame p_vol_start, AudioFrame p_vol_final, float p_attenuation_filter_cutoff_hz, float p_highshelf_gain, AudioFilterSW::Processor *p_processor_l, AudioFilterSW::Processor *p_processor_r) { + // TODO: In the future it could be nice to replace all of these hardcoded effects with something a bit cleaner and more flexible, but for now this is what we do to support 3D audio players. if (p_highshelf_gain != 0) { AudioFilterSW filter; filter.set_mode(AudioFilterSW::HIGHSHELF); @@ -665,7 +681,7 @@ void AudioServer::_mix_step_for_channel(AudioFrame *p_out_buf, AudioFrame *p_sou p_processor_r->update_coeffs(buffer_size); for (unsigned int frame_idx = 0; frame_idx < buffer_size; frame_idx++) { - // Make this buffer size invariant if buffer_size ever becomes a project setting. + // TODO: Make lerp speed buffer-size-invariant if buffer_size ever becomes a project setting to avoid very small buffer sizes causing pops due to too-fast lerps. float lerp_param = (float)frame_idx / buffer_size; AudioFrame vol = p_vol_final * lerp_param + (1 - lerp_param) * p_vol_start; AudioFrame mixed = vol * p_source_buf[frame_idx]; @@ -676,7 +692,7 @@ void AudioServer::_mix_step_for_channel(AudioFrame *p_out_buf, AudioFrame *p_sou } else { for (unsigned int frame_idx = 0; frame_idx < buffer_size; frame_idx++) { - // Make this buffer size invariant if buffer_size ever becomes a project setting. + // TODO: Make lerp speed buffer-size-invariant if buffer_size ever becomes a project setting to avoid very small buffer sizes causing pops due to too-fast lerps. float lerp_param = (float)frame_idx / buffer_size; p_out_buf[frame_idx] += (p_vol_final * lerp_param + (1 - lerp_param) * p_vol_start) * p_source_buf[frame_idx]; } @@ -701,6 +717,7 @@ void AudioServer::_delete_stream_playback(Ref<AudioStreamPlayback> p_playback) { } void AudioServer::_delete_stream_playback_list_node(AudioStreamPlaybackListNode *p_playback_node) { + // Remove the playback from the list, registering a destructor to be run on the main thread. playback_list.erase(p_playback_node, [](AudioStreamPlaybackListNode *p) { delete p->prev_bus_details; delete p->bus_details.load(); @@ -1440,6 +1457,10 @@ uint64_t AudioServer::get_mixed_frames() const { return mix_frames; } +String AudioServer::get_driver_name() const { + return AudioDriver::get_singleton()->get_name(); +} + void AudioServer::notify_listener_changed() { for (CallbackItem *ci : listener_changed_callback_list) { ci->callback(ci->userdata); @@ -1467,7 +1488,9 @@ void AudioServer::init_channels_and_buffers() { void AudioServer::init() { channel_disable_threshold_db = GLOBAL_DEF_RST("audio/buses/channel_disable_threshold_db", -60.0); channel_disable_frames = float(GLOBAL_DEF_RST(PropertyInfo(Variant::FLOAT, "audio/buses/channel_disable_time", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 2.0)) * get_mix_rate(); - buffer_size = 512; //hardcoded for now + // TODO: Buffer size is hardcoded for now. This would be really nice to have as a project setting because currently it limits audio latency to an absolute minimum of 11ms with default mix rate, but there's some additional work required to make that happen. See TODOs in `_mix_step_for_channel`. + // When this becomes a project setting, it should be specified in milliseconds rather than raw sample count, because 512 samples at 192khz is shorter than it is at 48khz, for example. + buffer_size = 512; init_channels_and_buffers(); @@ -1614,6 +1637,10 @@ float AudioServer::get_mix_rate() const { return AudioDriver::get_singleton()->get_mix_rate(); } +float AudioServer::get_input_mix_rate() const { + return AudioDriver::get_singleton()->get_input_mix_rate(); +} + float AudioServer::read_output_peak_db() const { return 0; } @@ -1946,6 +1973,9 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_speaker_mode"), &AudioServer::get_speaker_mode); ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioServer::get_mix_rate); + ClassDB::bind_method(D_METHOD("get_input_mix_rate"), &AudioServer::get_input_mix_rate); + + ClassDB::bind_method(D_METHOD("get_driver_name"), &AudioServer::get_driver_name); ClassDB::bind_method(D_METHOD("get_output_device_list"), &AudioServer::get_output_device_list); ClassDB::bind_method(D_METHOD("get_output_device"), &AudioServer::get_output_device); diff --git a/servers/audio_server.h b/servers/audio_server.h index 16fcc029b3..9a80882dd7 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -99,6 +99,7 @@ public: virtual Error init() = 0; virtual void start() = 0; virtual int get_mix_rate() const = 0; + virtual int get_input_mix_rate() const { return get_mix_rate(); } virtual SpeakerMode get_speaker_mode() const = 0; virtual float get_latency() { return 0; } @@ -270,6 +271,14 @@ private: }; struct AudioStreamPlaybackListNode { + // The state machine for audio stream playbacks is as follows: + // 1. The playback is created and added to the playback list in the playing state. + // 2. The playback is (maybe) paused, and the state is set to FADE_OUT_TO_PAUSE. + // 2.1. The playback is mixed after being paused, and the audio server thread atomically sets the state to PAUSED after performing a brief fade-out. + // 3. The playback is (maybe) deleted, and the state is set to FADE_OUT_TO_DELETION. + // 3.1. The playback is mixed after being deleted, and the audio server thread atomically sets the state to AWAITING_DELETION after performing a brief fade-out. + // NOTE: The playback is not deallocated at this time because allocation and deallocation are not realtime-safe. + // 4. The playback is removed and deallocated on the main thread using the SafeList maybe_cleanup method. enum PlaybackState { PAUSED = 0, // Paused. Keep this stream playback around though so it can be restarted. PLAYING = 1, // Playing. Fading may still be necessary if volume changes! @@ -427,6 +436,8 @@ public: uint64_t get_mix_count() const; uint64_t get_mixed_frames() const; + String get_driver_name() const; + void notify_listener_changed(); virtual void init(); @@ -441,6 +452,7 @@ public: virtual SpeakerMode get_speaker_mode() const; virtual float get_mix_rate() const; + virtual float get_input_mix_rate() const; virtual float read_output_peak_db() const; diff --git a/servers/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp index 4021d9564b..e93ab3a544 100644 --- a/servers/camera/camera_feed.cpp +++ b/servers/camera/camera_feed.cpp @@ -50,6 +50,8 @@ void CameraFeed::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rgb_image", "rgb_image"), &CameraFeed::set_rgb_image); ClassDB::bind_method(D_METHOD("set_ycbcr_image", "ycbcr_image"), &CameraFeed::set_ycbcr_image); + ClassDB::bind_method(D_METHOD("set_external", "width", "height"), &CameraFeed::set_external); + ClassDB::bind_method(D_METHOD("get_texture_tex_id", "feed_image_type"), &CameraFeed::get_texture_tex_id); ClassDB::bind_method(D_METHOD("get_datatype"), &CameraFeed::get_datatype); @@ -68,6 +70,7 @@ void CameraFeed::_bind_methods() { BIND_ENUM_CONSTANT(FEED_RGB); BIND_ENUM_CONSTANT(FEED_YCBCR); BIND_ENUM_CONSTANT(FEED_YCBCR_SEP); + BIND_ENUM_CONSTANT(FEED_EXTERNAL); BIND_ENUM_CONSTANT(FEED_UNSPECIFIED); BIND_ENUM_CONSTANT(FEED_FRONT); @@ -137,6 +140,10 @@ RID CameraFeed::get_texture(CameraServer::FeedImage p_which) { return texture[p_which]; } +uint64_t CameraFeed::get_texture_tex_id(CameraServer::FeedImage p_which) { + return RenderingServer::get_singleton()->texture_get_native_handle(texture[p_which]); +} + CameraFeed::CameraFeed() { // initialize our feed id = CameraServer::get_singleton()->get_free_id(); @@ -252,6 +259,19 @@ void CameraFeed::set_ycbcr_images(const Ref<Image> &p_y_img, const Ref<Image> &p } } +void CameraFeed::set_external(int p_width, int p_height) { + if ((base_width != p_width) || (base_height != p_height)) { + // We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot... + base_width = p_width; + base_height = p_height; + + auto new_texture = RenderingServer::get_singleton()->texture_external_create(p_width, p_height, 0); + RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_YCBCR_IMAGE], new_texture); + } + + datatype = CameraFeed::FEED_EXTERNAL; +} + bool CameraFeed::activate_feed() { // nothing to do here return true; diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h index 492a909239..365ed7c635 100644 --- a/servers/camera/camera_feed.h +++ b/servers/camera/camera_feed.h @@ -49,7 +49,8 @@ public: FEED_NOIMAGE, // we don't have an image yet FEED_RGB, // our texture will contain a normal RGB texture that can be used directly FEED_YCBCR, // our texture will contain a YCbCr texture that needs to be converted to RGB before output - FEED_YCBCR_SEP // our camera is split into two textures, first plane contains Y data, second plane contains CbCr data + FEED_YCBCR_SEP, // our camera is split into two textures, first plane contains Y data, second plane contains CbCr data + FEED_EXTERNAL, // specific for android atm, camera feed is managed externally, assumed RGB for now }; enum FeedPosition { @@ -104,6 +105,7 @@ public: void set_transform(const Transform2D &p_transform); RID get_texture(CameraServer::FeedImage p_which); + uint64_t get_texture_tex_id(CameraServer::FeedImage p_which); CameraFeed(); CameraFeed(String p_name, FeedPosition p_position = CameraFeed::FEED_UNSPECIFIED); @@ -113,6 +115,7 @@ public: void set_rgb_image(const Ref<Image> &p_rgb_img); void set_ycbcr_image(const Ref<Image> &p_ycbcr_img); void set_ycbcr_images(const Ref<Image> &p_y_img, const Ref<Image> &p_cbcr_img); + void set_external(int p_width, int p_height); virtual bool set_format(int p_index, const Dictionary &p_parameters); virtual Array get_formats() const; diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp index bf698e3945..b78a0c44e7 100644 --- a/servers/camera_server.cpp +++ b/servers/camera_server.cpp @@ -53,13 +53,13 @@ void CameraServer::_bind_methods() { BIND_ENUM_CONSTANT(FEED_YCBCR_IMAGE); BIND_ENUM_CONSTANT(FEED_Y_IMAGE); BIND_ENUM_CONSTANT(FEED_CBCR_IMAGE); -}; +} CameraServer *CameraServer::singleton = nullptr; CameraServer *CameraServer::get_singleton() { return singleton; -}; +} int CameraServer::get_free_id() { bool id_exists = true; @@ -77,7 +77,7 @@ int CameraServer::get_free_id() { }; return newid; -}; +} int CameraServer::get_feed_index(int p_id) { for (int i = 0; i < feeds.size(); i++) { @@ -87,7 +87,7 @@ int CameraServer::get_feed_index(int p_id) { }; return -1; -}; +} Ref<CameraFeed> CameraServer::get_feed_by_id(int p_id) { int index = get_feed_index(p_id); @@ -97,7 +97,7 @@ Ref<CameraFeed> CameraServer::get_feed_by_id(int p_id) { } else { return feeds[index]; } -}; +} void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) { ERR_FAIL_COND(p_feed.is_null()); @@ -109,7 +109,7 @@ void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) { // let whomever is interested know emit_signal(SNAME("camera_feed_added"), p_feed->get_id()); -}; +} void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) { for (int i = 0; i < feeds.size(); i++) { @@ -126,17 +126,17 @@ void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) { return; }; }; -}; +} Ref<CameraFeed> CameraServer::get_feed(int p_index) { ERR_FAIL_INDEX_V(p_index, feeds.size(), nullptr); return feeds[p_index]; -}; +} int CameraServer::get_feed_count() { return feeds.size(); -}; +} TypedArray<CameraFeed> CameraServer::get_feeds() { TypedArray<CameraFeed> return_feeds; @@ -148,7 +148,7 @@ TypedArray<CameraFeed> CameraServer::get_feeds() { }; return return_feeds; -}; +} RID CameraServer::feed_texture(int p_id, CameraServer::FeedImage p_texture) { int index = get_feed_index(p_id); @@ -157,12 +157,12 @@ RID CameraServer::feed_texture(int p_id, CameraServer::FeedImage p_texture) { Ref<CameraFeed> feed = get_feed(index); return feed->get_texture(p_texture); -}; +} CameraServer::CameraServer() { singleton = this; -}; +} CameraServer::~CameraServer() { singleton = nullptr; -}; +} diff --git a/servers/camera_server.h b/servers/camera_server.h index e9bcd771d2..6a79b62fbd 100644 --- a/servers/camera_server.h +++ b/servers/camera_server.h @@ -87,7 +87,7 @@ public: static CameraServer *create() { CameraServer *server = create_func ? create_func() : memnew(CameraServer); return server; - }; + } // Right now we identify our feed by it's ID when it's used in the background. // May see if we can change this to purely relying on CameraFeed objects or by name. diff --git a/servers/display_server.cpp b/servers/display_server.cpp index ce0d6cb996..82ac62bc9f 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -550,7 +550,7 @@ DisplayServer::ScreenOrientation DisplayServer::screen_get_orientation(int p_scr float DisplayServer::screen_get_scale(int p_screen) const { return 1.0f; -}; +} bool DisplayServer::is_touchscreen_available() const { return Input::get_singleton() && Input::get_singleton()->is_emulating_touch_from_mouse(); @@ -1056,6 +1056,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_NATIVE_HELP); BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_INPUT); BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_FILE); + BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_FILE_EXTRA); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); @@ -1128,6 +1129,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP); BIND_ENUM_CONSTANT(WINDOW_FLAG_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(WINDOW_FLAG_MOUSE_PASSTHROUGH); + BIND_ENUM_CONSTANT(WINDOW_FLAG_SHARP_CORNERS); BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX); BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER); @@ -1148,6 +1150,8 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(WINDOW_HANDLE); BIND_ENUM_CONSTANT(WINDOW_VIEW); BIND_ENUM_CONSTANT(OPENGL_CONTEXT); + BIND_ENUM_CONSTANT(EGL_DISPLAY); + BIND_ENUM_CONSTANT(EGL_CONFIG); BIND_ENUM_CONSTANT(TTS_UTTERANCE_STARTED); BIND_ENUM_CONSTANT(TTS_UTTERANCE_ENDED); @@ -1229,6 +1233,10 @@ void DisplayServer::_input_set_custom_mouse_cursor_func(const Ref<Resource> &p_i } bool DisplayServer::can_create_rendering_device() { + if (get_singleton()->get_name() == "headless") { + return false; + } + #if defined(RD_ENABLED) RenderingDevice *device = RenderingDevice::get_singleton(); if (device) { diff --git a/servers/display_server.h b/servers/display_server.h index 36798bd011..916c006f01 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -32,6 +32,7 @@ #define DISPLAY_SERVER_H #include "core/input/input.h" +#include "core/io/image.h" #include "core/io/resource.h" #include "core/os/os.h" #include "core/variant/callable.h" @@ -39,7 +40,6 @@ #include "display/native_menu.h" class Texture2D; -class Image; class DisplayServer : public Object { GDCLASS(DisplayServer, Object) @@ -82,6 +82,8 @@ public: WINDOW_HANDLE, WINDOW_VIEW, OPENGL_CONTEXT, + EGL_DISPLAY, + EGL_CONFIG, }; enum Context { @@ -150,6 +152,7 @@ public: FEATURE_NATIVE_HELP, FEATURE_NATIVE_DIALOG_INPUT, FEATURE_NATIVE_DIALOG_FILE, + FEATURE_NATIVE_DIALOG_FILE_EXTRA, }; virtual bool has_feature(Feature p_feature) const = 0; @@ -367,6 +370,7 @@ public: INVALID_INDICATOR_ID = -1 }; +public: typedef int WindowID; typedef int IndicatorID; @@ -381,6 +385,7 @@ public: WINDOW_FLAG_POPUP, WINDOW_FLAG_EXTEND_TO_TITLE, WINDOW_FLAG_MOUSE_PASSTHROUGH, + WINDOW_FLAG_SHARP_CORNERS, WINDOW_FLAG_MAX, }; @@ -394,6 +399,7 @@ public: WINDOW_FLAG_POPUP_BIT = (1 << WINDOW_FLAG_POPUP), WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE), WINDOW_FLAG_MOUSE_PASSTHROUGH_BIT = (1 << WINDOW_FLAG_MOUSE_PASSTHROUGH), + WINDOW_FLAG_SHARP_CORNERS_BIT = (1 << WINDOW_FLAG_SHARP_CORNERS), }; virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID); diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index a5277479ca..5f53e76235 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -72,7 +72,7 @@ public: // that don't affect the project's behavior in headless mode. int get_screen_count() const override { return 0; } - int get_primary_screen() const override { return 0; }; + int get_primary_screen() const override { return 0; } Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Point2i(); } Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Size2i(); } Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Rect2i(); } @@ -141,7 +141,7 @@ public: void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override {} void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override {} - bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override { return true; }; + bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override { return true; } bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override { return false; } diff --git a/servers/movie_writer/movie_writer.h b/servers/movie_writer/movie_writer.h index e1dc8ef8cf..69d6b1ba2b 100644 --- a/servers/movie_writer/movie_writer.h +++ b/servers/movie_writer/movie_writer.h @@ -31,6 +31,7 @@ #ifndef MOVIE_WRITER_H #define MOVIE_WRITER_H +#include "core/io/image.h" #include "core/templates/local_vector.h" #include "servers/audio/audio_driver_dummy.h" #include "servers/audio_server.h" diff --git a/servers/navigation_server_2d_dummy.h b/servers/navigation_server_2d_dummy.h index 0664b37ef0..5bc91830e6 100644 --- a/servers/navigation_server_2d_dummy.h +++ b/servers/navigation_server_2d_dummy.h @@ -58,7 +58,7 @@ public: TypedArray<RID> map_get_agents(RID p_map) const override { return TypedArray<RID>(); } TypedArray<RID> map_get_obstacles(RID p_map) const override { return TypedArray<RID>(); } void map_force_update(RID p_map) override {} - Vector2 map_get_random_point(RID p_map, uint32_t p_naviation_layers, bool p_uniformly) const override { return Vector2(); }; + Vector2 map_get_random_point(RID p_map, uint32_t p_naviation_layers, bool p_uniformly) const override { return Vector2(); } uint32_t map_get_iteration_id(RID p_map) const override { return 0; } RID region_create() override { return RID(); } @@ -84,7 +84,7 @@ public: Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override { return Vector2(); } Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override { return Vector2(); } Vector2 region_get_closest_point(RID p_region, const Vector2 &p_point) const override { return Vector2(); } - Vector2 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override { return Vector2(); }; + Vector2 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override { return Vector2(); } RID link_create() override { return RID(); } void link_set_map(RID p_link, RID p_map) override {} diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h index 7640afc711..6205193d9a 100644 --- a/servers/rendering/dummy/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -66,14 +66,14 @@ protected: RasterizerSceneDummy scene; public: - RendererUtilities *get_utilities() override { return &utilities; }; - RendererLightStorage *get_light_storage() override { return &light_storage; }; - RendererMaterialStorage *get_material_storage() override { return &material_storage; }; - RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; }; - RendererParticlesStorage *get_particles_storage() override { return &particles_storage; }; - RendererTextureStorage *get_texture_storage() override { return &texture_storage; }; - RendererGI *get_gi() override { return &gi; }; - RendererFog *get_fog() override { return &fog; }; + RendererUtilities *get_utilities() override { return &utilities; } + RendererLightStorage *get_light_storage() override { return &light_storage; } + RendererMaterialStorage *get_material_storage() override { return &material_storage; } + RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; } + RendererParticlesStorage *get_particles_storage() override { return &particles_storage; } + RendererTextureStorage *get_texture_storage() override { return &texture_storage; } + RendererGI *get_gi() override { return &gi; } + RendererFog *get_fog() override { return &fog; } RendererCanvasRender *get_canvas() override { return &canvas; } RendererSceneRender *get_scene() override { return &scene; } diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index c3b63cdbf6..d25523753c 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -78,6 +78,8 @@ public: virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {} virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {} virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {} + virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override {} + virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override { return 0xFFFFFFFF; } virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {} virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {} diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h index e4c58474e2..74ae71cba6 100644 --- a/servers/rendering/dummy/storage/material_storage.h +++ b/servers/rendering/dummy/storage/material_storage.h @@ -92,7 +92,7 @@ public: virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const override { return Variant(); } - virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); } /* MATERIAL API */ virtual RID material_allocate() override { return RID(); } diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index b0953b5dce..556d58f411 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -64,7 +64,7 @@ public: /* MESH API */ - bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); } virtual RID mesh_allocate() override; virtual void mesh_initialize(RID p_rid) override; @@ -170,6 +170,7 @@ public: virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); } virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); } virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override; + virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override { return RID(); } virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override; virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {} diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 6735f6bcda..63eb441915 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -53,7 +53,7 @@ public: /* Canvas Texture API */ - virtual RID canvas_texture_allocate() override { return RID(); }; + virtual RID canvas_texture_allocate() override { return RID(); } virtual void canvas_texture_initialize(RID p_rid) override {} virtual void canvas_texture_free(RID p_rid) override {} @@ -65,13 +65,13 @@ public: /* Texture API */ - bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); } virtual RID texture_allocate() override { DummyTexture *texture = memnew(DummyTexture); ERR_FAIL_NULL_V(texture, RID()); return texture_owner.make_rid(texture); - }; + } virtual void texture_free(RID p_rid) override { // delete the texture @@ -79,13 +79,13 @@ public: ERR_FAIL_NULL(texture); texture_owner.free(p_rid); memdelete(texture); - }; + } virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { DummyTexture *t = texture_owner.get_or_null(p_texture); ERR_FAIL_NULL(t); t->image = p_image->duplicate(); - }; + } virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {} virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {} virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override {} @@ -107,15 +107,15 @@ public: DummyTexture *t = texture_owner.get_or_null(p_texture); ERR_FAIL_NULL_V(t, Ref<Image>()); return t->image; - }; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }; + } + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); }; + virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); } virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} virtual void texture_set_path(RID p_texture, const String &p_path) override {} - virtual String texture_get_path(RID p_texture) const override { return String(); }; + virtual String texture_get_path(RID p_texture) const override { return String(); } virtual Image::Format texture_get_format(RID p_texture) const override { return Image::FORMAT_MAX; } @@ -127,11 +127,11 @@ public: virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {} - virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }; + virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); } virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) override {} - virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override { return RID(); }; - virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override { return 0; }; + virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override { return RID(); } + virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override { return 0; } /* DECAL API */ virtual RID decal_allocate() override { return RID(); } diff --git a/servers/rendering/dummy/storage/utilities.h b/servers/rendering/dummy/storage/utilities.h index ae83547afd..4e20dee640 100644 --- a/servers/rendering/dummy/storage/utilities.h +++ b/servers/rendering/dummy/storage/utilities.h @@ -124,7 +124,7 @@ public: virtual RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; } virtual String get_video_adapter_api_version() const override { return String(); } - virtual Size2i get_maximum_viewport_size() const override { return Size2i(); }; + virtual Size2i get_maximum_viewport_size() const override { return Size2i(); } }; } // namespace RendererDummy diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 701b4da8f8..22a9a4632d 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -278,6 +278,19 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 ci->children_order_dirty = false; } + if (ci->use_parent_material && p_material_owner) { + ci->material_owner = p_material_owner; + } else { + p_material_owner = ci; + ci->material_owner = nullptr; + } + + Color modulate = ci->modulate * p_modulate; + + if (modulate.a < 0.007) { + return; + } + Rect2 rect = ci->get_rect(); if (ci->visibility_notifier) { @@ -346,19 +359,6 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 } global_rect.position += p_clip_rect.position; - if (ci->use_parent_material && p_material_owner) { - ci->material_owner = p_material_owner; - } else { - p_material_owner = ci; - ci->material_owner = nullptr; - } - - Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a); - - if (modulate.a < 0.007) { - return; - } - int child_item_count = ci->child_items.size(); Item **child_items = ci->child_items.ptrw(); @@ -612,8 +612,9 @@ void RendererCanvasCull::canvas_item_set_visibility_layer(RID p_item, uint32_t p uint32_t RendererCanvasCull::canvas_item_get_visibility_layer(RID p_item) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); - if (!canvas_item) + if (!canvas_item) { return 0; + } return canvas_item->visibility_layer; } diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index a585c9430b..dbc8f155bf 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -106,7 +106,7 @@ public: virtual double get_total_time() const = 0; virtual bool can_create_resources_async() const = 0; - static bool is_low_end() { return low_end; }; + static bool is_low_end() { return low_end; } virtual bool is_xr_enabled() const; static RendererCompositor *get_singleton() { return singleton; } diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index c7a7532d76..808c82f712 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -1002,15 +1002,19 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); + Rect2i screen_rect; + float atlas_width = p_dst_size.width / p_rect.size.width; + float atlas_height = p_dst_size.height / p_rect.size.height; + screen_rect.position.x = (int32_t)(Math::round(p_rect.position.x * atlas_width)); + screen_rect.position.y = (int32_t)(Math::round(p_rect.position.y * atlas_height)); + screen_rect.size.width = (int32_t)(Math::round(p_dst_size.width)); + screen_rect.size.height = (int32_t)(Math::round(p_dst_size.height)); + CopyToDPPushConstant push_constant; - push_constant.screen_rect[0] = p_rect.position.x; - push_constant.screen_rect[1] = p_rect.position.y; - push_constant.screen_rect[2] = p_rect.size.width; - push_constant.screen_rect[3] = p_rect.size.height; push_constant.z_far = p_z_far; push_constant.z_near = p_z_near; - push_constant.texel_size[0] = 1.0f / p_dst_size.x; - push_constant.texel_size[1] = 1.0f / p_dst_size.y; + push_constant.texel_size[0] = 1.0f / p_dst_size.width; + push_constant.texel_size[1] = 1.0f / p_dst_size.height; push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign // setup our uniforms @@ -1021,7 +1025,7 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, Vector<Color>(), 1.0f, 0, screen_rect); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index 014f78e2b9..b6fc95d0f1 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -217,7 +217,6 @@ private: float z_far; float z_near; float texel_size[2]; - float screen_rect[4]; }; struct CopyToDP { diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 2dfcd67411..090eab384f 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -157,7 +157,7 @@ RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() { RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() { return Fog::get_singleton()->_create_fog_shader_func(); -}; +} RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); @@ -168,7 +168,7 @@ RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogSha RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); -}; +} //////////////////////////////////////////////////////////////////////////////// // FOG VOLUMES INSTANCE @@ -622,6 +622,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); bool any_uses_time = false; + Vector3 cam_position = p_cam_transform.get_origin(); for (int i = 0; i < (int)p_fog_volumes.size(); i++) { FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]); @@ -652,41 +653,68 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P any_uses_time |= shader_data->uses_time; - Vector3i min; - Vector3i max; + Vector3i froxel_min; + Vector3i froxel_max; Vector3i kernel_size; - Vector3 position = fog_volume_instance->transform.get_origin(); + Vector3 fog_position = fog_volume_instance->transform.get_origin(); RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_size(fog_volume) / 2; if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { // Local fog volume. - Vector3i points[8]; Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth); float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); - points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - - min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1); - max = Vector3i(1, 1, 1); - + Vector3 corners[8]{ + fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), + fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), + fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), + fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), + fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), + fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), + fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), + fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)) + }; + Vector3i froxels[8]; + Vector3 corner_min = corners[0]; + Vector3 corner_max = corners[0]; for (int j = 0; j < 8; j++) { - min = min.min(points[j]); - max = max.max(points[j]); + froxels[j] = _point_get_position_in_froxel_volume(corners[j], fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + corner_min = corner_min.min(corners[j]); + corner_max = corner_max.max(corners[j]); + } + + froxel_min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1); + froxel_max = Vector3i(1, 1, 1); + + // Tracking just the corners of the fog volume can result in missing some fog: + // when the camera's near plane is inside the fog, we must always consider the entire screen + Vector3 near_plane_corner(frustum_near_size.x, frustum_near_size.y, z_near); + float expand = near_plane_corner.length(); + if (cam_position.x > (corner_min.x - expand) && cam_position.x < (corner_max.x + expand) && + cam_position.y > (corner_min.y - expand) && cam_position.y < (corner_max.y + expand) && + cam_position.z > (corner_min.z - expand) && cam_position.z < (corner_max.z + expand)) { + froxel_min.x = 0; + froxel_min.y = 0; + froxel_min.z = 0; + froxel_max.x = int32_t(fog->width); + froxel_max.y = int32_t(fog->height); + for (int j = 0; j < 8; j++) { + froxel_max.z = MAX(froxel_max.z, froxels[j].z); + } + } else { + // Camera is guaranteed to be outside the fog volume + for (int j = 0; j < 8; j++) { + froxel_min = froxel_min.min(froxels[j]); + froxel_max = froxel_max.max(froxels[j]); + } } - kernel_size = max - min; + kernel_size = froxel_max - froxel_min; } else { // Volume type global runs on all cells extents = Vector3(fog->width, fog->height, fog->depth); - min = Vector3i(0, 0, 0); + froxel_min = Vector3i(0, 0, 0); kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth)); } @@ -695,15 +723,15 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P } VolumetricFogShader::FogPushConstant push_constant; - push_constant.position[0] = position.x; - push_constant.position[1] = position.y; - push_constant.position[2] = position.z; + push_constant.position[0] = fog_position.x; + push_constant.position[1] = fog_position.y; + push_constant.position[2] = fog_position.z; push_constant.size[0] = extents.x * 2; push_constant.size[1] = extents.y * 2; push_constant.size[2] = extents.z * 2; - push_constant.corner[0] = min.x; - push_constant.corner[1] = min.y; - push_constant.corner[2] = min.z; + push_constant.corner[0] = froxel_min.x; + push_constant.corner[1] = froxel_min.y; + push_constant.corner[2] = froxel_min.z; push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume)); RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform); diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 75b9c563f7..23de97a268 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -233,7 +233,7 @@ public: /* FOG VOLUMES */ - bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }; + bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); } virtual RID fog_volume_allocate() override; virtual void fog_volume_initialize(RID p_rid) override; @@ -250,7 +250,7 @@ public: /* FOG VOLUMES INSTANCE */ - bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }; + bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); } RID fog_volume_instance_create(RID p_fog_volume); void fog_instance_free(RID p_rid); diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 12ff28d7b0..235aa9f828 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -350,7 +350,7 @@ bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const { bool GI::voxel_gi_is_interior(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_NULL_V(voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, false); return voxel_gi->interior; } diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index f6f9ab4f75..f34bbde6f0 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -467,7 +467,7 @@ public: /* VOXEL GI API */ - bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }; + bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); } virtual RID voxel_gi_allocate() override; virtual void voxel_gi_free(RID p_voxel_gi) override; @@ -524,14 +524,14 @@ public: VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_NULL_V(voxel_gi, RID()); return voxel_gi->texture; - }; + } _FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_NULL(voxel_gi); voxel_gi->render_index = p_index; - }; + } bool voxel_gi_instance_owns(RID p_rid) const { return voxel_gi_instance_owner.owns(p_rid); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 2087989102..83ec52ea75 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -701,7 +701,7 @@ RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() { RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); -}; +} RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); @@ -713,7 +713,7 @@ RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyS RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); -}; +} SkyRD::SkyRD() { roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers"); @@ -972,26 +972,26 @@ SkyRD::~SkyRD() { } } -void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, Vector2 p_jitter, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup_sky(const RenderDataRD *p_render_data, const Size2i p_screen_size) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(p_env.is_null()); + ERR_FAIL_COND(p_render_data->environment.is_null()); - ERR_FAIL_COND(p_render_buffers.is_null()); + ERR_FAIL_COND(p_render_data->render_buffers.is_null()); // make sure we support our view count - ERR_FAIL_COND(p_view_count == 0); - ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); + ERR_FAIL_COND(p_render_data->scene_data->view_count == 0); + ERR_FAIL_COND(p_render_data->scene_data->view_count > RendererSceneRender::MAX_RENDER_VIEWS); SkyMaterialData *material = nullptr; - Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); + Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_render_data->environment)); RID sky_material; SkyShaderData *shader_data = nullptr; if (sky) { - sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); + sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_render_data->environment)); if (sky_material.is_valid()) { material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); @@ -1025,8 +1025,8 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con update_dirty_skys(); } - if (shader_data->uses_time && p_scene_render->time - sky->prev_time > 0.00001) { - sky->prev_time = p_scene_render->time; + if (shader_data->uses_time && p_render_data->scene_data->time - sky->prev_time > 0.00001) { + sky->prev_time = p_render_data->scene_data->time; sky->reflection.dirty = true; RenderingServerDefault::redraw_request(); } @@ -1041,29 +1041,30 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con sky->reflection.dirty = true; } - if (!p_cam_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) { - sky->prev_position = p_cam_transform.origin; + if (!p_render_data->scene_data->cam_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) { + sky->prev_position = p_render_data->scene_data->cam_transform.origin; sky->reflection.dirty = true; } } sky_scene_state.ubo.directional_light_count = 0; if (shader_data->uses_light) { + const PagedArray<RID> &lights = *p_render_data->lights; // Run through the list of lights in the scene and pick out the Directional Lights. // This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called // after the depth prepass, but this runs before the depth prepass. - for (int i = 0; i < (int)p_lights.size(); i++) { - if (!light_storage->owns_light_instance(p_lights[i])) { + for (int i = 0; i < (int)lights.size(); i++) { + if (!light_storage->owns_light_instance(lights[i])) { continue; } - RID base = light_storage->light_instance_get_base_light(p_lights[i]); + RID base = light_storage->light_instance_get_base_light(lights[i]); ERR_CONTINUE(base.is_null()); RS::LightType type = light_storage->light_get_type(base); if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) { SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count]; - Transform3D light_transform = light_storage->light_instance_get_base_transform(p_lights[i]); + Transform3D light_transform = light_storage->light_instance_get_base_transform(lights[i]); Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); sky_light_data.direction[0] = world_direction.x; @@ -1073,12 +1074,12 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con float sign = light_storage->light_is_negative(base) ? -1 : 1; sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); - if (p_scene_render->is_using_physical_light_units()) { + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY); } - if (p_camera_attributes.is_valid()) { - sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes); + if (p_render_data->camera_attributes.is_valid()) { + sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); } Color linear_col = light_storage->light_get_color(base).srgb_to_linear(); @@ -1149,43 +1150,48 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con // Setup fog variables. sky_scene_state.ubo.volumetric_fog_enabled = false; - if (p_render_buffers.is_valid()) { - if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { - Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); - sky_scene_state.ubo.volumetric_fog_enabled = true; - - float fog_end = fog->length; - if (fog_end > 0.0) { - sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end; - } else { - sky_scene_state.ubo.volumetric_fog_inv_length = 1.0; - } + if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = p_render_data->render_buffers->get_custom_data(RB_SCOPE_FOG); + sky_scene_state.ubo.volumetric_fog_enabled = true; - float fog_detail_spread = fog->spread; // Reverse lookup. - if (fog_detail_spread > 0.0) { - sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread; - } else { - sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0; - } + float fog_end = fog->length; + if (fog_end > 0.0) { + sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end; + } else { + sky_scene_state.ubo.volumetric_fog_inv_length = 1.0; + } - sky_scene_state.fog_uniform_set = fog->sky_uniform_set; + float fog_detail_spread = fog->spread; // Reverse lookup. + if (fog_detail_spread > 0.0) { + sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread; + } else { + sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0; } + + sky_scene_state.fog_uniform_set = fog->sky_uniform_set; } + sky_scene_state.view_count = p_render_data->scene_data->view_count; + sky_scene_state.cam_transform = p_render_data->scene_data->cam_transform; + Projection correction; - correction.set_depth_correction(false, true); - correction.add_jitter_offset(p_jitter); + correction.set_depth_correction(p_render_data->scene_data->flip_y, true); + correction.add_jitter_offset(p_render_data->scene_data->taa_jitter); + + Projection projection = p_render_data->scene_data->cam_projection; + if (p_render_data->scene_data->cam_frustum) { + // We don't use a full projection matrix for the sky, this is enough to make up for it. + projection[2].y = -projection[2].y; + } - sky_scene_state.view_count = p_view_count; - sky_scene_state.cam_transform = p_cam_transform; - sky_scene_state.cam_projection = correction * p_cam_projection; // We only use this when rendering a single view. + sky_scene_state.cam_projection = correction * projection; // Our info in our UBO is only used if we're rendering stereo. - for (uint32_t i = 0; i < p_view_count; i++) { - Projection view_inv_projection = (correction * p_view_projections[i]).inverse(); - if (p_view_count > 1) { + for (uint32_t i = 0; i < p_render_data->scene_data->view_count; i++) { + Projection view_inv_projection = (correction * p_render_data->scene_data->view_projection[i]).inverse(); + if (p_render_data->scene_data->view_count > 1) { // Reprojection is used when we need to have things in combined space. - RendererRD::MaterialStorage::store_camera(p_cam_projection * view_inv_projection, sky_scene_state.ubo.combined_reprojection[i]); + RendererRD::MaterialStorage::store_camera(p_render_data->scene_data->cam_projection * view_inv_projection, sky_scene_state.ubo.combined_reprojection[i]); } else { // This is unused so just reset to identity. Projection ident; @@ -1193,25 +1199,25 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con } RendererRD::MaterialStorage::store_camera(view_inv_projection, sky_scene_state.ubo.view_inv_projections[i]); - sky_scene_state.ubo.view_eye_offsets[i][0] = p_view_eye_offsets[i].x; - sky_scene_state.ubo.view_eye_offsets[i][1] = p_view_eye_offsets[i].y; - sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z; + sky_scene_state.ubo.view_eye_offsets[i][0] = p_render_data->scene_data->view_eye_offset[i].x; + sky_scene_state.ubo.view_eye_offsets[i][1] = p_render_data->scene_data->view_eye_offset[i].y; + sky_scene_state.ubo.view_eye_offsets[i][2] = p_render_data->scene_data->view_eye_offset[i].z; sky_scene_state.ubo.view_eye_offsets[i][3] = 0.0; } - sky_scene_state.ubo.z_far = p_view_projections[0].get_z_far(); // Should be the same for all projection. - sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env); - sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env); - sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env); - Color fog_color = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_color(p_env).srgb_to_linear(); - float fog_energy = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_energy(p_env); + sky_scene_state.ubo.z_far = p_render_data->scene_data->view_projection[0].get_z_far(); // Should be the same for all projection. + sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_render_data->environment); + sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_render_data->environment); + sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_render_data->environment); + Color fog_color = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_color(p_render_data->environment).srgb_to_linear(); + float fog_energy = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_energy(p_render_data->environment); sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; - sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env); + sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_render_data->environment); - sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_env); - sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_env); + sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_render_data->environment); + sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_render_data->environment); RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo); } @@ -1292,7 +1298,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, Projection cm; cm.set_perspective(90, 1, 0.01, 10.0); Projection correction; - correction.set_depth_correction(true); + correction.set_depth_correction(false); cm = correction * cm; // Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader. diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index b146a416f9..cc753efa01 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -36,6 +36,7 @@ #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_data_rd.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" @@ -294,7 +295,7 @@ public: void set_texture_format(RD::DataFormat p_texture_format); ~SkyRD(); - void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, Vector2 p_jitter, RendererSceneRenderRD *p_scene_render); + void setup_sky(const RenderDataRD *p_render_data, const Size2i p_screen_size); void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0); void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0); void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 76d8972ad9..b867e844c7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -395,6 +395,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p RID xforms_uniform_set = surf->owner->transforms_uniform_set; SceneShaderForwardClustered::ShaderSpecialization pipeline_specialization = p_params->base_specialization; + pipeline_specialization.multimesh = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH); + pipeline_specialization.multimesh_format_2d = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D); + pipeline_specialization.multimesh_has_color = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR); + pipeline_specialization.multimesh_has_custom_data = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA); if constexpr (p_pass_mode == PASS_MODE_COLOR) { pipeline_specialization.use_light_soft_shadows = element_info.uses_softshadow; @@ -1953,16 +1957,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Setup Sky"); // Setup our sky render information for this frame/viewport - if (is_reflection_probe) { - Vector3 eye_offset; - Projection correction; - correction.set_depth_correction(true); - Projection projection = correction * p_render_data->scene_data->cam_projection; - - sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, Vector2(0.0f, 0.0f), this); - } else { - sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, p_render_data->scene_data->taa_jitter, this); - } + sky.setup_sky(p_render_data, screen_size); sky_energy_multiplier *= bg_energy_multiplier; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 53982af590..00a70e3690 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -374,6 +374,10 @@ void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pip sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT; specialization_constants.push_back(sc); + sc.constant_id = 1; + sc.int_value = p_pipeline_key.shader_specialization.packed_1; + specialization_constants.push_back(sc); + RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.color_pass_flags, p_pipeline_key.ubershader); ERR_FAIL_COND(shader_rid.is_null()); @@ -610,6 +614,8 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); + actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR"; actions.renames["VIEWPORT_SIZE"] = "read_viewport_size"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; @@ -649,8 +655,6 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["CUSTOM1"] = "custom1_attrib"; actions.renames["CUSTOM2"] = "custom2_attrib"; actions.renames["CUSTOM3"] = "custom3_attrib"; - actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR"; actions.renames["LIGHT_VERTEX"] = "light_vertex"; actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz"; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 136514588a..1f4058a121 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -108,16 +108,26 @@ public: uint32_t projector_use_mipmaps : 1; uint32_t use_depth_fog : 1; uint32_t use_lightmap_bicubic_filter : 1; - uint32_t soft_shadow_samples : 4; - uint32_t penumbra_shadow_samples : 4; - uint32_t directional_soft_shadow_samples : 4; - uint32_t directional_penumbra_shadow_samples : 4; + uint32_t soft_shadow_samples : 6; + uint32_t penumbra_shadow_samples : 6; + uint32_t directional_soft_shadow_samples : 6; + uint32_t directional_penumbra_shadow_samples : 6; }; uint32_t packed_0; }; - uint32_t packed_1; + union { + struct { + uint32_t multimesh : 1; + uint32_t multimesh_format_2d : 1; + uint32_t multimesh_has_color : 1; + uint32_t multimesh_has_custom_data : 1; + }; + + uint32_t packed_1; + }; + uint32_t packed_2; }; @@ -263,7 +273,7 @@ public: _FORCE_INLINE_ bool uses_shared_shadow_material() const { bool backface_culling = cull_mode == CULL_BACK; - return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_position && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && backface_culling && !uses_point_size && !uses_world_coordinates; + return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_position && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && backface_culling && !uses_point_size && !uses_world_coordinates && !wireframe; } virtual void set_code(const String &p_Code); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 978ce097d3..411f0fe6a4 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -911,14 +911,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color Color clear_color = p_default_bg_color; bool load_color = false; bool copy_canvas = false; + bool use_ambient_cubemap = false; + bool use_reflection_cubemap = false; if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black } else if (is_environment(p_render_data->environment)) { + RS::EnvironmentAmbientSource ambient_source = environment_get_ambient_source(p_render_data->environment); RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment); float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment); bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment); RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment); + use_ambient_cubemap = (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY; + use_reflection_cubemap = (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY; if (p_render_data->camera_attributes.is_valid()) { bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); @@ -963,21 +968,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } // setup sky if used for ambient, reflections, or background - if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { + if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - // Setup our sky render information for this frame/viewport - if (is_reflection_probe) { - Vector3 eye_offset; - Projection correction; - correction.set_depth_correction(true); - Projection projection = correction * p_render_data->scene_data->cam_projection; - - sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, Vector2(0.0f, 0.0f), this); - } else { - sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, p_render_data->scene_data->taa_jitter, this); - } + sky.setup_sky(p_render_data, screen_size); sky_energy_multiplier *= bg_energy_multiplier; @@ -1008,13 +1003,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color SceneShaderForwardMobile::ShaderSpecialization base_specialization = scene_shader.default_specialization; { - //figure out spec constants - - if (p_render_data->directional_light_count > 0) { - base_specialization.use_directional_soft_shadows = p_render_data->directional_light_soft_shadows; - } else { - base_specialization.disable_directional_lights = true; - } + base_specialization.use_directional_soft_shadows = p_render_data->directional_light_count > 0 ? p_render_data->directional_light_soft_shadows : false; + base_specialization.directional_lights = p_render_data->directional_light_count; if (!is_environment(p_render_data->environment) || !environment_get_fog_enabled(p_render_data->environment)) { base_specialization.disable_fog = true; @@ -1023,6 +1013,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) { base_specialization.use_depth_fog = true; } + + base_specialization.scene_use_ambient_cubemap = use_ambient_cubemap; + base_specialization.scene_use_reflection_cubemap = use_reflection_cubemap; + base_specialization.scene_roughness_limiter_enabled = p_render_data->render_buffers.is_valid() && screen_space_roughness_limiter_is_active(); } { @@ -2054,6 +2048,10 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const surf = surf->next; } } + + if (p_render_list == RENDER_LIST_OPAQUE && lightmap_captures_used) { + RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures); + } } void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { @@ -2144,7 +2142,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr } SceneShaderForwardMobile::ShaderSpecialization pipeline_specialization = p_params->base_specialization; - pipeline_specialization.is_multimesh = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH); + pipeline_specialization.multimesh = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH); + pipeline_specialization.multimesh_format_2d = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D); + pipeline_specialization.multimesh_has_color = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR); + pipeline_specialization.multimesh_has_custom_data = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA); SceneState::PushConstant push_constant; push_constant.base_index = i + p_params->element_offset; @@ -2165,10 +2166,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr } else { pipeline_specialization.use_light_projector = inst->use_projector; pipeline_specialization.use_light_soft_shadows = inst->use_soft_shadow; - pipeline_specialization.disable_omni_lights = inst->omni_light_count == 0; - pipeline_specialization.disable_spot_lights = inst->spot_light_count == 0; - pipeline_specialization.disable_reflection_probes = inst->reflection_probe_count == 0; - pipeline_specialization.disable_decals = inst->decals_count == 0; + pipeline_specialization.omni_lights = inst->omni_light_count; + pipeline_specialization.spot_lights = inst->spot_light_count; + pipeline_specialization.reflection_probes = inst->reflection_probe_count; + pipeline_specialization.decals = inst->decals_count; #ifdef DEBUG_ENABLED if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) { diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 69f084f4c0..4525b50b6e 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -237,6 +237,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli "VERSION:", p_pipeline_key.version, "SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0, "SPEC PACKED #1:", p_pipeline_key.shader_specialization.packed_1, + "SPEC PACKED #2:", p_pipeline_key.shader_specialization.packed_2, "RENDER PASS:", p_pipeline_key.render_pass, "WIREFRAME:", p_pipeline_key.wireframe); #endif @@ -322,7 +323,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli specialization_constants.push_back(sc); sc.constant_id = 1; - sc.float_value = p_pipeline_key.shader_specialization.packed_1; + sc.int_value = p_pipeline_key.shader_specialization.packed_1; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT; + specialization_constants.push_back(sc); + + sc.constant_id = 2; + sc.float_value = p_pipeline_key.shader_specialization.packed_2; sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT; specialization_constants.push_back(sc); @@ -521,6 +527,8 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); + actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR"; actions.renames["VIEWPORT_SIZE"] = "read_viewport_size"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; @@ -560,8 +568,6 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["CUSTOM1"] = "custom1_attrib"; actions.renames["CUSTOM2"] = "custom2_attrib"; actions.renames["CUSTOM3"] = "custom3_attrib"; - actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR"; actions.renames["LIGHT_VERTEX"] = "light_vertex"; actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index c1095d29dc..e2549d1f00 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -65,31 +65,42 @@ public: uint32_t use_directional_soft_shadows : 1; uint32_t decal_use_mipmaps : 1; uint32_t projector_use_mipmaps : 1; - uint32_t disable_omni_lights : 1; - uint32_t disable_spot_lights : 1; - uint32_t disable_reflection_probes : 1; - uint32_t disable_directional_lights : 1; - uint32_t disable_decals : 1; uint32_t disable_fog : 1; uint32_t use_depth_fog : 1; - uint32_t is_multimesh : 1; uint32_t use_lightmap_bicubic_filter : 1; - uint32_t pad : 2; - uint32_t soft_shadow_samples : 4; - uint32_t penumbra_shadow_samples : 4; - uint32_t directional_soft_shadow_samples : 4; - uint32_t directional_penumbra_shadow_samples : 4; + uint32_t multimesh : 1; + uint32_t multimesh_format_2d : 1; + uint32_t multimesh_has_color : 1; + uint32_t multimesh_has_custom_data : 1; + uint32_t scene_use_ambient_cubemap : 1; + uint32_t scene_use_reflection_cubemap : 1; + uint32_t scene_roughness_limiter_enabled : 1; + uint32_t padding : 5; + uint32_t soft_shadow_samples : 6; + uint32_t penumbra_shadow_samples : 6; }; uint32_t packed_0; }; union { - float luminance_multiplier; - float packed_1; + struct { + uint32_t directional_soft_shadow_samples : 6; + uint32_t directional_penumbra_shadow_samples : 6; + uint32_t omni_lights : 4; + uint32_t spot_lights : 4; + uint32_t reflection_probes : 4; + uint32_t directional_lights : 4; + uint32_t decals : 4; + }; + + uint32_t packed_1; }; - uint32_t packed_2; + union { + float luminance_multiplier; + float packed_2; + }; }; struct UbershaderConstants { @@ -232,7 +243,7 @@ public: } _FORCE_INLINE_ bool uses_shared_shadow_material() const { - return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && !uses_world_coordinates; + return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && !uses_world_coordinates && !wireframe; } virtual void set_code(const String &p_Code); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 979f590c4c..165168cb29 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -666,6 +666,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * light_count, &state.light_uniforms[0]); } + bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_to_render_target); + { //update canvas state uniform buffer State::Buffer state_buffer; @@ -684,7 +686,6 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p normal_transform.columns[2] = Vector2(); _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform); - bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_to_render_target); Color modulate = p_modulate; if (use_linear_colors) { modulate = p_modulate.srgb_to_linear(); @@ -722,6 +723,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p //print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale)); state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5); + state_buffer.flags = use_linear_colors ? CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0; + RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer); } @@ -752,8 +755,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RenderTarget to_render_target; to_render_target.render_target = p_to_render_target; - bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_to_render_target); - to_render_target.base_flags = use_linear_colors ? FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0; + to_render_target.use_linear_colors = use_linear_colors; while (ci) { if (ci->copy_back_buffer && canvas_group_owner == nullptr) { @@ -911,7 +913,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RenderingServerDefault::redraw_request(); } - state.current_data_buffer_index = (state.current_data_buffer_index + 1) % state.canvas_instance_data_buffers.size(); + state.current_data_buffer_index = (state.current_data_buffer_index + 1) % BATCH_DATA_BUFFER_COUNT; state.current_instance_buffer_index = 0; } @@ -993,36 +995,43 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, Vector<Color> cc; cc.push_back(Color(p_far, p_far, p_far, 1.0)); - for (int i = 0; i < 4; i++) { - //make sure it remains orthogonal, makes easy to read angle later + Projection projection; + { + real_t fov = 90; + real_t nearp = p_near; + real_t farp = p_far; + real_t aspect = 1.0; - //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); + real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5)); + real_t ymin = -ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; - Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); + } - Projection projection; - { - real_t fov = 90; - real_t nearp = p_near; - real_t farp = p_far; - real_t aspect = 1.0; + // Precomputed: + // Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); + // projection = projection * Projection(Transform3D().looking_at(cam_targets[i], Vector3(0, 0, -1)).affine_inverse()); + const Projection projections[4] = { + projection * Projection(Vector4(0, 0, -1, 0), Vector4(1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)), - real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5)); - real_t ymin = -ymax; - real_t xmin = ymin * aspect; - real_t xmax = ymax * aspect; + projection * Projection(Vector4(-1, 0, 0, 0), Vector4(0, 0, -1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)), - projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); - } + projection * Projection(Vector4(0, 0, 1, 0), Vector4(-1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)), + + projection * Projection(Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)) + + }; - Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); - projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); + for (int i = 0; i < 4; i++) { + Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { - push_constant.projection[y * 4 + x] = projection.columns[y][x]; + push_constant.projection[y * 4 + x] = projections[i].columns[y][x]; } } static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; @@ -1647,6 +1656,9 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { default_samplers.default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; } + // preallocate 5 slots for uniform set 3 + state.batch_texture_uniforms.resize(5); + { //shader variants String global_defines; @@ -1974,15 +1986,18 @@ void fragment() { } { + uint32_t cache_size = uint32_t(GLOBAL_GET("rendering/2d/batching/uniform_set_cache_size")); + rid_set_to_uniform_set.set_capacity(cache_size); + } + + { state.max_instances_per_buffer = uint32_t(GLOBAL_GET("rendering/2d/batching/item_buffer_size")); state.max_instance_buffer_size = state.max_instances_per_buffer * sizeof(InstanceData); - state.canvas_instance_data_buffers.resize(3); state.canvas_instance_batches.reserve(200); - for (int i = 0; i < 3; i++) { - DataBuffer db; + for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) { + DataBuffer &db = state.canvas_instance_data_buffers[i]; db.instance_buffers.push_back(RD::get_singleton()->storage_buffer_create(state.max_instance_buffer_size)); - state.canvas_instance_data_buffers[i] = db; } state.instance_data_array = memnew_arr(InstanceData, state.max_instances_per_buffer); } @@ -2159,7 +2174,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors, 1, 0, Rect2(), RDD::BreadcrumbMarker::UI_PASS); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, fb_uniform_set, BASE_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET); @@ -2203,14 +2218,47 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RD::get_singleton()->draw_list_end(); + texture_info_map.clear(); state.current_batch_index = 0; state.canvas_instance_batches.clear(); state.last_instance_index += instance_index; } +RendererCanvasRenderRD::InstanceData *RendererCanvasRenderRD::new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info) { + InstanceData *instance_data = &state.instance_data_array[p_index]; + // Zero out most fields. + for (int i = 0; i < 4; i++) { + instance_data->modulation[i] = 0.0; + instance_data->ninepatch_margins[i] = 0.0; + instance_data->src_rect[i] = 0.0; + instance_data->dst_rect[i] = 0.0; + } + + instance_data->pad[0] = 0.0; + instance_data->pad[1] = 0.0; + + instance_data->lights[0] = p_lights[0]; + instance_data->lights[1] = p_lights[1]; + instance_data->lights[2] = p_lights[2]; + instance_data->lights[3] = p_lights[3]; + + for (int i = 0; i < 6; i++) { + instance_data->world[i] = p_world[i]; + } + + instance_data->flags = p_base_flags; // Reset on each command for safety. + + instance_data->color_texture_pixel_size[0] = p_info->texpixel_size.width; + instance_data->color_texture_pixel_size[1] = p_info->texpixel_size.height; + + instance_data->pad1 = 0; + + return instance_data; +} + void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch) { - RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter; - RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat; + const RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter; + const RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat; Transform2D base_transform = p_base_transform; @@ -2219,8 +2267,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar _update_transform_2d_to_mat2x3(base_transform, world); Color base_color = p_item->final_modulate; - bool use_linear_colors = bool(p_render_target.base_flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR); - uint32_t base_flags = p_render_target.base_flags; + bool use_linear_colors = p_render_target.use_linear_colors; + uint32_t base_flags = 0; bool reclip = false; @@ -2230,6 +2278,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar uint32_t lights[4] = { 0, 0, 0, 0 }; uint16_t light_count = 0; + uint16_t shadow_mask = 0; { Light *light = p_lights; @@ -2239,16 +2288,21 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar uint32_t light_index = light->render_index_cache; lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + if (p_item->light_mask & light->item_shadow_mask) { + shadow_mask |= 1 << light_count; + } + light_count++; - if (light_count == state.max_lights_per_item - 1) { + if (light_count == MAX_LIGHTS_PER_ITEM - 1) { break; } } light = light->next_ptr; } - base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= light_count << INSTANCE_FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= shadow_mask << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT; } bool use_lighting = (light_count > 0 || using_directional_lights); @@ -2258,38 +2312,6 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->use_lighting = use_lighting; } - // new_instance_data should be called after the current_batch is set. - auto new_instance_data = [&]() -> InstanceData * { - InstanceData *instance_data = &state.instance_data_array[r_index]; - // Zero out most fields. - for (int i = 0; i < 4; i++) { - instance_data->modulation[i] = 0.0; - instance_data->ninepatch_margins[i] = 0.0; - instance_data->src_rect[i] = 0.0; - instance_data->dst_rect[i] = 0.0; - } - - instance_data->pad[0] = 0.0; - instance_data->pad[1] = 0.0; - - instance_data->lights[0] = lights[0]; - instance_data->lights[1] = lights[1]; - instance_data->lights[2] = lights[2]; - instance_data->lights[3] = lights[3]; - - for (int i = 0; i < 6; i++) { - instance_data->world[i] = world[i]; - } - - instance_data->flags = base_flags | r_current_batch->tex_info.flags; // Reset on each command for safety, keep canvas texture binding config. - - instance_data->color_texture_pixel_size[0] = r_current_batch->tex_info.texpixel_size.width; - instance_data->color_texture_pixel_size[1] = r_current_batch->tex_info.texpixel_size.height; - instance_data->specular_shininess = r_current_batch->tex_info.specular_shininess; - - return instance_data; - }; - const Item::Command *c = p_item->commands; while (c) { if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { @@ -2309,19 +2331,12 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar // default variant r_current_batch->shader_variant = SHADER_VARIANT_QUAD; r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + r_current_batch->flags = 0; } + RenderingServer::CanvasItemTextureRepeat rect_repeat = texture_repeat; if (bool(rect->flags & CANVAS_RECT_TILE)) { - texture_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; - } - - bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF); - TextureState tex_state(rect->texture, texture_filter, texture_repeat, has_msdf, use_linear_colors); - - if (tex_state != r_current_batch->tex_info.state) { - r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, rect->texture); + rect_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; } Color modulated = rect->modulate * base_color; @@ -2340,12 +2355,25 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; } - InstanceData *instance_data = new_instance_data(); + bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF); + TextureState tex_state(rect->texture, texture_filter, rect_repeat, has_msdf, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(rect->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Rect2 src_rect; Rect2 dst_rect; if (rect->texture.is_valid()) { - src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_info.texpixel_size, rect->source.size * r_current_batch->tex_info.texpixel_size) : Rect2(0, 0, 1, 1); + src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * tex_info->texpixel_size, rect->source.size * tex_info->texpixel_size) : Rect2(0, 0, 1, 1); dst_rect = Rect2(rect->rect.position, rect->rect.size); if (dst_rect.size.width < 0) { @@ -2359,20 +2387,18 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar if (rect->flags & CANVAS_RECT_FLIP_H) { src_rect.size.x *= -1; - instance_data->flags |= FLAGS_FLIP_H; } if (rect->flags & CANVAS_RECT_FLIP_V) { src_rect.size.y *= -1; - instance_data->flags |= FLAGS_FLIP_V; } if (rect->flags & CANVAS_RECT_TRANSPOSE) { - instance_data->flags |= FLAGS_TRANSPOSE_RECT; + instance_data->flags |= INSTANCE_FLAGS_TRANSPOSE_RECT; } if (rect->flags & CANVAS_RECT_CLIP_UV) { - instance_data->flags |= FLAGS_CLIP_RECT_UV; + instance_data->flags |= INSTANCE_FLAGS_CLIP_RECT_UV; } } else { @@ -2391,13 +2417,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar } if (has_msdf) { - instance_data->flags |= FLAGS_USE_MSDF; + instance_data->flags |= INSTANCE_FLAGS_USE_MSDF; instance_data->msdf[0] = rect->px_range; // Pixel range. instance_data->msdf[1] = rect->outline; // Outline size. instance_data->msdf[2] = 0.f; // Reserved. instance_data->msdf[3] = 0.f; // Reserved. } else if (rect->flags & CANVAS_RECT_LCD) { - instance_data->flags |= FLAGS_USE_LCD; + instance_data->flags |= INSTANCE_FLAGS_USE_LCD; } instance_data->modulation[0] = modulated.r; @@ -2428,16 +2454,22 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->has_blend = false; r_current_batch->shader_variant = SHADER_VARIANT_NINEPATCH; r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + r_current_batch->flags = 0; } TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_info.state) { + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(np->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, np->texture); + r_current_batch->tex_info = tex_info; } - InstanceData *instance_data = new_instance_data(); + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Rect2 src_rect; Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); @@ -2446,7 +2478,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar src_rect = Rect2(0, 0, 1, 1); } else { if (np->source != Rect2()) { - src_rect = Rect2(np->source.position.x * r_current_batch->tex_info.texpixel_size.width, np->source.position.y * r_current_batch->tex_info.texpixel_size.height, np->source.size.x * r_current_batch->tex_info.texpixel_size.width, np->source.size.y * r_current_batch->tex_info.texpixel_size.height); + src_rect = Rect2(np->source.position.x * tex_info->texpixel_size.width, np->source.position.y * tex_info->texpixel_size.height, np->source.size.x * tex_info->texpixel_size.width, np->source.size.y * tex_info->texpixel_size.height); instance_data->color_texture_pixel_size[0] = 1.0 / np->source.size.width; instance_data->color_texture_pixel_size[1] = 1.0 / np->source.size.height; } else { @@ -2474,11 +2506,11 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar instance_data->dst_rect[2] = dst_rect.size.width; instance_data->dst_rect[3] = dst_rect.size.height; - instance_data->flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT; - instance_data->flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT; + instance_data->flags |= int(np->axis_x) << INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT; + instance_data->flags |= int(np->axis_y) << INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT; if (np->draw_center) { - instance_data->flags |= FLAGS_NINEPACH_DRAW_CENTER; + instance_data->flags |= INSTANCE_FLAGS_NINEPACH_DRAW_CENTER; } instance_data->ninepatch_margins[0] = np->margin[SIDE_LEFT]; @@ -2498,12 +2530,18 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->command_type = Item::Command::TYPE_POLYGON; r_current_batch->has_blend = false; r_current_batch->command = c; + r_current_batch->flags = 0; TextureState tex_state(polygon->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_info.state) { + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(polygon->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, polygon->texture); + r_current_batch->tex_info = tex_info; } // pipeline variant @@ -2513,7 +2551,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = _primitive_type_to_render_primitive(polygon->primitive); } - InstanceData *instance_data = new_instance_data(); + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Color color = base_color; if (use_linear_colors) { @@ -2537,6 +2575,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->has_blend = false; r_current_batch->command = c; r_current_batch->primitive_points = primitive->point_count; + r_current_batch->flags = 0; ERR_CONTINUE(primitive->point_count == 0 || primitive->point_count > 4); @@ -2557,17 +2596,22 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar default: // Unknown point count. break; - }; - - TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_info.state) { - r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, primitive->texture); } } - InstanceData *instance_data = new_instance_data(); + TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(primitive->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) { instance_data->points[j * 2 + 0] = primitive->points[j].x; @@ -2585,7 +2629,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar _add_to_batch(r_index, r_batch_broken, r_current_batch); if (primitive->point_count == 4) { - instance_data = new_instance_data(); + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); for (uint32_t j = 0; j < 3; j++) { int offset = j == 0 ? 0 : 1; @@ -2594,7 +2638,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar instance_data->points[j * 2 + 1] = primitive->points[j + offset].y; instance_data->uvs[j * 2 + 0] = primitive->uvs[j + offset].x; instance_data->uvs[j * 2 + 1] = primitive->uvs[j + offset].y; - Color col = primitive->colors[j] * base_color; + Color col = primitive->colors[j + offset] * base_color; if (use_linear_colors) { col = col.srgb_to_linear(); } @@ -2614,6 +2658,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->command = c; r_current_batch->command_type = c->type; r_current_batch->has_blend = false; + r_current_batch->flags = 0; InstanceData *instance_data = nullptr; @@ -2621,9 +2666,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c); TextureState tex_state(m->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, m->texture); - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(m->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); r_current_batch->mesh_instance_count = 1; _update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, instance_data->world); @@ -2644,17 +2693,21 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar } TextureState tex_state(mm->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, mm->texture); - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(mm->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); - instance_data->flags |= 1; // multimesh, trails disabled + r_current_batch->flags |= 1; // multimesh, trails disabled if (mesh_storage->multimesh_uses_colors(mm->multimesh)) { - instance_data->flags |= FLAGS_INSTANCING_HAS_COLORS; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; } if (mesh_storage->multimesh_uses_custom_data(mm->multimesh)) { - instance_data->flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; } } else if (c->type == Item::Command::TYPE_PARTICLES) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); @@ -2662,20 +2715,23 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c); TextureState tex_state(pt->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, pt->texture); - - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(pt->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); uint32_t divisor = 1; r_current_batch->mesh_instance_count = particles_storage->particles_get_amount(pt->particles, divisor); - instance_data->flags |= (divisor & FLAGS_INSTANCING_MASK); + r_current_batch->flags |= (divisor & BATCH_FLAGS_INSTANCING_MASK); r_current_batch->mesh_instance_count /= divisor; RID particles = pt->particles; - instance_data->flags |= FLAGS_INSTANCING_HAS_COLORS; - instance_data->flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target.render_target)) { // Pass collision information. @@ -2747,36 +2803,139 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_batch_broken = false; } +#ifdef DEBUG_ENABLED + if (debug_redraw && p_item->debug_redraw_time > 0.0) { + Color dc = debug_redraw_color; + dc.a *= p_item->debug_redraw_time / debug_redraw_time; + + // 1: If commands are different, start a new batch. + if (r_current_batch->command_type != Item::Command::TYPE_RECT) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->command_type = Item::Command::TYPE_RECT; + // it is ok to be null for a TYPE_RECT + r_current_batch->command = nullptr; + // default variant + r_current_batch->shader_variant = SHADER_VARIANT_QUAD; + r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + r_current_batch->flags = 0; + } + + // 2: If the current batch has lighting, start a new batch. + if (r_current_batch->use_lighting) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->use_lighting = false; + } + + // 3: If the current batch has blend, start a new batch. + if (r_current_batch->has_blend) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->has_blend = false; + } + + TextureState tex_state(default_canvas_texture, texture_filter, texture_repeat, false, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(default_canvas_texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); + + Rect2 src_rect; + Rect2 dst_rect; + + dst_rect = Rect2(Vector2(), p_item->rect.size); + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + src_rect = Rect2(0, 0, 1, 1); + + instance_data->modulation[0] = dc.r; + instance_data->modulation[1] = dc.g; + instance_data->modulation[2] = dc.b; + instance_data->modulation[3] = dc.a; + + instance_data->src_rect[0] = src_rect.position.x; + instance_data->src_rect[1] = src_rect.position.y; + instance_data->src_rect[2] = src_rect.size.width; + instance_data->src_rect[3] = src_rect.size.height; + + instance_data->dst_rect[0] = dst_rect.position.x; + instance_data->dst_rect[1] = dst_rect.position.y; + instance_data->dst_rect[2] = dst_rect.size.width; + instance_data->dst_rect[3] = dst_rect.size.height; + + _add_to_batch(r_index, r_batch_broken, r_current_batch); + + p_item->debug_redraw_time -= RSG::rasterizer->get_frame_delta_time(); + + RenderingServerDefault::redraw_request(); + + r_batch_broken = false; + } +#endif + if (r_current_clip && reclip) { // will make it re-enable clipping if needed afterwards r_current_clip = nullptr; } } -void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) { - UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); - ERR_FAIL_NULL(uniform_set_cache); +void RendererCanvasRenderRD::_before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid) { + RD::get_singleton()->uniform_set_set_invalidation_callback(p_rid, nullptr, nullptr); + RD::get_singleton()->free(p_rid); +} - ERR_FAIL_NULL(p_batch->command); +void RendererCanvasRenderRD::_uniform_set_invalidation_callback(void *p_userdata) { + const RIDSetKey *key = static_cast<RIDSetKey *>(p_userdata); + static_cast<RendererCanvasRenderRD *>(singleton)->rid_set_to_uniform_set.erase(*key); +} +void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) { { - RD::Uniform u_diffuse(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info.diffuse); - RD::Uniform u_normal(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info.normal); - RD::Uniform u_specular(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info.specular); - RD::Uniform u_sampler(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info.sampler); - RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); - - RID uniform_set = uniform_set_cache->get_cache(shader.default_version_rd_shader, BATCH_UNIFORM_SET, u_diffuse, u_normal, u_specular, u_sampler, u_instance_data); + RIDSetKey key( + p_batch->tex_info->state, + state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); + + const RID *uniform_set = rid_set_to_uniform_set.getptr(key); + if (uniform_set == nullptr) { + state.batch_texture_uniforms.write[0] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info->diffuse); + state.batch_texture_uniforms.write[1] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info->normal); + state.batch_texture_uniforms.write[2] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info->specular); + state.batch_texture_uniforms.write[3] = RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info->sampler); + state.batch_texture_uniforms.write[4] = RD::Uniform(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); + + RID rid = RD::get_singleton()->uniform_set_create(state.batch_texture_uniforms, shader.default_version_rd_shader, BATCH_UNIFORM_SET); + ERR_FAIL_COND_MSG(rid.is_null(), "Failed to create uniform set for batch."); + + const RIDCache::Pair *iter = rid_set_to_uniform_set.insert(key, rid); + uniform_set = &iter->data; + RD::get_singleton()->uniform_set_set_invalidation_callback(rid, RendererCanvasRenderRD::_uniform_set_invalidation_callback, (void *)&iter->key); + } - if (state.current_batch_uniform_set != uniform_set) { - state.current_batch_uniform_set = uniform_set; - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, BATCH_UNIFORM_SET); + if (state.current_batch_uniform_set != *uniform_set) { + state.current_batch_uniform_set = *uniform_set; + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, *uniform_set, BATCH_UNIFORM_SET); } } + PushConstant push_constant; + push_constant.base_instance_index = p_batch->start; + push_constant.specular_shininess = p_batch->tex_info->specular_shininess; + push_constant.batch_flags = p_batch->tex_info->flags | p_batch->flags; RID pipeline; PipelineKey pipeline_key; - PushConstant push_constant; pipeline_key.framebuffer_format_id = p_framebuffer_format; pipeline_key.variant = p_batch->shader_variant; pipeline_key.render_primitive = p_batch->render_primitive; @@ -2792,7 +2951,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, p_batch->modulate); } - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); RD::get_singleton()->draw_list_draw(p_draw_list, true, p_batch->instance_count); @@ -2805,6 +2963,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha } break; case Item::Command::TYPE_POLYGON: { + ERR_FAIL_NULL(p_batch->command); + const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(p_batch->command); PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id); @@ -2814,7 +2974,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array); if (pb->indices.is_valid()) { @@ -2830,12 +2989,13 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha } break; case Item::Command::TYPE_PRIMITIVE: { + ERR_FAIL_NULL(p_batch->command); + const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(p_batch->command); pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]); uint32_t instance_count = p_batch->instance_count; @@ -2852,6 +3012,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha case Item::Command::TYPE_MESH: case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { + ERR_FAIL_NULL(p_batch->command); + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); @@ -2912,7 +3074,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant, mesh_instance, surface, j, &vertex_array); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0); @@ -2994,7 +3155,7 @@ void RendererCanvasRenderRD::_allocate_instance_buffer() { state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(buf); } -void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const { +void RendererCanvasRenderRD::_prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info) { if (p_texture.is_null()) { p_texture = default_canvas_texture; } @@ -3002,38 +3163,38 @@ void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RendererRD::TextureStorage::CanvasTextureInfo info = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info( p_texture, - p_current_batch->tex_info.state.texture_filter(), - p_current_batch->tex_info.state.texture_repeat(), - p_current_batch->tex_info.state.linear_colors(), - p_current_batch->tex_info.state.texture_is_data()); - + p_state.texture_filter(), + p_state.texture_repeat(), + p_state.linear_colors(), + p_state.texture_is_data()); // something odd happened if (info.is_null()) { - _prepare_batch_texture_info(p_current_batch, default_canvas_texture); + _prepare_batch_texture_info(default_canvas_texture, p_state, p_info); return; } - p_current_batch->tex_info.diffuse = info.diffuse; - p_current_batch->tex_info.normal = info.normal; - p_current_batch->tex_info.specular = info.specular; - p_current_batch->tex_info.sampler = info.sampler; + p_info->state = p_state; + p_info->diffuse = info.diffuse; + p_info->normal = info.normal; + p_info->specular = info.specular; + p_info->sampler = info.sampler; // cache values to be copied to instance data if (info.specular_color.a < 0.999) { - p_current_batch->tex_info.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + p_info->flags |= BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED; } if (info.use_normal) { - p_current_batch->tex_info.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + p_info->flags |= BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED; } uint8_t a = uint8_t(CLAMP(info.specular_color.a * 255.0, 0.0, 255.0)); uint8_t b = uint8_t(CLAMP(info.specular_color.b * 255.0, 0.0, 255.0)); uint8_t g = uint8_t(CLAMP(info.specular_color.g * 255.0, 0.0, 255.0)); uint8_t r = uint8_t(CLAMP(info.specular_color.r * 255.0, 0.0, 255.0)); - p_current_batch->tex_info.specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r); + p_info->specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r); - p_current_batch->tex_info.texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height)); + p_info->texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height)); } RendererCanvasRenderRD::~RendererCanvasRenderRD() { @@ -3075,7 +3236,7 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { RD::get_singleton()->free(state.shadow_texture); memdelete_arr(state.instance_data_array); - for (uint32_t i = 0; i < state.canvas_instance_data_buffers.size(); i++) { + for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) { for (uint32_t j = 0; j < state.canvas_instance_data_buffers[i].instance_buffers.size(); j++) { RD::get_singleton()->free(state.canvas_instance_data_buffers[i].instance_buffers[j]); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 07445b5c53..e4f1779b09 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -31,6 +31,7 @@ #ifndef RENDERER_CANVAS_RENDER_RD_H #define RENDERER_CANVAS_RENDER_RD_H +#include "core/templates/lru.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" @@ -50,6 +51,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { }; const int SAMPLERS_BINDING_FIRST_INDEX = 10; + // The size of the ring buffer to store GPU buffers. Triple-buffering the max expected frames in flight. + static const uint32_t BATCH_DATA_BUFFER_COUNT = 3; enum ShaderVariant { SHADER_VARIANT_QUAD, @@ -62,31 +65,31 @@ class RendererCanvasRenderRD : public RendererCanvasRender { }; enum { + INSTANCE_FLAGS_LIGHT_COUNT_SHIFT = 0, // 4 bits for light count. - FLAGS_INSTANCING_MASK = 0x7F, - FLAGS_INSTANCING_HAS_COLORS = (1 << 7), - FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), + INSTANCE_FLAGS_CLIP_RECT_UV = (1 << 4), + INSTANCE_FLAGS_TRANSPOSE_RECT = (1 << 5), + INSTANCE_FLAGS_USE_MSDF = (1 << 6), + INSTANCE_FLAGS_USE_LCD = (1 << 7), - FLAGS_CLIP_RECT_UV = (1 << 9), - FLAGS_TRANSPOSE_RECT = (1 << 10), + INSTANCE_FLAGS_NINEPACH_DRAW_CENTER = (1 << 8), + INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT = 9, + INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT = 11, - FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 11), - - FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), - - FLAGS_USE_SKELETON = (1 << 15), - FLAGS_NINEPATCH_H_MODE_SHIFT = 16, - FLAGS_NINEPATCH_V_MODE_SHIFT = 18, - FLAGS_LIGHT_COUNT_SHIFT = 20, + INSTANCE_FLAGS_SHADOW_MASKED_SHIFT = 13, // 16 bits. + }; - FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 24), - FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 25), + enum { + BATCH_FLAGS_INSTANCING_MASK = 0x7F, + BATCH_FLAGS_INSTANCING_HAS_COLORS = (1 << 7), + BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), - FLAGS_USE_MSDF = (1 << 26), - FLAGS_USE_LCD = (1 << 27), + BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 9), + BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 10), + }; - FLAGS_FLIP_H = (1 << 28), - FLAGS_FLIP_V = (1 << 29), + enum { + CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 0), }; enum { @@ -339,7 +342,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct InstanceData { float world[6]; uint32_t flags; - uint32_t specular_shininess; + uint32_t pad1; union { //rect struct { @@ -366,8 +369,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct PushConstant { uint32_t base_instance_index; ShaderSpecialization shader_specialization; - uint32_t pad2; - uint32_t pad3; + uint32_t specular_shininess; + uint32_t batch_flags; }; // TextureState is used to determine when a new batch is required due to a change of texture state. @@ -398,50 +401,91 @@ class RendererCanvasRenderRD : public RendererCanvasRender { (((uint32_t)p_use_linear_colors & LINEAR_COLORS_MASK) << LINEAR_COLORS_SHIFT); } - _FORCE_INLINE_ RS::CanvasItemTextureFilter texture_filter() const { + _ALWAYS_INLINE_ RS::CanvasItemTextureFilter texture_filter() const { return (RS::CanvasItemTextureFilter)((other >> FILTER_SHIFT) & FILTER_MASK); } - _FORCE_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const { + _ALWAYS_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const { return (RS::CanvasItemTextureRepeat)((other >> REPEAT_SHIFT) & REPEAT_MASK); } - _FORCE_INLINE_ bool linear_colors() const { + _ALWAYS_INLINE_ bool linear_colors() const { return (other >> LINEAR_COLORS_SHIFT) & LINEAR_COLORS_MASK; } - _FORCE_INLINE_ bool texture_is_data() const { + _ALWAYS_INLINE_ bool texture_is_data() const { return (other >> TEXTURE_IS_DATA_SHIFT) & TEXTURE_IS_DATA_MASK; } - bool operator==(const TextureState &p_val) const { + _ALWAYS_INLINE_ bool operator==(const TextureState &p_val) const { return (texture == p_val.texture) && (other == p_val.other); } - bool operator!=(const TextureState &p_val) const { + _ALWAYS_INLINE_ bool operator!=(const TextureState &p_val) const { return (texture != p_val.texture) || (other != p_val.other); } + + _ALWAYS_INLINE_ bool is_valid() const { return texture.is_valid(); } + _ALWAYS_INLINE_ bool is_null() const { return texture.is_null(); } + + uint32_t hash() const { + uint32_t hash = hash_murmur3_one_64(texture.get_id()); + return hash_murmur3_one_32(other, hash); + } }; struct TextureInfo { TextureState state; - uint32_t specular_shininess = 0; - uint32_t flags = 0; - Vector2 texpixel_size; - RID diffuse; RID normal; RID specular; RID sampler; + Vector2 texpixel_size; + uint32_t specular_shininess = 0; + uint32_t flags = 0; }; + /// A key used to uniquely identify a distinct BATCH_UNIFORM_SET + struct RIDSetKey { + TextureState state; + RID instance_data; + + RIDSetKey() { + } + + RIDSetKey(TextureState p_state, RID p_instance_data) : + state(p_state), + instance_data(p_instance_data) { + } + + _ALWAYS_INLINE_ bool operator==(const RIDSetKey &p_val) const { + return state == p_val.state && instance_data == p_val.instance_data; + } + + _ALWAYS_INLINE_ bool operator!=(const RIDSetKey &p_val) const { + return !(*this == p_val); + } + + _ALWAYS_INLINE_ uint32_t hash() const { + uint32_t h = state.hash(); + h = hash_murmur3_one_64(instance_data.get_id(), h); + return hash_fmix32(h); + } + }; + + static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid); + static void _uniform_set_invalidation_callback(void *p_userdata); + + typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache; + RIDCache rid_set_to_uniform_set; + struct Batch { // Position in the UBO measured in bytes uint32_t start = 0; uint32_t instance_count = 0; uint32_t instance_buffer_index = 0; - TextureInfo tex_info; + TextureInfo *tex_info; Color modulate = Color(1.0, 1.0, 1.0, 1.0); @@ -464,8 +508,12 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t mesh_instance_count; }; bool has_blend = false; + uint32_t flags = 0; }; + HashMap<TextureState, TextureInfo, HashableHasher<TextureState>> texture_info_map; + + // per-frame buffers struct DataBuffer { LocalVector<RID> instance_buffers; }; @@ -488,11 +536,11 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t directional_light_count; float tex_to_sdf; - uint32_t pad1; + uint32_t flags; uint32_t pad2; }; - LocalVector<DataBuffer> canvas_instance_data_buffers; + DataBuffer canvas_instance_data_buffers[BATCH_DATA_BUFFER_COUNT]; LocalVector<Batch> canvas_instance_batches; uint32_t current_data_buffer_index = 0; uint32_t current_instance_buffer_index = 0; @@ -503,6 +551,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t max_instances_per_buffer = 16384; uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData); + Vector<RD::Uniform> batch_texture_uniforms; RID current_batch_uniform_set; LightUniform *light_uniforms = nullptr; @@ -518,7 +567,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { RID default_transforms_uniform_set; uint32_t max_lights_per_render; - uint32_t max_lights_per_item; double time; @@ -549,16 +597,15 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct RenderTarget { // Current render target for the canvas. RID render_target; - // The base flags for each InstanceData, derived from the render target. - // Either FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR or 0 - uint32_t base_flags = 0; + bool use_linear_colors = false; }; inline RID _get_pipeline_specialization_or_ubershader(CanvasShaderData *p_shader_data, PipelineKey &r_pipeline_key, PushConstant &r_push_constant, RID p_mesh_instance = RID(), void *p_surface = nullptr, uint32_t p_surface_index = 0, RID *r_vertex_array = nullptr); void _render_batch_items(RenderTarget p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr); void _record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch); void _render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const; + void _prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info); + InstanceData *new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info); [[nodiscard]] Batch *_new_batch(bool &r_batch_broken); void _add_to_batch(uint32_t &r_index, bool &r_batch_broken, Batch *&r_current_batch); void _allocate_instance_buffer(); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 84ea6a5da2..ba47508700 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -66,6 +66,16 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0); + // We need to invert the phone rotation. + const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(p_screen); + float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees); + + blit.push_constant.rotation_cos = Math::cos(screen_rotation); + blit.push_constant.rotation_sin = Math::sin(screen_rotation); + // Swap width and height when the orientation is not the native one. + if (screen_rotation_degrees % 180 != 0) { + SWAP(screen_size.width, screen_size.height); + } blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x; blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y; blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width; @@ -228,6 +238,10 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0); + const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(DisplayServer::MAIN_WINDOW_ID); + float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees); + blit.push_constant.rotation_cos = Math::cos(screen_rotation); + blit.push_constant.rotation_sin = Math::sin(screen_rotation); blit.push_constant.src_rect[0] = 0.0; blit.push_constant.src_rect[1] = 0.0; blit.push_constant.src_rect[2] = 1.0; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index dcd3e90e1b..6821fa737e 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -31,6 +31,7 @@ #ifndef RENDERER_COMPOSITOR_RD_H #define RENDERER_COMPOSITOR_RD_H +#include "core/io/image.h" #include "core/os/os.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/environment/fog.h" @@ -73,6 +74,10 @@ protected: float src_rect[4]; float dst_rect[4]; + float rotation_sin; + float rotation_cos; + float pad[2]; + float eye_center[2]; float k1; float k2; @@ -102,7 +107,7 @@ protected: static RendererCompositorRD *singleton; public: - RendererUtilities *get_utilities() { return utilities; }; + RendererUtilities *get_utilities() { return utilities; } RendererLightStorage *get_light_storage() { return light_storage; } RendererMaterialStorage *get_material_storage() { return material_storage; } RendererMeshStorage *get_mesh_storage() { return mesh_storage; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 0c21fec282..4417f6832c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -31,6 +31,7 @@ #include "renderer_scene_render_rd.h" #include "core/config/project_settings.h" +#include "core/io/image.h" #include "core/os/os.h" #include "renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/environment/fog.h" @@ -1129,6 +1130,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render scene_data.cam_transform = p_camera_data->main_transform; scene_data.cam_projection = p_camera_data->main_projection; scene_data.cam_orthogonal = p_camera_data->is_orthogonal; + scene_data.cam_frustum = p_camera_data->is_frustum; scene_data.camera_visible_layers = p_camera_data->visible_layers; scene_data.taa_jitter = p_camera_data->taa_jitter; scene_data.taa_frame_count = p_camera_data->taa_frame_count; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index b82d50378e..631ad21247 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -78,7 +78,7 @@ protected: //////////////////////////////// - virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); }; + virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); } void _update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers); diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl index d451647bec..fe6416f03c 100644 --- a/servers/rendering/renderer_rd/shaders/blit.glsl +++ b/servers/rendering/renderer_rd/shaders/blit.glsl @@ -8,6 +8,10 @@ layout(push_constant, std140) uniform Pos { vec4 src_rect; vec4 dst_rect; + float rotation_sin; + float rotation_cos; + vec2 pad; + vec2 eye_center; float k1; float k2; @@ -15,17 +19,23 @@ layout(push_constant, std140) uniform Pos { float upscale; float aspect_ratio; uint layer; - uint pad1; + bool convert_to_srgb; } data; layout(location = 0) out vec2 uv; void main() { + mat4 swapchain_transform = mat4(1.0); + swapchain_transform[0][0] = data.rotation_cos; + swapchain_transform[0][1] = -data.rotation_sin; + swapchain_transform[1][0] = data.rotation_sin; + swapchain_transform[1][1] = data.rotation_cos; + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw; vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw; - gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0); + gl_Position = swapchain_transform * vec4(vtx * 2.0 - 1.0, 0.0, 1.0); } #[fragment] @@ -38,6 +48,10 @@ layout(push_constant, std140) uniform Pos { vec4 src_rect; vec4 dst_rect; + float rotation_sin; + float rotation_cos; + vec2 pad; + vec2 eye_center; float k1; float k2; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index dafcce37ad..b66aa71f6b 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -28,7 +28,7 @@ layout(location = 11) in vec4 weight_attrib; layout(location = 4) out flat uint instance_index_interp; -#endif // USE_ATTRIBUTES +#endif // !USE_ATTRIBUTES layout(location = 0) out vec2 uv_interp; layout(location = 1) out vec4 color_interp; @@ -101,7 +101,7 @@ void main() { vec2 vertex = vertex_attrib; vec4 color = color_attrib; - if (bool(draw_data.flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) { + if (bool(canvas_data.flags & CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) { color.rgb = srgb_to_linear(color.rgb); } color *= draw_data.modulation; @@ -122,7 +122,7 @@ void main() { vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); vec2 vertex_base = vertex_base_arr[gl_VertexIndex]; - vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy); + vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & INSTANCE_FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy); vec4 color = draw_data.modulation; vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0))); uvec4 bones = uvec4(0, 0, 0, 0); @@ -133,7 +133,7 @@ void main() { #ifdef USE_ATTRIBUTES - uint instancing = draw_data.flags & FLAGS_INSTANCING_MASK; + uint instancing = params.batch_flags & BATCH_FLAGS_INSTANCING_MASK; if (instancing > 1) { // trails @@ -172,19 +172,19 @@ void main() { vertex = new_vertex; color *= pcolor; } else if (instancing == 1) { - uint stride = 2 + bitfieldExtract(draw_data.flags, FLAGS_INSTANCING_HAS_COLORS_SHIFT, 1) + bitfieldExtract(draw_data.flags, FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT, 1); + uint stride = 2 + bitfieldExtract(params.batch_flags, BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT, 1) + bitfieldExtract(params.batch_flags, BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT, 1); uint offset = stride * gl_InstanceIndex; mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); offset += 2; - if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) { + if (bool(params.batch_flags & BATCH_FLAGS_INSTANCING_HAS_COLORS)) { color *= transforms.data[offset]; offset += 1; } - if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { + if (bool(params.batch_flags & BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { instance_custom = transforms.data[offset]; } @@ -322,11 +322,7 @@ vec4 light_compute( #ifdef USE_NINEPATCH float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) { -#ifdef USE_ATTRIBUTES - const InstanceData draw_data = instances.data[params.base_instance_index]; -#else const InstanceData draw_data = instances.data[instance_index]; -#endif // USE_ATTRIBUTES float tex_size = 1.0 / tex_pixel_size; @@ -335,7 +331,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo } else if (pixel >= draw_size - margin_end) { return (tex_size - (draw_size - pixel)) * tex_pixel_size; } else { - draw_center -= 1 - int(bitfieldExtract(draw_data.flags, FLAGS_NINEPACH_DRAW_CENTER_SHIFT, 1)); + draw_center -= 1 - int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER_SHIFT, 1)); // np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum. if (np_repeat == 0) { // Stretch. @@ -476,8 +472,8 @@ void main() { int draw_center = 2; uv = vec2( - map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(bitfieldExtract(draw_data.flags, FLAGS_NINEPATCH_H_MODE_SHIFT, 2)), draw_center), - map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(bitfieldExtract(draw_data.flags, FLAGS_NINEPATCH_V_MODE_SHIFT, 2)), draw_center)); + map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT, 2)), draw_center), + map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT, 2)), draw_center)); if (draw_center == 0) { color.a = 0.0; @@ -486,7 +482,7 @@ void main() { uv = uv * draw_data.src_rect.zw + draw_data.src_rect.xy; //apply region if needed #endif - if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) { + if (bool(draw_data.flags & INSTANCE_FLAGS_CLIP_RECT_UV)) { vec2 half_texpixel = draw_data.color_texture_pixel_size * 0.5; uv = clamp(uv, draw_data.src_rect.xy + half_texpixel, draw_data.src_rect.xy + abs(draw_data.src_rect.zw) - half_texpixel); } @@ -494,7 +490,7 @@ void main() { #endif #ifndef USE_PRIMITIVE - if (bool(draw_data.flags & FLAGS_USE_MSDF)) { + if (bool(draw_data.flags & INSTANCE_FLAGS_USE_MSDF)) { float px_range = draw_data.ninepatch_margins.x; float outline_thickness = draw_data.ninepatch_margins.y; //float reserved1 = draw_data.ninepatch_margins.z; @@ -514,7 +510,7 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - } else if (bool(draw_data.flags & FLAGS_USE_LCD)) { + } else if (bool(draw_data.flags & INSTANCE_FLAGS_USE_LCD)) { vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv); if (lcd_sample.a == 1.0) { color.rgb = lcd_sample.rgb * color.a; @@ -528,7 +524,7 @@ void main() { color *= texture(sampler2D(color_texture, texture_sampler), uv); } - uint light_count = bitfieldExtract(draw_data.flags, FLAGS_LIGHT_COUNT_SHIFT, 4); //max 15 lights + uint light_count = draw_data.flags & 15u; //max 15 lights bool using_light = (light_count + canvas_data.directional_light_count) > 0; vec3 normal; @@ -539,17 +535,15 @@ void main() { bool normal_used = false; #endif - if (normal_used || (using_light && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { + if (normal_used || (using_light && bool(params.batch_flags & BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED))) { normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); - if (bool(draw_data.flags & FLAGS_TRANSPOSE_RECT)) { + +#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) + if (bool(draw_data.flags & INSTANCE_FLAGS_TRANSPOSE_RECT)) { normal.xy = normal.yx; } - if (bool(draw_data.flags & FLAGS_FLIP_H)) { - normal.x = -normal.x; - } - if (bool(draw_data.flags & FLAGS_FLIP_V)) { - normal.y = -normal.y; - } + normal.xy *= sign(draw_data.src_rect.zw); +#endif normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy))); normal_used = true; } else { @@ -565,9 +559,9 @@ void main() { bool specular_shininess_used = false; #endif - if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { + if (specular_shininess_used || (using_light && normal_used && bool(params.batch_flags & BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv); - specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess); + specular_shininess *= unpackUnorm4x8(params.specular_shininess); specular_shininess_used = true; } else { specular_shininess = vec4(1.0); @@ -636,7 +630,7 @@ void main() { } #endif - if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(draw_data.flags & (INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec4 shadow_uv = vec4(shadow_pos.x, light_array.data[light_base].shadow_y_ofs, shadow_pos.y * light_array.data[light_base].shadow_zfar_inv, 1.0); @@ -696,7 +690,7 @@ void main() { } #endif - if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(draw_data.flags & (INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec2 pos_norm = normalize(shadow_pos); diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index ead8c459a4..da582ec1b4 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -1,43 +1,29 @@ - #define MAX_LIGHTS_PER_ITEM 16 #define M_PI 3.14159265359 #define SDF_MAX_LENGTH 16384.0 -//1 means enabled, 2+ means trails in use -#define FLAGS_INSTANCING_MASK 0x7F -#define FLAGS_INSTANCING_HAS_COLORS_SHIFT 7 -#define FLAGS_INSTANCING_HAS_COLORS (1 << FLAGS_INSTANCING_HAS_COLORS_SHIFT) -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8 -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT) - -#define FLAGS_CLIP_RECT_UV (1 << 9) -#define FLAGS_TRANSPOSE_RECT (1 << 10) -#define FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 11) -#define FLAGS_NINEPACH_DRAW_CENTER_SHIFT 12 -#define FLAGS_NINEPACH_DRAW_CENTER (1 << FLAGS_NINEPACH_DRAW_CENTER_SHIFT) - -#define FLAGS_NINEPATCH_H_MODE_SHIFT 16 -#define FLAGS_NINEPATCH_V_MODE_SHIFT 18 +#define INSTANCE_FLAGS_LIGHT_COUNT_SHIFT 0 // 4 bits. -#define FLAGS_LIGHT_COUNT_SHIFT 20 +#define INSTANCE_FLAGS_CLIP_RECT_UV (1 << 4) +#define INSTANCE_FLAGS_TRANSPOSE_RECT (1 << 5) +#define INSTANCE_FLAGS_USE_MSDF (1 << 6) +#define INSTANCE_FLAGS_USE_LCD (1 << 7) -#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 24) -#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 25) +#define INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER_SHIFT 8 +#define INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT 9 +#define INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT 11 -#define FLAGS_USE_MSDF (1 << 26) -#define FLAGS_USE_LCD (1 << 27) - -#define FLAGS_FLIP_H (1 << 28) -#define FLAGS_FLIP_V (1 << 29) +#define INSTANCE_FLAGS_SHADOW_MASKED_SHIFT 13 // 16 bits. +#define INSTANCE_FLAGS_SHADOW_MASKED (1 << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT) struct InstanceData { vec2 world_x; vec2 world_y; vec2 world_ofs; uint flags; - uint specular_shininess; + uint pad2; #ifdef USE_PRIMITIVE vec2 points[3]; vec2 uvs[3]; @@ -54,11 +40,21 @@ struct InstanceData { uint lights[4]; }; +//1 means enabled, 2+ means trails in use +#define BATCH_FLAGS_INSTANCING_MASK 0x7F +#define BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT 7 +#define BATCH_FLAGS_INSTANCING_HAS_COLORS (1 << BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT) +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8 +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT) + +#define BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 9) +#define BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 10) + layout(push_constant, std430) uniform Params { uint base_instance_index; // base index to instance data uint sc_packed_0; - uint pad2; - uint pad3; + uint specular_shininess; + uint batch_flags; } params; @@ -68,7 +64,7 @@ params; // Pull the constants from the draw call's push constants. uint sc_packed_0() { - return draw_call.sc_packed_0; + return params.sc_packed_0; } #else @@ -94,6 +90,8 @@ bool sc_use_lighting() { /* SET0: Globals */ +#define CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 0) + // The values passed per draw primitives are cached within it layout(set = 0, binding = 1, std140) uniform CanvasData { @@ -111,7 +109,7 @@ layout(set = 0, binding = 1, std140) uniform CanvasData { uint directional_light_count; float tex_to_sdf; - uint pad1; + uint flags; uint pad2; } canvas_data; diff --git a/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl b/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl index 158096d3c7..3d6eaab8e1 100644 --- a/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl @@ -1,4 +1,3 @@ - struct DecalData { highp mat4 xform; //to decal transform highp vec3 inv_extents; diff --git a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl index 3fb93dda35..b45e310b61 100644 --- a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl @@ -8,7 +8,6 @@ layout(push_constant, std430) uniform Params { float z_far; float z_near; vec2 texel_size; - vec4 screen_rect; } params; @@ -17,8 +16,7 @@ layout(location = 0) out vec2 uv_interp; void main() { vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); uv_interp = base_arr[gl_VertexIndex]; - vec2 screen_pos = uv_interp * params.screen_rect.zw + params.screen_rect.xy; - gl_Position = vec4(screen_pos * 2.0 - 1.0, 0.0, 1.0); + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); } #[fragment] @@ -35,7 +33,6 @@ layout(push_constant, std430) uniform Params { float z_far; float z_near; vec2 texel_size; - vec4 screen_rect; } params; diff --git a/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl index b8860f6518..fc45b1f827 100644 --- a/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl @@ -1,4 +1,3 @@ - layout(push_constant, std430) uniform PushConstant { ivec2 source_size; ivec2 dest_size; diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index cc1c40cad1..7bb2e0a539 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -189,7 +189,7 @@ void main() { vec3 cube_normal; #ifdef USE_MULTIVIEW // In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject. - vec4 unproject = vec4(uv_interp.x, -uv_interp.y, 0.0, 1.0); // unproject at the far plane + vec4 unproject = vec4(uv_interp.x, uv_interp.y, 0.0, 1.0); // unproject at the far plane vec4 unprojected = sky_scene_data.view_inv_projections[ViewIndex] * unproject; cube_normal = unprojected.xyz / unprojected.w; @@ -198,7 +198,7 @@ void main() { #else cube_normal.z = -1.0; cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projection.x)) / params.projection.y; - cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projection.z)) / params.projection.w; + cube_normal.y = -(cube_normal.z * (uv_interp.y - params.projection.z)) / params.projection.w; #endif cube_normal = mat3(params.orientation) * cube_normal; cube_normal = normalize(cube_normal); diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl index a797891ab6..90bbdfe685 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl @@ -513,6 +513,7 @@ void main() { shadow_sample.z = 1.0 + abs(shadow_sample.z); vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - omni_lights.data[light_index].shadow_bias); pos.z *= omni_lights.data[light_index].inv_radius; + pos.z = 1.0 - pos.z; pos.xy = pos.xy * 0.5 + 0.5; pos.xy = uv_rect.xy + pos.xy * uv_rect.zw; diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 72236dcd9f..1e1b6d8937 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -211,6 +211,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec } #endif +uint multimesh_stride() { + uint stride = sc_multimesh_format_2d() ? 2 : 3; + stride += sc_multimesh_has_color() ? 1 : 0; + stride += sc_multimesh_has_custom_data() ? 1 : 0; + return stride; +} + void vertex_shader(vec3 vertex_input, #ifdef NORMAL_USED in vec3 normal_input, @@ -219,7 +226,7 @@ void vertex_shader(vec3 vertex_input, in vec3 tangent_input, in vec3 binormal_input, #endif - in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) { + in uint instance_index, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) { vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) color_interp = color_attrib; @@ -248,7 +255,7 @@ void vertex_shader(vec3 vertex_input, mat4 matrix; mat4 read_model_matrix = model_matrix; - if (is_multimesh) { + if (sc_multimesh()) { //multimesh, instances are for it #ifdef USE_PARTICLE_TRAILS @@ -296,25 +303,10 @@ void vertex_shader(vec3 vertex_input, #endif #else - uint stride = 0; - { - //TODO implement a small lookup table for the stride - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { - stride += 2; - } else { - stride += 3; - } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { - stride += 1; - } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { - stride += 1; - } - } - + uint stride = multimesh_stride(); uint offset = stride * (gl_InstanceIndex + multimesh_offset); - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { + if (sc_multimesh_format_2d()) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); offset += 2; } else { @@ -322,14 +314,14 @@ void vertex_shader(vec3 vertex_input, offset += 3; } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { + if (sc_multimesh_has_color()) { #ifdef COLOR_USED color_interp *= transforms.data[offset]; #endif offset += 1; } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { + if (sc_multimesh_has_custom_data()) { instance_custom = transforms.data[offset]; } @@ -427,7 +419,7 @@ void vertex_shader(vec3 vertex_input, // Then we combine the translations from the model matrix and the view matrix using emulated doubles. // We add the result to the vertex and ignore the final lost precision. vec3 model_origin = model_matrix[3].xyz; - if (is_multimesh) { + if (sc_multimesh()) { vertex = mat3(matrix) * vertex; model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision); } @@ -708,9 +700,7 @@ void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position void main() { uint instance_index = draw_call.instance_index; - - bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH); - if (!is_multimesh) { + if (!sc_multimesh()) { instance_index += gl_InstanceIndex; } @@ -753,7 +743,7 @@ void main() { prev_tangent, prev_binormal, #endif - instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position); + instance_index, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position); #else // Unused output. vec4 screen_position; @@ -792,7 +782,7 @@ void main() { tangent, binormal, #endif - instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position); + instance_index, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position); } #[fragment] @@ -2309,7 +2299,7 @@ void fragment_shader(in SceneData scene_data) { #else directional_lights.data[i].color * directional_lights.data[i].energy * tint, #endif - true, shadow, f0, orms, 1.0, albedo, alpha, + true, shadow, f0, orms, 1.0, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2383,7 +2373,7 @@ void fragment_shader(in SceneData scene_data) { shadow = blur_shadow(shadow); - light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -2455,7 +2445,7 @@ void fragment_shader(in SceneData scene_data) { shadow = blur_shadow(shadow); - light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 9f68d59be2..8f153f7ed5 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -59,6 +59,10 @@ uint sc_packed_0() { return draw_call.sc_packed_0; } +uint sc_packed_1() { + return draw_call.sc_packed_1; +} + uint uc_cull_mode() { return (draw_call.uc_packed_0 >> 0) & 3U; } @@ -67,11 +71,16 @@ uint uc_cull_mode() { // Pull the constants from the pipeline's specialization constants. layout(constant_id = 0) const uint pso_sc_packed_0 = 0; +layout(constant_id = 1) const uint pso_sc_packed_1 = 0; uint sc_packed_0() { return pso_sc_packed_0; } +uint sc_packed_1() { + return pso_sc_packed_1; +} + #endif bool sc_use_forward_gi() { @@ -107,19 +116,35 @@ bool sc_use_lightmap_bicubic_filter() { } uint sc_soft_shadow_samples() { - return (sc_packed_0() >> 8) & 15U; + return (sc_packed_0() >> 8) & 63U; } uint sc_penumbra_shadow_samples() { - return (sc_packed_0() >> 12) & 15U; + return (sc_packed_0() >> 14) & 63U; } uint sc_directional_soft_shadow_samples() { - return (sc_packed_0() >> 16) & 15U; + return (sc_packed_0() >> 20) & 63U; } uint sc_directional_penumbra_shadow_samples() { - return (sc_packed_0() >> 20) & 15U; + return (sc_packed_0() >> 26) & 63U; +} + +bool sc_multimesh() { + return ((sc_packed_1() >> 0) & 1U) != 0; +} + +bool sc_multimesh_format_2d() { + return ((sc_packed_1() >> 1) & 1U) != 0; +} + +bool sc_multimesh_has_color() { + return ((sc_packed_1() >> 2) & 1U) != 0; +} + +bool sc_multimesh_has_custom_data() { + return ((sc_packed_1() >> 3) & 1U) != 0; } float sc_luminance_multiplier() { @@ -144,10 +169,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; #define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9) #define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10) #define INSTANCE_FLAGS_PARTICLES (1 << 11) -#define INSTANCE_FLAGS_MULTIMESH (1 << 12) -#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) -#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) -#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15) #define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16 #define INSTANCE_FLAGS_FADE_SHIFT 24 //3 bits of stride diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 2f0e4e0bea..0cb34557ea 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -178,6 +178,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec } #endif +uint multimesh_stride() { + uint stride = sc_multimesh_format_2d() ? 2 : 3; + stride += sc_multimesh_has_color() ? 1 : 0; + stride += sc_multimesh_has_custom_data() ? 1 : 0; + return stride; +} + void main() { vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) @@ -208,7 +215,7 @@ void main() { mat4 matrix; mat4 read_model_matrix = model_matrix; - if (sc_is_multimesh()) { + if (sc_multimesh()) { //multimesh, instances are for it #ifdef USE_PARTICLE_TRAILS @@ -256,25 +263,10 @@ void main() { #endif #else - uint stride = 0; - { - //TODO implement a small lookup table for the stride - if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { - stride += 2; - } else { - stride += 3; - } - if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { - stride += 1; - } - if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { - stride += 1; - } - } - + uint stride = multimesh_stride(); uint offset = stride * gl_InstanceIndex; - if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { + if (sc_multimesh_format_2d()) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); offset += 2; } else { @@ -282,14 +274,14 @@ void main() { offset += 3; } - if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { + if (sc_multimesh_has_color()) { #ifdef COLOR_USED color_interp *= transforms.data[offset]; #endif offset += 1; } - if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { + if (sc_multimesh_has_custom_data()) { instance_custom = transforms.data[offset]; } @@ -404,7 +396,7 @@ void main() { // Then we combine the translations from the model matrix and the view matrix using emulated doubles. // We add the result to the vertex and ignore the final lost precision. vec3 model_origin = model_matrix[3].xyz; - if (sc_is_multimesh()) { + if (sc_multimesh()) { vertex = mat3(matrix) * vertex; model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision); } @@ -442,12 +434,12 @@ void main() { vertex_interp = vertex; #ifdef NORMAL_USED - normal_interp = normal; + normal_interp = normalize(normal); #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - tangent_interp = tangent; - binormal_interp = binormal; + tangent_interp = normalize(tangent); + binormal_interp = normalize(binormal); #endif // VERTEX LIGHTING @@ -461,50 +453,24 @@ void main() { diffuse_light_interp = vec4(0.0); specular_light_interp = vec4(0.0); - if (!sc_disable_omni_lights()) { - uint light_indices = instances.data[draw_call.instance_index].omni_lights.x; - for (uint i = 0; i < 8; i++) { - uint light_index = light_indices & 0xFF; - if (i == 3) { - light_indices = instances.data[draw_call.instance_index].omni_lights.y; - } else { - light_indices = light_indices >> 8; - } - - if (light_index == 0xFF) { - break; - } - - light_process_omni_vertex(light_index, vertex, view, normal, roughness, - diffuse_light_interp.rgb, specular_light_interp.rgb); - } + uvec2 omni_light_indices = instances.data[draw_call.instance_index].omni_lights; + for (uint i = 0; i < sc_omni_lights(); i++) { + uint light_index = (i > 3) ? ((omni_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_light_indices.x >> (i * 8)) & 0xFF); + light_process_omni_vertex(light_index, vertex, view, normal_interp, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb); } - if (!sc_disable_spot_lights()) { - uint light_indices = instances.data[draw_call.instance_index].spot_lights.x; - for (uint i = 0; i < 8; i++) { - uint light_index = light_indices & 0xFF; - if (i == 3) { - light_indices = instances.data[draw_call.instance_index].spot_lights.y; - } else { - light_indices = light_indices >> 8; - } - - if (light_index == 0xFF) { - break; - } - - light_process_spot_vertex(light_index, vertex, view, normal, roughness, - diffuse_light_interp.rgb, specular_light_interp.rgb); - } + uvec2 spot_light_indices = instances.data[draw_call.instance_index].spot_lights; + for (uint i = 0; i < sc_spot_lights(); i++) { + uint light_index = (i > 3) ? ((spot_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_light_indices.x >> (i * 8)) & 0xFF); + light_process_spot_vertex(light_index, vertex, view, normal_interp, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb); } - if (!sc_disable_directional_lights()) { + if (sc_directional_lights() > 0) { // We process the first directional light separately as it may have shadows. vec3 directional_diffuse = vec3(0.0); vec3 directional_specular = vec3(0.0); - for (uint i = 0; i < scene_data.directional_light_count; i++) { + for (uint i = 0; i < sc_directional_lights(); i++) { if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) { continue; // Not masked, skip. } @@ -513,13 +479,13 @@ void main() { continue; // Statically baked light and object uses lightmap, skip. } if (i == 0) { - light_compute_vertex(normal, directional_lights.data[0].direction, view, + light_compute_vertex(normal_interp, directional_lights.data[0].direction, view, directional_lights.data[0].color * directional_lights.data[0].energy, true, roughness, directional_diffuse, directional_specular); } else { - light_compute_vertex(normal, directional_lights.data[i].direction, view, + light_compute_vertex(normal_interp, directional_lights.data[i].direction, view, directional_lights.data[i].color * directional_lights.data[i].energy, true, roughness, diffuse_light_interp.rgb, @@ -823,7 +789,7 @@ vec4 fog_process(vec3 vertex) { float sun_total = 0.0; vec3 view = normalize(vertex); - for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) { + for (uint i = 0; i < sc_directional_lights(); i++) { vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy; float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0); fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter; @@ -1110,97 +1076,83 @@ void main() { vec3 vertex_ddx = dFdx(vertex); vec3 vertex_ddy = dFdy(vertex); - if (!sc_disable_decals()) { //Decals - // must implement - - uint decal_indices = instances.data[draw_call.instance_index].decals.x; - for (uint i = 0; i < 8; i++) { - uint decal_index = decal_indices & 0xFF; - if (i == 3) { - decal_indices = instances.data[draw_call.instance_index].decals.y; - } else { - decal_indices = decal_indices >> 8; - } + uvec2 decal_indices = instances.data[draw_call.instance_index].decals; + for (uint i = 0; i < sc_decals(); i++) { + uint decal_index = (i > 3) ? ((decal_indices.y >> ((i - 4) * 8)) & 0xFF) : ((decal_indices.x >> (i * 8)) & 0xFF); + if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) { + continue; //not masked + } - if (decal_index == 0xFF) { - break; - } + vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz; + if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) { + continue; //out of decal + } - if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) { - continue; //not masked - } + float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade); - vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz; - if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) { - continue; //out of decal - } + if (decals.data[decal_index].normal_fade > 0.0) { + fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5); + } - float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade); + //we need ddx/ddy for mipmaps, so simulate them + vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz; + vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz; - if (decals.data[decal_index].normal_fade > 0.0) { - fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5); + if (decals.data[decal_index].albedo_rect != vec4(0.0)) { + //has albedo + vec4 decal_albedo; + if (sc_decal_use_mipmaps()) { + decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw); + } else { + decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0); } + decal_albedo *= decals.data[decal_index].modulate; + decal_albedo.a *= fade; + albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix); - //we need ddx/ddy for mipmaps, so simulate them - vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz; - vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz; - - if (decals.data[decal_index].albedo_rect != vec4(0.0)) { - //has albedo - vec4 decal_albedo; + if (decals.data[decal_index].normal_rect != vec4(0.0)) { + vec3 decal_normal; if (sc_decal_use_mipmaps()) { - decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw); + decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz; } else { - decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0); - } - decal_albedo *= decals.data[decal_index].modulate; - decal_albedo.a *= fade; - albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix); - - if (decals.data[decal_index].normal_rect != vec4(0.0)) { - vec3 decal_normal; - if (sc_decal_use_mipmaps()) { - decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz; - } else { - decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz; - } - decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software - decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy))); - //convert to view space, use xzy because y is up - decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz; - - normal = normalize(mix(normal, decal_normal, decal_albedo.a)); + decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz; } + decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software + decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy))); + //convert to view space, use xzy because y is up + decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz; - if (decals.data[decal_index].orm_rect != vec4(0.0)) { - vec3 decal_orm; - if (sc_decal_use_mipmaps()) { - decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz; - } else { - decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz; - } - ao = mix(ao, decal_orm.r, decal_albedo.a); - roughness = mix(roughness, decal_orm.g, decal_albedo.a); - metallic = mix(metallic, decal_orm.b, decal_albedo.a); - } + normal = normalize(mix(normal, decal_normal, decal_albedo.a)); } - if (decals.data[decal_index].emission_rect != vec4(0.0)) { - //emission is additive, so its independent from albedo + if (decals.data[decal_index].orm_rect != vec4(0.0)) { + vec3 decal_orm; if (sc_decal_use_mipmaps()) { - emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz; } else { - emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade; + decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz; } + ao = mix(ao, decal_orm.r, decal_albedo.a); + roughness = mix(roughness, decal_orm.g, decal_albedo.a); + metallic = mix(metallic, decal_orm.b, decal_albedo.a); + } + } + + if (decals.data[decal_index].emission_rect != vec4(0.0)) { + //emission is additive, so its independent from albedo + if (sc_decal_use_mipmaps()) { + emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + } else { + emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade; } } - } //Decals + } #endif //!MODE_RENDER_DEPTH /////////////////////// LIGHTING ////////////////////////////// #ifdef NORMAL_USED - if (scene_data.roughness_limiter_enabled) { + if (sc_scene_roughness_limiter_enabled()) { //https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf float roughness2 = roughness * roughness; vec3 dndu = dFdx(normal), dndv = dFdy(normal); @@ -1225,7 +1177,7 @@ void main() { #ifndef AMBIENT_LIGHT_DISABLED - if (scene_data.use_reflection_cubemap) { + if (sc_scene_use_reflection_cubemap()) { #ifdef LIGHT_ANISOTROPY_USED // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; @@ -1266,7 +1218,7 @@ void main() { if (scene_data.use_ambient_light) { ambient_light = scene_data.ambient_light_color_energy.rgb; - if (scene_data.use_ambient_cubemap) { + if (sc_scene_use_ambient_cubemap()) { vec3 ambient_dir = scene_data.radiance_inverse_xform * normal; #ifdef USE_RADIANCE_CUBEMAP_ARRAY vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb; @@ -1285,7 +1237,7 @@ void main() { #endif // CUSTOM_IRRADIANCE_USED #ifdef LIGHT_CLEARCOAT_USED - if (scene_data.use_reflection_cubemap) { + if (sc_scene_use_reflection_cubemap()) { vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map float NoV = max(dot(n, view), 0.0001); vec3 ref_vec = reflect(-view, n); @@ -1393,12 +1345,10 @@ void main() { // skipping ssao, do we remove ssao totally? - if (!sc_disable_reflection_probes()) { //Reflection probes + if (sc_reflection_probes() > 0) { vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - uint reflection_indices = instances.data[draw_call.instance_index].reflection_probes.x; - #ifdef LIGHT_ANISOTROPY_USED // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; @@ -1411,18 +1361,9 @@ void main() { vec3 ref_vec = normalize(reflect(-view, bent_normal)); ref_vec = mix(ref_vec, bent_normal, roughness * roughness); - for (uint i = 0; i < 8; i++) { - uint reflection_index = reflection_indices & 0xFF; - if (i == 3) { - reflection_indices = instances.data[draw_call.instance_index].reflection_probes.y; - } else { - reflection_indices = reflection_indices >> 8; - } - - if (reflection_index == 0xFF) { - break; - } - + uvec2 reflection_indices = instances.data[draw_call.instance_index].reflection_probes; + for (uint i = 0; i < sc_reflection_probes(); i++) { + uint reflection_index = (i > 3) ? ((reflection_indices.y >> ((i - 4) * 8)) & 0xFF) : ((reflection_indices.x >> (i * 8)) & 0xFF); reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); } @@ -1487,7 +1428,7 @@ void main() { specular_light += specular_light_interp.rgb * f0; #endif - if (!sc_disable_directional_lights()) { //directional light + if (sc_directional_lights() > 0) { #ifndef SHADOWS_DISABLED // Do shadow and lighting in two passes to reduce register pressure uint shadow0 = 0; @@ -1497,7 +1438,7 @@ void main() { // Only process the first light's shadow for vertex lighting. for (uint i = 0; i < 1; i++) { #else - for (uint i = 0; i < scene_data.directional_light_count; i++) { + for (uint i = 0; i < sc_directional_lights(); i++) { #endif if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) { @@ -1612,7 +1553,7 @@ void main() { #endif // SHADOWS_DISABLED #ifndef USE_VERTEX_LIGHTING - for (uint i = 0; i < scene_data.directional_light_count; i++) { + for (uint i = 0; i < sc_directional_lights(); i++) { if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) { continue; //not masked } @@ -1650,7 +1591,7 @@ void main() { light_compute(normal, directional_lights.data[i].direction, view, size_A, directional_lights.data[i].color * directional_lights.data[i].energy * tint, - true, shadow, f0, orms, 1.0, albedo, alpha, + true, shadow, f0, orms, 1.0, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1678,95 +1619,72 @@ void main() { } //directional light #ifndef USE_VERTEX_LIGHTING - if (!sc_disable_omni_lights()) { //omni lights - uint light_indices = instances.data[draw_call.instance_index].omni_lights.x; - for (uint i = 0; i < 8; i++) { - uint light_index = light_indices & 0xFF; - if (i == 3) { - light_indices = instances.data[draw_call.instance_index].omni_lights.y; - } else { - light_indices = light_indices >> 8; - } - - if (light_index == 0xFF) { - break; - } + uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights; + for (uint i = 0; i < sc_omni_lights(); i++) { + uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF); - float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count); + float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count); - shadow = blur_shadow(shadow); + shadow = blur_shadow(shadow); - // Fragment lighting - light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, + // Fragment lighting + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED - backlight, + backlight, #endif /* #ifdef LIGHT_TRANSMITTANCE_USED - transmittance_color, - transmittance_depth, - transmittance_boost, + transmittance_color, + transmittance_depth, + transmittance_boost, #endif */ #ifdef LIGHT_RIM_USED - rim, - rim_tint, + rim, + rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_roughness, normalize(normal_interp), + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED - tangent, - binormal, anisotropy, + tangent, + binormal, anisotropy, #endif - diffuse_light, specular_light); - } - } //omni lights - - if (!sc_disable_spot_lights()) { //spot lights - - uint light_indices = instances.data[draw_call.instance_index].spot_lights.x; - for (uint i = 0; i < 8; i++) { - uint light_index = light_indices & 0xFF; - if (i == 3) { - light_indices = instances.data[draw_call.instance_index].spot_lights.y; - } else { - light_indices = light_indices >> 8; - } + diffuse_light, specular_light); + } - if (light_index == 0xFF) { - break; - } + uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights; + for (uint i = 0; i < sc_spot_lights(); i++) { + uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF); - float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count); + float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count); - shadow = blur_shadow(shadow); + shadow = blur_shadow(shadow); - light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED - backlight, + backlight, #endif /* #ifdef LIGHT_TRANSMITTANCE_USED - transmittance_color, - transmittance_depth, - transmittance_boost, + transmittance_color, + transmittance_depth, + transmittance_boost, #endif */ #ifdef LIGHT_RIM_USED - rim, - rim_tint, + rim, + rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_roughness, normalize(normal_interp), + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED - tangent, - binormal, anisotropy, + tangent, + binormal, anisotropy, #endif - diffuse_light, specular_light); - } - } //spot lights + diffuse_light, specular_light); + } #endif // !VERTEX_LIGHTING #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 495e52a29e..2cc86482f6 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -22,8 +22,8 @@ layout(push_constant, std430) uniform DrawCall { uint pad; #ifdef UBERSHADER uint sc_packed_0; - float sc_packed_1; - uint sc_packed_2; + uint sc_packed_1; + float sc_packed_2; uint uc_packed_0; #endif } @@ -42,10 +42,14 @@ uint sc_packed_0() { return draw_call.sc_packed_0; } -float sc_packed_1() { +uint sc_packed_1() { return draw_call.sc_packed_1; } +float sc_packed_2() { + return draw_call.sc_packed_2; +} + uint uc_cull_mode() { return (draw_call.uc_packed_0 >> 0) & 3U; } @@ -54,16 +58,21 @@ uint uc_cull_mode() { // Pull the constants from the pipeline's specialization constants. layout(constant_id = 0) const uint pso_sc_packed_0 = 0; -layout(constant_id = 1) const float pso_sc_packed_1 = 2.0; +layout(constant_id = 1) const uint pso_sc_packed_1 = 0; +layout(constant_id = 2) const float pso_sc_packed_2 = 2.0; uint sc_packed_0() { return pso_sc_packed_0; } -float sc_packed_1() { +uint sc_packed_1() { return pso_sc_packed_1; } +float sc_packed_2() { + return pso_sc_packed_2; +} + #endif bool sc_use_light_projector() { @@ -86,60 +95,84 @@ bool sc_projector_use_mipmaps() { return ((sc_packed_0() >> 4) & 1U) != 0; } -bool sc_disable_omni_lights() { +bool sc_disable_fog() { return ((sc_packed_0() >> 5) & 1U) != 0; } -bool sc_disable_spot_lights() { +bool sc_use_depth_fog() { return ((sc_packed_0() >> 6) & 1U) != 0; } -bool sc_disable_reflection_probes() { +bool sc_use_lightmap_bicubic_filter() { return ((sc_packed_0() >> 7) & 1U) != 0; } -bool sc_disable_directional_lights() { +bool sc_multimesh() { return ((sc_packed_0() >> 8) & 1U) != 0; } -bool sc_disable_decals() { +bool sc_multimesh_format_2d() { return ((sc_packed_0() >> 9) & 1U) != 0; } -bool sc_disable_fog() { +bool sc_multimesh_has_color() { return ((sc_packed_0() >> 10) & 1U) != 0; } -bool sc_use_depth_fog() { +bool sc_multimesh_has_custom_data() { return ((sc_packed_0() >> 11) & 1U) != 0; } -bool sc_is_multimesh() { +bool sc_scene_use_ambient_cubemap() { return ((sc_packed_0() >> 12) & 1U) != 0; } -bool sc_use_lightmap_bicubic_filter() { +bool sc_scene_use_reflection_cubemap() { return ((sc_packed_0() >> 13) & 1U) != 0; } +bool sc_scene_roughness_limiter_enabled() { + return ((sc_packed_0() >> 14) & 1U) != 0; +} + uint sc_soft_shadow_samples() { - return (sc_packed_0() >> 16) & 15U; + return (sc_packed_0() >> 20) & 63U; } uint sc_penumbra_shadow_samples() { - return (sc_packed_0() >> 20) & 15U; + return (sc_packed_0() >> 26) & 63U; } uint sc_directional_soft_shadow_samples() { - return (sc_packed_0() >> 24) & 15U; + return (sc_packed_1() >> 0) & 63U; } uint sc_directional_penumbra_shadow_samples() { - return (sc_packed_0() >> 28) & 15U; + return (sc_packed_1() >> 6) & 63U; +} + +uint sc_omni_lights() { + return (sc_packed_1() >> 12) & 15U; +} + +uint sc_spot_lights() { + return (sc_packed_1() >> 16) & 15U; +} + +uint sc_reflection_probes() { + return (sc_packed_1() >> 20) & 15U; +} + +uint sc_directional_lights() { + return (sc_packed_1() >> 24) & 15U; +} + +uint sc_decals() { + return (sc_packed_1() >> 28) & 15U; } float sc_luminance_multiplier() { - return sc_packed_1(); + return sc_packed_2(); } /* Set 0: Base Pass (never changes) */ @@ -157,10 +190,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; #define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9) #define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10) #define INSTANCE_FLAGS_PARTICLES (1 << 11) -#define INSTANCE_FLAGS_MULTIMESH (1 << 12) -#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) -#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) -#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15) #define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16 //3 bits of stride #define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index a1a185d0fd..1e8fc7eab4 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -39,7 +39,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) { return mix(vec3(dielectric), albedo, vec3(metallic)); } -void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, +void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, vec2 screen_uv, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -547,7 +547,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal, float taa_fr return 1.0; } -void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, +void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, vec2 screen_uv, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -675,7 +675,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -793,7 +793,7 @@ vec2 normal_to_panorama(vec3 n) { return panorama_coords; } -void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, +void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, vec2 screen_uv, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -884,7 +884,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v } light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 8f71909154..9de37050f0 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -285,6 +285,23 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } +void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_NULL(light); + + light->shadow_caster_mask = p_caster_mask; + + light->version++; + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); +} + +uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_NULL_V(light, 0); + + return light->shadow_caster_mask; +} + void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { Light *light = light_owner.get_or_null(p_light); ERR_FAIL_NULL(light); @@ -1032,7 +1049,7 @@ void LightStorage::reflection_probe_free(RID p_rid) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); reflection_probe->dependency.deleted_notify(p_rid); reflection_probe_owner.free(p_rid); -}; +} void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 59303e8a73..1a92c5470d 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -72,6 +72,7 @@ private: RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; uint32_t max_sdfgi_cascade = 2; uint32_t cull_mask = 0xFFFFFFFF; + uint32_t shadow_caster_mask = 0xFFFFFFFF; bool distance_fade = false; real_t distance_fade_begin = 40.0; real_t distance_fade_shadow = 50.0; @@ -480,6 +481,8 @@ public: virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override; virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override; + virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override; + virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override; virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override; virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override; @@ -587,7 +590,7 @@ public: /* LIGHT INSTANCE API */ - bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }; + bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); } virtual RID light_instance_create(RID p_light) override; virtual void light_instance_free(RID p_light) override; @@ -808,7 +811,7 @@ public: /* REFLECTION PROBE */ - bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }; + bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); } virtual RID reflection_probe_allocate() override; virtual void reflection_probe_initialize(RID p_reflection_probe) override; @@ -950,7 +953,7 @@ public: /* LIGHTMAP */ - bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }; + bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); } virtual RID lightmap_allocate() override; virtual void lightmap_initialize(RID p_lightmap) override; @@ -1016,7 +1019,7 @@ public: /* LIGHTMAP INSTANCE */ - bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }; + bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); } virtual RID lightmap_instance_create(RID p_lightmap) override; virtual void lightmap_instance_free(RID p_lightmap) override; @@ -1036,7 +1039,7 @@ public: /* SHADOW ATLAS API */ - bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }; + bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); } virtual RID shadow_atlas_create() override; virtual void shadow_atlas_free(RID p_atlas) override; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index 08c1064dcb..89a8b36853 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -254,7 +254,7 @@ private: MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; mutable RID_Owner<Material, true> material_owner; - Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); } SelfList<Material>::List material_update_list; Mutex material_update_list_mutex; @@ -403,7 +403,7 @@ public: /* SHADER API */ - bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; + bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); } virtual RID shader_allocate() override; virtual void shader_initialize(RID p_shader) override; @@ -423,7 +423,7 @@ public: /* MATERIAL API */ - bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; + bool owns_material(RID p_rid) { return material_owner.owns(p_rid); } void _material_queue_update(Material *material, bool p_uniform, bool p_texture); void _update_queued_materials(); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 0d468ad1e3..7537e70235 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -1997,6 +1997,12 @@ void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_ } } +RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_NULL_V(multimesh, RID()); + return multimesh->buffer; +} + Vector<float> MeshStorage::_multimesh_get_buffer(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_NULL_V(multimesh, Vector<float>()); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 322f3cc6f4..11962b05f4 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -351,7 +351,7 @@ public: /* MESH API */ - bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); } virtual RID mesh_allocate() override; virtual void mesh_initialize(RID p_mesh) override; @@ -616,7 +616,7 @@ public: /* MESH INSTANCE API */ - bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); }; + bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); } virtual RID mesh_instance_create(RID p_base) override; virtual void mesh_instance_free(RID p_rid) override; @@ -628,7 +628,7 @@ public: /* MULTIMESH API */ - bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; + bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); } virtual RID _multimesh_allocate() override; virtual void _multimesh_initialize(RID p_multimesh) override; @@ -651,6 +651,7 @@ public: virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override; virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override; + virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override; virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override; virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) override; @@ -737,7 +738,7 @@ public: /* SKELETON API */ - bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); }; + bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); } virtual RID skeleton_allocate() override; virtual void skeleton_initialize(RID p_skeleton) override; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 314cbf9aa9..6efb8c176f 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -306,9 +306,14 @@ void ParticlesStorage::_particles_free_data(Particles *particles) { particles->emission_storage_buffer = RID(); } - if (particles->unused_storage_buffer.is_valid()) { - RD::get_singleton()->free(particles->unused_storage_buffer); - particles->unused_storage_buffer = RID(); + if (particles->unused_emission_storage_buffer.is_valid()) { + RD::get_singleton()->free(particles->unused_emission_storage_buffer); + particles->unused_emission_storage_buffer = RID(); + } + + if (particles->unused_trail_storage_buffer.is_valid()) { + RD::get_singleton()->free(particles->unused_trail_storage_buffer); + particles->unused_trail_storage_buffer = RID(); } if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { @@ -534,9 +539,15 @@ void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles) } } -void ParticlesStorage::_particles_ensure_unused_buffer(Particles *particles) { - if (particles->unused_storage_buffer.is_null()) { - particles->unused_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); +void ParticlesStorage::_particles_ensure_unused_emission_buffer(Particles *particles) { + if (particles->unused_emission_storage_buffer.is_null()) { + particles->unused_emission_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); + } +} + +void ParticlesStorage::_particles_ensure_unused_trail_buffer(Particles *particles) { + if (particles->unused_trail_storage_buffer.is_null()) { + particles->unused_trail_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); } } @@ -763,8 +774,8 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta if (p_particles->emission_storage_buffer.is_valid()) { u.append_id(p_particles->emission_storage_buffer); } else { - _particles_ensure_unused_buffer(p_particles); - u.append_id(p_particles->unused_storage_buffer); + _particles_ensure_unused_emission_buffer(p_particles); + u.append_id(p_particles->unused_emission_storage_buffer); } uniforms.push_back(u); } @@ -779,8 +790,8 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta } u.append_id(sub_emitter->emission_storage_buffer); } else { - _particles_ensure_unused_buffer(p_particles); - u.append_id(p_particles->unused_storage_buffer); + _particles_ensure_unused_emission_buffer(p_particles); + u.append_id(p_particles->unused_emission_storage_buffer); } uniforms.push_back(u); } @@ -1481,8 +1492,8 @@ void ParticlesStorage::update_particles() { if (particles->trail_bind_pose_buffer.is_valid()) { u.append_id(particles->trail_bind_pose_buffer); } else { - _particles_ensure_unused_buffer(particles); - u.append_id(particles->unused_storage_buffer); + _particles_ensure_unused_trail_buffer(particles); + u.append_id(particles->unused_trail_storage_buffer); } uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 33f44f3045..ec897c4ea9 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -247,7 +247,8 @@ private: ParticleEmissionBuffer *emission_buffer = nullptr; RID emission_storage_buffer; - RID unused_storage_buffer; + RID unused_emission_storage_buffer; + RID unused_trail_storage_buffer; HashSet<RID> collisions; @@ -265,7 +266,8 @@ private: void _particles_process(Particles *p_particles, double p_delta); void _particles_allocate_emission_buffer(Particles *particles); - void _particles_ensure_unused_buffer(Particles *particles); + void _particles_ensure_unused_emission_buffer(Particles *particles); + void _particles_ensure_unused_trail_buffer(Particles *particles); void _particles_free_data(Particles *particles); void _particles_update_buffers(Particles *particles); @@ -509,7 +511,7 @@ public: _FORCE_INLINE_ bool particles_has_collision(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_NULL_V(particles, 0); + ERR_FAIL_NULL_V(particles, false); return particles->has_collision_cache; } diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h index 4a70482d72..59671c3a13 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -51,6 +51,7 @@ public: float taa_frame_count = 0.0f; uint32_t camera_visible_layers; bool cam_orthogonal = false; + bool cam_frustum = false; bool flip_y = false; // For billboards to cast correct shadows. diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 9dc606620b..8a9499dfc9 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -518,6 +518,32 @@ TextureStorage::TextureStorage() { rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i)); } } + + // Initialize texture placeholder data for the `texture_*_placeholder_initialize()` methods. + + constexpr int placeholder_size = 4; + texture_2d_placeholder = Image::create_empty(placeholder_size, placeholder_size, false, Image::FORMAT_RGBA8); + // Draw a magenta/black checkerboard pattern. + for (int i = 0; i < placeholder_size * placeholder_size; i++) { + const int x = i % placeholder_size; + const int y = i / placeholder_size; + texture_2d_placeholder->set_pixel(x, y, (x + y) % 2 == 0 ? Color(1, 0, 1) : Color(0, 0, 0)); + } + + texture_2d_array_placeholder.push_back(texture_2d_placeholder); + + for (int i = 0; i < 6; i++) { + cubemap_placeholder.push_back(texture_2d_placeholder); + } + + Ref<Image> texture_2d_placeholder_rotated; + texture_2d_placeholder_rotated.instantiate(); + texture_2d_placeholder_rotated->copy_from(texture_2d_placeholder); + texture_2d_placeholder_rotated->rotate_90(CLOCKWISE); + for (int i = 0; i < 4; i++) { + // Alternate checkerboard pattern on odd layers (by using a copy that is rotated 90 degrees). + texture_3d_placeholder.push_back(i % 2 == 0 ? texture_2d_placeholder : texture_2d_placeholder_rotated); + } } TextureStorage::~TextureStorage() { @@ -1365,46 +1391,19 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { //these two APIs can be used together or in combination with the others. void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - texture_2d_initialize(p_texture, image); + texture_2d_initialize(p_texture, texture_2d_placeholder); } void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { - images.push_back(image); + texture_2d_layered_initialize(p_texture, texture_2d_array_placeholder, p_layered_type); } else { - //cube - for (int i = 0; i < 6; i++) { - images.push_back(image); - } + texture_2d_layered_initialize(p_texture, cubemap_placeholder, p_layered_type); } - - texture_2d_layered_initialize(p_texture, images, p_layered_type); } void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - //cube - for (int i = 0; i < 4; i++) { - images.push_back(image); - } - - texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); + texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, texture_3d_placeholder); } Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { @@ -1667,7 +1666,9 @@ void TextureStorage::texture_rd_initialize(RID p_texture, const RID &p_rd_textur ERR_FAIL_COND(tf.array_layers != 1); texture.type = TextureStorage::TYPE_2D; } break; - case RD::TEXTURE_TYPE_2D_ARRAY: { + case RD::TEXTURE_TYPE_2D_ARRAY: + case RD::TEXTURE_TYPE_CUBE: + case RD::TEXTURE_TYPE_CUBE_ARRAY: { // RenderingDevice doesn't distinguish between Array textures and Cube textures // this condition covers TextureArrays, TextureCube, and TextureCubeArray. ERR_FAIL_COND(tf.array_layers == 1); @@ -2269,6 +2270,16 @@ void TextureStorage::_texture_format_from_rd(RD::DataFormat p_rd_format, Texture r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; } break; + case RD::DATA_FORMAT_B8G8R8A8_UNORM: + case RD::DATA_FORMAT_B8G8R8A8_SRGB: { + r_format.image_format = Image::FORMAT_RGBA8; + r_format.rd_format = RD::DATA_FORMAT_B8G8R8A8_UNORM; + r_format.rd_format_srgb = RD::DATA_FORMAT_B8G8R8A8_SRGB; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; case RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16: { r_format.image_format = Image::FORMAT_RGBA4444; r_format.rd_format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 2135ee3e3b..3d281cf98a 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -102,9 +102,9 @@ private: /* Canvas Texture API */ struct CanvasTextureCache { - RID diffuse = RID(); - RID normal = RID(); - RID specular = RID(); + RID diffuse; + RID normal; + RID specular; }; class CanvasTexture { @@ -122,7 +122,6 @@ private: Size2i size_cache = Size2i(1, 1); bool use_normal_cache = false; bool use_specular_cache = false; - bool cleared_cache = true; void clear_cache(); ~CanvasTexture(); @@ -195,7 +194,7 @@ private: // Textures can be created from threads, so this RID_Owner is thread safe. mutable RID_Owner<Texture, true> texture_owner; - Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); } struct TextureToRDFormat { RD::DataFormat format; @@ -439,7 +438,7 @@ private: }; mutable RID_Owner<RenderTarget> render_target_owner; - RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); }; + RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); } void _clear_render_target(RenderTarget *rt); void _update_render_target(RenderTarget *rt); @@ -486,7 +485,7 @@ public: /* Canvas Texture API */ - bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); } virtual RID canvas_texture_allocate() override; virtual void canvas_texture_initialize(RID p_rid) override; @@ -502,7 +501,7 @@ public: /* Texture API */ - bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); }; + bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); } virtual RID texture_allocate() override; virtual void texture_free(RID p_rid) override; @@ -520,6 +519,11 @@ public: virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override; virtual void texture_proxy_update(RID p_proxy, RID p_base) override; + Ref<Image> texture_2d_placeholder; + Vector<Ref<Image>> texture_2d_array_placeholder; + Vector<Ref<Image>> cubemap_placeholder; + Vector<Ref<Image>> texture_3d_placeholder; + //these two APIs can be used together or in combination with the others. virtual void texture_2d_placeholder_initialize(RID p_texture) override; virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; @@ -586,7 +590,7 @@ public: void update_decal_atlas(); - bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); }; + bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); } RID decal_atlas_get_texture() const; RID decal_atlas_get_texture_srgb() const; @@ -726,7 +730,7 @@ public: /* RENDER TARGET API */ - bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }; + bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); } virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h index 2ba3da7515..96508fd3ff 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.h +++ b/servers/rendering/renderer_rd/storage_rd/utilities.h @@ -77,8 +77,8 @@ public: /* VISIBILITY NOTIFIER */ - VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }; - bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }; + VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); } + bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); } virtual RID visibility_notifier_allocate() override; virtual void visibility_notifier_initialize(RID p_notifier) override; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 8b7ec08868..2420a24261 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -1998,6 +1998,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; } pair.cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base); + } else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) { + pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; + pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) { pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; @@ -2296,6 +2299,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in cull.shadow_count = p_shadow_index + 1; cull.shadows[p_shadow_index].cascade_count = splits; cull.shadows[p_shadow_index].light_instance = light->instance; + cull.shadows[p_shadow_index].caster_mask = RSG::light_storage->light_get_shadow_caster_mask(p_instance->base); for (int i = 0; i < splits; i++) { RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i)); @@ -2526,7 +2530,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) { continue; } else { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { @@ -2608,7 +2612,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) { continue; } else { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { @@ -2675,7 +2679,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) { continue; } else { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { @@ -2734,6 +2738,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu Projection projection; bool vaspect = camera->vaspect; bool is_orthogonal = false; + bool is_frustum = false; switch (camera->type) { case Camera::ORTHOGONAL: { @@ -2762,10 +2767,11 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu camera->znear, camera->zfar, camera->vaspect); + is_frustum = true; } break; } - camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, taa_frame_count, camera->visible_layers); + camera_data.set_camera(transform, projection, is_orthogonal, is_frustum, vaspect, jitter, taa_frame_count, camera->visible_layers); } else { // Setup our camera for our XR interface. // We can support multiple views here each with their own camera @@ -2787,9 +2793,9 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } if (view_count == 1) { - camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers); + camera_data.set_camera(transforms[0], projections[0], false, false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers); } else if (view_count == 2) { - camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect); + camera_data.set_multiview_camera(view_count, transforms, projections, false, false, camera->vaspect); } else { // this won't be called (see fail check above) but keeping this comment to indicate we may support more then 2 views in the future... } @@ -3011,7 +3017,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul cull_data.cull->lock.lock(); RSG::particles_storage->particles_request_process(idata.base_rid); cull_data.cull->lock.unlock(); - RSG::particles_storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_column(2).normalized(), cull_data.cam_transform.basis.get_column(1).normalized()); + + RS::get_singleton()->call_on_render_thread(callable_mp_static(&RendererSceneCull::_scene_particles_set_view_axis).bind(idata.base_rid, -cull_data.cam_transform.basis.get_column(2).normalized(), cull_data.cam_transform.basis.get_column(1).normalized())); //particles visible? request redraw RenderingServerDefault::redraw_request(); } @@ -3033,6 +3040,10 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul for (const Instance *E : geom->lights) { InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data); + if (!(RSG::light_storage->light_get_cull_mask(E->base) & idata.layer_mask)) { + continue; + } + instance_pair_buffer[idx++] = light->instance; if (idx == MAX_INSTANCE_PAIRS) { break; @@ -3137,7 +3148,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) { uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK; - if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && LAYER_CHECK) { + if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && (LAYER_CHECK & cull_data.cull->shadows[j].caster_mask)) { cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry); mesh_visible = true; } @@ -3182,6 +3193,10 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul } } +void RendererSceneCull::_scene_particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) { + RSG::particles_storage->particles_set_view_axis(p_particles, p_axis, p_up_axis); +} + void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, RID p_compositor, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RenderingMethod::RenderInfo *r_render_info) { Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it @@ -3633,7 +3648,7 @@ void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_rend RENDER_TIMESTAMP("Render Empty 3D Scene"); RendererSceneRender::CameraData camera_data; - camera_data.set_camera(Transform3D(), Projection(), true, false); + camera_data.set_camera(Transform3D(), Projection(), true, false, false); scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), environment, RID(), compositor, p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); #endif @@ -3711,7 +3726,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int RENDER_TIMESTAMP("Render ReflectionProbe, Step " + itos(p_step)); RendererSceneRender::CameraData camera_data; - camera_data.set_camera(xform, cm, false, false); + camera_data.set_camera(xform, cm, false, false, false); Ref<RenderSceneBuffers> render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas); _render_scene(&camera_data, render_buffers, environment, RID(), RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 5aae59eb51..8161f50a35 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -1121,6 +1121,7 @@ public: struct Cull { struct Shadow { RID light_instance; + uint32_t caster_mask; struct Cascade { Frustum frustum; @@ -1183,9 +1184,11 @@ public: void _scene_cull_threaded(uint32_t p_thread, CullData *cull_data); void _scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to); + static void _scene_particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis); _FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data); bool _render_reflection_probe_step(Instance *p_instance, int p_step); + void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, RID p_compositor, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr); void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas); @@ -1255,6 +1258,7 @@ public: PASS3(environment_set_bg_energy, RID, float, float) PASS2(environment_set_canvas_max_layer, RID, int) PASS6(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource) + PASS2(environment_set_camera_feed_id, RID, int) PASS1RC(RS::EnvironmentBG, environment_get_background, RID) PASS1RC(RID, environment_get_sky, RID) diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h index df403c5484..14b97918ec 100644 --- a/servers/rendering/renderer_scene_occlusion_cull.h +++ b/servers/rendering/renderer_scene_occlusion_cull.h @@ -72,7 +72,7 @@ public: return false; } - float min_depth = -closest_point_view.z * 0.95f; + float min_depth = (closest_point - p_cam_position).length(); Vector2 rect_min = Vector2(FLT_MAX, FLT_MAX); Vector2 rect_max = Vector2(FLT_MIN, FLT_MIN); @@ -83,6 +83,10 @@ public: Vector3 corner = Vector3(p_bounds[0] * c.x + p_bounds[3] * nc.x, p_bounds[1] * c.y + p_bounds[4] * nc.y, p_bounds[2] * c.z + p_bounds[5] * nc.z); Vector3 view = p_cam_inv_transform.xform(corner); + if (p_cam_projection.is_orthogonal()) { + min_depth = MIN(min_depth, -view.z); + } + Plane vp = Plane(view, 1.0); Plane projected = p_cam_projection.xform4(vp); @@ -230,11 +234,11 @@ public: RendererSceneOcclusionCull() { singleton = this; - }; + } virtual ~RendererSceneOcclusionCull() { singleton = nullptr; - }; + } }; #endif // RENDERER_SCENE_OCCLUSION_CULL_H diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index 797ba7eaf7..07259f73d2 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -33,9 +33,10 @@ ///////////////////////////////////////////////////////////////////////////// // CameraData -void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter, float p_taa_frame_count, const uint32_t p_visible_layers) { +void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect, const Vector2 &p_taa_jitter, float p_taa_frame_count, const uint32_t p_visible_layers) { view_count = 1; is_orthogonal = p_is_orthogonal; + is_frustum = p_is_frustum; vaspect = p_vaspect; main_transform = p_transform; @@ -48,12 +49,13 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, taa_frame_count = p_taa_frame_count; } -void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) { +void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect) { ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view"); visible_layers = 0xFFFFFFFF; view_count = p_view_count; is_orthogonal = p_is_orthogonal; + is_frustum = p_is_frustum; vaspect = p_vaspect; Vector<Plane> planes[2]; @@ -349,6 +351,14 @@ RS::EnvironmentReflectionSource RendererSceneRender::environment_get_reflection_ return environment_storage.environment_get_reflection_source(p_env); } +void RendererSceneRender::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { + environment_storage.environment_set_camera_feed_id(p_env, p_camera_feed_id); +} + +int RendererSceneRender::environment_get_camera_feed_id(RID p_env) const { + return environment_storage.environment_get_camera_feed_id(p_env); +} + // Tonemap void RendererSceneRender::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) { diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 4d81a9b6a3..99418e0411 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -118,10 +118,7 @@ public: void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value); void environment_set_canvas_max_layer(RID p_env, int p_max_layer); void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG); -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); -#endif RS::EnvironmentBG environment_get_background(RID p_env) const; RID environment_get_sky(RID p_env) const; @@ -136,6 +133,7 @@ public: float environment_get_ambient_light_energy(RID p_env) const; float environment_get_ambient_sky_contribution(RID p_env) const; RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; + int environment_get_camera_feed_id(RID p_env) const; // Tonemap void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white); @@ -302,6 +300,7 @@ public: // flags uint32_t view_count; bool is_orthogonal; + bool is_frustum; uint32_t visible_layers; bool vaspect; @@ -314,8 +313,8 @@ public: Vector2 taa_jitter; float taa_frame_count = 0.0f; - void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), float p_taa_frame_count = 0.0f, uint32_t p_visible_layers = 0xFFFFFFFF); - void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect); + void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), float p_taa_frame_count = 0.0f, uint32_t p_visible_layers = 0xFFFFFFFF); + void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect); }; virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RenderingMethod::RenderInfo *r_render_info = nullptr) = 0; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 942d5631e4..e9fa38475e 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -946,6 +946,7 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with RDG::ResourceTracker *tracker = RDG::resource_tracker_create(); tracker->texture_driver_id = texture.shared_fallback->texture; + tracker->texture_size = Size2i(texture.width, texture.height); tracker->texture_subresources = texture.barrier_range(); tracker->texture_usage = alias_format.usage_bits; tracker->reference_count = 1; @@ -1125,6 +1126,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, RDG::ResourceTracker *tracker = RDG::resource_tracker_create(); tracker->texture_driver_id = texture.shared_fallback->texture; + tracker->texture_size = Size2i(texture.width, texture.height); tracker->texture_subresources = slice_range; tracker->texture_usage = slice_format.usage_bits; tracker->reference_count = 1; @@ -1260,8 +1262,6 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons write_ptr = driver->buffer_map(transfer_worker->staging_buffer); ERR_FAIL_NULL_V(write_ptr, ERR_CANT_CREATE); - write_ptr += staging_worker_offset; - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { // Transition the texture to the optimal layout. RDD::TextureBarrier tb; @@ -1303,11 +1303,12 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons if (copy_pass) { const uint8_t *read_ptr_mipmap_layer = read_ptr_mipmap + (tight_mip_size / depth) * z; - _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size); - write_ptr += to_allocate; + uint64_t staging_buffer_offset = staging_worker_offset + staging_local_offset; + uint8_t *write_ptr_mipmap_layer = write_ptr + staging_buffer_offset; + _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr_mipmap_layer, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size); RDD::BufferTextureCopyRegion copy_region; - copy_region.buffer_offset = staging_worker_offset + staging_local_offset; + copy_region.buffer_offset = staging_buffer_offset; copy_region.texture_subresources.aspect = texture->read_aspect_flags; copy_region.texture_subresources.mipmap = mm_i; copy_region.texture_subresources.base_layer = p_layer; @@ -3758,6 +3759,15 @@ int RenderingDevice::screen_get_height(DisplayServer::WindowID p_screen) const { return context->surface_get_height(surface); } +int RenderingDevice::screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen) const { + _THREAD_SAFE_METHOD_ + + HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen); + ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), ERR_CANT_CREATE, "A swap chain was not created for the screen."); + + return driver->swap_chain_get_pre_rotation_degrees(it->value); +} + RenderingDevice::FramebufferFormatID RenderingDevice::screen_get_framebuffer_format(DisplayServer::WindowID p_screen) const { _THREAD_SAFE_METHOD_ @@ -4441,6 +4451,117 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint dl->state.draw_count++; } +void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { + ERR_RENDER_THREAD_GUARD(); + + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_NULL(dl); + + Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer); + ERR_FAIL_NULL(buffer); + + ERR_FAIL_COND_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT), "Buffer provided was not created to do indirect dispatch."); + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); +#endif + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.pipeline_active, + "No render pipeline was set before attempting to draw."); + if (dl->validation.pipeline_vertex_format != INVALID_ID) { + // Pipeline uses vertices, validate format. + ERR_FAIL_COND_MSG(dl->validation.vertex_format == INVALID_ID, + "No vertex array was bound, and render pipeline expects vertices."); + // Make sure format is right. + ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != dl->validation.vertex_format, + "The vertex format used to create the pipeline does not match the vertex format bound."); + } + + if (dl->validation.pipeline_push_constant_size > 0) { + // Using push constants, check that they were supplied. + ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_supplied, + "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); + } +#endif + +#ifdef DEBUG_ENABLED + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) { + if (dl->state.sets[i].uniform_set_format == 0) { + ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i)); + } else if (uniform_set_owner.owns(dl->state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(dl->state.pipeline_shader))); + } else { + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(dl->state.pipeline_shader))); + } + } + } +#endif + + // Prepare descriptor sets if the API doesn't use pipeline barriers. + if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + } + } + + // Bind descriptor sets. + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + continue; // Nothing expected by this pipeline. + } + if (!dl->state.sets[i].bound) { + // All good, see if this requires re-binding. + draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + + UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + _uniform_set_update_shared(uniform_set); + + draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); + + dl->state.sets[i].bound = true; + } + } + + if (p_use_indices) { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.index_array_count, + "Draw command requested indices, but no index buffer was set."); + + ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices, + "The usage of restart indices in index buffer does not match the render primitive in the pipeline."); +#endif + + ERR_FAIL_COND_MSG(p_offset + 20 > buffer->size, "Offset provided (+20) is past the end of buffer."); + + draw_graph.add_draw_list_draw_indexed_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride); + } else { + ERR_FAIL_COND_MSG(p_offset + 16 > buffer->size, "Offset provided (+16) is past the end of buffer."); + + draw_graph.add_draw_list_draw_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride); + } + + dl->state.draw_count++; + + if (buffer->draw_tracker != nullptr) { + draw_graph.add_draw_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ); + } + + _check_transfer_worker_buffer(buffer); +} + void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) { ERR_RENDER_THREAD_GUARD(); @@ -5153,14 +5274,13 @@ void RenderingDevice::_wait_for_transfer_worker(TransferWorker *p_transfer_worke p_transfer_worker->operations_processed = p_transfer_worker->operations_submitted; } - if (!p_transfer_worker->texture_barriers.is_empty()) { - MutexLock transfer_worker_lock(transfer_worker_pool_mutex); - _flush_barriers_for_transfer_worker(p_transfer_worker); - } + _flush_barriers_for_transfer_worker(p_transfer_worker); } void RenderingDevice::_flush_barriers_for_transfer_worker(TransferWorker *p_transfer_worker) { + // Caller must have already acquired the mutex for the worker. if (!p_transfer_worker->texture_barriers.is_empty()) { + MutexLock transfer_worker_lock(transfer_worker_pool_texture_barriers_mutex); for (uint32_t i = 0; i < p_transfer_worker->texture_barriers.size(); i++) { transfer_worker_pool_texture_barriers.push_back(p_transfer_worker->texture_barriers[i]); } @@ -5233,8 +5353,11 @@ void RenderingDevice::_submit_transfer_workers(RDD::CommandBufferID p_draw_comma } } } +} - if (p_draw_command_buffer && !transfer_worker_pool_texture_barriers.is_empty()) { +void RenderingDevice::_submit_transfer_barriers(RDD::CommandBufferID p_draw_command_buffer) { + MutexLock transfer_worker_lock(transfer_worker_pool_texture_barriers_mutex); + if (!transfer_worker_pool_texture_barriers.is_empty()) { driver->command_pipeline_barrier(p_draw_command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, {}, {}, transfer_worker_pool_texture_barriers); transfer_worker_pool_texture_barriers.clear(); } @@ -5294,6 +5417,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id draw_tracker = RDG::resource_tracker_create(); draw_tracker->parent = owner_texture->draw_tracker; draw_tracker->texture_driver_id = p_texture->driver_id; + draw_tracker->texture_size = Size2i(p_texture->width, p_texture->height); draw_tracker->texture_subresources = p_texture->barrier_range(); draw_tracker->texture_usage = p_texture->usage_flags; draw_tracker->texture_slice_or_dirty_rect = p_texture->slice_rect; @@ -5316,6 +5440,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id // Regular texture. p_texture->draw_tracker = RDG::resource_tracker_create(); p_texture->draw_tracker->texture_driver_id = p_texture->driver_id; + p_texture->draw_tracker->texture_size = Size2i(p_texture->width, p_texture->height); p_texture->draw_tracker->texture_subresources = p_texture->barrier_range(); p_texture->draw_tracker->texture_usage = p_texture->usage_flags; p_texture->draw_tracker->reference_count = 1; @@ -5834,6 +5959,7 @@ void RenderingDevice::_end_frame() { // The command buffer must be copied into a stack variable as the driver workarounds can change the command buffer in use. RDD::CommandBufferID command_buffer = frames[frame].command_buffer; _submit_transfer_workers(command_buffer); + _submit_transfer_barriers(command_buffer); draw_graph.end(RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS, command_buffer, frames[frame].command_buffer_pool); driver->command_buffer_end(command_buffer); @@ -6553,6 +6679,12 @@ void RenderingDevice::finalize() { ERR_FAIL_COND(reverse_dependency_map.size()); } +void RenderingDevice::_set_max_fps(int p_max_fps) { + for (const KeyValue<DisplayServer::WindowID, RDD::SwapChainID> &it : screen_swap_chains) { + driver->swap_chain_set_max_fps(it.value, p_max_fps); + } +} + RenderingDevice *RenderingDevice::create_local_device() { RenderingDevice *rd = memnew(RenderingDevice); rd->initialize(context); @@ -6651,6 +6783,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_set_push_constant", "draw_list", "buffer", "size_bytes"), &RenderingDevice::_draw_list_set_push_constant); ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("draw_list_draw_indirect", "draw_list", "use_indices", "buffer", "offset", "draw_count", "stride"), &RenderingDevice::draw_list_draw_indirect, DEFVAL(0), DEFVAL(1), DEFVAL(0)); ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2())); ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor); @@ -7260,6 +7393,10 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(DEBUG_PASS); } +void RenderingDevice::make_current() { + render_thread_id = Thread::get_caller_id(); +} + RenderingDevice::~RenderingDevice() { finalize(); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 71ffbfbd88..ccfe51043b 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -1083,6 +1083,7 @@ public: Error screen_prepare_for_drawing(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID); int screen_get_width(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const; int screen_get_height(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const; + int screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const; FramebufferFormatID screen_get_framebuffer_format(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const; Error screen_free(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID); @@ -1186,6 +1187,7 @@ public: void draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size); void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0); + void draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset = 0, uint32_t p_draw_count = 1, uint32_t p_stride = 0); void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect); void draw_list_disable_scissor(DrawListID p_list); @@ -1283,6 +1285,7 @@ private: LocalVector<uint32_t> transfer_worker_pool_available_list; LocalVector<RDD::TextureBarrier> transfer_worker_pool_texture_barriers; BinaryMutex transfer_worker_pool_mutex; + BinaryMutex transfer_worker_pool_texture_barriers_mutex; ConditionVariable transfer_worker_pool_condition; TransferWorker *_acquire_transfer_worker(uint32_t p_transfer_size, uint32_t p_required_align, uint32_t &r_staging_offset); @@ -1297,6 +1300,7 @@ private: void _check_transfer_worker_vertex_array(VertexArray *p_vertex_array); void _check_transfer_worker_index_array(IndexArray *p_index_array); void _submit_transfer_workers(RDD::CommandBufferID p_draw_command_buffer = RDD::CommandBufferID()); + void _submit_transfer_barriers(RDD::CommandBufferID p_draw_command_buffer); void _wait_for_transfer_workers(); void _free_transfer_workers(); @@ -1427,6 +1431,8 @@ public: Error initialize(RenderingContextDriver *p_context, DisplayServer::WindowID p_main_window = DisplayServer::INVALID_WINDOW_ID); void finalize(); + void _set_max_fps(int p_max_fps); + void free(RID p_id); /****************/ @@ -1496,6 +1502,8 @@ public: static RenderingDevice *get_singleton(); + void make_current(); + RenderingDevice(); ~RenderingDevice(); diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp index d9ca286b15..e41a56b0a3 100644 --- a/servers/rendering/rendering_device_binds.cpp +++ b/servers/rendering/rendering_device_binds.cpp @@ -31,7 +31,10 @@ #include "rendering_device_binds.h" Error RDShaderFile::parse_versions_from_text(const String &p_text, const String p_defines, OpenIncludeFunction p_include_func, void *p_include_func_userdata) { - ERR_FAIL_NULL_V(RenderingDevice::get_singleton(), ERR_UNAVAILABLE); + ERR_FAIL_NULL_V_MSG( + RenderingDevice::get_singleton(), + ERR_UNAVAILABLE, + "Cannot import custom .glsl shaders when running without a RenderingDevice. This can happen if you are using the headless more or the Compatibility backend."); Vector<String> lines = p_text.split("\n"); diff --git a/servers/rendering/rendering_device_driver.cpp b/servers/rendering/rendering_device_driver.cpp index 9ff7b83215..c1a3f34af8 100644 --- a/servers/rendering/rendering_device_driver.cpp +++ b/servers/rendering/rendering_device_driver.cpp @@ -376,6 +376,8 @@ uint64_t RenderingDeviceDriver::api_trait_get(ApiTrait p_trait) { return true; case API_TRAIT_USE_GENERAL_IN_COPY_QUEUES: return false; + case API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS: + return false; default: ERR_FAIL_V(0); } diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h index 637d52c060..d2d14676db 100644 --- a/servers/rendering/rendering_device_driver.h +++ b/servers/rendering/rendering_device_driver.h @@ -120,9 +120,9 @@ struct VersatileResourceTemplate { class RenderingDeviceDriver : public RenderingDeviceCommons { public: struct ID { - size_t id = 0; + uint64_t id = 0; _ALWAYS_INLINE_ ID() = default; - _ALWAYS_INLINE_ ID(size_t p_id) : + _ALWAYS_INLINE_ ID(uint64_t p_id) : id(p_id) {} }; @@ -138,11 +138,9 @@ public: _ALWAYS_INLINE_ bool operator!=(const m_name##ID &p_other) const { return id != p_other.id; } \ _ALWAYS_INLINE_ m_name##ID(const m_name##ID &p_other) : ID(p_other.id) {} \ _ALWAYS_INLINE_ explicit m_name##ID(uint64_t p_int) : ID(p_int) {} \ - _ALWAYS_INLINE_ explicit m_name##ID(void *p_ptr) : ID((size_t)p_ptr) {} \ + _ALWAYS_INLINE_ explicit m_name##ID(void *p_ptr) : ID((uint64_t)p_ptr) {} \ _ALWAYS_INLINE_ m_name##ID() = default; \ - }; \ - /* Ensure type-punnable to pointer. Makes some things easier.*/ \ - static_assert(sizeof(m_name##ID) == sizeof(void *)); + }; // Id types declared before anything else to prevent cyclic dependencies between the different concerns. DEFINE_ID(Buffer); @@ -454,9 +452,16 @@ public: // Retrieve the render pass that can be used to draw on the swap chain's framebuffers. virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) = 0; + // Retrieve the rotation in degrees to apply as a pre-transform. Usually 0 on PC. May be 0, 90, 180 & 270 on Android. + virtual int swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) { return 0; } + // Retrieve the format used by the swap chain's framebuffers. virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) = 0; + // Tells the swapchain the max_fps so it can use the proper frame pacing. + // Android uses this with Swappy library. Some implementations or platforms may ignore this hint. + virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) {} + // Wait until all rendering associated to the swap chain is finished before deleting it. virtual void swap_chain_free(SwapChainID p_swap_chain) = 0; @@ -752,6 +757,7 @@ public: API_TRAIT_SECONDARY_VIEWPORT_SCISSOR, API_TRAIT_CLEARS_WITH_COPY_ENGINE, API_TRAIT_USE_GENERAL_IN_COPY_QUEUES, + API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS, }; enum ShaderChangeInvalidation { diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp index abcb76cd43..ebfe328393 100644 --- a/servers/rendering/rendering_device_graph.cpp +++ b/servers/rendering/rendering_device_graph.cpp @@ -140,6 +140,42 @@ RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage #endif } +bool RenderingDeviceGraph::_check_command_intersection(ResourceTracker *p_resource_tracker, int32_t p_previous_command_index, int32_t p_command_index) const { + if (p_resource_tracker->usage != RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE && p_resource_tracker->usage != RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE) { + // We don't check possible intersections for usages that aren't consecutive color or depth writes. + return true; + } + + const uint32_t previous_command_data_offset = command_data_offsets[p_previous_command_index]; + const uint32_t current_command_data_offset = command_data_offsets[p_command_index]; + const RecordedDrawListCommand &previous_draw_list_command = *reinterpret_cast<const RecordedDrawListCommand *>(&command_data[previous_command_data_offset]); + const RecordedDrawListCommand ¤t_draw_list_command = *reinterpret_cast<const RecordedDrawListCommand *>(&command_data[current_command_data_offset]); + if (previous_draw_list_command.type != RecordedCommand::TYPE_DRAW_LIST || current_draw_list_command.type != RecordedCommand::TYPE_DRAW_LIST) { + // We don't check possible intersections if both commands aren't draw lists. + return true; + } + + // We check if the region used by both draw lists have an intersection. + return previous_draw_list_command.region.intersects(current_draw_list_command.region); +} + +bool RenderingDeviceGraph::_check_command_partial_coverage(ResourceTracker *p_resource_tracker, int32_t p_command_index) const { + if (p_resource_tracker->usage != RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE && p_resource_tracker->usage != RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE) { + // We don't check for partial coverage in usages that aren't attachment writes. + return true; + } + + const uint32_t command_data_offset = command_data_offsets[p_command_index]; + const RecordedDrawListCommand &draw_list_command = *reinterpret_cast<const RecordedDrawListCommand *>(&command_data[command_data_offset]); + if (draw_list_command.type != RecordedCommand::TYPE_DRAW_LIST) { + // We don't check for partial coverage on commands that aren't draw lists. + return false; + } + + Rect2i texture_region(Point2i(0, 0), p_resource_tracker->texture_size); + return !draw_list_command.region.encloses(texture_region); +} + int32_t RenderingDeviceGraph::_add_to_command_list(int32_t p_command_index, int32_t p_list_index) { DEV_ASSERT(p_command_index < int32_t(command_count)); DEV_ASSERT(p_list_index < int32_t(command_list_nodes.size())); @@ -175,7 +211,7 @@ int32_t RenderingDeviceGraph::_add_to_slice_read_list(int32_t p_command_index, R return next_index; } -int32_t RenderingDeviceGraph::_add_to_write_list(int32_t p_command_index, Rect2i p_subresources, int32_t p_list_index) { +int32_t RenderingDeviceGraph::_add_to_write_list(int32_t p_command_index, Rect2i p_subresources, int32_t p_list_index, bool p_partial_coverage) { DEV_ASSERT(p_command_index < int32_t(command_count)); DEV_ASSERT(p_list_index < int32_t(write_slice_list_nodes.size())); @@ -186,6 +222,7 @@ int32_t RenderingDeviceGraph::_add_to_write_list(int32_t p_command_index, Rect2i new_node.command_index = p_command_index; new_node.next_list_index = p_list_index; new_node.subresources = p_subresources; + new_node.partial_coverage = p_partial_coverage; return next_index; } @@ -425,11 +462,9 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr #if USE_BUFFER_BARRIERS _add_buffer_barrier_to_command(resource_tracker->buffer_driver_id, resource_tracker->usage_access, new_usage_access, r_command->buffer_barrier_index, r_command->buffer_barrier_count); #endif - // FIXME: Memory barriers are currently pushed regardless of whether buffer barriers are being used or not. Refer to the comment on the - // definition of USE_BUFFER_BARRIERS for the reason behind this. This can be fixed to be one case or the other once it's been confirmed - // the buffer and memory barrier behavior discrepancy has been solved. - r_command->memory_barrier.src_access = resource_tracker->usage_access; - r_command->memory_barrier.dst_access = new_usage_access; + // Memory barriers are pushed regardless of buffer barriers being used or not. + r_command->memory_barrier.src_access = r_command->memory_barrier.src_access | resource_tracker->usage_access; + r_command->memory_barrier.dst_access = r_command->memory_barrier.dst_access | new_usage_access; } else { DEV_ASSERT(false && "Resource tracker does not contain a valid buffer or texture ID."); } @@ -438,12 +473,23 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr // Always update the access of the tracker according to the latest usage. resource_tracker->usage_access = new_usage_access; + // Always accumulate the stages of the tracker with the commands that use it. + search_tracker->current_frame_stages = search_tracker->current_frame_stages | r_command->self_stages; + + if (!search_tracker->previous_frame_stages.is_empty()) { + // Add to the command the stages the tracker was used on in the previous frame. + r_command->previous_stages = r_command->previous_stages | search_tracker->previous_frame_stages; + search_tracker->previous_frame_stages.clear(); + } + if (different_usage) { // Even if the usage of the resource isn't a write usage explicitly, a different usage implies a transition and it should therefore be considered a write. - write_usage = true; + // In the case of buffers however, this is not exactly necessary if the driver does not consider different buffer usages as different states. + write_usage = write_usage || bool(resource_tracker->texture_driver_id) || driver_buffers_require_transitions; resource_tracker->usage = new_resource_usage; } + bool write_usage_has_partial_coverage = !different_usage && _check_command_partial_coverage(resource_tracker, p_command_index); if (search_tracker->write_command_or_list_index >= 0) { if (search_tracker->write_command_list_enabled) { // Make this command adjacent to any commands that wrote to this resource and intersect with the slice if it applies. @@ -455,11 +501,11 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr if (!resource_has_parent || search_tracker_rect.intersects(write_list_node.subresources)) { if (write_list_node.command_index == p_command_index) { ERR_FAIL_COND_MSG(!resource_has_parent, "Command can't have itself as a dependency."); - } else { + } else if (!write_list_node.partial_coverage || _check_command_intersection(resource_tracker, write_list_node.command_index, p_command_index)) { // Command is dependent on this command. Add this command to the adjacency list of the write command. _add_adjacent_command(write_list_node.command_index, p_command_index, r_command); - if (resource_has_parent && write_usage && search_tracker_rect.encloses(write_list_node.subresources)) { + if (resource_has_parent && write_usage && search_tracker_rect.encloses(write_list_node.subresources) && !write_usage_has_partial_coverage) { // Eliminate redundant writes from the list. if (previous_write_list_index >= 0) { RecordedSliceListNode &previous_list_node = write_slice_list_nodes[previous_write_list_index]; @@ -488,15 +534,16 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr } if (write_usage) { - if (resource_has_parent) { + bool use_write_list = resource_has_parent || write_usage_has_partial_coverage; + if (use_write_list) { if (!search_tracker->write_command_list_enabled && search_tracker->write_command_or_list_index >= 0) { // Write command list was not being used but there was a write command recorded. Add a new node with the entire parent resource's subresources and the recorded command index to the list. const RDD::TextureSubresourceRange &tracker_subresources = search_tracker->texture_subresources; Rect2i tracker_rect(tracker_subresources.base_mipmap, tracker_subresources.base_layer, tracker_subresources.mipmap_count, tracker_subresources.layer_count); - search_tracker->write_command_or_list_index = _add_to_write_list(search_tracker->write_command_or_list_index, tracker_rect, -1); + search_tracker->write_command_or_list_index = _add_to_write_list(search_tracker->write_command_or_list_index, tracker_rect, -1, false); } - search_tracker->write_command_or_list_index = _add_to_write_list(p_command_index, search_tracker_rect, search_tracker->write_command_or_list_index); + search_tracker->write_command_or_list_index = _add_to_write_list(p_command_index, search_tracker_rect, search_tracker->write_command_or_list_index, write_usage_has_partial_coverage); search_tracker->write_command_list_enabled = true; } else { search_tracker->write_command_or_list_index = p_command_index; @@ -521,7 +568,7 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr read_full_command_list_index = read_full_next_index; } - if (!resource_has_parent) { + if (!use_write_list) { // Clear the full list if this resource is not a slice. search_tracker->read_full_command_list_index = -1; } @@ -531,7 +578,7 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr int32_t read_slice_command_list_index = search_tracker->read_slice_command_list_index; while (read_slice_command_list_index >= 0) { const RecordedSliceListNode &read_list_node = read_slice_list_nodes[read_slice_command_list_index]; - if (!resource_has_parent || search_tracker_rect.encloses(read_list_node.subresources)) { + if (!use_write_list || search_tracker_rect.encloses(read_list_node.subresources)) { if (previous_slice_command_list_index >= 0) { // Erase this element and connect the previous one to the next element. read_slice_list_nodes[previous_slice_command_list_index].next_list_index = read_list_node.next_list_index; @@ -699,6 +746,16 @@ void RenderingDeviceGraph::_run_draw_list_command(RDD::CommandBufferID p_command driver->command_render_draw_indexed(p_command_buffer, draw_indexed_instruction->index_count, draw_indexed_instruction->instance_count, draw_indexed_instruction->first_index, 0, 0); instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction); } break; + case DrawListInstruction::TYPE_DRAW_INDIRECT: { + const DrawListDrawIndirectInstruction *draw_indirect_instruction = reinterpret_cast<const DrawListDrawIndirectInstruction *>(instruction); + driver->command_render_draw_indirect(p_command_buffer, draw_indirect_instruction->buffer, draw_indirect_instruction->offset, draw_indirect_instruction->draw_count, draw_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndirectInstruction); + } break; + case DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT: { + const DrawListDrawIndexedIndirectInstruction *draw_indexed_indirect_instruction = reinterpret_cast<const DrawListDrawIndexedIndirectInstruction *>(instruction); + driver->command_render_draw_indexed_indirect(p_command_buffer, draw_indexed_indirect_instruction->buffer, draw_indexed_indirect_instruction->offset, draw_indexed_indirect_instruction->draw_count, draw_indexed_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndexedIndirectInstruction); + } break; case DrawListInstruction::TYPE_EXECUTE_COMMANDS: { const DrawListExecuteCommandsInstruction *execute_commands_instruction = reinterpret_cast<const DrawListExecuteCommandsInstruction *>(instruction); driver->command_buffer_execute_secondary(p_command_buffer, execute_commands_instruction->command_buffer); @@ -874,7 +931,7 @@ void RenderingDeviceGraph::_run_label_command_change(RDD::CommandBufferID p_comm } if (p_ignore_previous_value || p_new_label_index != r_current_label_index || p_new_level != r_current_label_level) { - if (!p_ignore_previous_value && (p_use_label_for_empty || r_current_label_index >= 0)) { + if (!p_ignore_previous_value && (p_use_label_for_empty || r_current_label_index >= 0 || r_current_label_level >= 0)) { // End the current label. driver->command_end_label(p_command_buffer); } @@ -888,6 +945,8 @@ void RenderingDeviceGraph::_run_label_command_change(RDD::CommandBufferID p_comm } else if (p_use_label_for_empty) { label_name = "Command graph"; label_color = Color(1, 1, 1, 1); + } else { + return; } // Add the level to the name. @@ -1178,6 +1237,16 @@ void RenderingDeviceGraph::_print_draw_list(const uint8_t *p_instruction_data, u print_line("\tDRAW INDICES", draw_indexed_instruction->index_count, "INSTANCES", draw_indexed_instruction->instance_count, "FIRST INDEX", draw_indexed_instruction->first_index); instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction); } break; + case DrawListInstruction::TYPE_DRAW_INDIRECT: { + const DrawListDrawIndirectInstruction *draw_indirect_instruction = reinterpret_cast<const DrawListDrawIndirectInstruction *>(instruction); + print_line("\tDRAW INDIRECT BUFFER ID", itos(draw_indirect_instruction->buffer.id), "OFFSET", draw_indirect_instruction->offset, "DRAW COUNT", draw_indirect_instruction->draw_count, "STRIDE", draw_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndirectInstruction); + } break; + case DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT: { + const DrawListDrawIndexedIndirectInstruction *draw_indexed_indirect_instruction = reinterpret_cast<const DrawListDrawIndexedIndirectInstruction *>(instruction); + print_line("\tDRAW INDEXED INDIRECT BUFFER ID", itos(draw_indexed_indirect_instruction->buffer.id), "OFFSET", draw_indexed_indirect_instruction->offset, "DRAW COUNT", draw_indexed_indirect_instruction->draw_count, "STRIDE", draw_indexed_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndexedIndirectInstruction); + } break; case DrawListInstruction::TYPE_EXECUTE_COMMANDS: { print_line("\tEXECUTE COMMANDS"); instruction_data_cursor += sizeof(DrawListExecuteCommandsInstruction); @@ -1287,6 +1356,7 @@ void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Dev driver_honors_barriers = driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS); driver_clears_with_copy_engine = driver->api_trait_get(RDD::API_TRAIT_CLEARS_WITH_COPY_ENGINE); + driver_buffers_require_transitions = driver->api_trait_get(RDD::API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS); } void RenderingDeviceGraph::finalize() { @@ -1404,7 +1474,9 @@ void RenderingDeviceGraph::add_buffer_update(RDD::BufferID p_dst, ResourceTracke void RenderingDeviceGraph::add_compute_list_begin(RDD::BreadcrumbMarker p_phase, uint32_t p_breadcrumb_data) { compute_instruction_list.clear(); +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) compute_instruction_list.breadcrumb = p_breadcrumb_data | (p_phase & ((1 << 16) - 1)); +#endif compute_instruction_list.index++; } @@ -1500,7 +1572,9 @@ void RenderingDeviceGraph::add_draw_list_begin(RDD::RenderPassID p_render_pass, draw_instruction_list.render_pass = p_render_pass; draw_instruction_list.framebuffer = p_framebuffer; draw_instruction_list.region = p_region; +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) draw_instruction_list.breadcrumb = p_breadcrumb; +#endif draw_instruction_list.clear_values.resize(p_clear_values.size()); for (uint32_t i = 0; i < p_clear_values.size(); i++) { draw_instruction_list.clear_values[i] = p_clear_values[i]; @@ -1596,6 +1670,26 @@ void RenderingDeviceGraph::add_draw_list_draw_indexed(uint32_t p_index_count, ui instruction->first_index = p_first_index; } +void RenderingDeviceGraph::add_draw_list_draw_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { + DrawListDrawIndirectInstruction *instruction = reinterpret_cast<DrawListDrawIndirectInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawIndirectInstruction))); + instruction->type = DrawListInstruction::TYPE_DRAW_INDIRECT; + instruction->buffer = p_buffer; + instruction->offset = p_offset; + instruction->draw_count = p_draw_count; + instruction->stride = p_stride; + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); +} + +void RenderingDeviceGraph::add_draw_list_draw_indexed_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { + DrawListDrawIndexedIndirectInstruction *instruction = reinterpret_cast<DrawListDrawIndexedIndirectInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawIndexedIndirectInstruction))); + instruction->type = DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT; + instruction->buffer = p_buffer; + instruction->offset = p_offset; + instruction->draw_count = p_draw_count; + instruction->stride = p_stride; + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); +} + void RenderingDeviceGraph::add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer) { DrawListExecuteCommandsInstruction *instruction = reinterpret_cast<DrawListExecuteCommandsInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListExecuteCommandsInstruction))); instruction->type = DrawListInstruction::TYPE_EXECUTE_COMMANDS; @@ -1711,7 +1805,9 @@ void RenderingDeviceGraph::add_draw_list_end() { command->framebuffer = draw_instruction_list.framebuffer; command->command_buffer_type = command_buffer_type; command->region = draw_instruction_list.region; +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) command->breadcrumb = draw_instruction_list.breadcrumb; +#endif command->clear_values_count = draw_instruction_list.clear_values.size(); RDD::RenderPassClearValue *clear_values = command->clear_values(); @@ -2064,7 +2160,7 @@ void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RD } } - _run_label_command_change(r_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level); + _run_label_command_change(r_command_buffer, -1, -1, false, false, nullptr, 0, current_label_index, current_label_level); #if PRINT_COMMAND_RECORDING print_line(vformat("Recorded %d commands", command_count)); diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h index e13e3a0429..f7d9027147 100644 --- a/servers/rendering/rendering_device_graph.h +++ b/servers/rendering/rendering_device_graph.h @@ -69,6 +69,8 @@ public: TYPE_CLEAR_ATTACHMENTS, TYPE_DRAW, TYPE_DRAW_INDEXED, + TYPE_DRAW_INDIRECT, + TYPE_DRAW_INDEXED_INDIRECT, TYPE_EXECUTE_COMMANDS, TYPE_NEXT_SUBPASS, TYPE_SET_BLEND_CONSTANTS, @@ -151,6 +153,8 @@ public: struct ResourceTracker { uint32_t reference_count = 0; int64_t command_frame = -1; + BitField<RDD::PipelineStageBits> previous_frame_stages; + BitField<RDD::PipelineStageBits> current_frame_stages; int32_t read_full_command_list_index = -1; int32_t read_slice_command_list_index = -1; int32_t write_command_or_list_index = -1; @@ -163,6 +167,7 @@ public: RDD::BufferID buffer_driver_id; RDD::TextureID texture_driver_id; RDD::TextureSubresourceRange texture_subresources; + Size2i texture_size; uint32_t texture_usage = 0; int32_t texture_slice_command_index = -1; ResourceTracker *parent = nullptr; @@ -174,8 +179,9 @@ public: _FORCE_INLINE_ void reset_if_outdated(int64_t new_command_frame) { if (new_command_frame != command_frame) { - usage_access.clear(); command_frame = new_command_frame; + previous_frame_stages = current_frame_stages; + current_frame_stages.clear(); read_full_command_list_index = -1; read_slice_command_list_index = -1; write_command_or_list_index = -1; @@ -218,14 +224,18 @@ private: }; struct ComputeInstructionList : InstructionList { +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) uint32_t breadcrumb; +#endif }; struct DrawInstructionList : InstructionList { RDD::RenderPassID render_pass; RDD::FramebufferID framebuffer; Rect2i region; +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) uint32_t breadcrumb; +#endif LocalVector<RDD::RenderPassClearValue> clear_values; }; @@ -262,6 +272,7 @@ private: int32_t command_index = -1; int32_t next_list_index = -1; Rect2i subresources; + bool partial_coverage = false; }; struct RecordedBufferClearCommand : RecordedCommand { @@ -314,7 +325,9 @@ private: RDD::FramebufferID framebuffer; RDD::CommandBufferType command_buffer_type; Rect2i region; +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) uint32_t breadcrumb = 0; +#endif uint32_t clear_values_count = 0; _FORCE_INLINE_ RDD::RenderPassClearValue *clear_values() { @@ -463,6 +476,20 @@ private: uint32_t first_index = 0; }; + struct DrawListDrawIndirectInstruction : DrawListInstruction { + RDD::BufferID buffer; + uint32_t offset = 0; + uint32_t draw_count = 0; + uint32_t stride = 0; + }; + + struct DrawListDrawIndexedIndirectInstruction : DrawListInstruction { + RDD::BufferID buffer; + uint32_t offset = 0; + uint32_t draw_count = 0; + uint32_t stride = 0; + }; + struct DrawListEndRenderPassInstruction : DrawListInstruction { // No contents. }; @@ -612,6 +639,7 @@ private: BarrierGroup barrier_group; bool driver_honors_barriers : 1; bool driver_clears_with_copy_engine : 1; + bool driver_buffers_require_transitions : 1; WorkaroundsState workarounds_state; TightLocalVector<Frame> frames; uint32_t frame = 0; @@ -623,10 +651,12 @@ private: static bool _is_write_usage(ResourceUsage p_usage); static RDD::TextureLayout _usage_to_image_layout(ResourceUsage p_usage); static RDD::BarrierAccessBits _usage_to_access_bits(ResourceUsage p_usage); + bool _check_command_intersection(ResourceTracker *p_resource_tracker, int32_t p_previous_command_index, int32_t p_command_index) const; + bool _check_command_partial_coverage(ResourceTracker *p_resource_tracker, int32_t p_command_index) const; int32_t _add_to_command_list(int32_t p_command_index, int32_t p_list_index); void _add_adjacent_command(int32_t p_previous_command_index, int32_t p_command_index, RecordedCommand *r_command); int32_t _add_to_slice_read_list(int32_t p_command_index, Rect2i p_subresources, int32_t p_list_index); - int32_t _add_to_write_list(int32_t p_command_index, Rect2i p_subresources, int32_t p_list_index); + int32_t _add_to_write_list(int32_t p_command_index, Rect2i p_subresources, int32_t p_list_index, bool p_partial_coverage); RecordedCommand *_allocate_command(uint32_t p_command_size, int32_t &r_command_index); DrawListInstruction *_allocate_draw_list_instruction(uint32_t p_instruction_size); ComputeListInstruction *_allocate_compute_list_instruction(uint32_t p_instruction_size); @@ -675,6 +705,8 @@ public: void add_draw_list_clear_attachments(VectorView<RDD::AttachmentClear> p_attachments_clear, VectorView<Rect2i> p_attachments_clear_rect); void add_draw_list_draw(uint32_t p_vertex_count, uint32_t p_instance_count); void add_draw_list_draw_indexed(uint32_t p_index_count, uint32_t p_instance_count, uint32_t p_first_index); + void add_draw_list_draw_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride); + void add_draw_list_draw_indexed_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride); void add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer); void add_draw_list_next_subpass(RDD::CommandBufferType p_command_buffer_type); void add_draw_list_set_blend_constants(const Color &p_color); diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h index 4c277ac215..34f11924ce 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -168,6 +168,7 @@ public: virtual void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0; + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0; virtual RID environment_get_sky(RID p_env) const = 0; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 20f1f9ad6f..2ec693cbbf 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -370,6 +370,8 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const { void RenderingServerDefault::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) { server_thread = Thread::get_caller_id(); server_task_id = p_pump_task_id; + // This is needed because the main RD is created on the main thread. + RenderingDevice::get_singleton()->make_current(); } void RenderingServerDefault::_thread_exit() { diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 225a67fb52..29b1e163c7 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -403,6 +403,7 @@ public: FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int) FUNC2(multimesh_set_buffer, RID, const Vector<float> &) + FUNC1RC(RID, multimesh_get_buffer_rd_rid, RID) FUNC1RC(Vector<float>, multimesh_get_buffer, RID) FUNC3(multimesh_set_buffer_interpolated, RID, const Vector<float> &, const Vector<float> &) @@ -443,6 +444,7 @@ public: FUNC2(light_set_cull_mask, RID, uint32_t) FUNC5(light_set_distance_fade, RID, bool, float, float, float) FUNC2(light_set_reverse_cull_face_mode, RID, bool) + FUNC2(light_set_shadow_caster_mask, RID, uint32_t) FUNC2(light_set_bake_mode, RID, LightBakeMode) FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t) @@ -785,10 +787,8 @@ public: FUNC2(environment_set_canvas_max_layer, RID, int) FUNC6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource) -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 FUNC2(environment_set_camera_feed_id, RID, int) -#endif + FUNC6(environment_set_ssr, RID, bool, int, float, float, float) FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality) diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 119ac677eb..f52963f98f 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -489,7 +489,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene struct_code += _typestr(m->datatype); } struct_code += " "; - struct_code += m->name; + struct_code += _mkid(m->name); if (m->array_size > 0) { struct_code += "["; struct_code += itos(m->array_size); @@ -1448,7 +1448,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } break; case SL::Node::NODE_TYPE_MEMBER: { SL::MemberNode *mnode = (SL::MemberNode *)p_node; - code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name; + String name; + if (mnode->basetype == SL::TYPE_STRUCT) { + name = _mkid(mnode->name); + } else { + name = mnode->name; + } + code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + name; if (mnode->index_expression != nullptr) { code += "["; code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index b6770c773c..7c4128b0e3 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -356,7 +356,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_CF_BREAK, "break", CF_BLOCK, {}, {} }, { TK_CF_CONTINUE, "continue", CF_BLOCK, {}, {} }, { TK_CF_RETURN, "return", CF_BLOCK, {}, {} }, - { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "fragment" } }, + { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "vertex" } }, // function specifier keywords @@ -3565,28 +3565,33 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI int argcount = args.size(); - if (p_function_info.stage_functions.has(name)) { - //stage based function - const StageFunctionInfo &sf = p_function_info.stage_functions[name]; - if (argcount != sf.arguments.size()) { - _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size())); - return false; - } - //validate arguments - for (int i = 0; i < argcount; i++) { - if (args[i] != sf.arguments[i].type) { - _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type))); - return false; - } - } + if (stages) { + // Stage functions can be used in custom functions as well, that why need to check them all. + for (const KeyValue<StringName, FunctionInfo> &E : *stages) { + if (E.value.stage_functions.has(name)) { + // Stage-based function. + const StageFunctionInfo &sf = E.value.stage_functions[name]; + if (argcount != sf.arguments.size()) { + _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size())); + return false; + } + // Validate arguments. + for (int i = 0; i < argcount; i++) { + if (args[i] != sf.arguments[i].type) { + _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type))); + return false; + } + } - if (r_ret_type) { - *r_ret_type = sf.return_type; - } - if (r_ret_type_str) { - *r_ret_type_str = ""; + if (r_ret_type) { + *r_ret_type = sf.return_type; + } + if (r_ret_type_str) { + *r_ret_type_str = ""; + } + return true; + } } - return true; } bool failed_builtin = false; @@ -5937,22 +5942,35 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons calls_info[current_function].calls.push_back(&calls_info[name]); } - int idx = 0; bool is_builtin = false; - while (frag_only_func_defs[idx].name) { - if (frag_only_func_defs[idx].name == name) { - // If a built-in function not found for the current shader type, then it shouldn't be parsed further. - if (!is_supported_frag_only_funcs) { - _set_error(vformat(RTR("Built-in function '%s' is not supported for the '%s' shader type."), name, shader_type_identifier)); - return nullptr; + if (is_supported_frag_only_funcs && stages) { + for (const KeyValue<StringName, FunctionInfo> &E : *stages) { + if (E.value.stage_functions.has(name)) { + // Register usage of the restricted stage function. + calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos()))); + is_builtin = true; + break; } - // Register usage of the restricted function. - calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos()))); - is_builtin = true; - break; } - idx++; + } + + if (!is_builtin) { + int idx = 0; + while (frag_only_func_defs[idx].name) { + if (frag_only_func_defs[idx].name == name) { + // If a built-in function not found for the current shader type, then it shouldn't be parsed further. + if (!is_supported_frag_only_funcs) { + _set_error(vformat(RTR("Built-in function '%s' is not supported for the '%s' shader type."), name, shader_type_identifier)); + return nullptr; + } + // Register usage of the restricted function. + calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos()))); + is_builtin = true; + break; + } + idx++; + } } // Recursively checks for the restricted function call. @@ -8581,6 +8599,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun block = block->parent_block; } } else if (tk.type == TK_CF_DISCARD) { + if (!is_discard_supported) { + _set_error(vformat(RTR("Use of '%s' is not supported for the '%s' shader type."), "discard", shader_type_identifier)); + return ERR_PARSE_ERROR; + } + //check return type BlockNode *b = p_block; while (b && !b->parent_function) { @@ -8592,7 +8615,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (!b->parent_function->can_discard) { - _set_error(vformat(RTR("Use of '%s' is not allowed here."), "discard")); + _set_error(vformat(RTR("'%s' cannot be used within the '%s' processor function."), "discard", b->parent_function->name)); return ERR_PARSE_ERROR; } @@ -8601,6 +8624,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun pos = _get_tkpos(); tk = _get_token(); + + calls_info[b->parent_function->name].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>("discard", CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, pos))); + if (tk.type != TK_SEMICOLON) { _set_expected_after_error(";", "discard"); return ERR_PARSE_ERROR; @@ -8838,7 +8864,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL; stages = &p_functions; - is_supported_frag_only_funcs = shader_type_identifier == "canvas_item" || shader_type_identifier == "spatial" || shader_type_identifier == "sky"; + + is_discard_supported = shader_type_identifier == "canvas_item" || shader_type_identifier == "spatial"; + is_supported_frag_only_funcs = is_discard_supported || shader_type_identifier == "sky"; const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo(); @@ -10332,6 +10360,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f if (p_functions.has(name)) { func_node->can_discard = p_functions[name].can_discard; + } else { + func_node->can_discard = is_discard_supported; // Allow use it for custom functions (in supported shader types). } if (!function_overload_count.has(name)) { @@ -10922,10 +10952,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ break; // Ignore hint keywords (parsed below). } if (keyword_list[i].flags & keyword_completion_context) { - if (keyword_list[i].excluded_shader_types.has(shader_type_identifier)) { - continue; - } - if (!keyword_list[i].functions.is_empty() && !keyword_list[i].functions.has(current_function)) { + if (keyword_list[i].excluded_shader_types.has(shader_type_identifier) || keyword_list[i].excluded_functions.has(current_function)) { continue; } ScriptLanguage::CodeCompletionOption option(keyword_list[i].text, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); @@ -11160,9 +11187,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ int idx = 0; bool low_end = RenderingServer::get_singleton()->is_low_end(); - if (stages && stages->has(skip_function)) { - for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[skip_function].stage_functions) { - matches.insert(String(E.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); + if (stages) { + // Stage functions can be used in custom functions as well, that why need to check them all. + for (const KeyValue<StringName, FunctionInfo> &E : *stages) { + for (const KeyValue<StringName, StageFunctionInfo> &F : E.value.stage_functions) { + if (F.value.skip_function == skip_function && stages->has(skip_function)) { + continue; + } + matches.insert(String(F.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); + } } } @@ -11292,9 +11325,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ return OK; } - if (stages && stages->has(block_function)) { - for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[block_function].stage_functions) { - if (completion_function == E.key) { + if (stages) { + // Stage functions can be used in custom functions as well, that why need to check them all. + for (const KeyValue<StringName, FunctionInfo> &S : *stages) { + for (const KeyValue<StringName, StageFunctionInfo> &E : S.value.stage_functions) { + // No need to check for the skip function here. + if (completion_function != E.key) { + continue; + } + calltip += get_datatype_name(E.value.return_type); calltip += " "; calltip += E.key; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index fb0a526230..4dade4d79f 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -859,6 +859,7 @@ public: Vector<Argument> arguments; DataType return_type = TYPE_VOID; + String skip_function; }; struct ModeInfo { @@ -934,7 +935,7 @@ private: const char *text; uint32_t flags; const Vector<String> excluded_shader_types; - const Vector<String> functions; + const Vector<String> excluded_functions; }; static const KeyWord keyword_list[]; @@ -1150,6 +1151,7 @@ private: const HashMap<StringName, FunctionInfo> *stages = nullptr; bool is_supported_frag_only_funcs = false; + bool is_discard_supported = false; bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); static const BuiltinFuncDef builtin_func_defs[]; @@ -1211,7 +1213,7 @@ public: struct ShaderCompileInfo { HashMap<StringName, FunctionInfo> functions; Vector<ModeInfo> render_modes; - VaryingFunctionNames varying_function_names = VaryingFunctionNames(); + VaryingFunctionNames varying_function_names; HashSet<String> shader_types; GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr; bool is_include = false; diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index 27e39551ba..88ea74cdfc 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -393,6 +393,8 @@ void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) { process_else(p_tokenizer); } else if (directive == "endif") { process_endif(p_tokenizer); + } else if (directive == "error") { + process_error(p_tokenizer); } else if (directive == "define") { process_define(p_tokenizer); } else if (directive == "undef") { @@ -466,7 +468,7 @@ void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) { const int line = p_tokenizer->get_line(); if (state->current_branch == nullptr || state->current_branch->else_defined) { - set_error(RTR("Unmatched elif."), line); + set_error(vformat(RTR("Unmatched '%s' directive."), "elif"), line); return; } if (state->previous_region != nullptr) { @@ -523,7 +525,7 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { const int line = p_tokenizer->get_line(); if (state->current_branch == nullptr || state->current_branch->else_defined) { - set_error(RTR("Unmatched else."), line); + set_error(vformat(RTR("Unmatched '%s' directive."), "else"), line); return; } if (state->previous_region != nullptr) { @@ -531,7 +533,7 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { } if (!p_tokenizer->consume_empty_line()) { - set_error(RTR("Invalid else."), p_tokenizer->get_line()); + set_error(vformat(RTR("Invalid '%s' directive."), "else"), line); } bool skip = false; @@ -559,7 +561,7 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) { state->condition_depth--; if (state->condition_depth < 0) { - set_error(RTR("Unmatched endif."), line); + set_error(vformat(RTR("Unmatched '%s' directive."), "endif"), line); return; } if (state->previous_region != nullptr) { @@ -568,13 +570,28 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) { } if (!p_tokenizer->consume_empty_line()) { - set_error(RTR("Invalid endif."), line); + set_error(vformat(RTR("Invalid '%s' directive."), "endif"), line); } state->current_branch = state->current_branch->parent; state->branches.pop_back(); } +void ShaderPreprocessor::process_error(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + const String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + if (body.is_empty()) { + set_error(" ", line); + } else { + set_error(body, line); + } + + if (!p_tokenizer->consume_empty_line()) { + set_error(vformat(RTR("Invalid '%s' directive."), "error"), line); + } +} + void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { const int line = p_tokenizer->get_line(); @@ -626,7 +643,7 @@ void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) { } if (!p_tokenizer->consume_empty_line()) { - set_error(RTR("Invalid ifdef."), line); + set_error(vformat(RTR("Invalid '%s' directive."), "ifdef"), line); return; } @@ -648,7 +665,7 @@ void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) { } if (!p_tokenizer->consume_empty_line()) { - set_error(RTR("Invalid ifndef."), line); + set_error(vformat(RTR("Invalid '%s' directive."), "ifndef"), line); return; } @@ -771,21 +788,21 @@ void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) { } if (label.is_empty()) { - set_error(RTR("Invalid pragma directive."), line); + set_error(vformat(RTR("Invalid '%s' directive."), "pragma"), line); return; } - // Rxplicitly handle pragma values here. + // Explicitly handle pragma values here. // If more pragma options are created, then refactor into a more defined structure. if (label == "disable_preprocessor") { state->disabled = true; } else { - set_error(RTR("Invalid pragma directive."), line); + set_error(vformat(RTR("Invalid '%s' directive."), "pragma"), line); return; } if (!p_tokenizer->consume_empty_line()) { - set_error(RTR("Invalid pragma directive."), line); + set_error(vformat(RTR("Invalid '%s' directive."), "pragma"), line); return; } } @@ -794,11 +811,16 @@ void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) { const int line = p_tokenizer->get_line(); const String label = p_tokenizer->get_identifier(); if (label.is_empty() || !p_tokenizer->consume_empty_line()) { - set_error(RTR("Invalid undef."), line); + set_error(vformat(RTR("Invalid '%s' directive."), "undef"), line); return; } if (state->defines.has(label)) { + if (state->defines[label]->is_builtin) { + set_error(vformat(RTR("Cannot use '%s' on built-in define."), "undef"), line); + return; + } + memdelete(state->defines[label]); state->defines.erase(label); } @@ -1307,6 +1329,35 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen pp_state.current_filename = p_filename; pp_state.save_regions = r_regions != nullptr; } + + // Built-in defines. + { + static HashMap<StringName, String> defines; + + if (defines.is_empty()) { + const String rendering_method = OS::get_singleton()->get_current_rendering_method(); + + if (rendering_method == "forward_plus") { + defines["CURRENT_RENDERER"] = _MKSTR(2); + } else if (rendering_method == "mobile") { + defines["CURRENT_RENDERER"] = _MKSTR(1); + } else { // gl_compatibility + defines["CURRENT_RENDERER"] = _MKSTR(0); + } + + defines["RENDERER_COMPATIBILITY"] = _MKSTR(0); + defines["RENDERER_MOBILE"] = _MKSTR(1); + defines["RENDERER_FORWARD_PLUS"] = _MKSTR(2); + } + + for (const KeyValue<StringName, String> &E : defines) { + Define *define = memnew(Define); + define->is_builtin = true; + define->body = E.value; + pp_state.defines[E.key] = define; + } + } + Error err = preprocess(&pp_state, p_code, r_result); if (err != OK) { if (r_error_text) { @@ -1383,6 +1434,7 @@ void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_inclu r_keywords->push_back("else"); } r_keywords->push_back("endif"); + r_keywords->push_back("error"); if (p_include_shader_keywords) { r_keywords->push_back("if"); } diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h index b29239105a..b3d9594bcb 100644 --- a/servers/rendering/shader_preprocessor.h +++ b/servers/rendering/shader_preprocessor.h @@ -132,6 +132,7 @@ private: struct Define { Vector<String> arguments; String body; + bool is_builtin = false; }; struct Branch { @@ -191,6 +192,7 @@ private: void process_elif(Tokenizer *p_tokenizer); void process_else(Tokenizer *p_tokenizer); void process_endif(Tokenizer *p_tokenizer); + void process_error(Tokenizer *p_tokenizer); void process_if(Tokenizer *p_tokenizer); void process_ifdef(Tokenizer *p_tokenizer); void process_ifndef(Tokenizer *p_tokenizer); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index f498c0bf93..4b71007ebf 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -63,6 +63,8 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; @@ -96,8 +98,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MAIN_CAM_INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = constt(ShaderLanguage::TYPE_VEC3); @@ -159,9 +159,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EYE_OFFSET"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); @@ -203,9 +200,8 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true; shader_modes[RS::SHADER_SPATIAL].functions["light"].main_function = true; @@ -284,6 +280,7 @@ ShaderTypes::ShaderTypes() { { ShaderLanguage::StageFunctionInfo func; + func.skip_function = "vertex"; func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("sdf_pos", ShaderLanguage::TYPE_VEC2)); func.return_type = ShaderLanguage::TYPE_FLOAT; //whether it could emit shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf"] = func; @@ -297,6 +294,7 @@ ShaderTypes::ShaderTypes() { { ShaderLanguage::StageFunctionInfo func; + func.skip_function = "vertex"; func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("uv", ShaderLanguage::TYPE_VEC2)); func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["screen_uv_to_sdf"] = func; diff --git a/servers/rendering/storage/camera_attributes_storage.h b/servers/rendering/storage/camera_attributes_storage.h index 6fbcd3da7d..afb8ad23cf 100644 --- a/servers/rendering/storage/camera_attributes_storage.h +++ b/servers/rendering/storage/camera_attributes_storage.h @@ -72,8 +72,8 @@ public: RendererCameraAttributes(); ~RendererCameraAttributes(); - CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); }; - bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); }; + CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); } + bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); } RID camera_attributes_allocate(); void camera_attributes_initialize(RID p_rid); diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp index 1bbb5da6bb..e7556f9000 100644 --- a/servers/rendering/storage/environment_storage.cpp +++ b/servers/rendering/storage/environment_storage.cpp @@ -189,6 +189,18 @@ RS::EnvironmentReflectionSource RendererEnvironmentStorage::environment_get_refl return env->reflection_source; } +void RendererEnvironmentStorage::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_NULL(env); + env->camera_feed_id = p_camera_feed_id; +} + +int RendererEnvironmentStorage::environment_get_camera_feed_id(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_NULL_V(env, -1); + return env->camera_feed_id; +} + // Tonemap void RendererEnvironmentStorage::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) { diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h index 9f78808ff7..6fdc047ba2 100644 --- a/servers/rendering/storage/environment_storage.h +++ b/servers/rendering/storage/environment_storage.h @@ -57,6 +57,7 @@ private: float ambient_light_energy = 1.0; float ambient_sky_contribution = 1.0; RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG; + int camera_feed_id = 0; // Tonemap RS::EnvironmentToneMapper tone_mapper; @@ -181,10 +182,8 @@ public: void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value); void environment_set_canvas_max_layer(RID p_env, int p_max_layer); void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG); -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); -#endif + int environment_get_camera_feed_id(RID p_env) const; RS::EnvironmentBG environment_get_background(RID p_env) const; RID environment_get_sky(RID p_env) const; diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index 6a0adfa596..1e149e3a97 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -59,6 +59,8 @@ public: virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0; + virtual uint32_t light_get_shadow_caster_mask(RID p_light) const = 0; virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0; virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; diff --git a/servers/rendering/storage/mesh_storage.cpp b/servers/rendering/storage/mesh_storage.cpp index 6680920c98..4a6746e6c9 100644 --- a/servers/rendering/storage/mesh_storage.cpp +++ b/servers/rendering/storage/mesh_storage.cpp @@ -223,6 +223,10 @@ void RendererMeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<flo _multimesh_set_buffer(p_multimesh, p_buffer); } +RID RendererMeshStorage::multimesh_get_buffer_rd_rid(RID p_multimesh) const { + return _multimesh_get_buffer_rd_rid(p_multimesh); +} + Vector<float> RendererMeshStorage::multimesh_get_buffer(RID p_multimesh) const { return _multimesh_get_buffer(p_multimesh); } diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h index 5e3a4738e6..6a8b385a69 100644 --- a/servers/rendering/storage/mesh_storage.h +++ b/servers/rendering/storage/mesh_storage.h @@ -141,6 +141,7 @@ public: virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const; virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer); + virtual RID multimesh_get_buffer_rd_rid(RID p_multimesh) const; virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const; virtual void multimesh_set_buffer_interpolated(RID p_multimesh, const Vector<float> &p_buffer, const Vector<float> &p_buffer_prev); @@ -178,6 +179,7 @@ public: virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; + virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const = 0; virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const = 0; virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; diff --git a/servers/rendering/storage/render_scene_buffers.cpp b/servers/rendering/storage/render_scene_buffers.cpp index 96e6492854..6d18ae2f77 100644 --- a/servers/rendering/storage/render_scene_buffers.cpp +++ b/servers/rendering/storage/render_scene_buffers.cpp @@ -81,7 +81,7 @@ void RenderSceneBuffersExtension::_bind_methods() { void RenderSceneBuffersExtension::configure(const RenderSceneBuffersConfiguration *p_config) { GDVIRTUAL_CALL(_configure, p_config); -}; +} void RenderSceneBuffersExtension::set_fsr_sharpness(float p_fsr_sharpness) { GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 32ef5261f3..2051d0caac 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -309,7 +309,7 @@ RID RenderingServer::get_white_texture() { w[i] = 255; } } - Ref<Image> white = memnew(Image(4, 4, 0, Image::FORMAT_RGB8, wt)); + Ref<Image> white = memnew(Image(4, 4, false, Image::FORMAT_RGB8, wt)); white_texture = texture_2d_create(white); return white_texture; } @@ -2067,6 +2067,16 @@ void RenderingServer::_particles_set_trail_bind_poses(RID p_particles, const Typ particles_set_trail_bind_poses(p_particles, tbposes); } +String RenderingServer::get_current_rendering_driver_name() const { + // Needs to remain in OS, since it's actually OS that interacts with it, but it's better exposed here. + return ::OS::get_singleton()->get_current_rendering_driver_name(); +} + +String RenderingServer::get_current_rendering_method() const { + // Needs to remain in OS, since it's actually OS that interacts with it, but it's better exposed here. + return ::OS::get_singleton()->get_current_rendering_method(); +} + Vector<uint8_t> _convert_surface_version_1_to_surface_version_2(uint64_t p_format, Vector<uint8_t> p_vertex_data, uint32_t p_vertex_count, uint32_t p_old_stride, uint32_t p_vertex_size, uint32_t p_normal_size, uint32_t p_position_stride, uint32_t p_normal_tangent_stride) { Vector<uint8_t> new_vertex_data; new_vertex_data.resize(p_vertex_data.size()); @@ -2442,6 +2452,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &RenderingServer::multimesh_set_visible_instances); ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &RenderingServer::multimesh_get_visible_instances); ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &RenderingServer::multimesh_set_buffer); + ClassDB::bind_method(D_METHOD("multimesh_get_buffer_rd_rid", "multimesh"), &RenderingServer::multimesh_get_buffer_rd_rid); ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &RenderingServer::multimesh_get_buffer); ClassDB::bind_method(D_METHOD("multimesh_set_buffer_interpolated", "multimesh", "buffer", "buffer_previous"), &RenderingServer::multimesh_set_buffer_interpolated); @@ -2479,6 +2490,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask); ClassDB::bind_method(D_METHOD("light_set_distance_fade", "decal", "enabled", "begin", "shadow", "length"), &RenderingServer::light_set_distance_fade); ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode); + ClassDB::bind_method(D_METHOD("light_set_shadow_caster_mask", "light", "mask"), &RenderingServer::light_set_shadow_caster_mask); ClassDB::bind_method(D_METHOD("light_set_bake_mode", "light", "bake_mode"), &RenderingServer::light_set_bake_mode); ClassDB::bind_method(D_METHOD("light_set_max_sdfgi_cascade", "light", "cascade"), &RenderingServer::light_set_max_sdfgi_cascade); @@ -2979,6 +2991,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("environment_create"), &RenderingServer::environment_create); ClassDB::bind_method(D_METHOD("environment_set_background", "env", "bg"), &RenderingServer::environment_set_background); + ClassDB::bind_method(D_METHOD("environment_set_camera_id", "env", "id"), &RenderingServer::environment_set_camera_feed_id); ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &RenderingServer::environment_set_sky); ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &RenderingServer::environment_set_sky_custom_fov); ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &RenderingServer::environment_set_sky_orientation); @@ -3421,6 +3434,9 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_video_adapter_type"), &RenderingServer::get_video_adapter_type); ClassDB::bind_method(D_METHOD("get_video_adapter_api_version"), &RenderingServer::get_video_adapter_api_version); + ClassDB::bind_method(D_METHOD("get_current_rendering_driver_name"), &RenderingServer::get_current_rendering_driver_name); + ClassDB::bind_method(D_METHOD("get_current_rendering_method"), &RenderingServer::get_current_rendering_method); + ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &RenderingServer::make_sphere_mesh); ClassDB::bind_method(D_METHOD("get_test_cube"), &RenderingServer::get_test_cube); @@ -3568,6 +3584,7 @@ void RenderingServer::init() { GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/shadow_atlas/size", PROPERTY_HINT_RANGE, "128,16384"), 2048); GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/2d/batching/item_buffer_size", PROPERTY_HINT_RANGE, "128,1048576,1"), 16384); + GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/2d/batching/uniform_set_cache_size", PROPERTY_HINT_RANGE, "256,1048576,1"), 256); // Number of commands that can be drawn per frame. GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/gl_compatibility/item_buffer_size", PROPERTY_HINT_RANGE, "128,1048576,1"), 16384); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 0208a640a5..0917af73c6 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -475,6 +475,7 @@ public: virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; + virtual RID multimesh_get_buffer_rd_rid(RID p_multimesh) const = 0; virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0; // Interpolation. @@ -542,6 +543,7 @@ public: virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0; enum LightBakeMode { LIGHT_BAKE_DISABLED, @@ -1179,6 +1181,7 @@ public: virtual void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG) = 0; + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; enum EnvironmentGlowBlendMode { ENV_GLOW_BLEND_MODE_ADDITIVE, @@ -1785,6 +1788,9 @@ public: virtual bool is_on_render_thread() = 0; virtual void call_on_render_thread(const Callable &p_callable) = 0; + String get_current_rendering_driver_name() const; + String get_current_rendering_method() const; + #ifdef TOOLS_ENABLED virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; #endif diff --git a/servers/text/text_server_dummy.h b/servers/text/text_server_dummy.h index 1a945ac221..10fe3b4595 100644 --- a/servers/text/text_server_dummy.h +++ b/servers/text/text_server_dummy.h @@ -88,7 +88,7 @@ public: virtual int64_t font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const override { return 0; } virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const override { return false; } virtual String font_get_supported_chars(const RID &p_font_rid) const override { return String(); } - virtual PackedInt32Array font_get_supported_glyphs(const RID &p_font_rid) const override { return PackedInt32Array(); }; + virtual PackedInt32Array font_get_supported_glyphs(const RID &p_font_rid) const override { return PackedInt32Array(); } virtual void font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const override {} virtual void font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const override {} diff --git a/servers/text_server.h b/servers/text_server.h index ba3fdaa35e..f448d62cb2 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -31,6 +31,7 @@ #ifndef TEXT_SERVER_H #define TEXT_SERVER_H +#include "core/io/image.h" #include "core/object/ref_counted.h" #include "core/os/os.h" #include "core/templates/rid.h" @@ -543,8 +544,8 @@ public: virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "", int64_t p_chars_per_line = 0) const = 0; virtual PackedInt32Array string_get_character_breaks(const String &p_string, const String &p_language = "") const; - virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; }; - virtual bool spoof_check(const String &p_string) const { return false; }; + virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; } + virtual bool spoof_check(const String &p_string) const { return false; } virtual String strip_diacritics(const String &p_string) const; virtual bool is_valid_identifier(const String &p_string) const; diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 26f315a454..e9d2fc8520 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -108,7 +108,7 @@ void XRInterface::_bind_methods() { BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_OPAQUE); BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_ADDITIVE); BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_ALPHA_BLEND); -}; +} bool XRInterface::is_primary() { XRServer *xr_server = XRServer::get_singleton(); @@ -155,7 +155,7 @@ PackedVector3Array XRInterface::get_play_area() const { // Note implementation is responsible for applying our reference frame and world scale to the raw data. // `play_area_changed` should be emitted if play area data is available and either the reference frame or world scale changes. return PackedVector3Array(); -}; +} /** these will only be implemented on AR interfaces, so we want dummies for VR **/ bool XRInterface::get_anchor_detection_is_enabled() const { diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index 55495731c5..abd5476fc9 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -138,7 +138,7 @@ public: virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */ virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */ virtual void pre_render() {} - virtual bool pre_draw_viewport(RID p_render_target) { return true; }; /* inform XR interface we are about to start our viewport draw process */ + virtual bool pre_draw_viewport(RID p_render_target) { return true; } /* inform XR interface we are about to start our viewport draw process */ virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* inform XR interface we finished our viewport draw process */ virtual void end_frame() {} diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp index b479237730..225dab272f 100644 --- a/servers/xr/xr_positional_tracker.cpp +++ b/servers/xr/xr_positional_tracker.cpp @@ -61,7 +61,7 @@ void XRPositionalTracker::_bind_methods() { ADD_SIGNAL(MethodInfo("input_float_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value"))); ADD_SIGNAL(MethodInfo("input_vector2_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector"))); ADD_SIGNAL(MethodInfo("profile_changed", PropertyInfo(Variant::STRING, "role"))); -}; +} void XRPositionalTracker::set_tracker_profile(const String &p_profile) { if (profile != p_profile) { @@ -77,12 +77,12 @@ String XRPositionalTracker::get_tracker_profile() const { XRPositionalTracker::TrackerHand XRPositionalTracker::get_tracker_hand() const { return tracker_hand; -}; +} void XRPositionalTracker::set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand) { ERR_FAIL_INDEX(p_hand, TRACKER_HAND_MAX); tracker_hand = p_hand; -}; +} bool XRPositionalTracker::has_pose(const StringName &p_action_name) const { return poses.has(p_action_name); diff --git a/servers/xr/xr_tracker.cpp b/servers/xr/xr_tracker.cpp index 0b917a5dc3..b0b2f3f30a 100644 --- a/servers/xr/xr_tracker.cpp +++ b/servers/xr/xr_tracker.cpp @@ -42,24 +42,24 @@ void XRTracker::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tracker_desc"), &XRTracker::get_tracker_desc); ClassDB::bind_method(D_METHOD("set_tracker_desc", "description"), &XRTracker::set_tracker_desc); ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_tracker_desc", "get_tracker_desc"); -}; +} void XRTracker::set_tracker_type(XRServer::TrackerType p_type) { type = p_type; -}; +} XRServer::TrackerType XRTracker::get_tracker_type() const { return type; -}; +} void XRTracker::set_tracker_name(const StringName &p_name) { // Note: this should not be changed after the tracker is registered with the XRServer! name = p_name; -}; +} StringName XRTracker::get_tracker_name() const { return name; -}; +} void XRTracker::set_tracker_desc(const String &p_desc) { description = p_desc; diff --git a/tests/core/config/test_project_settings.h b/tests/core/config/test_project_settings.h index 0e1058a626..5a000b19a0 100644 --- a/tests/core/config/test_project_settings.h +++ b/tests/core/config/test_project_settings.h @@ -40,7 +40,7 @@ class TestProjectSettingsInternalsAccessor { public: static String &resource_path() { return ProjectSettings::get_singleton()->resource_path; - }; + } }; namespace TestProjectSettings { diff --git a/tests/core/io/test_file_access.h b/tests/core/io/test_file_access.h index a4d3fd1d70..00d33eaf30 100644 --- a/tests/core/io/test_file_access.h +++ b/tests/core/io/test_file_access.h @@ -39,7 +39,7 @@ namespace TestFileAccess { TEST_CASE("[FileAccess] CSV read") { Ref<FileAccess> f = FileAccess::open(TestUtils::get_data_path("testdata.csv"), FileAccess::READ); - REQUIRE(!f.is_null()); + REQUIRE(f.is_valid()); Vector<String> header = f->get_csv_line(); // Default delimiter: ",". REQUIRE(header.size() == 4); @@ -107,6 +107,98 @@ TEST_CASE("[FileAccess] Get as UTF-8 String") { CHECK(s_cr == "Hello darkness\rMy old friend\rI've come to talk\rWith you again\r"); CHECK(s_cr_nocr == "Hello darknessMy old friendI've come to talkWith you again"); } + +TEST_CASE("[FileAccess] Get/Store floating point values") { + // BigEndian Hex: 0x40490E56 + // LittleEndian Hex: 0x560E4940 + float value = 3.1415f; + + SUBCASE("Little Endian") { + const String file_path = TestUtils::get_data_path("floating_point_little_endian.bin"); + const String file_path_new = TestUtils::get_data_path("floating_point_little_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + CHECK_EQ(f->get_float(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->store_float(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } + + SUBCASE("Big Endian") { + const String file_path = TestUtils::get_data_path("floating_point_big_endian.bin"); + const String file_path_new = TestUtils::get_data_path("floating_point_big_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + f->set_big_endian(true); + CHECK_EQ(f->get_float(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->set_big_endian(true); + fw->store_float(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } +} + +TEST_CASE("[FileAccess] Get/Store floating point half precision values") { + // IEEE 754 half-precision binary floating-point format: + // sign exponent (5 bits) fraction (10 bits) + // 0 01101 0101010101 + // BigEndian Hex: 0x3555 + // LittleEndian Hex: 0x5535 + float value = 0.33325195f; + + SUBCASE("Little Endian") { + const String file_path = TestUtils::get_data_path("half_precision_floating_point_little_endian.bin"); + const String file_path_new = TestUtils::get_data_path("half_precision_floating_point_little_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + CHECK_EQ(f->get_half(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->store_half(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } + + SUBCASE("Big Endian") { + const String file_path = TestUtils::get_data_path("half_precision_floating_point_big_endian.bin"); + const String file_path_new = TestUtils::get_data_path("half_precision_floating_point_big_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + f->set_big_endian(true); + CHECK_EQ(f->get_half(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->set_big_endian(true); + fw->store_half(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } +} + } // namespace TestFileAccess #endif // TEST_FILE_ACCESS_H diff --git a/tests/core/io/test_marshalls.h b/tests/core/io/test_marshalls.h index de8d6e1406..eb92c3f752 100644 --- a/tests/core/io/test_marshalls.h +++ b/tests/core/io/test_marshalls.h @@ -90,6 +90,20 @@ TEST_CASE("[Marshalls] Unsigned 64 bit integer decoding") { CHECK(decode_uint64(arr) == 0x0f123456789abcdef); } +TEST_CASE("[Marshalls] Floating point half precision encoding") { + uint8_t arr[2]; + + // Decimal: 0.33325195 + // IEEE 754 half-precision binary floating-point format: + // sign exponent (5 bits) fraction (10 bits) + // 0 01101 0101010101 + // Hexadecimal: 0x3555 + unsigned int actual_size = encode_half(0.33325195f, arr); + CHECK(actual_size == sizeof(uint16_t)); + CHECK(arr[0] == 0x55); + CHECK(arr[1] == 0x35); +} + TEST_CASE("[Marshalls] Floating point single precision encoding") { uint8_t arr[4]; @@ -126,6 +140,13 @@ TEST_CASE("[Marshalls] Floating point double precision encoding") { CHECK(arr[7] == 0x3f); } +TEST_CASE("[Marshalls] Floating point half precision decoding") { + uint8_t arr[] = { 0x55, 0x35 }; + + // See floating point half precision encoding test case for details behind expected values. + CHECK(decode_half(arr) == 0.33325195f); +} + TEST_CASE("[Marshalls] Floating point single precision decoding") { uint8_t arr[] = { 0x00, 0x00, 0x20, 0x3e }; @@ -160,7 +181,7 @@ TEST_CASE("[Marshalls] NIL Variant encoding") { uint8_t buffer[4]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 4, "Length == 4 bytes for header"); + CHECK_MESSAGE(r_len == 4, "Length == 4 bytes for header."); CHECK_MESSAGE(buffer[0] == 0x00, "Variant::NIL"); CHECK(buffer[1] == 0x00); CHECK(buffer[2] == 0x00); @@ -174,7 +195,7 @@ TEST_CASE("[Marshalls] INT 32 bit Variant encoding") { uint8_t buffer[8]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for int32_t"); + CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for `int32_t`."); CHECK_MESSAGE(buffer[0] == 0x02, "Variant::INT"); CHECK(buffer[1] == 0x00); CHECK(buffer[2] == 0x00); @@ -192,7 +213,7 @@ TEST_CASE("[Marshalls] INT 64 bit Variant encoding") { uint8_t buffer[12]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for int64_t"); + CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for `int64_t`."); CHECK_MESSAGE(buffer[0] == 0x02, "Variant::INT"); CHECK(buffer[1] == 0x00); CHECK_MESSAGE(buffer[2] == 0x01, "HEADER_DATA_FLAG_64"); @@ -214,7 +235,7 @@ TEST_CASE("[Marshalls] FLOAT single precision Variant encoding") { uint8_t buffer[8]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for float"); + CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for `float`."); CHECK_MESSAGE(buffer[0] == 0x03, "Variant::FLOAT"); CHECK(buffer[1] == 0x00); CHECK(buffer[2] == 0x00); @@ -232,7 +253,7 @@ TEST_CASE("[Marshalls] FLOAT double precision Variant encoding") { uint8_t buffer[12]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for double"); + CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for `double`."); CHECK_MESSAGE(buffer[0] == 0x03, "Variant::FLOAT"); CHECK(buffer[1] == 0x00); CHECK_MESSAGE(buffer[2] == 0x01, "HEADER_DATA_FLAG_64"); @@ -335,10 +356,10 @@ TEST_CASE("[Marshalls] Typed array encoding") { uint8_t buffer[24]; CHECK(encode_variant(array, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 24, "Length == 4 bytes for header + 4 bytes for array type + 4 bytes for array size + 12 bytes for element"); + CHECK_MESSAGE(r_len == 24, "Length == 4 bytes for header + 4 bytes for array type + 4 bytes for array size + 12 bytes for element."); CHECK_MESSAGE(buffer[0] == 0x1c, "Variant::ARRAY"); CHECK(buffer[1] == 0x00); - CHECK_MESSAGE(buffer[2] == 0x01, "HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN"); + CHECK_MESSAGE(buffer[2] == 0x01, "CONTAINER_TYPE_KIND_BUILTIN"); CHECK(buffer[3] == 0x00); // Check array type. CHECK_MESSAGE(buffer[4] == 0x02, "Variant::INT"); @@ -370,7 +391,7 @@ TEST_CASE("[Marshalls] Typed array decoding") { Variant variant; int r_len; uint8_t buffer[] = { - 0x1c, 0x00, 0x01, 0x00, // Variant::ARRAY, HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN + 0x1c, 0x00, 0x01, 0x00, // Variant::ARRAY, CONTAINER_TYPE_KIND_BUILTIN 0x02, 0x00, 0x00, 0x00, // Array type (Variant::INT). 0x01, 0x00, 0x00, 0x00, // Array size. 0x02, 0x00, 0x01, 0x00, // Element type (Variant::INT, HEADER_DATA_FLAG_64). @@ -386,6 +407,89 @@ TEST_CASE("[Marshalls] Typed array decoding") { CHECK(array[0] == Variant(uint64_t(0x0f123456789abcdef))); } +TEST_CASE("[Marshalls] Typed dicttionary encoding") { + int r_len; + Dictionary dictionary; + dictionary.set_typed(Variant::INT, StringName(), Ref<Script>(), Variant::INT, StringName(), Ref<Script>()); + dictionary[Variant(uint64_t(0x0f123456789abcdef))] = Variant(uint64_t(0x0f123456789abcdef)); + uint8_t buffer[40]; + + CHECK(encode_variant(dictionary, buffer, r_len) == OK); + CHECK_MESSAGE(r_len == 40, "Length == 4 bytes for header + 8 bytes for dictionary type + 4 bytes for dictionary size + 24 bytes for key-value pair."); + CHECK_MESSAGE(buffer[0] == 0x1b, "Variant::DICTIONARY"); + CHECK(buffer[1] == 0x00); + CHECK_MESSAGE(buffer[2] == 0x05, "key: CONTAINER_TYPE_KIND_BUILTIN | value: CONTAINER_TYPE_KIND_BUILTIN"); + CHECK(buffer[3] == 0x00); + // Check dictionary key type. + CHECK_MESSAGE(buffer[4] == 0x02, "Variant::INT"); + CHECK(buffer[5] == 0x00); + CHECK(buffer[6] == 0x00); + CHECK(buffer[7] == 0x00); + // Check dictionary value type. + CHECK_MESSAGE(buffer[8] == 0x02, "Variant::INT"); + CHECK(buffer[9] == 0x00); + CHECK(buffer[10] == 0x00); + CHECK(buffer[11] == 0x00); + // Check dictionary size. + CHECK(buffer[12] == 0x01); + CHECK(buffer[13] == 0x00); + CHECK(buffer[14] == 0x00); + CHECK(buffer[15] == 0x00); + // Check key type. + CHECK_MESSAGE(buffer[16] == 0x02, "Variant::INT"); + CHECK(buffer[17] == 0x00); + CHECK_MESSAGE(buffer[18] == 0x01, "HEADER_DATA_FLAG_64"); + CHECK(buffer[19] == 0x00); + // Check key value. + CHECK(buffer[20] == 0xef); + CHECK(buffer[21] == 0xcd); + CHECK(buffer[22] == 0xab); + CHECK(buffer[23] == 0x89); + CHECK(buffer[24] == 0x67); + CHECK(buffer[25] == 0x45); + CHECK(buffer[26] == 0x23); + CHECK(buffer[27] == 0xf1); + // Check value type. + CHECK_MESSAGE(buffer[28] == 0x02, "Variant::INT"); + CHECK(buffer[29] == 0x00); + CHECK_MESSAGE(buffer[30] == 0x01, "HEADER_DATA_FLAG_64"); + CHECK(buffer[31] == 0x00); + // Check value value. + CHECK(buffer[32] == 0xef); + CHECK(buffer[33] == 0xcd); + CHECK(buffer[34] == 0xab); + CHECK(buffer[35] == 0x89); + CHECK(buffer[36] == 0x67); + CHECK(buffer[37] == 0x45); + CHECK(buffer[38] == 0x23); + CHECK(buffer[39] == 0xf1); +} + +TEST_CASE("[Marshalls] Typed dictionary decoding") { + Variant variant; + int r_len; + uint8_t buffer[] = { + 0x1b, 0x00, 0x05, 0x00, // Variant::DICTIONARY, key: CONTAINER_TYPE_KIND_BUILTIN | value: CONTAINER_TYPE_KIND_BUILTIN + 0x02, 0x00, 0x00, 0x00, // Dictionary key type (Variant::INT). + 0x02, 0x00, 0x00, 0x00, // Dictionary value type (Variant::INT). + 0x01, 0x00, 0x00, 0x00, // Dictionary size. + 0x02, 0x00, 0x01, 0x00, // Key type (Variant::INT, HEADER_DATA_FLAG_64). + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0xf1, // Key value. + 0x02, 0x00, 0x01, 0x00, // Value type (Variant::INT, HEADER_DATA_FLAG_64). + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0xf1, // Value value. + }; + + CHECK(decode_variant(variant, buffer, 40, &r_len) == OK); + CHECK(r_len == 40); + CHECK(variant.get_type() == Variant::DICTIONARY); + Dictionary dictionary = variant; + CHECK(dictionary.get_typed_key_builtin() == Variant::INT); + CHECK(dictionary.get_typed_value_builtin() == Variant::INT); + CHECK(dictionary.size() == 1); + CHECK(dictionary.has(Variant(uint64_t(0x0f123456789abcdef)))); + CHECK(dictionary[Variant(uint64_t(0x0f123456789abcdef))] == Variant(uint64_t(0x0f123456789abcdef))); +} + } // namespace TestMarshalls #endif // TEST_MARSHALLS_H diff --git a/tests/core/io/test_stream_peer.h b/tests/core/io/test_stream_peer.h index 31bd69edd0..961b4ac070 100644 --- a/tests/core/io/test_stream_peer.h +++ b/tests/core/io/test_stream_peer.h @@ -127,6 +127,17 @@ TEST_CASE("[StreamPeer] Get and sets through StreamPeerBuffer") { CHECK_EQ(spb->get_u64(), value); } + SUBCASE("A half-precision float value") { + float value = 3.1415927f; + float expected = 3.14062f; + + spb->clear(); + spb->put_half(value); + spb->seek(0); + + CHECK(spb->get_half() == doctest::Approx(expected)); + } + SUBCASE("A float value") { float value = 42.0f; @@ -255,6 +266,17 @@ TEST_CASE("[StreamPeer] Get and sets big endian through StreamPeerBuffer") { CHECK_EQ(spb->get_float(), value); } + SUBCASE("A half-precision float value") { + float value = 3.1415927f; + float expected = 3.14062f; + + spb->clear(); + spb->put_half(value); + spb->seek(0); + + CHECK(spb->get_half() == doctest::Approx(expected)); + } + SUBCASE("A double value") { double value = 42.0; diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h index 741e6af5d4..eb6977fd69 100644 --- a/tests/core/math/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -48,7 +48,7 @@ TEST_CASE("[AABB] Constructor methods") { TEST_CASE("[AABB] String conversion") { CHECK_MESSAGE( - String(AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6))) == "[P: (-1.5, 2, -2.5), S: (4, 5, 6)]", + String(AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6))) == "[P: (-1.5, 2.0, -2.5), S: (4.0, 5.0, 6.0)]", "The string representation should match the expected value."); } diff --git a/tests/core/math/test_color.h b/tests/core/math/test_color.h index bd2d4f40e5..3d36079102 100644 --- a/tests/core/math/test_color.h +++ b/tests/core/math/test_color.h @@ -140,7 +140,7 @@ TEST_CASE("[Color] Conversion methods") { cyan.to_rgba64() == 0x0000'ffff'ffff'ffff, "The returned 64-bit BGR number should match the expected value."); CHECK_MESSAGE( - String(cyan) == "(0, 1, 1, 1)", + String(cyan) == "(0.0, 1.0, 1.0, 1.0)", "The string representation should match the expected value."); } diff --git a/tests/core/math/test_projection.h b/tests/core/math/test_projection.h new file mode 100644 index 0000000000..7f41aaee3e --- /dev/null +++ b/tests/core/math/test_projection.h @@ -0,0 +1,87 @@ +/**************************************************************************/ +/* test_projection.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_PROJECTION_H +#define TEST_PROJECTION_H + +#include "core/math/projection.h" + +#include "core/string/print_string.h" +#include "tests/test_macros.h" + +namespace TestProjection { + +TEST_CASE("[Projection] Default construct") { + Projection p; + CHECK(p.columns[0][0] == 1.0); + CHECK(p.columns[0][1] == 0.0); + CHECK(p.columns[0][2] == 0.0); + CHECK(p.columns[0][3] == 0.0); + + CHECK(p.columns[1][0] == 0.0); + CHECK(p.columns[1][1] == 1.0); + CHECK(p.columns[1][2] == 0.0); + CHECK(p.columns[1][3] == 0.0); + + CHECK(p.columns[2][0] == 0.0); + CHECK(p.columns[2][1] == 0.0); + CHECK(p.columns[2][2] == 1.0); + CHECK(p.columns[2][3] == 0.0); + + CHECK(p.columns[3][0] == 0.0); + CHECK(p.columns[3][1] == 0.0); + CHECK(p.columns[3][2] == 0.0); + CHECK(p.columns[3][3] == 1.0); +} + +bool projection_is_equal_approx(const Projection &p_a, const Projection &p_b) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (!Math::is_equal_approx(p_a.columns[i][j], p_b.columns[i][j])) { + return false; + } + } + } + return true; +} + +TEST_CASE("[Projection] Orthogonal projection matrix inversion") { + Projection p = Projection::create_orthogonal(-125.0f, 125.0f, -125.0f, 125.0f, 0.01f, 25.0f); + CHECK(projection_is_equal_approx(p.inverse() * p, Projection())); +} + +TEST_CASE("[Projection] Perspective projection matrix inversion") { + Projection p = Projection::create_perspective(90.0f, 1.77777f, 0.05f, 4000.0f); + CHECK(projection_is_equal_approx(p.inverse() * p, Projection())); +} + +} //namespace TestProjection + +#endif // TEST_PROJECTION_H diff --git a/tests/core/math/test_rect2.h b/tests/core/math/test_rect2.h index c4368808a6..a93bfeb71b 100644 --- a/tests/core/math/test_rect2.h +++ b/tests/core/math/test_rect2.h @@ -57,7 +57,7 @@ TEST_CASE("[Rect2] Constructor methods") { TEST_CASE("[Rect2] String conversion") { // Note: This also depends on the Vector2 string representation. CHECK_MESSAGE( - String(Rect2(0, 100, 1280, 720)) == "[P: (0, 100), S: (1280, 720)]", + String(Rect2(0, 100, 1280, 720)) == "[P: (0.0, 100.0), S: (1280.0, 720.0)]", "The string representation should match the expected value."); } diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h index 924e93129d..b38d3d3e61 100644 --- a/tests/core/object/test_class_db.h +++ b/tests/core/object/test_class_db.h @@ -863,16 +863,19 @@ void add_global_enums(Context &r_context) { } } - // HARDCODED - List<StringName> hardcoded_enums; - hardcoded_enums.push_back("Vector2.Axis"); - hardcoded_enums.push_back("Vector2i.Axis"); - hardcoded_enums.push_back("Vector3.Axis"); - hardcoded_enums.push_back("Vector3i.Axis"); - for (const StringName &E : hardcoded_enums) { - // These enums are not generated and must be written manually (e.g.: Vector3.Axis) - // Here, we assume core types do not begin with underscore - r_context.enum_types.push_back(E); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + if (i == Variant::OBJECT) { + continue; + } + + const Variant::Type type = Variant::Type(i); + + List<StringName> enum_names; + Variant::get_enums_for_type(type, &enum_names); + + for (const StringName &enum_name : enum_names) { + r_context.enum_types.push_back(Variant::get_type_name(type) + "." + enum_name); + } } } diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h index e703698ec6..55c53e2d03 100644 --- a/tests/core/object/test_object.h +++ b/tests/core/object/test_object.h @@ -95,10 +95,10 @@ public: } bool property_can_revert(const StringName &p_name) const override { return false; - }; + } bool property_get_revert(const StringName &p_name, Variant &r_ret) const override { return false; - }; + } void get_method_list(List<MethodInfo> *p_list) const override { } bool has_method(const StringName &p_method) const override { diff --git a/tests/core/string/test_fuzzy_search.h b/tests/core/string/test_fuzzy_search.h new file mode 100644 index 0000000000..d647ebdd1a --- /dev/null +++ b/tests/core/string/test_fuzzy_search.h @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* test_fuzzy_search.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_FUZZY_SEARCH_H +#define TEST_FUZZY_SEARCH_H + +#include "core/string/fuzzy_search.h" +#include "tests/test_macros.h" + +namespace TestFuzzySearch { + +struct FuzzySearchTestCase { + String query; + String expected; +}; + +// Ideally each of these test queries should represent a different aspect, and potentially bottleneck, of the search process. +const FuzzySearchTestCase test_cases[] = { + // Short query, many matches, few adjacent characters + { "///gd", "./menu/hud/hud.gd" }, + // Filename match with typo + { "sm.png", "./entity/blood_sword/sam.png" }, + // Multipart filename word matches + { "ham ", "./entity/game_trap/ha_missed_me.wav" }, + // Single word token matches + { "push background", "./entity/background_zone1/background/push.png" }, + // Long token matches + { "background_freighter background png", "./entity/background_freighter/background/background.png" }, + // Many matches, many short tokens + { "menu menu characters wav", "./menu/menu/characters/smoker/0.wav" }, + // Maximize total matches + { "entity gd", "./entity/entity_man.gd" } +}; + +Vector<String> load_test_data() { + Ref<FileAccess> fp = FileAccess::open(TestUtils::get_data_path("fuzzy_search/project_dir_tree.txt"), FileAccess::READ); + REQUIRE(fp.is_valid()); + return fp->get_as_utf8_string().split("\n"); +} + +TEST_CASE("[FuzzySearch] Test fuzzy search results") { + FuzzySearch search; + Vector<FuzzySearchResult> results; + Vector<String> targets = load_test_data(); + + for (FuzzySearchTestCase test_case : test_cases) { + search.set_query(test_case.query); + search.search_all(targets, results); + CHECK_GT(results.size(), 0); + CHECK_EQ(results[0].target, test_case.expected); + } +} + +} //namespace TestFuzzySearch + +#endif // TEST_FUZZY_SEARCH_H diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index 8559737e74..9adc97e845 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -389,6 +389,19 @@ TEST_CASE("[String] Find") { MULTICHECK_STRING_INT_EQ(s, rfind, "", 15, -1); } +TEST_CASE("[String] Find character") { + String s = "racecar"; + CHECK_EQ(s.find_char('r'), 0); + CHECK_EQ(s.find_char('r', 1), 6); + CHECK_EQ(s.find_char('e'), 3); + CHECK_EQ(s.find_char('e', 4), -1); + + CHECK_EQ(s.rfind_char('r'), 6); + CHECK_EQ(s.rfind_char('r', 5), 0); + CHECK_EQ(s.rfind_char('e'), 3); + CHECK_EQ(s.rfind_char('e', 2), -1); +} + TEST_CASE("[String] Find case insensitive") { String s = "Pretty Whale Whale"; MULTICHECK_STRING_EQ(s, findn, "WHA", 7); @@ -455,16 +468,32 @@ TEST_CASE("[String] Erasing") { } TEST_CASE("[String] Number to string") { - CHECK(String::num(0) == "0"); - CHECK(String::num(0.0) == "0"); // No trailing zeros. - CHECK(String::num(-0.0) == "-0"); // Includes sign even for zero. + CHECK(String::num(0) == "0.0"); // The method takes double, so always add zeros. + CHECK(String::num(0.0) == "0.0"); + CHECK(String::num(-0.0) == "-0.0"); // Includes sign even for zero. CHECK(String::num(3.141593) == "3.141593"); CHECK(String::num(3.141593, 3) == "3.142"); + CHECK(String::num(42.100023, 4) == "42.1"); // No trailing zeros. CHECK(String::num_scientific(30000000) == "3e+07"); + + // String::num_int64 tests. CHECK(String::num_int64(3141593) == "3141593"); + CHECK(String::num_int64(-3141593) == "-3141593"); CHECK(String::num_int64(0xA141593, 16) == "a141593"); CHECK(String::num_int64(0xA141593, 16, true) == "A141593"); - CHECK(String::num(42.100023, 4) == "42.1"); // No trailing zeros. + ERR_PRINT_OFF; + CHECK(String::num_int64(3141593, 1) == ""); // Invalid base < 2. + CHECK(String::num_int64(3141593, 37) == ""); // Invalid base > 36. + ERR_PRINT_ON; + + // String::num_uint64 tests. + CHECK(String::num_uint64(4294967295) == "4294967295"); + CHECK(String::num_uint64(0xF141593, 16) == "f141593"); + CHECK(String::num_uint64(0xF141593, 16, true) == "F141593"); + ERR_PRINT_OFF; + CHECK(String::num_uint64(4294967295, 1) == ""); // Invalid base < 2. + CHECK(String::num_uint64(4294967295, 37) == ""); // Invalid base > 36. + ERR_PRINT_ON; // String::num_real tests. CHECK(String::num_real(1.0) == "1.0"); @@ -476,15 +505,15 @@ TEST_CASE("[String] Number to string") { CHECK(String::num_real(3.141593) == "3.141593"); CHECK(String::num_real(3.141) == "3.141"); // No trailing zeros. #ifdef REAL_T_IS_DOUBLE - CHECK_MESSAGE(String::num_real(123.456789) == "123.456789", "Prints the appropriate amount of digits for real_t = double."); - CHECK_MESSAGE(String::num_real(-123.456789) == "-123.456789", "Prints the appropriate amount of digits for real_t = double."); - CHECK_MESSAGE(String::num_real(Math_PI) == "3.14159265358979", "Prints the appropriate amount of digits for real_t = double."); - CHECK_MESSAGE(String::num_real(3.1415f) == "3.1414999961853", "Prints more digits of 32-bit float when real_t = double (ones that would be reliable for double) and no trailing zero."); + CHECK_MESSAGE(String::num_real(real_t(123.456789)) == "123.456789", "Prints the appropriate amount of digits for real_t = double."); + CHECK_MESSAGE(String::num_real(real_t(-123.456789)) == "-123.456789", "Prints the appropriate amount of digits for real_t = double."); + CHECK_MESSAGE(String::num_real(real_t(Math_PI)) == "3.14159265358979", "Prints the appropriate amount of digits for real_t = double."); + CHECK_MESSAGE(String::num_real(real_t(3.1415f)) == "3.1414999961853", "Prints more digits of 32-bit float when real_t = double (ones that would be reliable for double) and no trailing zero."); #else - CHECK_MESSAGE(String::num_real(123.456789) == "123.4568", "Prints the appropriate amount of digits for real_t = float."); - CHECK_MESSAGE(String::num_real(-123.456789) == "-123.4568", "Prints the appropriate amount of digits for real_t = float."); - CHECK_MESSAGE(String::num_real(Math_PI) == "3.141593", "Prints the appropriate amount of digits for real_t = float."); - CHECK_MESSAGE(String::num_real(3.1415f) == "3.1415", "Prints only reliable digits of 32-bit float when real_t = float."); + CHECK_MESSAGE(String::num_real(real_t(123.456789)) == "123.4568", "Prints the appropriate amount of digits for real_t = float."); + CHECK_MESSAGE(String::num_real(real_t(-123.456789)) == "-123.4568", "Prints the appropriate amount of digits for real_t = float."); + CHECK_MESSAGE(String::num_real(real_t(Math_PI)) == "3.141593", "Prints the appropriate amount of digits for real_t = float."); + CHECK_MESSAGE(String::num_real(real_t(3.1415f)) == "3.1415", "Prints only reliable digits of 32-bit float when real_t = float."); #endif // REAL_T_IS_DOUBLE // Checks doubles with many decimal places. @@ -493,7 +522,7 @@ TEST_CASE("[String] Number to string") { CHECK(String::num(-0.0000012345432123454321) == "-0.00000123454321"); CHECK(String::num(-10000.0000012345432123454321) == "-10000.0000012345"); CHECK(String::num(0.0000000000012345432123454321) == "0.00000000000123"); - CHECK(String::num(0.0000000000012345432123454321, 3) == "0"); + CHECK(String::num(0.0000000000012345432123454321, 3) == "0.0"); // Note: When relevant (remainder > 0.5), the last digit gets rounded up, // which can also lead to not include a trailing zero, e.g. "...89" -> "...9". @@ -1238,6 +1267,12 @@ TEST_CASE("[String] is_subsequence_of") { CHECK(String("Sub").is_subsequence_ofn(a)); } +TEST_CASE("[String] is_lowercase") { + CHECK(String("abcd1234 !@#$%^&*()_-=+,.<>/\\|[]{};':\"`~").is_lowercase()); + CHECK(String("").is_lowercase()); + CHECK(!String("abc_ABC").is_lowercase()); +} + TEST_CASE("[String] match") { CHECK(String("img1.png").match("*.png")); CHECK(!String("img1.jpeg").match("*.png")); diff --git a/tests/core/string/test_translation.h b/tests/core/string/test_translation.h index 7c389191e3..2b1069d40c 100644 --- a/tests/core/string/test_translation.h +++ b/tests/core/string/test_translation.h @@ -161,7 +161,7 @@ TEST_CASE("[TranslationCSV] CSV import") { List<String> gen_files; - Error result = import_csv_translation->import(TestUtils::get_data_path("translations.csv"), + Error result = import_csv_translation->import(0, TestUtils::get_data_path("translations.csv"), "", options, nullptr, &gen_files); CHECK(result == OK); CHECK(gen_files.size() == 4); diff --git a/tests/core/string/test_translation_server.h b/tests/core/string/test_translation_server.h index ac1599f2e8..1274d8810e 100644 --- a/tests/core/string/test_translation_server.h +++ b/tests/core/string/test_translation_server.h @@ -37,27 +37,37 @@ namespace TestTranslationServer { TEST_CASE("[TranslationServer] Translation operations") { - Ref<Translation> t = memnew(Translation); - t->set_locale("uk"); - t->add_message("Good Morning", String::utf8("Добрий ранок")); + Ref<Translation> t1 = memnew(Translation); + t1->set_locale("uk"); + t1->add_message("Good Morning", String(U"Добрий ранок")); + + Ref<Translation> t2 = memnew(Translation); + t2->set_locale("uk"); + t2->add_message("Hello Godot", String(U"你好戈多")); TranslationServer *ts = TranslationServer::get_singleton(); + // Adds translation for UK locale for the first time. int l_count_before = ts->get_loaded_locales().size(); - ts->add_translation(t); + ts->add_translation(t1); int l_count_after = ts->get_loaded_locales().size(); - // Newly created Translation object should be added to the list, so the counter should increase, too. CHECK(l_count_after > l_count_before); - Ref<Translation> trans = ts->get_translation_object("uk"); - CHECK(trans.is_valid()); + // Adds translation for UK locale again. + ts->add_translation(t2); + CHECK_EQ(ts->get_loaded_locales().size(), l_count_after); + + // Removing that translation. + ts->remove_translation(t2); + CHECK_EQ(ts->get_loaded_locales().size(), l_count_after); + + CHECK(ts->get_translation_object("uk").is_valid()); ts->set_locale("uk"); CHECK(ts->translate("Good Morning") == String::utf8("Добрий ранок")); - ts->remove_translation(t); - trans = ts->get_translation_object("uk"); - CHECK(trans.is_null()); + ts->remove_translation(t1); + CHECK(ts->get_translation_object("uk").is_null()); // If no suitable Translation object has been found - the original message should be returned. CHECK(ts->translate("Good Morning") == "Good Morning"); } @@ -94,6 +104,36 @@ TEST_CASE("[TranslationServer] Locale operations") { res = ts->standardize_locale(loc); CHECK(res == "de_DE"); + + // No added defaults. + loc = "es_ES"; + res = ts->standardize_locale(loc, true); + + CHECK(res == "es_ES"); + + // Add default script. + loc = "az_AZ"; + res = ts->standardize_locale(loc, true); + + CHECK(res == "az_Latn_AZ"); + + // Add default country. + loc = "pa_Arab"; + res = ts->standardize_locale(loc, true); + + CHECK(res == "pa_Arab_PK"); + + // Add default script and country. + loc = "zh"; + res = ts->standardize_locale(loc, true); + + CHECK(res == "zh_Hans_CN"); + + // Explicitly don't add defaults. + loc = "zh"; + res = ts->standardize_locale(loc, false); + + CHECK(res == "zh"); } TEST_CASE("[TranslationServer] Comparing locales") { @@ -110,18 +150,50 @@ TEST_CASE("[TranslationServer] Comparing locales") { locale_a = "sr-Latn-CS"; locale_b = "sr-Latn-RS"; - // Two elements from locales match. + // Script matches (+1) but country doesn't (-1). res = ts->compare_locales(locale_a, locale_b); - CHECK(res == 2); + CHECK(res == 5); locale_a = "uz-Cyrl-UZ"; locale_b = "uz-Latn-UZ"; - // Two elements match, but they are not sequentual. + // Country matches (+1) but script doesn't (-1). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 5); + + locale_a = "aa-Latn-ER"; + locale_b = "aa-Latn-ER-saaho"; + + // Script and country match (+2) with variant on one locale (+0). res = ts->compare_locales(locale_a, locale_b); - CHECK(res == 2); + CHECK(res == 7); + + locale_a = "uz-Cyrl-UZ"; + locale_b = "uz-Latn-KG"; + + // Both script and country mismatched (-2). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 3); + + locale_a = "es-ES"; + locale_b = "es-AR"; + + // Mismatched country (-1). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 4); + + locale_a = "es"; + locale_b = "es-AR"; + + // No country for one locale (+0). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 5); locale_a = "es-EC"; locale_b = "fr-LU"; @@ -130,6 +202,24 @@ TEST_CASE("[TranslationServer] Comparing locales") { res = ts->compare_locales(locale_a, locale_b); CHECK(res == 0); + + locale_a = "zh-HK"; + locale_b = "zh"; + + // In full standardization, zh-HK becomes zh_Hant_HK and zh becomes + // zh_Hans_CN. Both script and country mismatch (-2). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 3); + + locale_a = "zh-CN"; + locale_b = "zh"; + + // In full standardization, zh and zh-CN both become zh_Hans_CN for an + // exact match. + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 10); } } // namespace TestTranslationServer diff --git a/tests/core/templates/test_a_hash_map.h b/tests/core/templates/test_a_hash_map.h new file mode 100644 index 0000000000..e67ee7b441 --- /dev/null +++ b/tests/core/templates/test_a_hash_map.h @@ -0,0 +1,295 @@ +/**************************************************************************/ +/* test_a_hash_map.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_A_HASH_MAP_H +#define TEST_A_HASH_MAP_H + +#include "core/templates/a_hash_map.h" + +#include "tests/test_macros.h" + +namespace TestAHashMap { + +TEST_CASE("[AHashMap] Insert element") { + AHashMap<int, int> map; + AHashMap<int, int>::Iterator e = map.insert(42, 84); + + CHECK(e); + CHECK(e->key == 42); + CHECK(e->value == 84); + CHECK(map[42] == 84); + CHECK(map.has(42)); + CHECK(map.find(42)); +} + +TEST_CASE("[AHashMap] Overwrite element") { + AHashMap<int, int> map; + map.insert(42, 84); + map.insert(42, 1234); + + CHECK(map[42] == 1234); +} + +TEST_CASE("[AHashMap] Erase via element") { + AHashMap<int, int> map; + AHashMap<int, int>::Iterator e = map.insert(42, 84); + map.remove(e); + CHECK(!map.has(42)); + CHECK(!map.find(42)); +} + +TEST_CASE("[AHashMap] Erase via key") { + AHashMap<int, int> map; + map.insert(42, 84); + map.erase(42); + CHECK(!map.has(42)); + CHECK(!map.find(42)); +} + +TEST_CASE("[AHashMap] Size") { + AHashMap<int, int> map; + map.insert(42, 84); + map.insert(123, 84); + map.insert(123, 84); + map.insert(0, 84); + map.insert(123485, 84); + + CHECK(map.size() == 4); +} + +TEST_CASE("[AHashMap] Iteration") { + AHashMap<int, int> map; + + map.insert(42, 84); + map.insert(123, 12385); + map.insert(0, 12934); + map.insert(123485, 1238888); + map.insert(123, 111111); + + Vector<Pair<int, int>> expected; + expected.push_back(Pair<int, int>(42, 84)); + expected.push_back(Pair<int, int>(123, 111111)); + expected.push_back(Pair<int, int>(0, 12934)); + expected.push_back(Pair<int, int>(123485, 1238888)); + + int idx = 0; + for (const KeyValue<int, int> &E : map) { + CHECK(expected[idx] == Pair<int, int>(E.key, E.value)); + idx++; + } + + idx--; + for (AHashMap<int, int>::Iterator it = map.last(); it; --it) { + CHECK(expected[idx] == Pair<int, int>(it->key, it->value)); + idx--; + } +} + +TEST_CASE("[AHashMap] Const iteration") { + AHashMap<int, int> map; + map.insert(42, 84); + map.insert(123, 12385); + map.insert(0, 12934); + map.insert(123485, 1238888); + map.insert(123, 111111); + + const AHashMap<int, int> const_map = map; + + Vector<Pair<int, int>> expected; + expected.push_back(Pair<int, int>(42, 84)); + expected.push_back(Pair<int, int>(123, 111111)); + expected.push_back(Pair<int, int>(0, 12934)); + expected.push_back(Pair<int, int>(123485, 1238888)); + expected.push_back(Pair<int, int>(123, 111111)); + + int idx = 0; + for (const KeyValue<int, int> &E : const_map) { + CHECK(expected[idx] == Pair<int, int>(E.key, E.value)); + idx++; + } + + idx--; + for (AHashMap<int, int>::ConstIterator it = const_map.last(); it; --it) { + CHECK(expected[idx] == Pair<int, int>(it->key, it->value)); + idx--; + } +} + +TEST_CASE("[AHashMap] Replace key") { + AHashMap<int, int> map; + map.insert(42, 84); + map.insert(0, 12934); + CHECK(map.replace_key(0, 1)); + CHECK(map.has(1)); + CHECK(map[1] == 12934); +} + +TEST_CASE("[AHashMap] Clear") { + AHashMap<int, int> map; + map.insert(42, 84); + map.insert(123, 12385); + map.insert(0, 12934); + + map.clear(); + CHECK(!map.has(42)); + CHECK(map.size() == 0); + CHECK(map.is_empty()); +} + +TEST_CASE("[AHashMap] Get") { + AHashMap<int, int> map; + map.insert(42, 84); + map.insert(123, 12385); + map.insert(0, 12934); + + CHECK(map.get(123) == 12385); + map.get(123) = 10; + CHECK(map.get(123) == 10); + + CHECK(*map.getptr(0) == 12934); + *map.getptr(0) = 1; + CHECK(*map.getptr(0) == 1); + + CHECK(map.get(42) == 84); + CHECK(map.getptr(-10) == nullptr); +} + +TEST_CASE("[AHashMap] Insert, iterate and remove many elements") { + const int elem_max = 1234; + AHashMap<int, int> map; + for (int i = 0; i < elem_max; i++) { + map.insert(i, i); + } + + //insert order should have been kept + int idx = 0; + for (auto &K : map) { + CHECK(idx == K.key); + CHECK(idx == K.value); + CHECK(map.has(idx)); + idx++; + } + + Vector<int> elems_still_valid; + + for (int i = 0; i < elem_max; i++) { + if ((i % 5) == 0) { + map.erase(i); + } else { + elems_still_valid.push_back(i); + } + } + + CHECK(elems_still_valid.size() == map.size()); + + for (int i = 0; i < elems_still_valid.size(); i++) { + CHECK(map.has(elems_still_valid[i])); + } +} + +TEST_CASE("[AHashMap] Insert, iterate and remove many strings") { + const int elem_max = 432; + AHashMap<String, String> map; + for (int i = 0; i < elem_max; i++) { + map.insert(itos(i), itos(i)); + } + + //insert order should have been kept + int idx = 0; + for (auto &K : map) { + CHECK(itos(idx) == K.key); + CHECK(itos(idx) == K.value); + CHECK(map.has(itos(idx))); + idx++; + } + + Vector<String> elems_still_valid; + + for (int i = 0; i < elem_max; i++) { + if ((i % 5) == 0) { + map.erase(itos(i)); + } else { + elems_still_valid.push_back(itos(i)); + } + } + + CHECK(elems_still_valid.size() == map.size()); + + for (int i = 0; i < elems_still_valid.size(); i++) { + CHECK(map.has(elems_still_valid[i])); + } + + elems_still_valid.clear(); +} + +TEST_CASE("[AHashMap] Copy constructor") { + AHashMap<int, int> map0; + const uint32_t count = 5; + for (uint32_t i = 0; i < count; i++) { + map0.insert(i, i); + } + AHashMap<int, int> map1(map0); + CHECK(map0.size() == map1.size()); + CHECK(map0.get_capacity() == map1.get_capacity()); + CHECK(*map0.getptr(0) == *map1.getptr(0)); +} + +TEST_CASE("[AHashMap] Operator =") { + AHashMap<int, int> map0; + AHashMap<int, int> map1; + const uint32_t count = 5; + map1.insert(1234, 1234); + for (uint32_t i = 0; i < count; i++) { + map0.insert(i, i); + } + map1 = map0; + CHECK(map0.size() == map1.size()); + CHECK(map0.get_capacity() == map1.get_capacity()); + CHECK(*map0.getptr(0) == *map1.getptr(0)); +} + +TEST_CASE("[AHashMap] Array methods") { + AHashMap<int, int> map; + for (int i = 0; i < 100; i++) { + map.insert(100 - i, i); + } + for (int i = 0; i < 100; i++) { + CHECK(map.get_by_index(i).value == i); + } + int index = map.get_index(1); + CHECK(map.get_by_index(index).value == 99); + CHECK(map.erase_by_index(index)); + CHECK(!map.erase_by_index(index)); + CHECK(map.get_index(1) == -1); +} + +} // namespace TestAHashMap + +#endif // TEST_A_HASH_MAP_H diff --git a/tests/core/variant/test_callable.h b/tests/core/variant/test_callable.h index 3228e0a583..34ea8fad5c 100644 --- a/tests/core/variant/test_callable.h +++ b/tests/core/variant/test_callable.h @@ -135,6 +135,70 @@ TEST_CASE("[Callable] Argument count") { memdelete(my_test); } + +class TestBoundUnboundArgumentCount : public Object { + GDCLASS(TestBoundUnboundArgumentCount, Object); + +protected: + static void _bind_methods() { + ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "test_func", &TestBoundUnboundArgumentCount::test_func, MethodInfo("test_func")); + } + +public: + Variant test_func(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + Array result; + result.resize(p_argcount); + for (int i = 0; i < p_argcount; i++) { + result[i] = *p_args[i]; + } + return result; + } + + static String get_output(const Callable &p_callable) { + Array effective_args; + effective_args.push_back(7); + effective_args.push_back(8); + effective_args.push_back(9); + + effective_args.resize(3 - p_callable.get_unbound_arguments_count()); + effective_args.append_array(p_callable.get_bound_arguments()); + + return vformat( + "%d %d %s %s %s", + p_callable.get_unbound_arguments_count(), + p_callable.get_bound_arguments_count(), + p_callable.get_bound_arguments(), + p_callable.call(7, 8, 9), + effective_args); + } +}; + +TEST_CASE("[Callable] Bound and unbound argument count") { + String (*get_output)(const Callable &) = TestBoundUnboundArgumentCount::get_output; + + TestBoundUnboundArgumentCount *test_instance = memnew(TestBoundUnboundArgumentCount); + + Callable test_func = Callable(test_instance, "test_func"); + + CHECK(get_output(test_func) == "0 0 [] [7, 8, 9] [7, 8, 9]"); + CHECK(get_output(test_func.bind(1, 2)) == "0 2 [1, 2] [7, 8, 9, 1, 2] [7, 8, 9, 1, 2]"); + CHECK(get_output(test_func.bind(1, 2).unbind(1)) == "1 2 [1, 2] [7, 8, 1, 2] [7, 8, 1, 2]"); + CHECK(get_output(test_func.bind(1, 2).unbind(1).bind(3, 4)) == "0 3 [3, 1, 2] [7, 8, 9, 3, 1, 2] [7, 8, 9, 3, 1, 2]"); + CHECK(get_output(test_func.bind(1, 2).unbind(1).bind(3, 4).unbind(1)) == "1 3 [3, 1, 2] [7, 8, 3, 1, 2] [7, 8, 3, 1, 2]"); + + CHECK(get_output(test_func.bind(1).bind(2).bind(3).unbind(1)) == "1 3 [3, 2, 1] [7, 8, 3, 2, 1] [7, 8, 3, 2, 1]"); + CHECK(get_output(test_func.bind(1).bind(2).unbind(1).bind(3)) == "0 2 [2, 1] [7, 8, 9, 2, 1] [7, 8, 9, 2, 1]"); + CHECK(get_output(test_func.bind(1).unbind(1).bind(2).bind(3)) == "0 2 [3, 1] [7, 8, 9, 3, 1] [7, 8, 9, 3, 1]"); + CHECK(get_output(test_func.unbind(1).bind(1).bind(2).bind(3)) == "0 2 [3, 2] [7, 8, 9, 3, 2] [7, 8, 9, 3, 2]"); + + CHECK(get_output(test_func.unbind(1).unbind(1).unbind(1).bind(1, 2, 3)) == "0 0 [] [7, 8, 9] [7, 8, 9]"); + CHECK(get_output(test_func.unbind(1).unbind(1).bind(1, 2, 3).unbind(1)) == "1 1 [1] [7, 8, 1] [7, 8, 1]"); + CHECK(get_output(test_func.unbind(1).bind(1, 2, 3).unbind(1).unbind(1)) == "2 2 [1, 2] [7, 1, 2] [7, 1, 2]"); + CHECK(get_output(test_func.bind(1, 2, 3).unbind(1).unbind(1).unbind(1)) == "3 3 [1, 2, 3] [1, 2, 3] [1, 2, 3]"); + + memdelete(test_instance); +} + } // namespace TestCallable #endif // TEST_CALLABLE_H diff --git a/tests/core/variant/test_variant.h b/tests/core/variant/test_variant.h index be615975f8..599a282b20 100644 --- a/tests/core/variant/test_variant.h +++ b/tests/core/variant/test_variant.h @@ -1806,6 +1806,14 @@ TEST_CASE("[Variant] Writer and parser dictionary") { CHECK_MESSAGE(d_parsed == Variant(d), "Should parse back."); } +TEST_CASE("[Variant] Writer key sorting") { + Dictionary d = build_dictionary(StringName("C"), 3, "A", 1, StringName("B"), 2, "D", 4); + String d_str; + VariantWriter::write_to_string(d, d_str); + + CHECK_EQ(d_str, "{\n\"A\": 1,\n&\"B\": 2,\n&\"C\": 3,\n\"D\": 4\n}"); +} + TEST_CASE("[Variant] Writer recursive dictionary") { // There is no way to accurately represent a recursive dictionary, // the only thing we can do is make sure the writer doesn't blow up diff --git a/tests/core/variant/test_variant_utility.h b/tests/core/variant/test_variant_utility.h index 93458b63f4..34b4880d51 100644 --- a/tests/core/variant/test_variant_utility.h +++ b/tests/core/variant/test_variant_utility.h @@ -89,7 +89,7 @@ TEST_CASE("[VariantUtility] Type conversion") { converted = VariantUtilityFunctions::type_convert(basis, Variant::Type::STRING); CHECK(converted.get_type() == Variant::Type::STRING); - CHECK(converted == Variant("[X: (1.2, 0, 0), Y: (0, 3.4, 0), Z: (0, 0, 5.6)]")); + CHECK(converted == Variant("[X: (1.2, 0.0, 0.0), Y: (0.0, 3.4, 0.0), Z: (0.0, 0.0, 5.6)]")); } { diff --git a/tests/data/floating_point_big_endian.bin b/tests/data/floating_point_big_endian.bin new file mode 100644 index 0000000000..9534605ce1 --- /dev/null +++ b/tests/data/floating_point_big_endian.bin @@ -0,0 +1 @@ +@IV
\ No newline at end of file diff --git a/tests/data/floating_point_little_endian.bin b/tests/data/floating_point_little_endian.bin new file mode 100644 index 0000000000..8cd66219d8 --- /dev/null +++ b/tests/data/floating_point_little_endian.bin @@ -0,0 +1 @@ +VI@
\ No newline at end of file diff --git a/tests/data/fuzzy_search/project_dir_tree.txt b/tests/data/fuzzy_search/project_dir_tree.txt new file mode 100644 index 0000000000..153dd8802a --- /dev/null +++ b/tests/data/fuzzy_search/project_dir_tree.txt @@ -0,0 +1,999 @@ +./menu/home/home_menu.tscn +./menu/tooltips/tooltip_server.tscn +./menu/tooltips/tooltip_server.gd +./menu/tooltips/tooltip.gd +./menu/menu/characters/smoker/4.wav +./menu/menu/characters/smoker/6.wav +./menu/menu/characters/smoker/10.wav +./menu/menu/characters/smoker/smoker.tscn +./menu/menu/characters/smoker/8.wav +./menu/menu/characters/smoker/type.gd +./menu/menu/characters/smoker/9.wav +./menu/menu/characters/smoker/5.wav +./menu/menu/characters/smoker/0.wav +./menu/menu/characters/smoker/back_light.png +./menu/menu/characters/smoker/glasses.png +./menu/menu/characters/smoker/smoker.gd +./menu/menu/characters/smoker/cig.gd +./menu/menu/characters/smoker/eyes.png +./menu/menu/characters/smoker/3.wav +./menu/menu/characters/smoker/to_pixelate.gd +./menu/menu/characters/smoker/7.wav +./menu/menu/characters/smoker/cig.png +./menu/menu/characters/smoker/2.wav +./menu/menu/characters/smoker/1.wav +./menu/menu/characters/smoke.png +./menu/menu/characters/space_bandit.tres +./menu/menu/characters/dead_guy/blood_texture.png +./menu/menu/characters/dead_guy/head_gibbed.png +./menu/menu/characters/dead_guy/back_light.png +./menu/menu/characters/dead_guy/smoker.gd +./menu/menu/characters/dead_guy/eyes.png +./menu/menu/characters/dead_guy/to_pixelate.gd +./menu/menu/characters/dead_guy/dead_guy.gd +./menu/menu/characters/dead_guy/eyes.gd +./menu/menu/characters/dead_guy/x.png +./menu/menu/characters/dead_guy/dead_guy.tscn +./menu/menu/characters/dead_guy/mouth.png +./menu/menu/characters/dead_guy/dead_guy.tres +./menu/menu/characters/Label.gd +./menu/menu/characters/guns2.png +./menu/menu/characters/c.gd +./menu/menu/characters/smoke.gd +./menu/menu/characters/character.gd +./menu/menu/characters/space_bandit/eyes.tres +./menu/menu/characters/space_bandit/space_bandit_face_happy.png +./menu/menu/characters/space_bandit/space_bandit.gd +./menu/menu/characters/space_bandit/space_bandit.tscn +./menu/menu/characters/boss/smoker.tscn +./menu/menu/characters/boss/back_light.png +./menu/menu/characters/boss/glasses.png +./menu/menu/characters/boss/smoker.gd +./menu/menu/characters/boss/cig.gd +./menu/menu/characters/boss/eyes.png +./menu/menu/characters/boss/to_pixelate.gd +./menu/menu/characters/boss/x.png +./menu/menu/characters/boss/cig.png +./menu/menu/characters/eye.gd +./menu/menu/characters/space_bandit_face_happy.png +./menu/menu/characters/face.gd +./menu/menu/characters/color.tres +./menu/menu/characters/space_bandit.tscn +./menu/menu/characters/space_bandit_face_bloody.png +./menu/menu/characters/guns.png +./menu/menu/characters/eyes2.tres +./menu/options/controls/use.tres +./menu/options/controls/input_map_button.gd +./menu/options/controls/swap.tres +./menu/options/controls/teleport.tres +./menu/options/controls/joy_controls.tscn +./menu/options/controls/mouse_and_keyboard_controls.tscn +./menu/options/controls/input_map_button.tscn +./menu/options/controls/special.tres +./menu/options/controls/throw.tres +./menu/options/controls/center.tres +./menu/options/controls/input_action.gd +./menu/options/controls/move.tres +./menu/options/controls/melee.tres +./menu/options/controls/controls.gd +./menu/options/options.gd +./menu/options/options.tscn +./menu/options/graphics/graphics.tscn +./menu/options/graphics/graphics.gd +./menu/options/audio/audio.gd +./menu/options/audio/audio.tscn +./menu/options/game/game.gd +./menu/options/game/game.tscn +./menu/circle.tres +./menu/fonts/keys.png +./menu/fonts/rainbow_font.tres +./menu/fonts/fallback_font.tres +./menu/fonts/taxi_Driver.png +./menu/fonts/NotoSansJP-Regular.ttf +./menu/fonts/taxi_Driver_noise.png +./menu/fonts/rainbow_font_shader.tres +./menu/fonts/m5x7.ttf +./menu/colors.gd +./menu/toast_enter.wav +./menu/ui_colors.tres +./menu/pause/pause.gd +./menu/pause/rainbow.tres +./menu/pause/Label.gd +./menu/pause/label.tscn +./menu/pause/pause.tscn +./menu/hoola.wav +./menu/in_game_fallback.tres +./menu/widgets/next_unlock.gd +./menu/widgets/slider.gd +./menu/widgets/fade.tscn +./menu/widgets/background_hint.gd +./menu/widgets/panel_container_smoke.gd +./menu/widgets/wishlist_sticker.gd +./menu/widgets/smoke.tres +./menu/widgets/color_grade.gd +./menu/widgets/rich_text_button.gd +./menu/widgets/panel_container_smok2.tscn +./menu/widgets/slider.tscn +./menu/widgets/rich_text_heading.gd +./menu/widgets/background_hint.tscn +./menu/widgets/tip.tscn +./menu/widgets/rich_text_button.tscn +./menu/widgets/toggle.tscn +./menu/widgets/heading.tscn +./menu/widgets/hover.tscn +./menu/widgets/toggle.gd +./menu/widgets/smoke_panel_material.tres +./menu/widgets/confirm.gd +./menu/widgets/tip.gd +./menu/widgets/panel.gd +./menu/widgets/modal.gd +./menu/widgets/NinePatchRect.gd +./menu/widgets/smoke.shader +./menu/widgets/9patch.png +./menu/widgets/big_hint.gd +./menu/widgets/TDVB1i.png +./menu/widgets/color_grade.tscn +./menu/widgets/text.gd +./menu/widgets/panel_container_smoke.tscn +./menu/widgets/1x1.png +./menu/widgets/confirm.tscn +./menu/widgets/RichTextPanel.tscn +./menu/hud/cursor.png +./menu/hud/inventory/draggable.gd +./menu/hud/inventory/menu/characters/color.tres +./menu/hud/inventory/drop_zone.tscn +./menu/hud/inventory/RichTextLabel.gd +./menu/hud/inventory/hud_icon_mutation.tscn +./menu/hud/inventory/use_count.gd +./menu/hud/inventory/draggable.tscn +./menu/hud/inventory/black_shadow_font.tres +./menu/hud/inventory/x.png +./menu/hud/inventory/hud_icon_mutation.gd +./menu/hud/inventory/flash_parent.gd +./menu/hud/inventory/TextureRect4.gd +./menu/hud/cursor.tscn +./menu/hud/hud.tscn +./menu/hud/cursor.gd +./menu/hud/hud.gd +./menu/metal_text.tres +./menu/rich_text_effects/RichTextType.gd +./menu/rich_text_effects/RichTextPanel.gd +./menu/rich_text_effects/RichTextFlash.gd +./menu/rich_text_effects/RichTextTranslate.gd +./menu/in_game.tres +./menu/lcd_screen_font.tres +./menu/toast_exit.wav +./menu/stack/ahses_material.tres +./menu/stack/home.kra +./menu/stack/fade.gd +./menu/stack/stack.tscn +./menu/stack/stack.gd +./menu/stack/version.gd +./menu/stack/art.kra +./entity/unlock_skin_classic/icon.png +./entity/use.gd +./entity/chair/entity.tscn +./entity/chair/icon.png +./entity/chair/data.gd +./entity/man_desert/entity.tscn +./entity/man_desert/icon.png +./entity/man_desert/teleprompts/need_medbay.wav +./entity/man_desert/teleprompts/me_too.wav +./entity/man_desert/teleprompts/get_up_alt.wav +./entity/man_desert/teleprompts/getting_a_medpack.wav +./entity/man_desert/teleprompts/firstaid-incoming.wav +./entity/man_desert/teleprompts/batch_name.py +./entity/man_desert/teleprompts/what.wav +./entity/man_desert/teleprompts/oo.wav +./entity/man_desert/teleprompts/yell.wav +./entity/man_desert/teleprompts/rushing.wav +./entity/man_desert/teleprompts/ooo.wav +./entity/man_desert/teleprompts/coming_to_heal_ya.wav +./entity/man_desert/teleprompts/where_is_the_medpack.wav +./entity/man_desert/teleprompts/ah.wav +./entity/man_desert/teleprompts/no.wav +./entity/man_desert/teleprompts/going_to_camp_medbay.wav +./entity/man_desert/teleprompts/aa.wav +./entity/man_desert/teleprompts/pirate_alt.wav +./entity/man_desert/teleprompts/take_morphine.wav +./entity/man_desert/teleprompts/ee.wav +./entity/man_desert/teleprompts/get_up.wav +./entity/man_desert/teleprompts/aw.wav +./entity/man_desert/teleprompts/easy.wav +./entity/man_desert/teleprompts/intruder.wav +./entity/man_desert/teleprompts/amateur.wav +./entity/man_desert/teleprompts/hes_not_moving.wav +./entity/man_desert/teleprompts/pirate.wav +./entity/man_desert/teleprompts/i_dont_know.wav +./entity/man_desert/teleprompts/index.txt +./entity/man_desert/teleprompts/move.wav +./entity/man_desert/teleprompts/hes_stuck.wav +./entity/man_desert/teleprompts/how.wav +./entity/man_desert/teleprompts/uu.wav +./entity/man_desert/teleprompts/where_is_the_gun.wav +./entity/man_desert/teleprompts/getting_a_gun.wav +./entity/man_desert/data.gd +./entity/man_desert/hand.png +./entity/barrel_side_smoke/entity.tscn +./entity/barrel_side_smoke/icon.png +./entity/barrel_side_smoke/data.gd +./entity/barrel_smoke/entity.tscn +./entity/barrel_smoke/icon.png +./entity/barrel_smoke/data.gd +./entity/project_box/entity.tscn +./entity/project_box/icon.png +./entity/project_box/data.gd +./entity/mutation_saw/entity.tscn +./entity/mutation_saw/icon.png +./entity/mutation_saw/special.gd +./entity/mutation_saw/data.gd +./entity/lift_entrance/entity.tscn +./entity/lift_entrance/icon.png +./entity/lift_entrance/special.gd +./entity/lift_entrance/data.gd +./entity/mutation_accuracy_boost_DELETE/entity.tscn +./entity/mutation_accuracy_boost_DELETE/icon.png +./entity/mutation_accuracy_boost_DELETE/special.gd +./entity/mutation_accuracy_boost_DELETE/data.gd +./entity/skin_ruffle/entity.tscn +./entity/skin_ruffle/icon.png +./entity/skin_ruffle/carried.png +./entity/skin_ruffle/data.gd +./entity/editor_only_icon.gd +./entity/console_dark/entity.tscn +./entity/console_dark/icon.png +./entity/console_dark/data.gd +./entity/console_dark/animation.png +./entity/smg2/entity.tscn +./entity/smg2/used.wav +./entity/smg2/icon.png +./entity/smg2/data.gd +./entity/smg2/debug.gd +./entity/grenade_launcher/entity.tscn +./entity/grenade_launcher/used.wav +./entity/grenade_launcher/icon.png +./entity/grenade_launcher/special.gd +./entity/grenade_launcher/data.gd +./entity/floor_tile_full_square/entity.tscn +./entity/floor_tile_full_square/icon.png +./entity/floor_tile_full_square/data.gd +./entity/grate_1/entity.tscn +./entity/grate_1/icon.png +./entity/grate_1/data.gd +./entity/bed_bunk_corner/entity.tscn +./entity/bed_bunk_corner/icon.png +./entity/bed_bunk_corner/data.gd +./entity/kill_streak_rail_gun_level_3/entity.tscn +./entity/kill_streak_rail_gun_level_3/data.gd +./entity/teleporter_random_weak/entity.tscn +./entity/teleporter_random_weak/teleporter_model.gd +./entity/teleporter_random_weak/used.wav +./entity/teleporter_random_weak/icon.png +./entity/teleporter_random_weak/special.gd +./entity/teleporter_random_weak/ray.gd +./entity/teleporter_random_weak/data.gd +./entity/teleporter_random_weak/flap.png +./entity/entities.kra +./entity/jerry_can/entity.tscn +./entity/jerry_can/icon.png +./entity/jerry_can/data.gd +./entity/kill_streak_helmet_full/entity.tscn +./entity/kill_streak_helmet_full/data.gd +./entity/background_derelict/background2.gd +./entity/background_derelict/entity.tscn +./entity/background_derelict/icon.png +./entity/background_derelict/background/space.png +./entity/background_derelict/background/line.png +./entity/background_derelict/background/overlay.png +./entity/background_derelict/background/background2.png +./entity/background_derelict/background/background.png +./entity/background_derelict/background/engine_glow.tscn +./entity/background_derelict/background/lines3.png +./entity/background_derelict/background/background.tscn +./entity/background_derelict/background/lines.tres +./entity/background_derelict/background/xx.gd +./entity/background_derelict/background/background.gd +./entity/background_derelict/background/bayer16tile2.png +./entity/background_derelict/background/push.png +./entity/background_derelict/background/palette_mono.png +./entity/background_derelict/background/stars.gd +./entity/background_derelict/background/lines2.png +./entity/background_derelict/background/lines.shader +./entity/background_derelict/background/ambience.gd +./entity/background_derelict/background/space_ship_ambience.ogg +./entity/background_derelict/background/stars.png +./entity/background_derelict/data.gd +./entity/smoker/entity.tscn +./entity/smoker/right_hand.png +./entity/smoker/eyes.png +./entity/smoker/data.gd +./entity/smoker/animate.gd +./entity/smoker/left_hand.png +./entity/EntityStatic.gd +./entity/level_model.gd +./entity/class_teleporter_drop_chance/entity.tscn +./entity/class_teleporter_drop_chance/icon.png +./entity/class_teleporter_drop_chance/special.gd +./entity/class_teleporter_drop_chance/data.gd +./entity/smg4/entity.tscn +./entity/smg4/used.wav +./entity/smg4/icon.png +./entity/smg4/data.gd +./entity/medpack/entity.tscn +./entity/medpack/icon.png +./entity/medpack/dead.png +./entity/medpack/data.gd +./entity/model.gd +./entity/doom_transition/entity.tscn +./entity/doom_transition/icon.png +./entity/doom_transition/special.gd +./entity/doom_transition/Screenshot from 2021-12-08 18-25-03.png +./entity/doom_transition/data.gd +./entity/glass_block_exploding/entity.tscn +./entity/glass_block_exploding/icon.png +./entity/glass_block_exploding/special.gd +./entity/glass_block_exploding/dead.png +./entity/glass_block_exploding/data.gd +./entity/floor_ting/entity.tscn +./entity/floor_ting/icon.png +./entity/floor_ting/data.gd +./entity/background_crashed_ship/entity.tscn +./entity/background_crashed_ship/icon.png +./entity/background_crashed_ship/background/background2.kra +./entity/background_crashed_ship/background/dust_storm_negative.png +./entity/background_crashed_ship/background/background2.png +./entity/background_crashed_ship/background/background2 (copy 1).png +./entity/background_crashed_ship/background/dust_bowl.ogg +./entity/background_crashed_ship/background/background.tscn +./entity/background_crashed_ship/background/background.kra +./entity/background_crashed_ship/data.gd +./entity/game_aim_hack_boss/entity.tscn +./entity/game_aim_hack_boss/icon.png +./entity/game_aim_hack_boss/special.gd +./entity/game_aim_hack_boss/give_my_arm_back.wav +./entity/game_aim_hack_boss/my_arm_came_off.wav +./entity/game_aim_hack_boss/data.gd +./entity/sink/entity.tscn +./entity/sink/icon.png +./entity/sink/data.gd +./entity/grate_2/entity.tscn +./entity/grate_2/icon.png +./entity/grate_2/data.gd +./entity/barrel_side/entity.tscn +./entity/barrel_side/icon.png +./entity/barrel_side/data.gd +./entity/oxygen/entity.tscn +./entity/oxygen/icon.png +./entity/oxygen/shadow.png +./entity/oxygen/data.gd +./entity/oxygen/normal.png +./entity/unlock_skin_robo/entity.tscn +./entity/unlock_skin_robo/icon.png +./entity/unlock_skin_robo/special.gd +./entity/unlock_skin_robo/data.gd +./entity/entity_agency_model.gd +./entity/floor_tile_wood/entity.tscn +./entity/floor_tile_wood/icon.png +./entity/floor_tile_wood/data.gd +./entity/qr_code/entity.tscn +./entity/qr_code/icon.png +./entity/qr_code/data.gd +./entity/background_sun/overlay.png +./entity/background_sun/entity.tscn +./entity/background_sun/c.gd +./entity/background_sun/kill.tscn +./entity/background_sun/icon.png +./entity/background_sun/special.gd +./entity/background_sun/wtf.tres +./entity/background_sun/background/background2.png +./entity/background_sun/background/background.tscn +./entity/background_sun/background/color2s.tres +./entity/background_sun/background/background_glow.png +./entity/background_sun/data.gd +./entity/background_sun/kill.gd +./entity/background_sun/stars.png +./entity/background_zone_intro/overlay.png +./entity/background_zone_intro/entity.tscn +./entity/background_zone_intro/icon.png +./entity/background_zone_intro/special.gd +./entity/background_zone_intro/background/space.png +./entity/background_zone_intro/background/line.png +./entity/background_zone_intro/background/background2.png +./entity/background_zone_intro/background/background.png +./entity/background_zone_intro/background/engine_glow.tscn +./entity/background_zone_intro/background/lines3.png +./entity/background_zone_intro/background/background.tscn +./entity/background_zone_intro/background/lines.tres +./entity/background_zone_intro/background/background.gd +./entity/background_zone_intro/background/bayer16tile2.png +./entity/background_zone_intro/background/push.png +./entity/background_zone_intro/background/palette_mono.png +./entity/background_zone_intro/background/stars.gd +./entity/background_zone_intro/background/lines2.png +./entity/background_zone_intro/background/lines.shader +./entity/background_zone_intro/background/ambience.gd +./entity/background_zone_intro/background/space_ship_ambience.ogg +./entity/background_zone_intro/background/stars.png +./entity/background_zone_intro/background_end.png +./entity/background_zone_intro/data.gd +./entity/background_zone_intro/tinge.png +./entity/closet_alt/entity.tscn +./entity/closet_alt/icon.png +./entity/closet_alt/data.gd +./entity/meta_random_sound/entity.tscn +./entity/meta_random_sound/giberish.wav +./entity/meta_random_sound/icon.png +./entity/meta_random_sound/special.gd +./entity/meta_random_sound/who.wav +./entity/meta_random_sound/data.gd +./entity/meta_random_sound/hoola_boola.wav +./entity/meta_random_sound/space_bandit.wav +./entity/lines/entity.tscn +./entity/lines/icon.png +./entity/lines/data.gd +./entity/teleporter_random_avoid_ray/entity.tscn +./entity/teleporter_random_avoid_ray/used.wav +./entity/teleporter_random_avoid_ray/icon.png +./entity/teleporter_random_avoid_ray/ray.gd +./entity/teleporter_random_avoid_ray/data.gd +./entity/teleporter_random_avoid_ray/flap.png +./entity/teleporter_random_avoid_ray/RayCast2D.gd +./entity/teleporter_random_avoid_ray/area.gd +./entity/teleporter_random_avoid_ray/flap.gd +./entity/saw/blades.gd +./entity/saw/entity.tscn +./entity/saw/used.wav +./entity/saw/icon.png +./entity/saw/special.gd +./entity/saw/carried.png +./entity/saw/data.gd +./entity/saw/used (copy 1).wav +./entity/saw/saw.wav +./entity/saw/carried_blades.png +./entity/floor_tile_checkerdboard/damage.png +./entity/floor_tile_checkerdboard/entity.tscn +./entity/floor_tile_checkerdboard/icon.png +./entity/floor_tile_checkerdboard/entity.tres +./entity/floor_tile_checkerdboard/data.gd +./entity/mutation_smoke_grenade_upgrade/entity.tscn +./entity/mutation_smoke_grenade_upgrade/icon.png +./entity/mutation_smoke_grenade_upgrade/special.gd +./entity/mutation_smoke_grenade_upgrade/data.gd +./entity/mutation_smoke_grenade_upgrade/mutation_model.gd +./entity/helmet_full/entity.tscn +./entity/helmet_full/pick_up.wav +./entity/helmet_full/icon.png +./entity/helmet_full/data.gd +./entity/helmet_full/helmet-ping.wav +./entity/barrel_explosive/entity.tscn +./entity/barrel_explosive/icon.png +./entity/barrel_explosive/data.gd +./entity/bank/entity.tscn +./entity/bank/icon.png +./entity/bank/special.gd +./entity/bank/data.gd +./entity/kick/entity.tscn +./entity/kick/swipe.png +./entity/kick/used.wav +./entity/kick/icon.png +./entity/kick/AnimatedSprite.gd +./entity/kick/data.gd +./entity/battery/entity.tscn +./entity/battery/icon.png +./entity/battery/data.gd +./entity/lift/entity.tscn +./entity/lift/opening.wav +./entity/lift/doors_open.png +./entity/lift/RichTextLabel.gd +./entity/lift/icon.png +./entity/lift/open.wav +./entity/lift/elevator_end.wav +./entity/lift/lift_model.gd +./entity/lift/label.tscn +./entity/lift/rumble.gd +./entity/lift/level_portal_model.gd +./entity/lift/data.gd +./entity/lift/doors.png +./entity/lift/area.gd +./entity/snes/entity.tscn +./entity/snes/icon.png +./entity/snes/data.gd +./entity/passive_disarm/entity.tscn +./entity/passive_disarm/icon.png +./entity/passive_disarm/special.gd +./entity/passive_disarm/data.gd +./entity/mutation_lots_of_shot/entity.tscn +./entity/mutation_lots_of_shot/icon.png +./entity/mutation_lots_of_shot/special.gd +./entity/mutation_lots_of_shot/data.gd +./entity/pallet2/entity.tscn +./entity/pallet2/icon.png +./entity/pallet2/data.gd +./entity/kill_streak_sword/entity.tscn +./entity/kill_streak_sword/data.gd +./entity/rain/entity.tscn +./entity/rain/icon.png +./entity/rain/special.gd +./entity/rain/rain.png +./entity/rain/rain.tscn +./entity/rain/data.gd +./entity/rain/rain.gd +./entity/white_line/entity.tscn +./entity/white_line/icon.png +./entity/white_line/data.gd +./entity/game_break_sword/entity.tscn +./entity/game_break_sword/icon.png +./entity/game_break_sword/special.gd +./entity/game_break_sword/data.gd +./entity/background_zone1/overlay.png +./entity/background_zone1/entity.tscn +./entity/background_zone1/icon.png +./entity/background_zone1/special.gd +./entity/background_zone1/background/space.png +./entity/background_zone1/background/line.png +./entity/background_zone1/background/background2.png +./entity/background_zone1/background/background.png +./entity/background_zone1/background/engine_glow.tscn +./entity/background_zone1/background/lines3.png +./entity/background_zone1/background/background.tscn +./entity/background_zone1/background/lines.tres +./entity/background_zone1/background/background.gd +./entity/background_zone1/background/bayer16tile2.png +./entity/background_zone1/background/push.png +./entity/background_zone1/background/palette_mono.png +./entity/background_zone1/background/stars.gd +./entity/background_zone1/background/lines2.png +./entity/background_zone1/background/lines.shader +./entity/background_zone1/background/ambience.gd +./entity/background_zone1/background/space_ship_ambience.ogg +./entity/background_zone1/background/stars.png +./entity/background_zone1/data.gd +./entity/background_zone1/tinge.png +./entity/mutation_throw_trap_DELETE/entity.tscn +./entity/mutation_throw_trap_DELETE/icon.png +./entity/mutation_throw_trap_DELETE/special.gd +./entity/mutation_throw_trap_DELETE/data.gd +./entity/agency.gd +./entity/skin_cheese/entity.tscn +./entity/skin_cheese/icon.png +./entity/skin_cheese/carried.png +./entity/skin_cheese/data.gd +./entity/toilet/entity.tscn +./entity/toilet/icon.png +./entity/toilet/special.gd +./entity/toilet/water.png +./entity/toilet/drink.wav +./entity/toilet/data.gd +./entity/smg3/entity.tscn +./entity/smg3/used.wav +./entity/smg3/icon.png +./entity/smg3/dead.png +./entity/smg3/data.gd +./entity/smg3/debug.gd +./entity/teleporter_super/entity.tscn +./entity/teleporter_super/icon.png +./entity/teleporter_super/data.gd +./entity/background_zone_end/overlay.png +./entity/background_zone_end/entity.tscn +./entity/background_zone_end/icon.png +./entity/background_zone_end/special.gd +./entity/background_zone_end/stars2.png +./entity/background_zone_end/background_end.png +./entity/background_zone_end/data.gd +./entity/background_zone_end/tinge.png +./entity/kill_streak_barricade/entity.tscn +./entity/kill_streak_barricade/data.gd +./entity/game_zone_4_boss_1/entity.tscn +./entity/game_zone_4_boss_1/icon.png +./entity/game_zone_4_boss_1/special.gd +./entity/game_zone_4_boss_1/data.gd +./entity/game_zone_4_boss_1/kill_me_and_explode_ship.wav +./entity/mutation_remove_melee/entity.tscn +./entity/mutation_remove_melee/icon.png +./entity/mutation_remove_melee/special.gd +./entity/mutation_remove_melee/data.gd +./entity/he_grenade_level_2/entity.tscn +./entity/he_grenade_level_2/icon.png +./entity/he_grenade_level_2/data.gd +./entity/background_zone_2/entity.tscn +./entity/background_zone_2/icon.png +./entity/background_zone_2/background/background2.kra +./entity/background_zone_2/background/grad.png +./entity/background_zone_2/background/background2.png +./entity/background_zone_2/background/background.png +./entity/background_zone_2/background/background2 (copy 1).png +./entity/background_zone_2/background/backgrounds.gd +./entity/background_zone_2/background/wall_overlay.png +./entity/background_zone_2/background/background.tscn +./entity/background_zone_2/background/Screenshot from 2022-07-07 10-58-48.png +./entity/background_zone_2/background/background.gd +./entity/background_zone_2/background/shadow.png +./entity/background_zone_2/background/engine smoke.png +./entity/background_zone_2/background/background.kra +./entity/background_zone_2/background/sea.ogg +./entity/background_zone_2/background/background2blur.png +./entity/background_zone_2/background/test.gd +./entity/background_zone_2/background/grad3.png +./entity/background_zone_2/background/lines2.png +./entity/background_zone_2/background/smoke.tscn +./entity/background_zone_2/background/left_water.tscn +./entity/background_zone_2/background/grad2.png +./entity/background_zone_2/background/para.png +./entity/background_zone_2/data.gd +./entity/pipe_corner/entity.tscn +./entity/pipe_corner/icon.png +./entity/pipe_corner/data.gd +./entity/floor_tile_metal_cow_trap/entity.tscn +./entity/floor_tile_metal_cow_trap/icon.png +./entity/floor_tile_metal_cow_trap/data.gd +./entity/skin_naked/entity.tscn +./entity/skin_naked/icon.png +./entity/skin_naked/carried.png +./entity/skin_naked/data.gd +./entity/valve/entity.tscn +./entity/valve/icon.png +./entity/valve/.icon.png-autosave.kra +./entity/valve/data.gd +./entity/bed/entity.tscn +./entity/bed/icon.png +./entity/bed/data.gd +./entity/game_invisible_guy/entity.tscn +./entity/game_invisible_guy/icon.png +./entity/game_invisible_guy/special.gd +./entity/game_invisible_guy/data.gd +./entity/smg/entity.tscn +./entity/smg/used.wav +./entity/smg/icon.png +./entity/smg/data.gd +./entity/skin_robo/entity.tscn +./entity/skin_robo/icon.png +./entity/skin_robo/carried.png +./entity/skin_robo/data.gd +./entity/bandana/entity.tscn +./entity/bandana/bob.gd +./entity/bandana/icon.png +./entity/bandana/special.gd +./entity/bandana/carried.png +./entity/bandana/data.gd +./entity/bandana/pixel.png +./entity/floor_plug/entity.tscn +./entity/floor_plug/icon.png +./entity/floor_plug/data.gd +./entity/bench/entity.tscn +./entity/bench/icon.png +./entity/bench/data.gd +./entity/meta_strip_items/entity.tscn +./entity/meta_strip_items/special.gd +./entity/meta_strip_items/meta_strip_items_model.gd +./entity/meta_strip_items/data.gd +./entity/crate_teleporter/entity.tscn +./entity/crate_teleporter/icon.png +./entity/crate_teleporter/data.gd +./entity/crate_teleporter/satellite.kra +./entity/crate_garbage/entity.tscn +./entity/crate_garbage/icon.png +./entity/crate_garbage/data.gd +./entity/crate_garbage/gibbed.png +./entity/meta_stats/entity.tscn +./entity/meta_stats/letters.tres +./entity/meta_stats/icon.png +./entity/meta_stats/special.gd +./entity/meta_stats/data.gd +./entity/meta_stats/meta_stats_model.gd +./entity/rail_gun/entity.tscn +./entity/rail_gun/used.wav +./entity/rail_gun/icon.png +./entity/rail_gun/special.gd +./entity/rail_gun/carried.png +./entity/rail_gun/data.gd +./entity/drop_ship_door/entity.tscn +./entity/drop_ship_door/icon.png +./entity/drop_ship_door/data.gd +./entity/floor_lines/entity.tscn +./entity/floor_lines/icon.png +./entity/floor_lines/data.gd +./entity/game_trap/entity.tscn +./entity/game_trap/you_blew_up_my_force_field.wav +./entity/game_trap/droped_my_grenade_2.wav +./entity/game_trap/icon.png +./entity/game_trap/special.gd +./entity/game_trap/droped_my_grenade_0.wav +./entity/game_trap/shock.wav +./entity/game_trap/uh_my_helmet.wav +./entity/game_trap/ha_missed_me.wav +./entity/game_trap/data.gd +./entity/game_trap/try_beat_this_force_field.wav +./entity/game_trap/droped_my_grenade_1.wav +./entity/blood_sword/entity.tscn +./entity/blood_sword/pick_up.wav +./entity/blood_sword/used.wav +./entity/blood_sword/sam2.png +./entity/blood_sword/icon.png +./entity/blood_sword/special.gd +./entity/blood_sword/hit_bar.gd +./entity/blood_sword/data.gd +./entity/blood_sword/sam.png +./entity/blood_sword/dead.wav +./entity/blood_sword/animation.png +./entity/auto_cables_thick/entity.tscn +./entity/auto_cables_thick/data.gd +./entity/auto_cables_thick/wires2.png +./entity/shield/entity.tscn +./entity/shield/pick_up.wav +./entity/shield/icon.png +./entity/shield/carried.png +./entity/shield/data.gd +./entity/shield/helmet-ping.wav +./entity/game_teleport_in/entity.tscn +./entity/game_teleport_in/icon.png +./entity/game_teleport_in/special.gd +./entity/game_teleport_in/data.gd +./entity/shotgun_super/entity.tscn +./entity/shotgun_super/icon.png +./entity/shotgun_super/data.gd +./entity/bottle/entity.tscn +./entity/bottle/icon.png +./entity/bottle/data.gd +./entity/bottle/normal.png +./entity/bottle/icon_shadow.png +./entity/kill_streak_p90/entity.tscn +./entity/kill_streak_p90/data.gd +./entity/drain/entity.tscn +./entity/drain/icon.png +./entity/drain/data.gd +./entity/auto_wires_three/entity.tscn +./entity/auto_wires_three/data.gd +./entity/light/entity.tscn +./entity/light/icon.png +./entity/light/special.gd +./entity/light/light.wav +./entity/light/data.gd +./entity/debris/entity.tscn +./entity/debris/icon.png +./entity/debris/data.gd +./entity/debris/gibbed.png +./entity/mutation_rail_gun_upgrade/entity.tscn +./entity/mutation_rail_gun_upgrade/icon.png +./entity/mutation_rail_gun_upgrade/special.gd +./entity/mutation_rail_gun_upgrade/data.gd +./entity/mutation_rail_gun_upgrade/mutation_model.gd +./entity/auto_cables/entity.tscn +./entity/auto_cables/data.gd +./entity/auto_cables/wires2.png +./entity/stealth_camo/entity.tscn +./entity/stealth_camo/special.gd +./entity/stealth_camo/data.gd +./entity/colt_45/entity.tscn +./entity/colt_45/used.wav +./entity/colt_45/icon.png +./entity/colt_45/dead.png +./entity/colt_45/data.gd +./entity/quantum_suicide_drive/entity.tscn +./entity/quantum_suicide_drive/heart.ogg +./entity/quantum_suicide_drive/icon.png +./entity/quantum_suicide_drive/special.gd +./entity/quantum_suicide_drive/qsd_model.gd +./entity/quantum_suicide_drive/multi.gd +./entity/quantum_suicide_drive/multi.tscn +./entity/quantum_suicide_drive/CenterContainer.gd +./entity/quantum_suicide_drive/carried.png +./entity/quantum_suicide_drive/data.gd +./entity/helmet/entity.tscn +./entity/helmet/pick_up.wav +./entity/helmet/icon.png +./entity/helmet/special.gd +./entity/helmet/die.wav +./entity/helmet/carried.png +./entity/helmet/data.gd +./entity/helmet/helmet-ping.wav +./entity/ammo_box/entity.tscn +./entity/ammo_box/icon.png +./entity/ammo_box/data.gd +./entity/rail_gun_level_2/entity.tscn +./entity/rail_gun_level_2/icon.png +./entity/rail_gun_level_2/data.gd +./entity/glass_block_backup/entity.tscn +./entity/glass_block_backup/icon.png +./entity/glass_block_backup/data.gd +./entity/closet/entity.tscn +./entity/closet/icon.png +./entity/closet/data.gd +./entity/little_boxes/entity.tscn +./entity/little_boxes/icon.png +./entity/little_boxes/data.gd +./entity/meta_health_bar/entity.tscn +./entity/meta_health_bar/health_bar_model.gd +./entity/meta_health_bar/icon.png +./entity/meta_health_bar/special.gd +./entity/meta_health_bar/invunerable.png +./entity/meta_health_bar/data.gd +./entity/night_stand/entity.tscn +./entity/night_stand/icon_normal.png +./entity/night_stand/icon.png +./entity/night_stand/shadow.png +./entity/night_stand/data.gd +./entity/fan/entity.tscn +./entity/fan/flap2.png +./entity/fan/flaps.gd +./entity/fan/icon.png +./entity/fan/data.gd +./entity/fan/flap.png +./entity/fan/icon_shadow.png +./entity/fan/animation.png +./entity/fan/gibbed.png +./entity/game_tutorial_end/entity.tscn +./entity/game_tutorial_end/icon.png +./entity/game_tutorial_end/special.gd +./entity/game_tutorial_end/data.gd +./entity/mutation_disarmament/entity.tscn +./entity/mutation_disarmament/icon.png +./entity/mutation_disarmament/special.gd +./entity/mutation_disarmament/data.gd +./entity/air_lock/icon_open.png +./entity/air_lock/entity.tscn +./entity/air_lock/door_close.wav +./entity/air_lock/icon.png +./entity/air_lock/special.gd +./entity/air_lock/air_lock_model.gd +./entity/air_lock/data.gd +./entity/scorpion/entity.tscn +./entity/scorpion/used.wav +./entity/scorpion/laser.gd +./entity/scorpion/icon.png +./entity/scorpion/data.gd +./entity/kill_streak_aim_hack/entity.tscn +./entity/kill_streak_aim_hack/data.gd +./entity/dungeon_proc_debug/entity.tscn +./entity/dungeon_proc_debug/icon.png +./entity/dungeon_proc_debug/data.gd +./entity/dungeon_proc_debug/debug.gd +./entity/dungeon_proc_debug/debug.tscn +./entity/tarp/entity.tscn +./entity/tarp/icon.png +./entity/tarp/data.gd +./entity/hit_indicator/entity.tscn +./entity/hit_indicator/data.gd +./entity/console_corner/entity.tscn +./entity/console_corner/animation2.tscn +./entity/console_corner/icon.png +./entity/console_corner/data.gd +./entity/console_corner/animation.tscn +./entity/icon.png +./entity/couch_corner/entity.tscn +./entity/couch_corner/icon.png +./entity/couch_corner/data.gd +./entity/m4/entity.tscn +./entity/m4/used.wav +./entity/m4/icon.png +./entity/m4/data.gd +./entity/game_hud/entity.tscn +./entity/game_hud/icon.png +./entity/game_hud/data.gd +./entity/game_hud/inventory_game.tscn +./entity/prototypes.gd +./entity/agent_chicken/emotes.png +./entity/agent_chicken/entity.tscn +./entity/agent_chicken/sound_board.gd +./entity/agent_chicken/bones.tscn +./entity/agent_chicken/bones.gd +./entity/agent_chicken/barks.gd +./entity/agent_chicken/emote.gd +./entity/agent_chicken/icon.png +./entity/agent_chicken/special.gd +./entity/agent_chicken/bark.gd +./entity/agent_chicken/deaad.png +./entity/agent_chicken/icon.gd +./entity/agent_chicken/data.gd +./entity/agent_chicken/animation.tscn +./entity/agent_chicken/emote.tscn +./entity/agent_chicken/hand.png +./entity/velocity/entity.tscn +./entity/velocity/icon.png +./entity/velocity/special.gd +./entity/velocity/data.gd +./entity/aircon/entity.tscn +./entity/aircon/grate.png +./entity/aircon/icon.png +./entity/aircon/data.gd +./entity/aircon/animation.png +./entity/floor_tile_bricks/entity.tscn +./entity/floor_tile_bricks/icon.png +./entity/floor_tile_bricks/data.gd +./entity/pallet/entity.tscn +./entity/pallet/icon.png +./entity/pallet/data.gd +./entity/barricade_deployed/debug.png +./entity/barricade_deployed/field.tscn +./entity/barricade_deployed/entity.tscn +./entity/barricade_deployed/ambience.ogg +./entity/barricade_deployed/icon.png +./entity/barricade_deployed/field.gd +./entity/barricade_deployed/field_material.tres +./entity/barricade_deployed/debug2.png +./entity/barricade_deployed/data.gd +./entity/barricade_deployed/field_material_invert.tres +./entity/barricade_deployed/field_material.gd +./entity/barricade_deployed/gibbed.png +./entity/helmet_nv/entity.tscn +./entity/helmet_nv/pick_up.wav +./entity/helmet_nv/icon.png +./entity/helmet_nv/special.gd +./entity/helmet_nv/carried.png +./entity/helmet_nv/eyes.png +./entity/helmet_nv/data.gd +./entity/helmet_nv/helmet-ping.wav +./entity/helmet_nv/eyes.gd +./entity/mutation_sword/entity.tscn +./entity/mutation_sword/icon.png +./entity/mutation_sword/special.gd +./entity/mutation_sword/data.gd +./entity/field_full_super/entity.tscn +./entity/field_full_super/icon.png +./entity/field_full_super/special.gd +./entity/field_full_super/carried.png +./entity/field_full_super/data.gd +./entity/entity_man.gd +./entity/couch/entity.tscn +./entity/couch/icon.png +./entity/couch/data.gd +./entity/teleporter_lil_hunter/entity.tscn +./entity/teleporter_lil_hunter/icon.png +./entity/teleporter_lil_hunter/tubes.png +./entity/teleporter_lil_hunter/osc_shader.tres +./entity/teleporter_lil_hunter/eyes.png +./entity/teleporter_lil_hunter/data.gd +./entity/teleporter_lil_hunter/osc.tres +./entity/game_tutorial_melee_zone/entity.tscn +./entity/game_tutorial_melee_zone/icon.png +./entity/game_tutorial_melee_zone/special.gd +./entity/game_tutorial_melee_zone/data.gd +./entity/kill_streak_glock/entity.tscn +./entity/kill_streak_glock/data.gd +./entity/skin_mime/entity.tscn +./entity/skin_mime/icon.png +./entity/skin_mime/special.gd +./entity/skin_mime/carried.png +./entity/skin_mime/data.gd +./entity/medpack_hard/entity.tscn +./entity/medpack_hard/icon.png +./entity/medpack_hard/data.gd +./entity/teleporter_overload/entity.tscn +./entity/teleporter_overload/icon.png +./entity/teleporter_overload/special.gd +./entity/teleporter_overload/carried.png +./entity/teleporter_overload/data.gd +./entity/background_freighter/overlay.png +./entity/background_freighter/entity.tscn +./entity/background_freighter/icon.png +./entity/background_freighter/Master.ogg +./entity/background_freighter/background/space.png +./entity/background_freighter/background/line.png +./entity/background_freighter/background/background2.gd +./entity/background_freighter/background/good create.png +./entity/background_freighter/background/backgip.png +./entity/background_freighter/background/background2.png +./entity/background_freighter/background/background.png +./entity/background_freighter/background/engine_glow.tscn +./entity/background_freighter/background/gra2d.png +./entity/background_freighter/background/lines3.png +./entity/background_freighter/background/background.tscn +./entity/background_freighter/background/lines.tres +./entity/background_freighter/background/background.gd +./entity/background_freighter/background/bayer16tile2.png +./entity/background_freighter/background/goodcrate.png +./entity/background_freighter/background/push.png +./entity/background_freighter/background/background_floor.png +./entity/background_freighter/background/palette_mono.png +./entity/background_freighter/background/stars.gd +./entity/background_freighter/background/lines2.png +./entity/background_freighter/background/lines.shader +./entity/background_freighter/background/ambience.gd +./entity/background_freighter/background/bacsdas.png +./entity/background_freighter/background/space_ship_ambience.ogg +./entity/background_freighter/background/stars.png +./entity/background_freighter/data.gd +./entity/auto_wires/entity.tscn +./entity/auto_wires/data.gd +./entity/kill_streak/entity.tscn +./entity/kill_streak/kill_streak_toast.tscn +./entity/kill_streak/icon.png diff --git a/tests/data/half_precision_floating_point_big_endian.bin b/tests/data/half_precision_floating_point_big_endian.bin new file mode 100644 index 0000000000..6519f7500a --- /dev/null +++ b/tests/data/half_precision_floating_point_big_endian.bin @@ -0,0 +1 @@ +5U
\ No newline at end of file diff --git a/tests/data/half_precision_floating_point_little_endian.bin b/tests/data/half_precision_floating_point_little_endian.bin new file mode 100644 index 0000000000..4f748ab1e9 --- /dev/null +++ b/tests/data/half_precision_floating_point_little_endian.bin @@ -0,0 +1 @@ +U5
\ No newline at end of file diff --git a/tests/scene/test_audio_stream_wav.h b/tests/scene/test_audio_stream_wav.h index d3d5cc8a30..7276dd0878 100644 --- a/tests/scene/test_audio_stream_wav.h +++ b/tests/scene/test_audio_stream_wav.h @@ -162,7 +162,7 @@ void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo, // Compressed streams can't be saved, disable compression. options_map["compress/mode"] = 0; - REQUIRE(wav_importer->import(save_path, save_path, options_map, nullptr) == OK); + REQUIRE(wav_importer->import(0, save_path, save_path, options_map, nullptr) == OK); String load_path = save_path + "." + wav_importer->get_save_extension(); Ref<AudioStreamWAV> loaded_stream = ResourceLoader::load(load_path, "AudioStreamWAV", ResourceFormatImporter::CACHE_MODE_IGNORE, &error); diff --git a/tests/scene/test_fontfile.h b/tests/scene/test_fontfile.h new file mode 100644 index 0000000000..8c9ba6d6ff --- /dev/null +++ b/tests/scene/test_fontfile.h @@ -0,0 +1,82 @@ +/**************************************************************************/ +/* test_fontfile.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_FONTFILE_H +#define TEST_FONTFILE_H + +#include "modules/modules_enabled.gen.h" + +#include "scene/resources/font.h" +#include "tests/test_macros.h" + +namespace TestFontfile { + +TEST_CASE("[FontFile] Create font file and check data") { + // Create test instance. + Ref<FontFile> font_file; + font_file.instantiate(); + +#ifdef MODULE_FREETYPE_ENABLED + // Try to load non-existent files. + ERR_PRINT_OFF + CHECK(font_file->load_dynamic_font("") == OK); + CHECK_MESSAGE(font_file->get_data().is_empty() == true, "Invalid fontfile should not be loaded."); + + CHECK(font_file->load_dynamic_font("thirdparty/fonts/nofonthasthisname.woff2") == OK); + CHECK_MESSAGE(font_file->get_data().is_empty() == true, "Invalid fontfile should not be loaded."); + ERR_PRINT_ON + + // Load a valid file. + CHECK(font_file->load_dynamic_font("thirdparty/fonts/NotoSans_Regular.woff2") == OK); + + // Check fontfile data. + CHECK_MESSAGE(font_file->get_data().is_empty() == false, "Fontfile should have been loaded."); + CHECK_MESSAGE(font_file->get_font_name() == "Noto Sans", "Loaded correct font name."); + CHECK_MESSAGE(font_file->get_font_style_name() == "Regular", "Loaded correct font style."); + CHECK_MESSAGE(font_file->get_data().size() == 148480llu, "Whole fontfile was loaded."); + + // Valid glyphs. + CHECK_MESSAGE(font_file->get_glyph_index(2, 'a', 0) != 0, "Glyph index for 'a' is valid."); + CHECK_MESSAGE(font_file->get_glyph_index(2, 'b', 0) != 0, "Glyph index for 'b' is valid."); + CHECK_MESSAGE(font_file->get_glyph_index(2, 0x0103, 0) != 0, "Glyph index for 'latin small letter a with breve' is valid."); + CHECK_MESSAGE(font_file->get_glyph_index(2, 0x03a8, 0) != 0, "Glyph index for 'Greek psi' is valid."); + CHECK_MESSAGE(font_file->get_glyph_index(2, 0x0416, 0) != 0, "Glyph index for 'Cyrillic zhe' is valid."); + CHECK_MESSAGE(font_file->get_glyph_index(2, '&', 0) != 0, "Glyph index for '&' is valid."); + + // Invalid glyphs. + CHECK_MESSAGE(font_file->get_glyph_index(2, 0x4416, 0) == 0, "Glyph index is invalid."); + CHECK_MESSAGE(font_file->get_glyph_index(2, 0x5555, 0) == 0, "Glyph index is invalid."); + CHECK_MESSAGE(font_file->get_glyph_index(2, 0x2901, 0) == 0, "Glyph index is invalid."); +#endif +} + +} // namespace TestFontfile + +#endif // TEST_FONTFILE_H diff --git a/tests/scene/test_primitives.h b/tests/scene/test_primitives.h index 59f23983e5..7426a9ce29 100644 --- a/tests/scene/test_primitives.h +++ b/tests/scene/test_primitives.h @@ -104,8 +104,9 @@ TEST_CASE("[SceneTree][Primitive][Capsule] Capsule Primitive") { float dist_to_yaxis = 0.f; for (Vector3 point : points) { float new_dist_to_y = point.x * point.x + point.z * point.z; - if (new_dist_to_y > dist_to_yaxis) + if (new_dist_to_y > dist_to_yaxis) { dist_to_yaxis = new_dist_to_y; + } } CHECK(dist_to_yaxis <= radius * radius); @@ -114,10 +115,12 @@ TEST_CASE("[SceneTree][Primitive][Capsule] Capsule Primitive") { float max_y{ 0.f }; float min_y{ 0.f }; for (Vector3 point : points) { - if (point.y > max_y) + if (point.y > max_y) { max_y = point.y; - if (point.y < min_y) + } + if (point.y < min_y) { min_y = point.y; + } } CHECK(max_y - min_y <= height); @@ -196,12 +199,14 @@ TEST_CASE("[SceneTree][Primitive][Box] Box Primitive") { for (const Vector3 &normal : normals) { bool add_normal{ true }; for (const Vector3 &vec : distinct_normals) { - if (vec.is_equal_approx(normal)) + if (vec.is_equal_approx(normal)) { add_normal = false; + } } - if (add_normal) + if (add_normal) { distinct_normals.push_back(normal); + } } CHECK_MESSAGE(distinct_normals.size() == 6, @@ -218,8 +223,9 @@ TEST_CASE("[SceneTree][Primitive][Box] Box Primitive") { break; } } - if (!normal_correct_direction) + if (!normal_correct_direction) { break; + } } CHECK_MESSAGE(normal_correct_direction, diff --git a/tests/scene/test_texture_progress_bar.h b/tests/scene/test_texture_progress_bar.h new file mode 100644 index 0000000000..5eb7495a29 --- /dev/null +++ b/tests/scene/test_texture_progress_bar.h @@ -0,0 +1,92 @@ +/**************************************************************************/ +/* test_texture_progress_bar.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_TEXTURE_PROGRESS_BAR_H +#define TEST_TEXTURE_PROGRESS_BAR_H + +#include "scene/gui/texture_progress_bar.h" + +#include "tests/test_macros.h" + +namespace TestTextureProgressBar { + +TEST_CASE("[SceneTree][TextureProgressBar]") { + TextureProgressBar *texture_progress_bar = memnew(TextureProgressBar); + + SUBCASE("[TextureProgressBar] set_radial_initial_angle() should wrap angle between 0 and 360 degrees (inclusive).") { + texture_progress_bar->set_radial_initial_angle(0.0); + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)0.0)); + + texture_progress_bar->set_radial_initial_angle(360.0); + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)360.0)); + + texture_progress_bar->set_radial_initial_angle(30.5); + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)30.5)); + + texture_progress_bar->set_radial_initial_angle(-30.5); + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)(360 - 30.5))); + + texture_progress_bar->set_radial_initial_angle(36000 + 30.5); + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)30.5)); + + texture_progress_bar->set_radial_initial_angle(-(36000 + 30.5)); + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)(360 - 30.5))); + } + + SUBCASE("[TextureProgressBar] set_radial_initial_angle() should not set non-finite values.") { + texture_progress_bar->set_radial_initial_angle(30.5); + + ERR_PRINT_OFF; + texture_progress_bar->set_radial_initial_angle(INFINITY); + ERR_PRINT_ON; + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)30.5)); + + ERR_PRINT_OFF; + texture_progress_bar->set_radial_initial_angle(-INFINITY); + ERR_PRINT_ON; + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)30.5)); + + ERR_PRINT_OFF; + texture_progress_bar->set_radial_initial_angle(NAN); + ERR_PRINT_ON; + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)30.5)); + + ERR_PRINT_OFF; + texture_progress_bar->set_radial_initial_angle(-NAN); + ERR_PRINT_ON; + CHECK(Math::is_equal_approx(texture_progress_bar->get_radial_initial_angle(), (float)30.5)); + } + + memdelete(texture_progress_bar); +} + +} // namespace TestTextureProgressBar + +#endif // TEST_TEXTURE_PROGRESS_BAR_H diff --git a/tests/scene/test_tree.h b/tests/scene/test_tree.h index e19f8311e2..a74158d328 100644 --- a/tests/scene/test_tree.h +++ b/tests/scene/test_tree.h @@ -139,18 +139,30 @@ TEST_CASE("[SceneTree][Tree]") { TreeItem *child1 = tree->create_item(); TreeItem *child2 = tree->create_item(); TreeItem *child3 = tree->create_item(); + CHECK_EQ(root->get_next(), nullptr); + CHECK_EQ(root->get_next_visible(), child1); + CHECK_EQ(root->get_next_in_tree(), child1); CHECK_EQ(child1->get_next(), child2); + CHECK_EQ(child1->get_next_visible(), child2); CHECK_EQ(child1->get_next_in_tree(), child2); CHECK_EQ(child2->get_next(), child3); + CHECK_EQ(child2->get_next_visible(), child3); CHECK_EQ(child2->get_next_in_tree(), child3); CHECK_EQ(child3->get_next(), nullptr); + CHECK_EQ(child3->get_next_visible(), nullptr); CHECK_EQ(child3->get_next_in_tree(), nullptr); + CHECK_EQ(root->get_prev(), nullptr); + CHECK_EQ(root->get_prev_visible(), nullptr); + CHECK_EQ(root->get_prev_in_tree(), nullptr); CHECK_EQ(child1->get_prev(), nullptr); + CHECK_EQ(child1->get_prev_visible(), root); CHECK_EQ(child1->get_prev_in_tree(), root); CHECK_EQ(child2->get_prev(), child1); + CHECK_EQ(child2->get_prev_visible(), child1); CHECK_EQ(child2->get_prev_in_tree(), child1); CHECK_EQ(child3->get_prev(), child2); + CHECK_EQ(child3->get_prev_visible(), child2); CHECK_EQ(child3->get_prev_in_tree(), child2); TreeItem *nested1 = tree->create_item(child2); @@ -158,13 +170,127 @@ TEST_CASE("[SceneTree][Tree]") { TreeItem *nested3 = tree->create_item(child2); CHECK_EQ(child1->get_next(), child2); + CHECK_EQ(child1->get_next_visible(), child2); CHECK_EQ(child1->get_next_in_tree(), child2); CHECK_EQ(child2->get_next(), child3); + CHECK_EQ(child2->get_next_visible(), nested1); CHECK_EQ(child2->get_next_in_tree(), nested1); CHECK_EQ(child3->get_prev(), child2); + CHECK_EQ(child3->get_prev_visible(), nested3); CHECK_EQ(child3->get_prev_in_tree(), nested3); CHECK_EQ(nested1->get_prev_in_tree(), child2); CHECK_EQ(nested1->get_next_in_tree(), nested2); + CHECK_EQ(nested3->get_next_in_tree(), child3); + + memdelete(tree); + } + + SUBCASE("[Tree] Previous and Next items with hide root.") { + Tree *tree = memnew(Tree); + tree->set_hide_root(true); + TreeItem *root = tree->create_item(); + + TreeItem *child1 = tree->create_item(); + TreeItem *child2 = tree->create_item(); + TreeItem *child3 = tree->create_item(); + CHECK_EQ(root->get_next(), nullptr); + CHECK_EQ(root->get_next_visible(), child1); + CHECK_EQ(root->get_next_in_tree(), child1); + CHECK_EQ(child1->get_next(), child2); + CHECK_EQ(child1->get_next_visible(), child2); + CHECK_EQ(child1->get_next_in_tree(), child2); + CHECK_EQ(child2->get_next(), child3); + CHECK_EQ(child2->get_next_visible(), child3); + CHECK_EQ(child2->get_next_in_tree(), child3); + CHECK_EQ(child3->get_next(), nullptr); + CHECK_EQ(child3->get_next_visible(), nullptr); + CHECK_EQ(child3->get_next_in_tree(), nullptr); + + CHECK_EQ(root->get_prev(), nullptr); + CHECK_EQ(root->get_prev_visible(), nullptr); + CHECK_EQ(root->get_prev_in_tree(), nullptr); + CHECK_EQ(child1->get_prev(), nullptr); + CHECK_EQ(child1->get_prev_visible(), nullptr); + CHECK_EQ(child1->get_prev_in_tree(), nullptr); + CHECK_EQ(child2->get_prev(), child1); + CHECK_EQ(child2->get_prev_visible(), child1); + CHECK_EQ(child2->get_prev_in_tree(), child1); + CHECK_EQ(child3->get_prev(), child2); + CHECK_EQ(child3->get_prev_visible(), child2); + CHECK_EQ(child3->get_prev_in_tree(), child2); + + memdelete(tree); + } + + SUBCASE("[Tree] Previous and Next items wrapping.") { + Tree *tree = memnew(Tree); + TreeItem *root = tree->create_item(); + + TreeItem *child1 = tree->create_item(); + TreeItem *child2 = tree->create_item(); + TreeItem *child3 = tree->create_item(); + CHECK_EQ(root->get_next_visible(true), child1); + CHECK_EQ(root->get_next_in_tree(true), child1); + CHECK_EQ(child1->get_next_visible(true), child2); + CHECK_EQ(child1->get_next_in_tree(true), child2); + CHECK_EQ(child2->get_next_visible(true), child3); + CHECK_EQ(child2->get_next_in_tree(true), child3); + CHECK_EQ(child3->get_next_visible(true), root); + CHECK_EQ(child3->get_next_in_tree(true), root); + + CHECK_EQ(root->get_prev_visible(true), child3); + CHECK_EQ(root->get_prev_in_tree(true), child3); + CHECK_EQ(child1->get_prev_visible(true), root); + CHECK_EQ(child1->get_prev_in_tree(true), root); + CHECK_EQ(child2->get_prev_visible(true), child1); + CHECK_EQ(child2->get_prev_in_tree(true), child1); + CHECK_EQ(child3->get_prev_visible(true), child2); + CHECK_EQ(child3->get_prev_in_tree(true), child2); + + TreeItem *nested1 = tree->create_item(child2); + TreeItem *nested2 = tree->create_item(child2); + TreeItem *nested3 = tree->create_item(child2); + + CHECK_EQ(child1->get_next_visible(true), child2); + CHECK_EQ(child1->get_next_in_tree(true), child2); + CHECK_EQ(child2->get_next_visible(true), nested1); + CHECK_EQ(child2->get_next_in_tree(true), nested1); + CHECK_EQ(nested3->get_next_visible(true), child3); + CHECK_EQ(nested3->get_next_in_tree(true), child3); + CHECK_EQ(child3->get_prev_visible(true), nested3); + CHECK_EQ(child3->get_prev_in_tree(true), nested3); + CHECK_EQ(nested1->get_prev_in_tree(true), child2); + CHECK_EQ(nested1->get_next_in_tree(true), nested2); + CHECK_EQ(nested3->get_next_in_tree(true), child3); + + memdelete(tree); + } + + SUBCASE("[Tree] Previous and Next items wrapping with hide root.") { + Tree *tree = memnew(Tree); + tree->set_hide_root(true); + TreeItem *root = tree->create_item(); + + TreeItem *child1 = tree->create_item(); + TreeItem *child2 = tree->create_item(); + TreeItem *child3 = tree->create_item(); + CHECK_EQ(root->get_next_visible(true), child1); + CHECK_EQ(root->get_next_in_tree(true), child1); + CHECK_EQ(child1->get_next_visible(true), child2); + CHECK_EQ(child1->get_next_in_tree(true), child2); + CHECK_EQ(child2->get_next_visible(true), child3); + CHECK_EQ(child2->get_next_in_tree(true), child3); + CHECK_EQ(child3->get_next_visible(true), root); + CHECK_EQ(child3->get_next_in_tree(true), root); + + CHECK_EQ(root->get_prev_visible(true), child3); + CHECK_EQ(root->get_prev_in_tree(true), child3); + CHECK_EQ(child1->get_prev_visible(true), child3); + CHECK_EQ(child1->get_prev_in_tree(true), child3); + CHECK_EQ(child2->get_prev_visible(true), child1); + CHECK_EQ(child2->get_prev_in_tree(true), child1); + CHECK_EQ(child3->get_prev_visible(true), child2); + CHECK_EQ(child3->get_prev_in_tree(true), child2); memdelete(tree); } diff --git a/tests/scene/test_viewport.h b/tests/scene/test_viewport.h index dde37944ec..06a38f234b 100644 --- a/tests/scene/test_viewport.h +++ b/tests/scene/test_viewport.h @@ -1577,7 +1577,7 @@ TEST_CASE("[SceneTree][Viewport] Physics Picking 2D") { PickingCollider pc; pc.a = memnew(TestArea2D); pc.c = memnew(CollisionShape2D); - pc.r = Ref<RectangleShape2D>(memnew(RectangleShape2D)); + pc.r.instantiate(); pc.r->set_size(Size2(150, 150)); pc.c->set_shape(pc.r); pc.a->add_child(pc.c); diff --git a/tests/servers/test_navigation_server_3d.h b/tests/servers/test_navigation_server_3d.h index 4411b1aae5..1b2a5e0db2 100644 --- a/tests/servers/test_navigation_server_3d.h +++ b/tests/servers/test_navigation_server_3d.h @@ -49,7 +49,7 @@ public: } unsigned function1_calls{ 0 }; - Variant function1_latest_arg0{}; + Variant function1_latest_arg0; }; static inline Array build_array() { diff --git a/tests/test_macros.h b/tests/test_macros.h index d32b26f111..9cc075b6d3 100644 --- a/tests/test_macros.h +++ b/tests/test_macros.h @@ -474,6 +474,6 @@ public: for (int i = 0; i < string_list.size(); ++i) { \ CHECK(string_list[i] == m_slices[i]); \ } \ - } while (0) + } while (false) #endif // TEST_MACROS_H diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 465484d605..9acdc98b1d 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -65,6 +65,7 @@ #include "tests/core/math/test_geometry_3d.h" #include "tests/core/math/test_math_funcs.h" #include "tests/core/math/test_plane.h" +#include "tests/core/math/test_projection.h" #include "tests/core/math/test_quaternion.h" #include "tests/core/math/test_random_number_generator.h" #include "tests/core/math/test_rect2.h" @@ -82,10 +83,12 @@ #include "tests/core/object/test_object.h" #include "tests/core/object/test_undo_redo.h" #include "tests/core/os/test_os.h" +#include "tests/core/string/test_fuzzy_search.h" #include "tests/core/string/test_node_path.h" #include "tests/core/string/test_string.h" #include "tests/core/string/test_translation.h" #include "tests/core/string/test_translation_server.h" +#include "tests/core/templates/test_a_hash_map.h" #include "tests/core/templates/test_command_queue.h" #include "tests/core/templates/test_hash_map.h" #include "tests/core/templates/test_hash_set.h" @@ -114,6 +117,7 @@ #include "tests/scene/test_curve.h" #include "tests/scene/test_curve_2d.h" #include "tests/scene/test_curve_3d.h" +#include "tests/scene/test_fontfile.h" #include "tests/scene/test_gradient.h" #include "tests/scene/test_gradient_texture.h" #include "tests/scene/test_image_texture.h" @@ -128,6 +132,7 @@ #include "tests/scene/test_physics_material.h" #include "tests/scene/test_sprite_frames.h" #include "tests/scene/test_style_box_texture.h" +#include "tests/scene/test_texture_progress_bar.h" #include "tests/scene/test_theme.h" #include "tests/scene/test_timer.h" #include "tests/scene/test_viewport.h" diff --git a/thirdparty/README.md b/thirdparty/README.md index 2ce82e82df..7a95e3c724 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -99,9 +99,14 @@ Files extracted from upstream source: ## certs - Upstream: Mozilla, via https://github.com/bagder/ca-bundle -- Version: git (c5a419971b1bec220368c619aaafd0b818aa119f, 2024) +- Version: git (4d3fe6683f651d96be1bbef316b201e9b33b274d, 2024), + generated from mozilla-release changeset b8ea2342548b8571e58f9176d9555ccdb5ec199f - License: MPL 2.0 +Files extracted from upstream source: + +- `ca-bundle.crt` renamed to `ca-certificates.crt` + ## clipper2 @@ -403,7 +408,7 @@ Files extracted from upstream source: ## icu4c - Upstream: https://github.com/unicode-org/icu -- Version: 75.1 (7750081bda4b3bc1768ae03849ec70f67ea10625, 2024) +- Version: 76.1 (8eca245c7484ac6cc179e3e5f7c1ea7680810f39, 2024) - License: Unicode Files extracted from upstream source: @@ -415,7 +420,7 @@ Files extracted from upstream source: Files generated from upstream source: -- The `icudt75l.dat` built with the provided `godot_data.json` config file (see +- The `icudt76l.dat` built with the provided `godot_data.json` config file (see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md for instructions). @@ -425,7 +430,7 @@ Files generated from upstream source: 3. Reconfigure ICU with custom data config: `ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common` 4. Delete `data/out` folder and rebuild data: `cd data && rm -rf ./out && make` -5. Copy `source/data/out/icudt75l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt75l.dat` +5. Copy `source/data/out/icudt76l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt76l.dat` ## jpeg-compressor @@ -551,8 +556,11 @@ File extracted from upstream release tarball: - All `.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` and all `.h` from `include/psa/` to `thirdparty/mbedtls/include/psa/` -- All `.c` and `.h` from `library/` to `thirdparty/mbedtls/library/` except - for the `psa_*.c` source files +- All `.c` and `.h` from `library/` to `thirdparty/mbedtls/library/` +- From `library/` to `thirdparty/mbedtls/library/`: + - All `.c` and `.h` files + - Except `bignum_mod.c`, `block_cipher.c`, `ecp_curves_new.c`, `lmots.c`, + `lms.c` - The `LICENSE` file (edited to keep only the Apache 2.0 variant) - Applied the patch `msvc-redeclaration-bug.diff` to fix a compilation error with some MSVC versions @@ -565,7 +573,7 @@ File extracted from upstream release tarball: ## meshoptimizer - Upstream: https://github.com/zeux/meshoptimizer -- Version: 0.20 (c21d3be6ddf627f8ca852ba4b6db9903b0557858, 2023) +- Version: 0.22 (4affad044571506a5724c9a6f15424f43e86f731, 2024) - License: MIT Files extracted from upstream repository: @@ -709,7 +717,7 @@ Collection of single-file libraries used in Godot components. * Modifications: use `const char*` instead of `char*` for input string - `smolv.{cpp,h}` * Upstream: https://github.com/aras-p/smol-v - * Version: git (4b52c165c13763051a18e80ffbc2ee436314ceb2, 2020) + * Version: git (9dd54c379ac29fa148cb1b829bb939ba7381d8f4, 2024) * License: Public Domain or MIT - `stb_rect_pack.h` * Upstream: https://github.com/nothings/stb @@ -1063,7 +1071,7 @@ Files extracted from upstream source: Files extracted from upstream source: -- All `.c` and `.h` files, minus `infback.c` +- All `.c` and `.h` files, except `gz*.c` and `infback.c` - `LICENSE` diff --git a/thirdparty/certs/ca-certificates.crt b/thirdparty/certs/ca-certificates.crt index f437587091..c559ab795b 100644 --- a/thirdparty/certs/ca-certificates.crt +++ b/thirdparty/certs/ca-certificates.crt @@ -1,7 +1,9 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Mon Mar 11 15:15:21 2024 GMT +## Certificate data from Mozilla as of: Sat Oct 19 21:26:09 2024 GMT +## +## Find updated versions here: https://curl.se/docs/caextract.html ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,7 +16,7 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.29. -## SHA256: 4d96bd539f4719e9ace493757afbe4a23ee8579de1c97fbebc50bba3c12e8c1e +## SHA256: 36105b01631f9fc03b1eca779b44a30a1a5890b9bf8dc07ccb001a07301e01cf ## @@ -2600,36 +2602,6 @@ vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ CAezNIm8BZ/3Hobui3A= -----END CERTIFICATE----- -GLOBALTRUST 2020 -================ ------BEGIN CERTIFICATE----- -MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx -IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT -VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh -BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy -MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi -D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO -VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM -CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm -fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA -A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR -JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG -DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU -clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ -mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud -IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA -VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw -4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 -iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS -8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 -HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS -vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 -oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF -YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl -gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== ------END CERTIFICATE----- - ANF Secure Server Root CA ========================= -----BEGIN CERTIFICATE----- @@ -3579,3 +3551,116 @@ wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeE HVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0 o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A= -----END CERTIFICATE----- + +FIRMAPROFESIONAL CA ROOT-A WEB +============================== +-----BEGIN CERTIFICATE----- +MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQswCQYDVQQGEwJF +UzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4 +MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2 +WhcNNDcwMzMxMDkwMTM2WjBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25h +bCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFM +IENBIFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zfe9MEkVz6 +iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6CcyvHZpsKjECcfIr28jlg +st7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FD +Y1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB +/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgL +cFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQ +pYXFuXqUPoeovQA= +-----END CERTIFICATE----- + +TWCA CYBER Root CA +================== +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYDVQQG +EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB +IENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQG +EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB +IENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1s +Ts6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxFavcokPFh +V8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/34bKS1PE2Y2yHer43CdT +o0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684iJkXXYJndzk834H/nY62wuFm40AZoNWDT +Nq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK +/c/WMw+f+5eesRycnupfXtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkH +IuNZW0CP2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TM +fAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF +2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzR +wyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83 +QOGt4A1WNzAdBgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB +AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olN +c79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/x +X9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDR +IG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq +/p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0R +FxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz8ppy6rBe +Pm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4NxKfKjLji7gh7MMrZQzv +It6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrruoBa3lwtcHb4yOWHh8qgnaHl +IhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X +-----END CERTIFICATE----- + +SecureSign Root CA12 +==================== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT +ZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJ +BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU +U2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3 +emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwcc +J/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZl +fO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBF +EaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1Uef +NzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOC +AQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQi +LUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpce +mik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPS +vWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhga +aaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== +-----END CERTIFICATE----- + +SecureSign Root CA14 +==================== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTELMAkG +A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT +ZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJ +BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU +U2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh +1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOgvlIfX8xn +bacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy6pJxaeQp8E+BgQQ8sqVb +1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa +/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOE +kJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSx +jVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18iz +ju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0 +dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsY +AFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeq +YR3r6/wtbyPk86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E +rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoA +ymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/Ds +Hzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPG +FrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6q +nsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/ +OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6dB7h7sxa +OgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtlLor6CZpO2oYofaphNdgO +pygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6UeTo3cKXhZ+PmhIIynJkBugnLN +eLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S +-----END CERTIFICATE----- + +SecureSign Root CA15 +==================== +-----BEGIN CERTIFICATE----- +MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UE +BhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1 +cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNV +BAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2Vj +dXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5G +dCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB +2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6J +fl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJ +SwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= +-----END CERTIFICATE----- diff --git a/thirdparty/icu4c/LICENSE b/thirdparty/icu4c/LICENSE index d67e1c8c66..180db98fcc 100644 --- a/thirdparty/icu4c/LICENSE +++ b/thirdparty/icu4c/LICENSE @@ -433,6 +433,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- +JSON parsing library (nlohmann/json) + +File: vendor/json/upstream/single_include/nlohmann/json.hpp (only for ICU4C) + +MIT License + +Copyright (c) 2013-2022 Niels Lohmann + +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. + +---------------------------------------------------------------------- + File: aclocal.m4 (only for ICU4C) Section: pkg.m4 - Macros to locate and utilise pkg-config. @@ -473,7 +501,7 @@ File: config.guess (only for ICU4C) This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or +the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but diff --git a/thirdparty/icu4c/common/appendable.cpp b/thirdparty/icu4c/common/appendable.cpp index c0fbcc6530..de18148fe6 100644 --- a/thirdparty/icu4c/common/appendable.cpp +++ b/thirdparty/icu4c/common/appendable.cpp @@ -25,7 +25,7 @@ Appendable::~Appendable() {} UBool Appendable::appendCodePoint(UChar32 c) { if(c<=0xffff) { - return appendCodeUnit((char16_t)c); + return appendCodeUnit(static_cast<char16_t>(c)); } else { return appendCodeUnit(U16_LEAD(c)) && appendCodeUnit(U16_TRAIL(c)); } diff --git a/thirdparty/icu4c/common/bmpset.cpp b/thirdparty/icu4c/common/bmpset.cpp index 641c675c67..9b2a2967f0 100644 --- a/thirdparty/icu4c/common/bmpset.cpp +++ b/thirdparty/icu4c/common/bmpset.cpp @@ -75,7 +75,7 @@ static void set32x64Bits(uint32_t table[64], int32_t start, int32_t limit) { int32_t trail=start&0x3f; // Named for UTF-8 2-byte trail byte with lower 6 bits. // Set one bit indicating an all-one block. - uint32_t bits=(uint32_t)1<<lead; + uint32_t bits = static_cast<uint32_t>(1) << lead; if((start+1)==limit) { // Single-character shortcut. table[trail]|=bits; return; @@ -100,9 +100,9 @@ static void set32x64Bits(uint32_t table[64], int32_t start, int32_t limit) { ++lead; } if(lead<limitLead) { - bits=~(((unsigned)1<<lead)-1); + bits = ~((static_cast<unsigned>(1) << lead) - 1); if(limitLead<0x20) { - bits&=((unsigned)1<<limitLead)-1; + bits &= (static_cast<unsigned>(1) << limitLead) - 1; } for(trail=0; trail<64; ++trail) { table[trail]|=bits; @@ -111,7 +111,7 @@ static void set32x64Bits(uint32_t table[64], int32_t start, int32_t limit) { // limit<=0x800. If limit==0x800 then limitLead=32 and limitTrail=0. // In that case, bits=1<<limitLead is undefined but the bits value // is not used because trail<limitTrail is already false. - bits=(uint32_t)1<<((limitLead == 0x20) ? (limitLead - 1) : limitLead); + bits = static_cast<uint32_t>(1) << ((limitLead == 0x20) ? (limitLead - 1) : limitLead); for(trail=0; trail<limitTrail; ++trail) { table[trail]|=bits; } @@ -290,22 +290,22 @@ int32_t BMPSet::findCodePoint(UChar32 c, int32_t lo, int32_t hi) const { UBool BMPSet::contains(UChar32 c) const { - if((uint32_t)c<=0xff) { - return (UBool)latin1Contains[c]; - } else if((uint32_t)c<=0x7ff) { - return (UBool)((table7FF[c&0x3f]&((uint32_t)1<<(c>>6)))!=0); - } else if((uint32_t)c<0xd800 || (c>=0xe000 && c<=0xffff)) { + if (static_cast<uint32_t>(c) <= 0xff) { + return latin1Contains[c]; + } else if (static_cast<uint32_t>(c) <= 0x7ff) { + return (table7FF[c & 0x3f] & (static_cast<uint32_t>(1) << (c >> 6))) != 0; + } else if (static_cast<uint32_t>(c) < 0xd800 || (c >= 0xe000 && c <= 0xffff)) { int lead=c>>12; uint32_t twoBits=(bmpBlockBits[(c>>6)&0x3f]>>lead)&0x10001; if(twoBits<=1) { // All 64 code points with the same bits 15..6 // are either in the set or not. - return (UBool)twoBits; + return twoBits; } else { // Look up the code point in its 4k block of code points. return containsSlow(c, list4kStarts[lead], list4kStarts[lead+1]); } - } else if((uint32_t)c<=0x10ffff) { + } else if (static_cast<uint32_t>(c) <= 0x10ffff) { // surrogate or supplementary code point return containsSlow(c, list4kStarts[0xd], list4kStarts[0x11]); } else { @@ -332,7 +332,7 @@ BMPSet::span(const char16_t *s, const char16_t *limit, USetSpanCondition spanCon break; } } else if(c<=0x7ff) { - if((table7FF[c&0x3f]&((uint32_t)1<<(c>>6)))==0) { + if ((table7FF[c & 0x3f] & (static_cast<uint32_t>(1) << (c >> 6))) == 0) { break; } } else if(c<0xd800 || c>=0xe000) { @@ -372,7 +372,7 @@ BMPSet::span(const char16_t *s, const char16_t *limit, USetSpanCondition spanCon break; } } else if(c<=0x7ff) { - if((table7FF[c&0x3f]&((uint32_t)1<<(c>>6)))!=0) { + if ((table7FF[c & 0x3f] & (static_cast<uint32_t>(1) << (c >> 6))) != 0) { break; } } else if(c<0xd800 || c>=0xe000) { @@ -421,7 +421,7 @@ BMPSet::spanBack(const char16_t *s, const char16_t *limit, USetSpanCondition spa break; } } else if(c<=0x7ff) { - if((table7FF[c&0x3f]&((uint32_t)1<<(c>>6)))==0) { + if ((table7FF[c & 0x3f] & (static_cast<uint32_t>(1) << (c >> 6))) == 0) { break; } } else if(c<0xd800 || c>=0xe000) { @@ -464,7 +464,7 @@ BMPSet::spanBack(const char16_t *s, const char16_t *limit, USetSpanCondition spa break; } } else if(c<=0x7ff) { - if((table7FF[c&0x3f]&((uint32_t)1<<(c>>6)))!=0) { + if ((table7FF[c & 0x3f] & (static_cast<uint32_t>(1) << (c >> 6))) != 0) { break; } } else if(c<0xd800 || c>=0xe000) { @@ -527,7 +527,7 @@ BMPSet::spanUTF8(const uint8_t *s, int32_t length, USetSpanCondition spanConditi b=*s; } while(U8_IS_SINGLE(b)); } - length=(int32_t)(limit-s); + length = static_cast<int32_t>(limit - s); } if(spanCondition!=USET_SPAN_NOT_CONTAINED) { @@ -547,7 +547,7 @@ BMPSet::spanUTF8(const uint8_t *s, int32_t length, USetSpanCondition spanConditi * the truncated sequence. */ b=*(limit-1); - if((int8_t)b<0) { + if (static_cast<int8_t>(b) < 0) { // b>=0x80: lead or trail byte if(b<0xc0) { // single trail byte, check for preceding 3- or 4-byte lead byte @@ -602,15 +602,15 @@ BMPSet::spanUTF8(const uint8_t *s, int32_t length, USetSpanCondition spanConditi if(b>=0xe0) { if(b<0xf0) { if( /* handle U+0000..U+FFFF inline */ - (t1=(uint8_t)(s[0]-0x80)) <= 0x3f && - (t2=(uint8_t)(s[1]-0x80)) <= 0x3f + (t1 = static_cast<uint8_t>(s[0] - 0x80)) <= 0x3f && + (t2 = static_cast<uint8_t>(s[1] - 0x80)) <= 0x3f ) { b&=0xf; uint32_t twoBits=(bmpBlockBits[t1]>>b)&0x10001; if(twoBits<=1) { // All 64 code points with this lead byte and middle trail byte // are either in the set or not. - if(twoBits!=(uint32_t)spanCondition) { + if (twoBits != static_cast<uint32_t>(spanCondition)) { return s-1; } } else { @@ -624,12 +624,12 @@ BMPSet::spanUTF8(const uint8_t *s, int32_t length, USetSpanCondition spanConditi continue; } } else if( /* handle U+10000..U+10FFFF inline */ - (t1=(uint8_t)(s[0]-0x80)) <= 0x3f && - (t2=(uint8_t)(s[1]-0x80)) <= 0x3f && - (t3=(uint8_t)(s[2]-0x80)) <= 0x3f + (t1 = static_cast<uint8_t>(s[0] - 0x80)) <= 0x3f && + (t2 = static_cast<uint8_t>(s[1] - 0x80)) <= 0x3f && + (t3 = static_cast<uint8_t>(s[2] - 0x80)) <= 0x3f ) { // Give an illegal sequence the same value as the result of contains(FFFD). - UChar32 c=((UChar32)(b-0xf0)<<18)|((UChar32)t1<<12)|(t2<<6)|t3; + UChar32 c = (static_cast<UChar32>(b - 0xf0) << 18) | (static_cast<UChar32>(t1) << 12) | (t2 << 6) | t3; if( ( (0x10000<=c && c<=0x10ffff) ? containsSlow(c, list4kStarts[0x10], list4kStarts[0x11]) : containsFFFD @@ -643,9 +643,9 @@ BMPSet::spanUTF8(const uint8_t *s, int32_t length, USetSpanCondition spanConditi } else { if( /* handle U+0000..U+07FF inline */ b>=0xc0 && - (t1=(uint8_t)(*s-0x80)) <= 0x3f + (t1 = static_cast<uint8_t>(*s - 0x80)) <= 0x3f ) { - if((USetSpanCondition)((table7FF[t1]&((uint32_t)1<<(b&0x1f)))!=0) != spanCondition) { + if (static_cast<USetSpanCondition>((table7FF[t1] & (static_cast<uint32_t>(1) << (b & 0x1f))) != 0) != spanCondition) { return s-1; } ++s; @@ -711,7 +711,7 @@ BMPSet::spanBackUTF8(const uint8_t *s, int32_t length, USetSpanCondition spanCon c=utf8_prevCharSafeBody(s, 0, &length, b, -3); // c is a valid code point, not ASCII, not a surrogate if(c<=0x7ff) { - if((USetSpanCondition)((table7FF[c&0x3f]&((uint32_t)1<<(c>>6)))!=0) != spanCondition) { + if (static_cast<USetSpanCondition>((table7FF[c & 0x3f] & (static_cast<uint32_t>(1) << (c >> 6))) != 0) != spanCondition) { return prev+1; } } else if(c<=0xffff) { @@ -720,7 +720,7 @@ BMPSet::spanBackUTF8(const uint8_t *s, int32_t length, USetSpanCondition spanCon if(twoBits<=1) { // All 64 code points with the same bits 15..6 // are either in the set or not. - if(twoBits!=(uint32_t)spanCondition) { + if (twoBits != static_cast<uint32_t>(spanCondition)) { return prev+1; } } else { diff --git a/thirdparty/icu4c/common/bmpset.h b/thirdparty/icu4c/common/bmpset.h index fad0310038..00253f97c1 100644 --- a/thirdparty/icu4c/common/bmpset.h +++ b/thirdparty/icu4c/common/bmpset.h @@ -156,7 +156,7 @@ private: }; inline UBool BMPSet::containsSlow(UChar32 c, int32_t lo, int32_t hi) const { - return (UBool)(findCodePoint(c, lo, hi) & 1); + return findCodePoint(c, lo, hi) & 1; } U_NAMESPACE_END diff --git a/thirdparty/icu4c/common/brkeng.cpp b/thirdparty/icu4c/common/brkeng.cpp index e53a7b2ce4..a903357938 100644 --- a/thirdparty/icu4c/common/brkeng.cpp +++ b/thirdparty/icu4c/common/brkeng.cpp @@ -86,7 +86,7 @@ UnhandledEngine::findBreaks( UText *text, if (U_FAILURE(status)) return 0; utext_setNativeIndex(text, startPos); UChar32 c = utext_current32(text); - while((int32_t)utext_getNativeIndex(text) < endPos && fHandled->contains(c)) { + while (static_cast<int32_t>(utext_getNativeIndex(text)) < endPos && fHandled->contains(c)) { utext_next32(text); // TODO: recast loop to work with post-increment operations. c = utext_current32(text); } @@ -146,7 +146,7 @@ ICULanguageBreakFactory::getEngineFor(UChar32 c, const char* locale) { Mutex m(&gBreakEngineMutex); int32_t i = fEngines->size(); while (--i >= 0) { - lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); + lbe = static_cast<const LanguageBreakEngine*>(fEngines->elementAt(i)); if (lbe != nullptr && lbe->handles(c, locale)) { return lbe; } @@ -259,7 +259,7 @@ ICULanguageBreakFactory::loadDictionaryMatcherFor(UScriptCode script) { CharString ext; const char16_t *extStart = u_memrchr(dictfname, 0x002e, dictnlength); // last dot if (extStart != nullptr) { - int32_t len = (int32_t)(extStart - dictfname); + int32_t len = static_cast<int32_t>(extStart - dictfname); ext.appendInvariantChars(UnicodeString(false, extStart + 1, dictnlength - len - 1), status); dictnlength = len; } @@ -269,18 +269,18 @@ ICULanguageBreakFactory::loadDictionaryMatcherFor(UScriptCode script) { UDataMemory *file = udata_open(U_ICUDATA_BRKITR, ext.data(), dictnbuf.data(), &status); if (U_SUCCESS(status)) { // build trie - const uint8_t *data = (const uint8_t *)udata_getMemory(file); - const int32_t *indexes = (const int32_t *)data; + const uint8_t* data = static_cast<const uint8_t*>(udata_getMemory(file)); + const int32_t* indexes = reinterpret_cast<const int32_t*>(data); const int32_t offset = indexes[DictionaryData::IX_STRING_TRIE_OFFSET]; const int32_t trieType = indexes[DictionaryData::IX_TRIE_TYPE] & DictionaryData::TRIE_TYPE_MASK; DictionaryMatcher *m = nullptr; if (trieType == DictionaryData::TRIE_TYPE_BYTES) { const int32_t transform = indexes[DictionaryData::IX_TRANSFORM]; - const char *characters = (const char *)(data + offset); + const char* characters = reinterpret_cast<const char*>(data + offset); m = new BytesDictionaryMatcher(characters, transform, file); } else if (trieType == DictionaryData::TRIE_TYPE_UCHARS) { - const char16_t *characters = (const char16_t *)(data + offset); + const char16_t* characters = reinterpret_cast<const char16_t*>(data + offset); m = new UCharsDictionaryMatcher(characters, file); } if (m == nullptr) { @@ -337,12 +337,12 @@ int32_t BreakEngineWrapper::findBreaks( // extends towards the start or end of the text, depending on 'reverse'. utext_setNativeIndex(text, startPos); - int32_t start = (int32_t)utext_getNativeIndex(text); + int32_t start = static_cast<int32_t>(utext_getNativeIndex(text)); int32_t current; int32_t rangeStart; int32_t rangeEnd; UChar32 c = utext_current32(text); - while((current = (int32_t)utext_getNativeIndex(text)) < endPos && delegate->handles(c)) { + while ((current = static_cast<int32_t>(utext_getNativeIndex(text))) < endPos && delegate->handles(c)) { utext_next32(text); // TODO: recast loop for postincrement c = utext_current32(text); } diff --git a/thirdparty/icu4c/common/brkiter.cpp b/thirdparty/icu4c/common/brkiter.cpp index 4f2f0f3ace..4d945cc17e 100644 --- a/thirdparty/icu4c/common/brkiter.cpp +++ b/thirdparty/icu4c/common/brkiter.cpp @@ -85,7 +85,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st // Get the actual string brkfname = ures_getString(brkName, &size, &status); U_ASSERT((size_t)size<sizeof(fnbuff)); - if ((size_t)size>=sizeof(fnbuff)) { + if (static_cast<size_t>(size) >= sizeof(fnbuff)) { size=0; if (U_SUCCESS(status)) { status = U_BUFFER_OVERFLOW_ERROR; @@ -99,7 +99,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st char16_t* extStart=u_strchr(brkfname, 0x002e); int len = 0; if (extStart != nullptr){ - len = (int)(extStart-brkfname); + len = static_cast<int>(extStart - brkfname); u_UCharsToChars(extStart+1, ext, sizeof(ext)); // nul terminates the buff u_UCharsToChars(brkfname, fnbuff, len); } diff --git a/thirdparty/icu4c/common/bytesinkutil.cpp b/thirdparty/icu4c/common/bytesinkutil.cpp index a32254a7db..e99c10f083 100644 --- a/thirdparty/icu4c/common/bytesinkutil.cpp +++ b/thirdparty/icu4c/common/bytesinkutil.cpp @@ -64,7 +64,7 @@ ByteSinkUtil::appendChange(const uint8_t *s, const uint8_t *limit, errorCode = U_INDEX_OUTOFBOUNDS_ERROR; return false; } - return appendChange((int32_t)(limit - s), s16, s16Length, sink, edits, errorCode); + return appendChange(static_cast<int32_t>(limit - s), s16, s16Length, sink, edits, errorCode); } void @@ -81,15 +81,15 @@ ByteSinkUtil::appendCodePoint(int32_t length, UChar32 c, ByteSink &sink, Edits * namespace { // See unicode/utf8.h U8_APPEND_UNSAFE(). -inline uint8_t getTwoByteLead(UChar32 c) { return (uint8_t)((c >> 6) | 0xc0); } -inline uint8_t getTwoByteTrail(UChar32 c) { return (uint8_t)((c & 0x3f) | 0x80); } +inline uint8_t getTwoByteLead(UChar32 c) { return static_cast<uint8_t>((c >> 6) | 0xc0); } +inline uint8_t getTwoByteTrail(UChar32 c) { return static_cast<uint8_t>((c & 0x3f) | 0x80); } } // namespace void ByteSinkUtil::appendTwoBytes(UChar32 c, ByteSink &sink) { U_ASSERT(0x80 <= c && c <= 0x7ff); // 2-byte UTF-8 - char s8[2] = { (char)getTwoByteLead(c), (char)getTwoByteTrail(c) }; + char s8[2] = {static_cast<char>(getTwoByteLead(c)), static_cast<char>(getTwoByteTrail(c))}; sink.Append(s8, 2); } @@ -114,7 +114,7 @@ ByteSinkUtil::appendUnchanged(const uint8_t *s, const uint8_t *limit, errorCode = U_INDEX_OUTOFBOUNDS_ERROR; return false; } - int32_t length = (int32_t)(limit - s); + int32_t length = static_cast<int32_t>(limit - s); if (length > 0) { appendNonEmptyUnchanged(s, length, sink, options, edits); } diff --git a/thirdparty/icu4c/common/bytesinkutil.h b/thirdparty/icu4c/common/bytesinkutil.h index b3bd487be1..eb3a622ae9 100644 --- a/thirdparty/icu4c/common/bytesinkutil.h +++ b/thirdparty/icu4c/common/bytesinkutil.h @@ -73,7 +73,7 @@ public: /** The few bytes at [src, nextSrc[ were mapped/changed to valid code point c. */ static inline void appendCodePoint(const uint8_t *src, const uint8_t *nextSrc, UChar32 c, ByteSink &sink, Edits *edits = nullptr) { - appendCodePoint((int32_t)(nextSrc - src), c, sink, edits); + appendCodePoint(static_cast<int32_t>(nextSrc - src), c, sink, edits); } /** Append the two-byte character (U+0080..U+07FF). */ diff --git a/thirdparty/icu4c/common/bytestrie.cpp b/thirdparty/icu4c/common/bytestrie.cpp index 532ea9e9c0..048bbebb01 100644 --- a/thirdparty/icu4c/common/bytestrie.cpp +++ b/thirdparty/icu4c/common/bytestrie.cpp @@ -327,7 +327,7 @@ BytesTrie::findUniqueValueFromBranch(const uint8_t *pos, int32_t length, ++pos; // ignore a comparison byte // handle its value int32_t node=*pos++; - UBool isFinal=(UBool)(node&kValueIsFinal); + UBool isFinal = static_cast<UBool>(node & kValueIsFinal); int32_t value=readValue(pos, node>>1); pos=skipValue(pos, node); if(isFinal) { @@ -366,7 +366,7 @@ BytesTrie::findUniqueValue(const uint8_t *pos, UBool haveUniqueValue, int32_t &u // linear-match node pos+=node-kMinLinearMatch+1; // Ignore the match bytes. } else { - UBool isFinal=(UBool)(node&kValueIsFinal); + UBool isFinal = static_cast<UBool>(node & kValueIsFinal); int32_t value=readValue(pos, node>>1); if(haveUniqueValue) { if(value!=uniqueValue) { @@ -434,7 +434,7 @@ BytesTrie::getNextBranchBytes(const uint8_t *pos, int32_t length, ByteSink &out) void BytesTrie::append(ByteSink &out, int c) { - char ch=(char)c; + char ch = static_cast<char>(c); out.Append(&ch, 1); } diff --git a/thirdparty/icu4c/common/bytestriebuilder.cpp b/thirdparty/icu4c/common/bytestriebuilder.cpp index 876e0dfa16..03bbc28e65 100644 --- a/thirdparty/icu4c/common/bytestriebuilder.cpp +++ b/thirdparty/icu4c/common/bytestriebuilder.cpp @@ -43,10 +43,10 @@ public: int32_t offset=stringOffset; int32_t length; if(offset>=0) { - length=(uint8_t)strings[offset++]; + length = static_cast<uint8_t>(strings[offset++]); } else { offset=~offset; - length=((int32_t)(uint8_t)strings[offset]<<8)|(uint8_t)strings[offset+1]; + length = (static_cast<int32_t>(static_cast<uint8_t>(strings[offset])) << 8) | static_cast<uint8_t>(strings[offset + 1]); offset+=2; } return StringPiece(strings.data()+offset, length); @@ -54,10 +54,10 @@ public: int32_t getStringLength(const CharString &strings) const { int32_t offset=stringOffset; if(offset>=0) { - return (uint8_t)strings[offset]; + return static_cast<uint8_t>(strings[offset]); } else { offset=~offset; - return ((int32_t)(uint8_t)strings[offset]<<8)|(uint8_t)strings[offset+1]; + return (static_cast<int32_t>(static_cast<uint8_t>(strings[offset])) << 8) | static_cast<uint8_t>(strings[offset + 1]); } } @@ -102,9 +102,9 @@ BytesTrieElement::setTo(StringPiece s, int32_t val, int32_t offset=strings.length(); if(length>0xff) { offset=~offset; - strings.append((char)(length>>8), errorCode); + strings.append(static_cast<char>(length >> 8), errorCode); } - strings.append((char)length, errorCode); + strings.append(static_cast<char>(length), errorCode); stringOffset=offset; value=val; strings.append(s, errorCode); @@ -229,7 +229,7 @@ BytesTrieBuilder::buildBytes(UStringTrieBuildOption buildOption, UErrorCode &err errorCode=U_INDEX_OUTOFBOUNDS_ERROR; return; } - uprv_sortArray(elements, elementsLength, (int32_t)sizeof(BytesTrieElement), + uprv_sortArray(elements, elementsLength, static_cast<int32_t>(sizeof(BytesTrieElement)), compareElementStrings, strings, false, // need not be a stable sort &errorCode); @@ -284,7 +284,7 @@ BytesTrieBuilder::getElementStringLength(int32_t i) const { char16_t BytesTrieBuilder::getElementUnit(int32_t i, int32_t byteIndex) const { - return (uint8_t)elements[i].charAt(byteIndex, *strings); + return static_cast<uint8_t>(elements[i].charAt(byteIndex, *strings)); } int32_t @@ -330,7 +330,7 @@ BytesTrieBuilder::skipElementsBySomeUnits(int32_t i, int32_t byteIndex, int32_t int32_t BytesTrieBuilder::indexOfElementWithNextUnit(int32_t i, int32_t byteIndex, char16_t byte) const { - char b=(char)byte; + char b = static_cast<char>(byte); while(b==elements[i].charAt(byteIndex, *strings)) { ++i; } @@ -404,7 +404,7 @@ BytesTrieBuilder::write(int32_t byte) { int32_t newLength=bytesLength+1; if(ensureCapacity(newLength)) { bytesLength=newLength; - bytes[bytesCapacity-bytesLength]=(char)byte; + bytes[bytesCapacity - bytesLength] = static_cast<char>(byte); } return bytesLength; } @@ -432,30 +432,30 @@ BytesTrieBuilder::writeValueAndFinal(int32_t i, UBool isFinal) { char intBytes[5]; int32_t length=1; if(i<0 || i>0xffffff) { - intBytes[0]=(char)BytesTrie::kFiveByteValueLead; - intBytes[1]=(char)((uint32_t)i>>24); - intBytes[2]=(char)((uint32_t)i>>16); - intBytes[3]=(char)((uint32_t)i>>8); - intBytes[4]=(char)i; + intBytes[0] = static_cast<char>(BytesTrie::kFiveByteValueLead); + intBytes[1] = static_cast<char>(static_cast<uint32_t>(i) >> 24); + intBytes[2] = static_cast<char>(static_cast<uint32_t>(i) >> 16); + intBytes[3] = static_cast<char>(static_cast<uint32_t>(i) >> 8); + intBytes[4] = static_cast<char>(i); length=5; // } else if(i<=BytesTrie::kMaxOneByteValue) { // intBytes[0]=(char)(BytesTrie::kMinOneByteValueLead+i); } else { if(i<=BytesTrie::kMaxTwoByteValue) { - intBytes[0]=(char)(BytesTrie::kMinTwoByteValueLead+(i>>8)); + intBytes[0] = static_cast<char>(BytesTrie::kMinTwoByteValueLead + (i >> 8)); } else { if(i<=BytesTrie::kMaxThreeByteValue) { - intBytes[0]=(char)(BytesTrie::kMinThreeByteValueLead+(i>>16)); + intBytes[0] = static_cast<char>(BytesTrie::kMinThreeByteValueLead + (i >> 16)); } else { - intBytes[0]=(char)BytesTrie::kFourByteValueLead; - intBytes[1]=(char)(i>>16); + intBytes[0] = static_cast<char>(BytesTrie::kFourByteValueLead); + intBytes[1] = static_cast<char>(i >> 16); length=2; } - intBytes[length++]=(char)(i>>8); + intBytes[length++] = static_cast<char>(i >> 8); } - intBytes[length++]=(char)i; + intBytes[length++] = static_cast<char>(i); } - intBytes[0]=(char)((intBytes[0]<<1)|isFinal); + intBytes[0] = static_cast<char>((intBytes[0] << 1) | isFinal); return write(intBytes, length); } @@ -484,28 +484,28 @@ int32_t BytesTrieBuilder::internalEncodeDelta(int32_t i, char intBytes[]) { U_ASSERT(i>=0); if(i<=BytesTrie::kMaxOneByteDelta) { - intBytes[0]=(char)i; + intBytes[0] = static_cast<char>(i); return 1; } int32_t length=1; if(i<=BytesTrie::kMaxTwoByteDelta) { - intBytes[0]=(char)(BytesTrie::kMinTwoByteDeltaLead+(i>>8)); + intBytes[0] = static_cast<char>(BytesTrie::kMinTwoByteDeltaLead + (i >> 8)); } else { if(i<=BytesTrie::kMaxThreeByteDelta) { - intBytes[0]=(char)(BytesTrie::kMinThreeByteDeltaLead+(i>>16)); + intBytes[0] = static_cast<char>(BytesTrie::kMinThreeByteDeltaLead + (i >> 16)); } else { if(i<=0xffffff) { - intBytes[0]=(char)BytesTrie::kFourByteDeltaLead; + intBytes[0] = static_cast<char>(BytesTrie::kFourByteDeltaLead); } else { - intBytes[0]=(char)BytesTrie::kFiveByteDeltaLead; - intBytes[1]=(char)(i>>24); + intBytes[0] = static_cast<char>(BytesTrie::kFiveByteDeltaLead); + intBytes[1] = static_cast<char>(i >> 24); length=2; } - intBytes[length++]=(char)(i>>16); + intBytes[length++] = static_cast<char>(i >> 16); } - intBytes[length++]=(char)(i>>8); + intBytes[length++] = static_cast<char>(i >> 8); } - intBytes[length++]=(char)i; + intBytes[length++] = static_cast<char>(i); return length; } diff --git a/thirdparty/icu4c/common/bytestrieiterator.cpp b/thirdparty/icu4c/common/bytestrieiterator.cpp index 65f54be48a..b60806f1f3 100644 --- a/thirdparty/icu4c/common/bytestrieiterator.cpp +++ b/thirdparty/icu4c/common/bytestrieiterator.cpp @@ -115,14 +115,14 @@ BytesTrie::Iterator::next(UErrorCode &errorCode) { pos=bytes_+stack_->elementAti(stackSize-2); stack_->setSize(stackSize-2); str_->truncate(length&0xffff); - length=(int32_t)((uint32_t)length>>16); + length = static_cast<int32_t>(static_cast<uint32_t>(length) >> 16); if(length>1) { pos=branchNext(pos, length, errorCode); if(pos==nullptr) { return true; // Reached a final value. } } else { - str_->append((char)*pos++, errorCode); + str_->append(static_cast<char>(*pos++), errorCode); } } if(remainingMatchLength_>=0) { @@ -134,7 +134,7 @@ BytesTrie::Iterator::next(UErrorCode &errorCode) { int32_t node=*pos++; if(node>=kMinValueLead) { // Deliver value for the byte sequence so far. - UBool isFinal=(UBool)(node&kValueIsFinal); + UBool isFinal = static_cast<UBool>(node & kValueIsFinal); value_=readValue(pos, node>>1); if(isFinal || (maxLength_>0 && str_->length()==maxLength_)) { pos_=nullptr; @@ -186,7 +186,7 @@ BytesTrie::Iterator::branchNext(const uint8_t *pos, int32_t length, UErrorCode & while(length>kMaxBranchLinearSubNodeLength) { ++pos; // ignore the comparison byte // Push state for the greater-or-equal edge. - stack_->addElement((int32_t)(skipDelta(pos)-bytes_), errorCode); + stack_->addElement(static_cast<int32_t>(skipDelta(pos) - bytes_), errorCode); stack_->addElement(((length-(length>>1))<<16)|str_->length(), errorCode); // Follow the less-than edge. length>>=1; @@ -196,12 +196,12 @@ BytesTrie::Iterator::branchNext(const uint8_t *pos, int32_t length, UErrorCode & // Read the first (key, value) pair. uint8_t trieByte=*pos++; int32_t node=*pos++; - UBool isFinal=(UBool)(node&kValueIsFinal); + UBool isFinal = static_cast<UBool>(node & kValueIsFinal); int32_t value=readValue(pos, node>>1); pos=skipValue(pos, node); - stack_->addElement((int32_t)(pos-bytes_), errorCode); + stack_->addElement(static_cast<int32_t>(pos - bytes_), errorCode); stack_->addElement(((length-1)<<16)|str_->length(), errorCode); - str_->append((char)trieByte, errorCode); + str_->append(static_cast<char>(trieByte), errorCode); if(isFinal) { pos_=nullptr; value_=value; diff --git a/thirdparty/icu4c/common/caniter.cpp b/thirdparty/icu4c/common/caniter.cpp index 2c987306ec..1b2bc2ada0 100644 --- a/thirdparty/icu4c/common/caniter.cpp +++ b/thirdparty/icu4c/common/caniter.cpp @@ -183,10 +183,10 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st // catch degenerate case if (newSource.length() == 0) { - pieces = (UnicodeString **)uprv_malloc(sizeof(UnicodeString *)); - pieces_lengths = (int32_t*)uprv_malloc(1 * sizeof(int32_t)); + pieces = static_cast<UnicodeString**>(uprv_malloc(sizeof(UnicodeString*))); + pieces_lengths = static_cast<int32_t*>(uprv_malloc(1 * sizeof(int32_t))); pieces_length = 1; - current = (int32_t*)uprv_malloc(1 * sizeof(int32_t)); + current = static_cast<int32_t*>(uprv_malloc(1 * sizeof(int32_t))); current_length = 1; if (pieces == nullptr || pieces_lengths == nullptr || current == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; @@ -229,10 +229,10 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st // allocate the arrays, and find the strings that are CE to each segment - pieces = (UnicodeString **)uprv_malloc(list_length * sizeof(UnicodeString *)); + pieces = static_cast<UnicodeString**>(uprv_malloc(list_length * sizeof(UnicodeString*))); pieces_length = list_length; - pieces_lengths = (int32_t*)uprv_malloc(list_length * sizeof(int32_t)); - current = (int32_t*)uprv_malloc(list_length * sizeof(int32_t)); + pieces_lengths = static_cast<int32_t*>(uprv_malloc(list_length * sizeof(int32_t))); + current = static_cast<int32_t*>(uprv_malloc(list_length * sizeof(int32_t))); current_length = list_length; if (pieces == nullptr || pieces_lengths == nullptr || current == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; @@ -330,7 +330,7 @@ void U_EXPORT2 CanonicalIterator::permute(UnicodeString &source, UBool skipZeros // prefix this character to all of them ne = subpermute.nextElement(el); while (ne != nullptr) { - UnicodeString *permRes = (UnicodeString *)(ne->value.pointer); + UnicodeString* permRes = static_cast<UnicodeString*>(ne->value.pointer); UnicodeString *chStr = new UnicodeString(cp); //test for nullptr if (chStr == nullptr) { @@ -363,6 +363,9 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i char16_t USeg[256]; int32_t segLen = segment.extract(USeg, 256, status); getEquivalents2(&basic, USeg, segLen, status); + if (U_FAILURE(status)) { + return nullptr; + } // now get all the permutations // add only the ones that are canonically equivalent @@ -375,7 +378,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i //while (it.hasNext()) while (ne != nullptr) { //String item = (String) it.next(); - UnicodeString item = *((UnicodeString *)(ne->value.pointer)); + UnicodeString item = *static_cast<UnicodeString*>(ne->value.pointer); permutations.removeAll(); permute(item, CANITER_SKIP_ZEROES, &permutations, status); @@ -387,7 +390,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i while (ne2 != nullptr) { //String possible = (String) it2.next(); //UnicodeString *possible = new UnicodeString(*((UnicodeString *)(ne2->value.pointer))); - UnicodeString possible(*((UnicodeString *)(ne2->value.pointer))); + UnicodeString possible(*static_cast<UnicodeString*>(ne2->value.pointer)); UnicodeString attempt; nfd->normalize(possible, attempt, status); @@ -429,7 +432,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i el = UHASH_FIRST; ne = result.nextElement(el); while(ne != nullptr) { - finalResult[result_len++] = *((UnicodeString *)(ne->value.pointer)); + finalResult[result_len++] = *static_cast<UnicodeString*>(ne->value.pointer); ne = result.nextElement(el); } @@ -466,6 +469,9 @@ Hashtable *CanonicalIterator::getEquivalents2(Hashtable *fillinResult, const cha Hashtable remainder(status); remainder.setValueDeleter(uprv_deleteUObject); if (extract(&remainder, cp2, segment, segLen, i, status) == nullptr) { + if (U_FAILURE(status)) { + return nullptr; + } continue; } @@ -476,7 +482,7 @@ Hashtable *CanonicalIterator::getEquivalents2(Hashtable *fillinResult, const cha int32_t el = UHASH_FIRST; const UHashElement *ne = remainder.nextElement(el); while (ne != nullptr) { - UnicodeString item = *((UnicodeString *)(ne->value.pointer)); + UnicodeString item = *static_cast<UnicodeString*>(ne->value.pointer); UnicodeString *toAdd = new UnicodeString(prefix); /* test for nullptr */ if (toAdd == nullptr) { @@ -490,6 +496,13 @@ Hashtable *CanonicalIterator::getEquivalents2(Hashtable *fillinResult, const cha ne = remainder.nextElement(el); } + // ICU-22642 Guards against strings that have so many permutations + // that they would otherwise hang the function. + constexpr int32_t kResultLimit = 4096; + if (fillinResult->count() > kResultLimit) { + status = U_UNSUPPORTED_ERROR; + return nullptr; + } } } diff --git a/thirdparty/icu4c/common/characterproperties.cpp b/thirdparty/icu4c/common/characterproperties.cpp index f1e15b488d..963ac83421 100644 --- a/thirdparty/icu4c/common/characterproperties.cpp +++ b/thirdparty/icu4c/common/characterproperties.cpp @@ -58,17 +58,17 @@ icu::UMutex cpMutex; // Does not use uset.h to reduce code dependencies void U_CALLCONV _set_add(USet *set, UChar32 c) { - ((UnicodeSet *)set)->add(c); + reinterpret_cast<UnicodeSet*>(set)->add(c); } void U_CALLCONV _set_addRange(USet *set, UChar32 start, UChar32 end) { - ((UnicodeSet *)set)->add(start, end); + reinterpret_cast<UnicodeSet*>(set)->add(start, end); } void U_CALLCONV _set_addString(USet *set, const char16_t *str, int32_t length) { - ((UnicodeSet *)set)->add(icu::UnicodeString((UBool)(length<0), str, length)); + reinterpret_cast<UnicodeSet*>(set)->add(icu::UnicodeString(static_cast<UBool>(length < 0), str, length)); } UBool U_CALLCONV characterproperties_cleanup() { @@ -103,7 +103,7 @@ void U_CALLCONV initInclusion(UPropertySource src, UErrorCode &errorCode) { return; } USetAdder sa = { - (USet *)incl.getAlias(), + reinterpret_cast<USet*>(incl.getAlias()), _set_add, _set_addRange, _set_addString, @@ -184,8 +184,12 @@ void U_CALLCONV initInclusion(UPropertySource src, UErrorCode &errorCode) { sa.add(sa.set, 0x2FFF + 1); break; case UPROPS_SRC_ID_COMPAT_MATH: + case UPROPS_SRC_MCM: uprops_addPropertyStarts(src, &sa, &errorCode); break; + case UPROPS_SRC_BLOCK: + ublock_addPropertyStarts(&sa, errorCode); + break; default: errorCode = U_INTERNAL_PROGRAM_ERROR; break; @@ -289,7 +293,7 @@ UnicodeSet *makeSet(UProperty property, UErrorCode &errorCode) { const icu::EmojiProps *ep = icu::EmojiProps::getSingleton(errorCode); if (U_FAILURE(errorCode)) { return nullptr; } USetAdder sa = { - (USet *)set.getAlias(), + reinterpret_cast<USet*>(set.getAlias()), _set_add, _set_addRange, _set_addString, diff --git a/thirdparty/icu4c/common/cstring.cpp b/thirdparty/icu4c/common/cstring.cpp index e95816c130..cc3f6deed8 100644 --- a/thirdparty/icu4c/common/cstring.cpp +++ b/thirdparty/icu4c/common/cstring.cpp @@ -126,7 +126,7 @@ T_CString_toLowerCase(char* str) if (str) { do - *str = (char)uprv_tolower(*str); + *str = uprv_tolower(*str); while (*(str++)); } @@ -140,7 +140,7 @@ T_CString_toUpperCase(char* str) if (str) { do - *str = (char)uprv_toupper(*str); + *str = uprv_toupper(*str); while (*(str++)); } diff --git a/thirdparty/icu4c/common/dictbe.cpp b/thirdparty/icu4c/common/dictbe.cpp index 3d672c03bf..888716c8d8 100644 --- a/thirdparty/icu4c/common/dictbe.cpp +++ b/thirdparty/icu4c/common/dictbe.cpp @@ -61,12 +61,12 @@ DictionaryBreakEngine::findBreaks( UText *text, // extends towards the start or end of the text, depending on 'reverse'. utext_setNativeIndex(text, startPos); - int32_t start = (int32_t)utext_getNativeIndex(text); + int32_t start = static_cast<int32_t>(utext_getNativeIndex(text)); int32_t current; int32_t rangeStart; int32_t rangeEnd; UChar32 c = utext_current32(text); - while((current = (int32_t)utext_getNativeIndex(text)) < endPos && fSet.contains(c)) { + while ((current = static_cast<int32_t>(utext_getNativeIndex(text))) < endPos && fSet.contains(c)) { utext_next32(text); // TODO: recast loop for postincrement c = utext_current32(text); } @@ -137,7 +137,7 @@ public: int32_t PossibleWord::candidates( UText *text, DictionaryMatcher *dict, int32_t rangeEnd ) { // TODO: If getIndex is too slow, use offset < 0 and add discardAll() - int32_t start = (int32_t)utext_getNativeIndex(text); + int32_t start = static_cast<int32_t>(utext_getNativeIndex(text)); if (start != offset) { offset = start; count = dict->matches(text, rangeEnd-start, UPRV_LENGTHOF(cuLengths), cuLengths, cpLengths, nullptr, &prefix); @@ -253,7 +253,7 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text, utext_setNativeIndex(text, rangeStart); - while (U_SUCCESS(status) && (current = (int32_t)utext_getNativeIndex(text)) < rangeEnd) { + while (U_SUCCESS(status) && (current = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd) { cpWordLength = 0; cuWordLength = 0; @@ -269,7 +269,7 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text, // If there was more than one, see which one can take us forward the most words else if (candidates > 1) { // If we're already at the end of the range, we're done - if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) >= rangeEnd) { goto foundBest; } do { @@ -278,7 +278,7 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text, words[wordsFound%THAI_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done - if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) >= rangeEnd) { goto foundBest; } @@ -308,7 +308,7 @@ foundBest: // The text iterator should now be positioned at the end of the word we found. UChar32 uc = 0; - if ((int32_t)utext_getNativeIndex(text) < rangeEnd && cpWordLength < THAI_ROOT_COMBINE_THRESHOLD) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) < rangeEnd && cpWordLength < THAI_ROOT_COMBINE_THRESHOLD) { // if it is a dictionary word, do nothing. If it isn't, then if there is // no preceding word, or the non-word shares less than the minimum threshold // of characters with a dictionary word, then scan to resynchronize @@ -320,9 +320,9 @@ foundBest: UChar32 pc; int32_t chars = 0; for (;;) { - int32_t pcIndex = (int32_t)utext_getNativeIndex(text); + int32_t pcIndex = static_cast<int32_t>(utext_getNativeIndex(text)); pc = utext_next32(text); - int32_t pcSize = (int32_t)utext_getNativeIndex(text) - pcIndex; + int32_t pcSize = static_cast<int32_t>(utext_getNativeIndex(text)) - pcIndex; chars += pcSize; remaining -= pcSize; if (remaining <= 0) { @@ -356,28 +356,28 @@ foundBest: utext_setNativeIndex(text, current+cuWordLength); } } - + // Never stop before a combining mark. int32_t currPos; - while ((currPos = (int32_t)utext_getNativeIndex(text)) < rangeEnd && fMarkSet.contains(utext_current32(text))) { + while ((currPos = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd && fMarkSet.contains(utext_current32(text))) { utext_next32(text); - cuWordLength += (int32_t)utext_getNativeIndex(text) - currPos; + cuWordLength += static_cast<int32_t>(utext_getNativeIndex(text)) - currPos; } - + // Look ahead for possible suffixes if a dictionary word does not follow. // We do this in code rather than using a rule so that the heuristic // resynch continues to function. For example, one of the suffix characters // could be a typo in the middle of a word. - if ((int32_t)utext_getNativeIndex(text) < rangeEnd && cuWordLength > 0) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) < rangeEnd && cuWordLength > 0) { if (words[wordsFound%THAI_LOOKAHEAD].candidates(text, fDictionary, rangeEnd) <= 0 && fSuffixSet.contains(uc = utext_current32(text))) { if (uc == THAI_PAIYANNOI) { if (!fSuffixSet.contains(utext_previous32(text))) { // Skip over previous end and PAIYANNOI utext_next32(text); - int32_t paiyannoiIndex = (int32_t)utext_getNativeIndex(text); + int32_t paiyannoiIndex = static_cast<int32_t>(utext_getNativeIndex(text)); utext_next32(text); - cuWordLength += (int32_t)utext_getNativeIndex(text) - paiyannoiIndex; // Add PAIYANNOI to word + cuWordLength += static_cast<int32_t>(utext_getNativeIndex(text)) - paiyannoiIndex; // Add PAIYANNOI to word uc = utext_current32(text); // Fetch next character } else { @@ -389,9 +389,9 @@ foundBest: if (utext_previous32(text) != THAI_MAIYAMOK) { // Skip over previous end and MAIYAMOK utext_next32(text); - int32_t maiyamokIndex = (int32_t)utext_getNativeIndex(text); + int32_t maiyamokIndex = static_cast<int32_t>(utext_getNativeIndex(text)); utext_next32(text); - cuWordLength += (int32_t)utext_getNativeIndex(text) - maiyamokIndex; // Add MAIYAMOK to word + cuWordLength += static_cast<int32_t>(utext_getNativeIndex(text)) - maiyamokIndex; // Add MAIYAMOK to word } else { // Restore prior position @@ -489,7 +489,7 @@ LaoBreakEngine::divideUpDictionaryRange( UText *text, utext_setNativeIndex(text, rangeStart); - while (U_SUCCESS(status) && (current = (int32_t)utext_getNativeIndex(text)) < rangeEnd) { + while (U_SUCCESS(status) && (current = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd) { cuWordLength = 0; cpWordLength = 0; @@ -514,7 +514,7 @@ LaoBreakEngine::divideUpDictionaryRange( UText *text, words[wordsFound%LAO_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done - if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) >= rangeEnd) { goto foundBest; } @@ -541,7 +541,7 @@ foundBest: // just found (if there is one), but only if the preceding word does not exceed // the threshold. // The text iterator should now be positioned at the end of the word we found. - if ((int32_t)utext_getNativeIndex(text) < rangeEnd && cpWordLength < LAO_ROOT_COMBINE_THRESHOLD) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) < rangeEnd && cpWordLength < LAO_ROOT_COMBINE_THRESHOLD) { // if it is a dictionary word, do nothing. If it isn't, then if there is // no preceding word, or the non-word shares less than the minimum threshold // of characters with a dictionary word, then scan to resynchronize @@ -554,9 +554,9 @@ foundBest: UChar32 uc; int32_t chars = 0; for (;;) { - int32_t pcIndex = (int32_t)utext_getNativeIndex(text); + int32_t pcIndex = static_cast<int32_t>(utext_getNativeIndex(text)); pc = utext_next32(text); - int32_t pcSize = (int32_t)utext_getNativeIndex(text) - pcIndex; + int32_t pcSize = static_cast<int32_t>(utext_getNativeIndex(text)) - pcIndex; chars += pcSize; remaining -= pcSize; if (remaining <= 0) { @@ -590,9 +590,9 @@ foundBest: // Never stop before a combining mark. int32_t currPos; - while ((currPos = (int32_t)utext_getNativeIndex(text)) < rangeEnd && fMarkSet.contains(utext_current32(text))) { + while ((currPos = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd && fMarkSet.contains(utext_current32(text))) { utext_next32(text); - cuWordLength += (int32_t)utext_getNativeIndex(text) - currPos; + cuWordLength += static_cast<int32_t>(utext_getNativeIndex(text)) - currPos; } // Look ahead for possible suffixes if a dictionary word does not follow. @@ -682,7 +682,7 @@ BurmeseBreakEngine::divideUpDictionaryRange( UText *text, utext_setNativeIndex(text, rangeStart); - while (U_SUCCESS(status) && (current = (int32_t)utext_getNativeIndex(text)) < rangeEnd) { + while (U_SUCCESS(status) && (current = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd) { cuWordLength = 0; cpWordLength = 0; @@ -707,7 +707,7 @@ BurmeseBreakEngine::divideUpDictionaryRange( UText *text, words[wordsFound%BURMESE_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done - if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) >= rangeEnd) { goto foundBest; } @@ -734,7 +734,7 @@ foundBest: // just found (if there is one), but only if the preceding word does not exceed // the threshold. // The text iterator should now be positioned at the end of the word we found. - if ((int32_t)utext_getNativeIndex(text) < rangeEnd && cpWordLength < BURMESE_ROOT_COMBINE_THRESHOLD) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) < rangeEnd && cpWordLength < BURMESE_ROOT_COMBINE_THRESHOLD) { // if it is a dictionary word, do nothing. If it isn't, then if there is // no preceding word, or the non-word shares less than the minimum threshold // of characters with a dictionary word, then scan to resynchronize @@ -747,9 +747,9 @@ foundBest: UChar32 uc; int32_t chars = 0; for (;;) { - int32_t pcIndex = (int32_t)utext_getNativeIndex(text); + int32_t pcIndex = static_cast<int32_t>(utext_getNativeIndex(text)); pc = utext_next32(text); - int32_t pcSize = (int32_t)utext_getNativeIndex(text) - pcIndex; + int32_t pcSize = static_cast<int32_t>(utext_getNativeIndex(text)) - pcIndex; chars += pcSize; remaining -= pcSize; if (remaining <= 0) { @@ -783,9 +783,9 @@ foundBest: // Never stop before a combining mark. int32_t currPos; - while ((currPos = (int32_t)utext_getNativeIndex(text)) < rangeEnd && fMarkSet.contains(utext_current32(text))) { + while ((currPos = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd && fMarkSet.contains(utext_current32(text))) { utext_next32(text); - cuWordLength += (int32_t)utext_getNativeIndex(text) - currPos; + cuWordLength += static_cast<int32_t>(utext_getNativeIndex(text)) - currPos; } // Look ahead for possible suffixes if a dictionary word does not follow. @@ -888,7 +888,7 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, utext_setNativeIndex(text, rangeStart); - while (U_SUCCESS(status) && (current = (int32_t)utext_getNativeIndex(text)) < rangeEnd) { + while (U_SUCCESS(status) && (current = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd) { cuWordLength = 0; cpWordLength = 0; @@ -905,7 +905,7 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, // If there was more than one, see which one can take us forward the most words else if (candidates > 1) { // If we're already at the end of the range, we're done - if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) >= rangeEnd) { goto foundBest; } do { @@ -914,7 +914,7 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, words[wordsFound % KHMER_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done - if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) >= rangeEnd) { goto foundBest; } @@ -941,7 +941,7 @@ foundBest: // just found (if there is one), but only if the preceding word does not exceed // the threshold. // The text iterator should now be positioned at the end of the word we found. - if ((int32_t)utext_getNativeIndex(text) < rangeEnd && cpWordLength < KHMER_ROOT_COMBINE_THRESHOLD) { + if (static_cast<int32_t>(utext_getNativeIndex(text)) < rangeEnd && cpWordLength < KHMER_ROOT_COMBINE_THRESHOLD) { // if it is a dictionary word, do nothing. If it isn't, then if there is // no preceding word, or the non-word shares less than the minimum threshold // of characters with a dictionary word, then scan to resynchronize @@ -954,9 +954,9 @@ foundBest: UChar32 uc; int32_t chars = 0; for (;;) { - int32_t pcIndex = (int32_t)utext_getNativeIndex(text); + int32_t pcIndex = static_cast<int32_t>(utext_getNativeIndex(text)); pc = utext_next32(text); - int32_t pcSize = (int32_t)utext_getNativeIndex(text) - pcIndex; + int32_t pcSize = static_cast<int32_t>(utext_getNativeIndex(text)) - pcIndex; chars += pcSize; remaining -= pcSize; if (remaining <= 0) { @@ -989,9 +989,9 @@ foundBest: // Never stop before a combining mark. int32_t currPos; - while ((currPos = (int32_t)utext_getNativeIndex(text)) < rangeEnd && fMarkSet.contains(utext_current32(text))) { + while ((currPos = static_cast<int32_t>(utext_getNativeIndex(text))) < rangeEnd && fMarkSet.contains(utext_current32(text))) { utext_next32(text); - cuWordLength += (int32_t)utext_getNativeIndex(text) - currPos; + cuWordLength += static_cast<int32_t>(utext_getNativeIndex(text)) - currPos; } // Look ahead for possible suffixes if a dictionary word does not follow. @@ -1120,7 +1120,7 @@ static inline bool isKatakana(UChar32 value) { // Replicates an internal UText function. static inline int32_t utext_i32_flag(int32_t bitIndex) { - return (int32_t)1 << bitIndex; + return static_cast<int32_t>(1) << bitIndex; } /* @@ -1167,14 +1167,14 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, int32_t limit = rangeEnd; U_ASSERT(limit <= utext_nativeLength(inText)); if (limit > utext_nativeLength(inText)) { - limit = (int32_t)utext_nativeLength(inText); + limit = static_cast<int32_t>(utext_nativeLength(inText)); } inputMap.adoptInsteadAndCheckErrorCode(new UVector32(status), status); if (U_FAILURE(status)) { return 0; } while (utext_getNativeIndex(inText) < limit) { - int32_t nativePosition = (int32_t)utext_getNativeIndex(inText); + int32_t nativePosition = static_cast<int32_t>(utext_getNativeIndex(inText)); UChar32 c = utext_next32(inText); U_ASSERT(c != U_SENTINEL); inString.append(c); @@ -1304,7 +1304,7 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, int32_t ix = 0; bool is_prev_katakana = false; for (int32_t i = 0; i < numCodePts; ++i, ix = inString.moveIndex32(ix, 1)) { - if ((uint32_t)bestSnlp.elementAti(i) == kuint32max) { + if (static_cast<uint32_t>(bestSnlp.elementAti(i)) == kuint32max) { continue; } @@ -1327,9 +1327,9 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, } for (int32_t j = 0; j < count; j++) { - uint32_t newSnlp = (uint32_t)bestSnlp.elementAti(i) + (uint32_t)values.elementAti(j); + uint32_t newSnlp = static_cast<uint32_t>(bestSnlp.elementAti(i)) + static_cast<uint32_t>(values.elementAti(j)); int32_t ln_j_i = lengths.elementAti(j) + i; - if (newSnlp < (uint32_t)bestSnlp.elementAti(ln_j_i)) { + if (newSnlp < static_cast<uint32_t>(bestSnlp.elementAti(ln_j_i))) { bestSnlp.setElementAt(newSnlp, ln_j_i); prev.setElementAt(i, ln_j_i); } @@ -1353,7 +1353,7 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, } if (katakanaRunLength < kMaxKatakanaGroupLength) { uint32_t newSnlp = bestSnlp.elementAti(i) + getKatakanaCost(katakanaRunLength); - if (newSnlp < (uint32_t)bestSnlp.elementAti(i+katakanaRunLength)) { + if (newSnlp < static_cast<uint32_t>(bestSnlp.elementAti(i + katakanaRunLength))) { bestSnlp.setElementAt(newSnlp, i+katakanaRunLength); prev.setElementAt(i, i+katakanaRunLength); // prev[j] = i; } @@ -1371,7 +1371,7 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, int32_t numBreaks = 0; // No segmentation found, set boundary to end of range - if ((uint32_t)bestSnlp.elementAti(numCodePts) == kuint32max) { + if (static_cast<uint32_t>(bestSnlp.elementAti(numCodePts)) == kuint32max) { t_boundary.addElement(numCodePts, status); numBreaks++; } else if (isPhraseBreaking) { diff --git a/thirdparty/icu4c/common/dictionarydata.cpp b/thirdparty/icu4c/common/dictionarydata.cpp index 80b6d82d56..4bae0c6d33 100644 --- a/thirdparty/icu4c/common/dictionarydata.cpp +++ b/thirdparty/icu4c/common/dictionarydata.cpp @@ -47,13 +47,13 @@ int32_t UCharsDictionaryMatcher::matches(UText *text, int32_t maxLength, int32_t int32_t *prefix) const { UCharsTrie uct(characters); - int32_t startingTextIndex = (int32_t)utext_getNativeIndex(text); + int32_t startingTextIndex = static_cast<int32_t>(utext_getNativeIndex(text)); int32_t wordCount = 0; int32_t codePointsMatched = 0; for (UChar32 c = utext_next32(text); c >= 0; c=utext_next32(text)) { UStringTrieResult result = (codePointsMatched == 0) ? uct.first(c) : uct.next(c); - int32_t lengthMatched = (int32_t)utext_getNativeIndex(text) - startingTextIndex; + int32_t lengthMatched = static_cast<int32_t>(utext_getNativeIndex(text)) - startingTextIndex; codePointsMatched += 1; if (USTRINGTRIE_HAS_VALUE(result)) { if (wordCount < limit) { @@ -101,7 +101,7 @@ UChar32 BytesDictionaryMatcher::transform(UChar32 c) const { if (delta < 0 || 0xFD < delta) { return U_SENTINEL; } - return (UChar32)delta; + return static_cast<UChar32>(delta); } return c; } @@ -114,13 +114,13 @@ int32_t BytesDictionaryMatcher::matches(UText *text, int32_t maxLength, int32_t int32_t *lengths, int32_t *cpLengths, int32_t *values, int32_t *prefix) const { BytesTrie bt(characters); - int32_t startingTextIndex = (int32_t)utext_getNativeIndex(text); + int32_t startingTextIndex = static_cast<int32_t>(utext_getNativeIndex(text)); int32_t wordCount = 0; int32_t codePointsMatched = 0; for (UChar32 c = utext_next32(text); c >= 0; c=utext_next32(text)) { UStringTrieResult result = (codePointsMatched == 0) ? bt.first(transform(c)) : bt.next(transform(c)); - int32_t lengthMatched = (int32_t)utext_getNativeIndex(text) - startingTextIndex; + int32_t lengthMatched = static_cast<int32_t>(utext_getNativeIndex(text)) - startingTextIndex; codePointsMatched += 1; if (USTRINGTRIE_HAS_VALUE(result)) { if (wordCount < limit) { diff --git a/thirdparty/icu4c/common/edits.cpp b/thirdparty/icu4c/common/edits.cpp index 3348145d48..82055e5e54 100644 --- a/thirdparty/icu4c/common/edits.cpp +++ b/thirdparty/icu4c/common/edits.cpp @@ -47,7 +47,7 @@ Edits &Edits::copyArray(const Edits &other) { return *this; } if (length > capacity) { - uint16_t *newArray = (uint16_t *)uprv_malloc((size_t)length * 2); + uint16_t* newArray = static_cast<uint16_t*>(uprv_malloc(static_cast<size_t>(length) * 2)); if (newArray == nullptr) { length = delta = numChanges = 0; errorCode_ = U_MEMORY_ALLOCATION_ERROR; @@ -186,30 +186,30 @@ void Edits::addReplace(int32_t oldLength, int32_t newLength) { head |= oldLength << 6; } else if(oldLength <= 0x7fff) { head |= LENGTH_IN_1TRAIL << 6; - array[limit++] = (uint16_t)(0x8000 | oldLength); + array[limit++] = static_cast<uint16_t>(0x8000 | oldLength); } else { head |= (LENGTH_IN_2TRAIL + (oldLength >> 30)) << 6; - array[limit++] = (uint16_t)(0x8000 | (oldLength >> 15)); - array[limit++] = (uint16_t)(0x8000 | oldLength); + array[limit++] = static_cast<uint16_t>(0x8000 | (oldLength >> 15)); + array[limit++] = static_cast<uint16_t>(0x8000 | oldLength); } if(newLength < LENGTH_IN_1TRAIL) { head |= newLength; } else if(newLength <= 0x7fff) { head |= LENGTH_IN_1TRAIL; - array[limit++] = (uint16_t)(0x8000 | newLength); + array[limit++] = static_cast<uint16_t>(0x8000 | newLength); } else { head |= LENGTH_IN_2TRAIL + (newLength >> 30); - array[limit++] = (uint16_t)(0x8000 | (newLength >> 15)); - array[limit++] = (uint16_t)(0x8000 | newLength); + array[limit++] = static_cast<uint16_t>(0x8000 | (newLength >> 15)); + array[limit++] = static_cast<uint16_t>(0x8000 | newLength); } - array[length] = (uint16_t)head; + array[length] = static_cast<uint16_t>(head); length = limit; } } void Edits::append(int32_t r) { if(length < capacity || growArray()) { - array[length++] = (uint16_t)r; + array[length++] = static_cast<uint16_t>(r); } } @@ -232,7 +232,7 @@ UBool Edits::growArray() { errorCode_ = U_INDEX_OUTOFBOUNDS_ERROR; return false; } - uint16_t *newArray = (uint16_t *)uprv_malloc((size_t)newCapacity * 2); + uint16_t* newArray = static_cast<uint16_t*>(uprv_malloc(static_cast<size_t>(newCapacity) * 2)); if (newArray == nullptr) { errorCode_ = U_MEMORY_ALLOCATION_ERROR; return false; @@ -415,7 +415,7 @@ int32_t Edits::Iterator::readLength(int32_t head) { U_ASSERT(array[index] >= 0x8000); U_ASSERT(array[index + 1] >= 0x8000); int32_t len = ((head & 1) << 30) | - ((int32_t)(array[index] & 0x7fff) << 15) | + (static_cast<int32_t>(array[index] & 0x7fff) << 15) | (array[index + 1] & 0x7fff); index += 2; return len; diff --git a/thirdparty/icu4c/common/emojiprops.cpp b/thirdparty/icu4c/common/emojiprops.cpp index f2b3f4762f..2e4fb0130c 100644 --- a/thirdparty/icu4c/common/emojiprops.cpp +++ b/thirdparty/icu4c/common/emojiprops.cpp @@ -83,8 +83,8 @@ void EmojiProps::load(UErrorCode &errorCode) { memory = udata_openChoice(nullptr, "icu", "uemoji", isAcceptable, this, &errorCode); if (U_FAILURE(errorCode)) { return; } - const uint8_t *inBytes = (const uint8_t *)udata_getMemory(memory); - const int32_t *inIndexes = (const int32_t *)inBytes; + const uint8_t* inBytes = static_cast<const uint8_t*>(udata_getMemory(memory)); + const int32_t* inIndexes = reinterpret_cast<const int32_t*>(inBytes); int32_t indexesLength = inIndexes[IX_CPTRIE_OFFSET] / 4; if (indexesLength <= IX_RGI_EMOJI_ZWJ_SEQUENCE_TRIE_OFFSET) { errorCode = U_INVALID_FORMAT_ERROR; // Not enough indexes. @@ -104,7 +104,7 @@ EmojiProps::load(UErrorCode &errorCode) { offset = inIndexes[i]; nextOffset = inIndexes[i + 1]; // Set/leave nullptr if there is no UCharsTrie. - const char16_t *p = nextOffset > offset ? (const char16_t *)(inBytes + offset) : nullptr; + const char16_t* p = nextOffset > offset ? reinterpret_cast<const char16_t*>(inBytes + offset) : nullptr; stringTries[getStringTrieIndex(i)] = p; } } diff --git a/thirdparty/icu4c/common/filteredbrk.cpp b/thirdparty/icu4c/common/filteredbrk.cpp index a1490b6121..29b02dd384 100644 --- a/thirdparty/icu4c/common/filteredbrk.cpp +++ b/thirdparty/icu4c/common/filteredbrk.cpp @@ -50,8 +50,8 @@ static void _fb_trace(const char *m, const UnicodeString *s, UBool b, int32_t d, * Used with sortedInsert() */ static int32_t U_CALLCONV compareUnicodeString(UElement t1, UElement t2) { - const UnicodeString &a = *(const UnicodeString*)t1.pointer; - const UnicodeString &b = *(const UnicodeString*)t2.pointer; + const UnicodeString& a = *static_cast<const UnicodeString*>(t1.pointer); + const UnicodeString& b = *static_cast<const UnicodeString*>(t2.pointer); return a.compare(b); } @@ -76,7 +76,7 @@ class UStringSet : public UVector { * Return the ith UnicodeString alias */ inline const UnicodeString* getStringAt(int32_t i) const { - return (const UnicodeString*)elementAt(i); + return static_cast<const UnicodeString*>(elementAt(i)); } /** * Adopt the UnicodeString if not already contained. diff --git a/thirdparty/icu4c/common/icuplug.cpp b/thirdparty/icu4c/common/icuplug.cpp index 7aa70a506b..521a125e43 100644 --- a/thirdparty/icu4c/common/icuplug.cpp +++ b/thirdparty/icu4c/common/icuplug.cpp @@ -747,7 +747,7 @@ uplug_init(UErrorCode *status) { FILE *f; CharString pluginFile; -#ifdef OS390BATCH +#ifdef ICU_PLUGINS_DD /* There are potentially a lot of ways to implement a plugin directory on OS390/zOS */ /* Keeping in mind that unauthorized file access is logged, monitored, and enforced */ /* I've chosen to open a DDNAME if BATCH and leave it alone for (presumably) UNIX */ diff --git a/thirdparty/icu4c/common/loadednormalizer2impl.cpp b/thirdparty/icu4c/common/loadednormalizer2impl.cpp index 99b8f3e86c..bb5736137d 100644 --- a/thirdparty/icu4c/common/loadednormalizer2impl.cpp +++ b/thirdparty/icu4c/common/loadednormalizer2impl.cpp @@ -63,7 +63,7 @@ LoadedNormalizer2Impl::isAcceptable(void * /*context*/, pInfo->dataFormat[1]==0x72 && pInfo->dataFormat[2]==0x6d && pInfo->dataFormat[3]==0x32 && - pInfo->formatVersion[0]==4 + pInfo->formatVersion[0]==5 ) { // Normalizer2Impl *me=(Normalizer2Impl *)context; // uprv_memcpy(me->dataVersion, pInfo->dataVersion, 4); @@ -82,8 +82,8 @@ LoadedNormalizer2Impl::load(const char *packageName, const char *name, UErrorCod if(U_FAILURE(errorCode)) { return; } - const uint8_t *inBytes=(const uint8_t *)udata_getMemory(memory); - const int32_t *inIndexes=(const int32_t *)inBytes; + const uint8_t* inBytes = static_cast<const uint8_t*>(udata_getMemory(memory)); + const int32_t* inIndexes = reinterpret_cast<const int32_t*>(inBytes); int32_t indexesLength=inIndexes[IX_NORM_TRIE_OFFSET]/4; if(indexesLength<=IX_MIN_LCCC_CP) { errorCode=U_INVALID_FORMAT_ERROR; // Not enough indexes. @@ -101,7 +101,7 @@ LoadedNormalizer2Impl::load(const char *packageName, const char *name, UErrorCod offset=nextOffset; nextOffset=inIndexes[IX_SMALL_FCD_OFFSET]; - const uint16_t *inExtraData=(const uint16_t *)(inBytes+offset); + const uint16_t* inExtraData = reinterpret_cast<const uint16_t*>(inBytes + offset); // smallFCD: new in formatVersion 2 offset=nextOffset; @@ -311,7 +311,7 @@ Normalizer2::getInstance(const char *packageName, { Mutex lock; if(cache!=nullptr) { - allModes=(Norm2AllModes *)uhash_get(cache, name); + allModes = static_cast<Norm2AllModes*>(uhash_get(cache, name)); } } if(allModes==nullptr) { @@ -331,7 +331,7 @@ Normalizer2::getInstance(const char *packageName, void *temp=uhash_get(cache, name); if(temp==nullptr) { int32_t keyLength= static_cast<int32_t>(uprv_strlen(name)+1); - char *nameCopy=(char *)uprv_malloc(keyLength); + char* nameCopy = static_cast<char*>(uprv_malloc(keyLength)); if(nameCopy==nullptr) { errorCode=U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -341,7 +341,7 @@ Normalizer2::getInstance(const char *packageName, uhash_put(cache, nameCopy, localAllModes.orphan(), &errorCode); } else { // race condition - allModes=(Norm2AllModes *)temp; + allModes = static_cast<Norm2AllModes*>(temp); } } } diff --git a/thirdparty/icu4c/common/localebuilder.cpp b/thirdparty/icu4c/common/localebuilder.cpp index e53065a8a6..71969c847b 100644 --- a/thirdparty/icu4c/common/localebuilder.cpp +++ b/thirdparty/icu4c/common/localebuilder.cpp @@ -1,6 +1,8 @@ // © 2019 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html +#include <optional> +#include <string_view> #include <utility> #include "bytesinkutil.h" // StringByteSink<CharString> @@ -162,12 +164,15 @@ _isKeywordValue(const char* key, const char* value, int32_t value_len) // otherwise: unicode extension value // We need to convert from legacy key/value to unicode // key/value - const char* unicode_locale_key = uloc_toUnicodeLocaleKey(key); - const char* unicode_locale_type = uloc_toUnicodeLocaleType(key, value); - - return unicode_locale_key && unicode_locale_type && - ultag_isUnicodeLocaleKey(unicode_locale_key, -1) && - ultag_isUnicodeLocaleType(unicode_locale_type, -1); + std::optional<std::string_view> unicode_locale_key = ulocimp_toBcpKeyWithFallback(key); + std::optional<std::string_view> unicode_locale_type = ulocimp_toBcpTypeWithFallback(key, value); + + return unicode_locale_key.has_value() && + unicode_locale_type.has_value() && + ultag_isUnicodeLocaleKey(unicode_locale_key->data(), + static_cast<int32_t>(unicode_locale_key->size())) && + ultag_isUnicodeLocaleType(unicode_locale_type->data(), + static_cast<int32_t>(unicode_locale_type->size())); } void diff --git a/thirdparty/icu4c/common/localefallback_data.h b/thirdparty/icu4c/common/localefallback_data.h index 7441ee307a..0accf0324d 100644 --- a/thirdparty/icu4c/common/localefallback_data.h +++ b/thirdparty/icu4c/common/localefallback_data.h @@ -15,111 +15,112 @@ const char scriptCodeChars[] = "Brah\0Cakm\0Cans\0Cari\0Cham\0Cher\0Chrs\0Copt\0Cprt\0Cyrl\0Deva\0" "Egyp\0Elym\0Ethi\0Geor\0Gong\0Gonm\0Goth\0Gran\0Grek\0Gujr\0Guru\0" "Hang\0Hani\0Hans\0Hant\0Hebr\0Hluw\0Hmnp\0Ital\0Java\0Jpan\0Kali\0" - "Kana\0Kawi\0Khar\0Khmr\0Kits\0Knda\0Kore\0Lana\0Laoo\0Lepc\0Lina\0" - "Linb\0Lisu\0Lyci\0Lydi\0Mand\0Mani\0Marc\0Medf\0Merc\0Mlym\0Modi\0" - "Mong\0Mroo\0Mtei\0Mymr\0Narb\0Newa\0Nkoo\0Nshu\0Ogam\0Olck\0Orkh\0" - "Orya\0Osge\0Pauc\0Phli\0Phnx\0Plrd\0Prti\0Rjng\0Rohg\0Runr\0Samr\0" - "Sarb\0Saur\0Sgnw\0Sinh\0Sogd\0Sora\0Soyo\0Syrc\0Tagb\0Takr\0Tale\0" - "Talu\0Taml\0Tang\0Tavt\0Telu\0Tfng\0Thaa\0Thai\0Tibt\0Tnsa\0Toto\0" - "Ugar\0Vaii\0Wcho\0Xpeo\0Xsux\0Yiii\0"; + "Kana\0Kawi\0Khar\0Khmr\0Kits\0Knda\0Kore\0Lana\0Laoo\0Latf\0Latg\0" + "Lepc\0Lina\0Linb\0Lisu\0Lyci\0Lydi\0Mand\0Mani\0Marc\0Medf\0Merc\0" + "Mlym\0Modi\0Mong\0Mroo\0Mtei\0Mymr\0Narb\0Newa\0Nkoo\0Nshu\0Ogam\0" + "Olck\0Orkh\0Orya\0Osge\0Ougr\0Pauc\0Phli\0Phnx\0Plrd\0Prti\0Rjng\0" + "Rohg\0Runr\0Samr\0Sarb\0Saur\0Sgnw\0Sinh\0Sogd\0Sora\0Soyo\0Sunu\0" + "Syrc\0Tagb\0Takr\0Tale\0Talu\0Taml\0Tang\0Tavt\0Telu\0Tfng\0Thaa\0" + "Thai\0Tibt\0Tnsa\0Toto\0Ugar\0Vaii\0Wcho\0Xpeo\0Xsux\0Yiii\0"; const char dsLocaleIDChars[] = "aaf\0aao\0aat\0ab\0abh\0abl\0abv\0acm\0acq\0acw\0acx\0adf\0adx\0" "ady\0ae\0aeb\0aec\0aee\0aeq\0afb\0agi\0agj\0agx\0ahg\0aho\0ahr\0" - "aib\0aij\0ain\0aio\0aiq\0akk\0akv\0alk\0all\0alr\0alt\0alw\0am\0" - "ams\0amw\0ani\0anp\0anr\0anu\0aot\0apc\0apd\0aph\0aqc\0ar\0arc\0" - "arq\0ars\0ary\0arz\0as\0ase\0ask\0atn\0atv\0auj\0auz\0av\0avd\0" - "avl\0awa\0awn\0axm\0ayh\0ayl\0ayn\0ayp\0az_IQ\0az_IR\0az_RU\0" - "azb\0ba\0bal\0bap\0bax\0bbl\0bcq\0bdv\0bdz\0be\0bee\0bej\0bfb\0" - "bfq\0bft\0bfu\0bfw\0bfy\0bfz\0bg\0bgc\0bgd\0bgn\0bgp\0bgq\0bgw\0" - "bgx\0bha\0bhb\0bhd\0bhe\0bhh\0bhi\0bhj\0bhm\0bhn\0bho\0bht\0bhu\0" - "biy\0bjf\0bjj\0bjm\0blk\0blt\0bmj\0bn\0bns\0bo\0bph\0bpx\0bpy\0" - "bqi\0bra\0brb\0brd\0brh\0brk\0brv\0brx\0bsh\0bsk\0bsq\0bst\0btd\0" - "btm\0btv\0bua\0bwe\0bxm\0bxu\0byh\0byn\0byw\0bzi\0cbn\0ccp\0cde\0" - "cdh\0cdi\0cdj\0cdm\0cdo\0cdz\0ce\0cgk\0chg\0chm\0chr\0chx\0cih\0" - "cja\0cji\0cjm\0cjy\0ckb\0ckt\0clh\0clw\0cmg\0cna\0cnp\0cog\0cop\0" - "cpg\0cr\0crh\0crj\0crk\0crl\0crm\0csh\0csp\0csw\0ctd\0ctg\0ctn\0" - "ctt\0cu\0cuu\0cv\0czh\0czk\0daq\0dar\0dcc\0ddo\0def\0deh\0der\0" - "dhi\0dhn\0dho\0dhw\0dka\0dlg\0dmf\0dmk\0dml\0dng\0dnu\0dnv\0doi\0" - "dox\0dre\0drq\0drs\0dry\0dso\0dty\0dub\0duh\0dus\0dv\0dwk\0dwz\0" - "dz\0dzl\0ecr\0ecy\0egy\0eky\0el\0emg\0emu\0enf\0enh\0era\0esg\0" - "esh\0ett\0eve\0evn\0fa\0fay\0faz\0fia\0fmu\0fub\0gan\0gaq\0gas\0" - "gau\0gbj\0gbk\0gbl\0gbm\0gbz\0gdb\0gdo\0gdx\0gez\0ggg\0gha\0ghe\0" - "ghr\0ght\0gig\0gin\0gjk\0gju\0gld\0glh\0glk\0gmv\0gmy\0goe\0gof\0" - "gok\0gom\0gon\0got\0gra\0grc\0grt\0gru\0gu\0gvr\0gwc\0gwf\0gwt\0" - "gyo\0gzi\0ha_CM\0ha_SD\0hac\0hak\0har\0haz\0hbo\0hdy\0he\0hi\0" - "hii\0hit\0hkh\0hlb\0hlu\0hmd\0hmj\0hmq\0hnd\0hne\0hnj\0hnj_AU\0" - "hnj_CN\0hnj_FR\0hnj_GF\0hnj_LA\0hnj_MM\0hnj_SR\0hnj_TH\0hnj_VN\0" - "hno\0hoc\0hoh\0hoj\0how\0hoy\0hpo\0hrt\0hrz\0hsn\0hss\0htx\0hut\0" - "huy\0huz\0hy\0hyw\0ii\0imy\0inh\0int\0ior\0iru\0isk\0itk\0itl\0" - "iu\0iw\0ja\0jad\0jat\0jbe\0jbn\0jct\0jda\0jdg\0jdt\0jee\0jge\0" - "ji\0jje\0jkm\0jml\0jna\0jnd\0jnl\0jns\0jog\0jpa\0jpr\0jrb\0jrb_MA\0" - "jul\0jun\0juy\0jya\0jye\0ka\0kaa\0kap\0kaw\0kbd\0kbu\0kby\0kca\0" - "kdq\0kdt\0ket\0kex\0key\0kfa\0kfb\0kfc\0kfd\0kfe\0kfh\0kfi\0kfk\0" - "kfm\0kfp\0kfq\0kfr\0kfs\0kfx\0kfy\0kgj\0kgy\0khb\0khf\0khg\0khn\0" - "kht\0khv\0khw\0kif\0kim\0kip\0kjg\0kjh\0kjl\0kjo\0kjp\0kjt\0kk\0" - "kk_AF\0kk_CN\0kk_IR\0kk_MN\0kkf\0kkh\0kkt\0kle\0klj\0klr\0km\0" - "kmj\0kmz\0kn\0ko\0koi\0kok\0kpt\0kpy\0kqd\0kqy\0kra\0krc\0krk\0" - "krr\0kru\0krv\0ks\0ksu\0ksw\0ksz\0ktb\0ktl\0ktp\0ku_LB\0kuf\0" - "kum\0kv\0kva\0kvq\0kvt\0kvx\0kvy\0kxf\0kxk\0kxm\0kxp\0ky\0ky_CN\0" - "kyu\0kyv\0kyw\0lab\0lad\0lae\0lah\0lbc\0lbe\0lbf\0lbj\0lbm\0lbo\0" - "lbr\0lcp\0lep\0lez\0lhm\0lhs\0lif\0lis\0lkh\0lki\0lmh\0lmn\0lo\0" - "loy\0lpo\0lrc\0lrk\0lrl\0lsa\0lsd\0lss\0luk\0luu\0luv\0luz\0lwl\0" - "lwm\0lya\0lzh\0mag\0mai\0man_GN\0mby\0mde\0mdf\0mdx\0mdy\0mfa\0" - "mfi\0mgp\0mhj\0mid\0mjl\0mjq\0mjr\0mjt\0mju\0mjv\0mjz\0mk\0mkb\0" - "mke\0mki\0mkm\0ml\0mlf\0mn\0mn_CN\0mni\0mnj\0mns\0mnw\0mpz\0mr\0" - "mra\0mrd\0mrj\0mro\0mrr\0ms_CC\0mtm\0mtr\0mud\0muk\0mut\0muv\0" - "muz\0mvf\0mvy\0mvz\0mwr\0mwt\0mww\0my\0mym\0myv\0myz\0mzn\0nan\0" - "nao\0ncd\0ncq\0ndf\0ne\0neg\0neh\0nei\0new\0ngt\0nio\0nit\0niv\0" - "nli\0nlm\0nlx\0nmm\0nnp\0nod\0noe\0nog\0noi\0non\0nos\0npb\0nqo\0" - "nsd\0nsf\0nsk\0nst\0nsv\0nty\0ntz\0nwc\0nwx\0nyl\0nyq\0oaa\0oac\0" - "oar\0oav\0obm\0obr\0odk\0oht\0oj\0ojs\0okm\0oko\0okz\0ola\0ole\0" - "omk\0omp\0omr\0oon\0or\0ort\0oru\0orv\0os\0osa\0osc\0osi\0ota\0" - "otb\0otk\0oty\0pa\0pa_PK\0pal\0paq\0pbt\0pcb\0pce\0pcf\0pcg\0" - "pch\0pci\0pcj\0peg\0peo\0pgd\0pgg\0pgl\0pgn\0phd\0phk\0phl\0phn\0" - "pho\0phr\0pht\0phv\0phw\0pi\0pka\0pkr\0plk\0pll\0pmh\0pnt\0pra\0" - "prc\0prd\0prt\0prx\0ps\0psh\0psi\0pst\0pum\0pwo\0pwr\0pww\0pyx\0" + "aib\0aii\0aij\0ain\0aio\0aiq\0akk\0akv\0alk\0all\0alr\0alt\0alw\0" + "am\0ams\0amw\0ani\0anp\0anq\0anr\0anu\0aot\0apc\0apd\0aph\0aqc\0" + "ar\0arc\0arq\0ars\0ary\0arz\0as\0ase\0ask\0asr\0atn\0atv\0auj\0" + "auz\0av\0avd\0avl\0awa\0awn\0axm\0ayh\0ayl\0ayn\0ayp\0az_IQ\0" + "az_IR\0az_RU\0azb\0ba\0bal\0bap\0bax\0bbl\0bcq\0bdv\0bdz\0be\0" + "bee\0bej\0bfb\0bfq\0bft\0bfu\0bfw\0bfy\0bfz\0bg\0bgc\0bgd\0bgn\0" + "bgp\0bgq\0bgw\0bgx\0bha\0bhb\0bhd\0bhe\0bhh\0bhi\0bhj\0bhm\0bhn\0" + "bho\0bht\0bhu\0biy\0bjf\0bjj\0bjm\0bkk\0blk\0blt\0bmj\0bn\0bns\0" + "bo\0bph\0bpx\0bpy\0bqi\0bra\0brb\0brd\0brh\0brk\0bro\0brv\0brw\0" + "brx\0bsh\0bsk\0bsq\0bst\0btd\0btm\0btv\0bua\0bwe\0bxm\0bxu\0byh\0" + "byn\0byw\0bzi\0cbn\0ccp\0cde\0cdh\0cdi\0cdj\0cdm\0cdo\0cdz\0ce\0" + "cgk\0chg\0chm\0chr\0chx\0cih\0cja\0cji\0cjm\0cjy\0ckb\0ckt\0clh\0" + "clw\0cmg\0cna\0cnp\0cog\0cop\0cpg\0cr\0crh\0crj\0crk\0crl\0crm\0" + "csh\0csp\0csw\0ctd\0ctg\0ctn\0ctt\0cty\0cu\0cuu\0cv\0czh\0czk\0" + "daq\0dar\0dcc\0ddo\0def\0deh\0der\0dgl\0dhi\0dhn\0dho\0dhw\0dka\0" + "dlg\0dmf\0dmk\0dml\0dng\0dnu\0dnv\0doi\0dox\0dre\0drq\0drs\0dry\0" + "dso\0dty\0dub\0duh\0dus\0dv\0dwk\0dwz\0dz\0dzl\0ecr\0ecy\0egy\0" + "eky\0el\0emg\0emu\0enf\0enh\0era\0esg\0esh\0ett\0eve\0evn\0fa\0" + "fay\0faz\0fia\0fmu\0fub\0gan\0gaq\0gas\0gau\0gbj\0gbk\0gbl\0gbm\0" + "gbz\0gdb\0gdo\0gdx\0gez\0ggg\0gha\0ghe\0gho\0ghr\0ght\0gig\0gin\0" + "gjk\0gju\0gld\0glh\0glk\0gml\0gmv\0gmy\0goe\0gof\0goj\0gok\0gon\0" + "got\0gra\0grc\0grt\0gru\0gu\0gvr\0gwc\0gwf\0gwt\0gyo\0gzi\0ha_CM\0" + "ha_SD\0hac\0hak\0har\0haz\0hbo\0hdy\0he\0hi\0hif\0hii\0hit\0hkh\0" + "hlb\0hlu\0hmd\0hmj\0hmq\0hnd\0hne\0hnj\0hno\0hoc\0hoh\0hoj\0how\0" + "hoy\0hpo\0hrt\0hrz\0hsn\0hss\0htx\0hut\0huy\0huz\0hy\0hyw\0ii\0" + "imy\0inh\0int\0ior\0iru\0isk\0itk\0itl\0iu\0iw\0ja\0jad\0jat\0" + "jbe\0jbn\0jct\0jda\0jdg\0jdt\0jee\0jge\0ji\0jje\0jkm\0jml\0jna\0" + "jnd\0jnl\0jns\0jog\0jpa\0jpr\0jrb\0jul\0jun\0juy\0jya\0jye\0ka\0" + "kaa\0kap\0kaw\0kbd\0kbg\0kbu\0kby\0kca\0kcy\0kdq\0kdt\0ket\0kev\0" + "kex\0key\0kfa\0kfb\0kfc\0kfd\0kfe\0kfg\0kfh\0kfi\0kfk\0kfm\0kfp\0" + "kfq\0kfr\0kfs\0kfu\0kfx\0kfy\0kgj\0kgy\0khb\0khf\0khg\0khn\0kho\0" + "kht\0khv\0khw\0kif\0kim\0kip\0kjg\0kjh\0kjl\0kjo\0kjp\0kjt\0kjz\0" + "kk\0kk_AF\0kk_CN\0kk_IR\0kk_MN\0kkf\0kkh\0kkt\0kle\0klj\0klr\0" + "km\0kmj\0kmz\0kn\0knn\0ko\0koi\0kok\0kpt\0kpy\0kqd\0kqy\0kra\0" + "krc\0krk\0krr\0kru\0krv\0ks\0ksu\0ksw\0ksz\0ktb\0kte\0ktl\0ktp\0" + "ku_LB\0kuf\0kum\0kv\0kva\0kvq\0kvt\0kvx\0kvy\0kxf\0kxk\0kxm\0" + "kxp\0ky\0ky_CN\0kyu\0kyv\0kyw\0lab\0lad\0lae\0lah\0lbe\0lbf\0" + "lbj\0lbm\0lbo\0lbr\0lcp\0lep\0lez\0lhm\0lhs\0lif\0lis\0lkh\0lki\0" + "lmh\0lmn\0lo\0loy\0lpo\0lrc\0lrk\0lrl\0lsa\0lsd\0lss\0ltc\0luk\0" + "luu\0luv\0luz\0lwl\0lwm\0lya\0lzh\0mag\0mai\0man_GN\0mby\0mde\0" + "mdf\0mdx\0mdy\0mfa\0mfi\0mga\0mgp\0mhj\0mid\0mjl\0mjq\0mjr\0mjt\0" + "mju\0mjv\0mjz\0mk\0mkb\0mke\0mki\0mkm\0ml\0mlf\0mn\0mn_CN\0mnc\0" + "mni\0mnj\0mns\0mnw\0mpz\0mr\0mra\0mrd\0mrj\0mro\0mrr\0ms_CC\0" + "mtm\0mtr\0mud\0muk\0mut\0muv\0muz\0mve\0mvf\0mvy\0mvz\0mwr\0mwt\0" + "mww\0my\0mym\0myv\0myz\0mzn\0nan\0nao\0ncd\0ncq\0ndf\0ne\0neg\0" + "neh\0nei\0new\0ngt\0nio\0nit\0niv\0nli\0nlm\0nlx\0nmm\0nnp\0nod\0" + "noe\0nog\0noi\0non\0nos\0npb\0nqo\0nrn\0nsd\0nsf\0nsk\0nst\0nsv\0" + "nty\0ntz\0nwc\0nwx\0nyl\0nyq\0nyw\0oaa\0oac\0oar\0oav\0obm\0obr\0" + "odk\0oht\0oj\0ojs\0okm\0oko\0okz\0ola\0ole\0omk\0omp\0omr\0omx\0" + "oon\0or\0ort\0oru\0orv\0os\0osa\0osc\0osi\0ota\0otb\0otk\0oty\0" + "oui\0pa\0pa_PK\0pal\0paq\0pbt\0pcb\0pce\0pcf\0pcg\0pch\0pci\0" + "pcj\0peg\0peo\0pgd\0pgg\0pgl\0pgn\0phd\0phk\0phl\0phn\0pho\0phr\0" + "pht\0phu\0phv\0phw\0pi\0pka\0pkr\0plk\0pll\0pmh\0pnt\0pra\0prc\0" + "prd\0prt\0prx\0ps\0psh\0psi\0pst\0psu\0pum\0pwo\0pwr\0pww\0pyx\0" "qxq\0raa\0rab\0raf\0rah\0raj\0rav\0rbb\0rdb\0rei\0rhg\0rji\0rjs\0" - "rka\0rki\0rkt\0rmi\0rmt\0rmz\0rom_BG\0rsk\0rtw\0ru\0rue\0rut\0" - "rwr\0ryu\0sa\0sah\0sam\0sat\0saz\0sbn\0sbu\0sck\0scl\0scl_IN\0" - "scp\0sct\0scu\0scx\0sd\0sd_IN\0sdb\0sdf\0sdg\0sdh\0sds\0sel\0" - "sfm\0sga\0sgh\0sgj\0sgr\0sgt\0sgw\0sgy\0shd\0shi\0shm\0shn\0shu\0" - "shv\0si\0sia\0sip\0siy\0siz\0sjd\0sjp\0sjt\0skb\0skj\0skr\0smh\0" - "smp\0smu\0smy\0soa\0sog\0soi\0sou\0spt\0spv\0sqo\0sqq\0sqt\0sr\0" - "srb\0srh\0srx\0srz\0ssh\0sss\0sts\0stv\0sty\0suz\0sva\0swb\0swi\0" - "swv\0syc\0syl\0syn\0syr\0syw\0ta\0tab\0taj\0tbk\0tcn\0tco\0tcx\0" - "tcy\0tda\0tdb\0tdd\0tdg\0tdh\0te\0tes\0tg\0tg_PK\0tge\0tgf\0th\0" - "the\0thf\0thi\0thl\0thm\0thq\0thr\0ths\0ti\0tig\0tij\0tin\0tjl\0" - "tjo\0tkb\0tks\0tkt\0tmr\0tnv\0tov\0tpu\0tra\0trg\0trm\0trw\0tsd\0" - "tsj\0tt\0tth\0tto\0tts\0tvn\0twm\0txg\0txo\0tyr\0tyv\0ude\0udg\0" - "udi\0udm\0ug\0ug_KZ\0ug_MN\0uga\0ugh\0ugo\0uk\0uki\0ulc\0unr\0" - "unr_NP\0unx\0ur\0urk\0ush\0uum\0uz_AF\0uz_CN\0uzs\0vaa\0vaf\0" - "vah\0vai\0vas\0vav\0vay\0vgr\0vmd\0vmh\0wal\0wbk\0wbq\0wbr\0wlo\0" - "wme\0wne\0wni\0wsg\0wsv\0wtm\0wuu\0xal\0xan\0xas\0xco\0xcr\0xdq\0" - "xhe\0xhm\0xis\0xka\0xkc\0xkj\0xkp\0xlc\0xld\0xly\0xmf\0xmn\0xmr\0" - "xna\0xnr\0xpg\0xpi\0xpm\0xpr\0xrm\0xrn\0xsa\0xsr\0xub\0xuj\0xve\0" - "xvi\0xwo\0xzh\0yai\0ybh\0ybi\0ydg\0yea\0yej\0yeu\0ygp\0yhd\0yi\0" - "yig\0yih\0yiv\0ykg\0yna\0ynk\0yoi\0yoy\0yrk\0ysd\0ysn\0ysp\0ysr\0" - "ysy\0yud\0yue\0yue_CN\0yug\0yux\0ywq\0ywu\0zau\0zba\0zch\0zdj\0" - "zeh\0zen\0zgb\0zgh\0zgm\0zgn\0zh\0zh_AU\0zh_BN\0zh_GB\0zh_GF\0" - "zh_HK\0zh_ID\0zh_MO\0zh_PA\0zh_PF\0zh_PH\0zh_SR\0zh_TH\0zh_TW\0" - "zh_US\0zh_VN\0zhd\0zhx\0zko\0zkt\0zkz\0zlj\0zln\0zlq\0zqe\0zrp\0" - "zum\0zyg\0zyn\0zzj\0"; + "rka\0rki\0rkt\0rmi\0rmt\0rmz\0rsk\0rtw\0ru\0rue\0rut\0rwr\0ryu\0" + "sa\0sah\0sam\0sat\0saz\0sbn\0sbu\0sck\0scl\0scp\0sct\0scu\0scx\0" + "sd\0sd_IN\0sdb\0sdf\0sdg\0sdh\0sdr\0sds\0sel\0sfm\0sga\0sgh\0" + "sgj\0sgr\0sgt\0sgw\0sgy\0shd\0shi\0shm\0shn\0shu\0shv\0si\0sia\0" + "sip\0siy\0siz\0sjd\0sjp\0sjt\0skb\0skj\0skr\0smh\0smp\0smu\0smy\0" + "soa\0sog\0soi\0sou\0spt\0spv\0sqo\0sqq\0sqt\0sr\0srb\0srh\0srx\0" + "srz\0ssh\0sss\0sts\0stv\0sty\0suz\0sva\0swb\0swi\0swv\0sxu\0syc\0" + "syl\0syn\0syr\0syw\0ta\0tab\0taj\0tbk\0tcn\0tco\0tcx\0tcy\0tda\0" + "tdb\0tdd\0tdg\0tdh\0te\0tes\0tg\0tg_PK\0tge\0tgf\0th\0the\0thf\0" + "thi\0thl\0thm\0thq\0thr\0ths\0ti\0tig\0tij\0tin\0tjl\0tjo\0tkb\0" + "tks\0tkt\0tmr\0tnv\0tov\0tpu\0tra\0trg\0trm\0trw\0tsd\0tsj\0tt\0" + "tth\0tto\0tts\0ttz\0tvn\0twm\0txg\0txo\0tyr\0tyv\0ude\0udg\0udi\0" + "udm\0ug\0ug_KZ\0ug_MN\0uga\0ugh\0ugo\0uk\0uki\0ulc\0unr\0unr_NP\0" + "unx\0ur\0urk\0ush\0uum\0uz_AF\0uz_CN\0uzs\0vaa\0vaf\0vah\0vai\0" + "vas\0vav\0vay\0vgr\0vjk\0vmd\0vmh\0wal\0wbk\0wbq\0wbr\0wle\0wlo\0" + "wme\0wne\0wni\0wsg\0wsv\0wtm\0wuu\0xag\0xal\0xan\0xas\0xco\0xcr\0" + "xdq\0xhe\0xhm\0xis\0xka\0xkc\0xkf\0xkj\0xkp\0xlc\0xld\0xly\0xmf\0" + "xmn\0xmr\0xna\0xnr\0xpg\0xpi\0xpm\0xpr\0xrm\0xrn\0xsa\0xsr\0xtq\0" + "xub\0xuj\0xve\0xvi\0xwo\0xzh\0yai\0ybh\0ybi\0ydg\0yea\0yej\0yeu\0" + "ygp\0yhd\0yi\0yig\0yih\0yiv\0ykg\0ykh\0yna\0ynk\0yoi\0yoy\0yrk\0" + "ysd\0ysn\0ysp\0ysr\0ysy\0yud\0yue\0yue_CN\0yug\0yux\0ywq\0ywu\0" + "zau\0zba\0zch\0zdj\0zeh\0zen\0zgb\0zgh\0zgm\0zgn\0zh\0zh_AU\0" + "zh_BN\0zh_GB\0zh_GF\0zh_HK\0zh_ID\0zh_MO\0zh_PA\0zh_PF\0zh_PH\0" + "zh_SR\0zh_TH\0zh_TW\0zh_US\0zh_VN\0zhd\0zhx\0zko\0zkt\0zkz\0zlj\0" + "zln\0zlq\0zqe\0zrg\0zrp\0zum\0zwa\0zyg\0zyn\0zzj\0"; const int32_t defaultScriptTable[] = { - 0, 320, // aaf -> Mlym + 0, 330, // aaf -> Mlym 4, 10, // aao -> Arab 8, 150, // aat -> Grek 12, 100, // ab -> Cyrl 15, 10, // abh -> Arab - 19, 420, // abl -> Rjng + 19, 435, // abl -> Rjng 23, 10, // abv -> Arab 27, 10, // acm -> Arab 31, 10, // acq -> Arab 35, 10, // acw -> Arab 39, 10, // acx -> Arab 43, 10, // adf -> Arab - 47, 535, // adx -> Tibt + 47, 555, // adx -> Tibt 51, 100, // ady -> Cyrl 55, 25, // ae -> Avst 58, 10, // aeb -> Arab @@ -134,994 +135,1022 @@ const int32_t defaultScriptTable[] = { 94, 5, // aho -> Ahom 98, 105, // ahr -> Deva 102, 10, // aib -> Arab - 106, 185, // aij -> Hebr - 110, 220, // ain -> Kana - 114, 345, // aio -> Mymr - 118, 10, // aiq -> Arab - 122, 570, // akk -> Xsux - 126, 100, // akv -> Cyrl - 130, 260, // alk -> Laoo - 134, 320, // all -> Mlym - 138, 100, // alr -> Cyrl - 142, 100, // alt -> Cyrl - 146, 120, // alw -> Ethi - 150, 120, // am -> Ethi - 153, 210, // ams -> Jpan - 157, 475, // amw -> Syrc - 161, 100, // ani -> Cyrl - 165, 105, // anp -> Deva - 169, 105, // anr -> Deva - 173, 120, // anu -> Ethi - 177, 45, // aot -> Beng - 181, 10, // apc -> Arab - 185, 10, // apd -> Arab - 189, 105, // aph -> Deva - 193, 100, // aqc -> Cyrl - 197, 10, // ar -> Arab - 200, 15, // arc -> Armi - 204, 10, // arq -> Arab - 208, 10, // ars -> Arab - 212, 10, // ary -> Arab - 216, 10, // arz -> Arab - 220, 45, // as -> Beng - 223, 450, // ase -> Sgnw - 227, 10, // ask -> Arab - 231, 10, // atn -> Arab - 235, 100, // atv -> Cyrl - 239, 10, // auj -> Arab - 243, 10, // auz -> Arab - 247, 100, // av -> Cyrl - 250, 10, // avd -> Arab - 254, 10, // avl -> Arab - 258, 105, // awa -> Deva - 262, 120, // awn -> Ethi - 266, 20, // axm -> Armn - 270, 10, // ayh -> Arab - 274, 10, // ayl -> Arab - 278, 10, // ayn -> Arab - 282, 10, // ayp -> Arab - 286, 10, // az_IQ -> Arab - 292, 10, // az_IR -> Arab - 298, 100, // az_RU -> Cyrl - 304, 10, // azb -> Arab - 308, 100, // ba -> Cyrl - 311, 10, // bal -> Arab - 315, 105, // bap -> Deva - 319, 30, // bax -> Bamu - 323, 125, // bbl -> Geor - 327, 120, // bcq -> Ethi - 331, 385, // bdv -> Orya - 335, 10, // bdz -> Arab - 339, 100, // be -> Cyrl - 342, 105, // bee -> Deva - 346, 10, // bej -> Arab - 350, 105, // bfb -> Deva - 354, 500, // bfq -> Taml - 358, 10, // bft -> Arab - 362, 535, // bfu -> Tibt - 366, 385, // bfw -> Orya - 370, 105, // bfy -> Deva - 374, 105, // bfz -> Deva - 378, 100, // bg -> Cyrl - 381, 105, // bgc -> Deva - 385, 105, // bgd -> Deva - 389, 10, // bgn -> Arab - 393, 10, // bgp -> Arab - 397, 105, // bgq -> Deva - 401, 105, // bgw -> Deva - 405, 150, // bgx -> Grek - 409, 105, // bha -> Deva - 413, 105, // bhb -> Deva - 417, 105, // bhd -> Deva - 421, 10, // bhe -> Arab - 425, 100, // bhh -> Cyrl - 429, 105, // bhi -> Deva - 433, 105, // bhj -> Deva - 437, 10, // bhm -> Arab - 441, 475, // bhn -> Syrc - 445, 105, // bho -> Deva - 449, 485, // bht -> Takr - 453, 105, // bhu -> Deva - 457, 105, // biy -> Deva - 461, 475, // bjf -> Syrc - 465, 105, // bjj -> Deva - 469, 10, // bjm -> Arab - 473, 345, // blk -> Mymr - 477, 510, // blt -> Tavt - 481, 105, // bmj -> Deva - 485, 45, // bn -> Beng - 488, 105, // bns -> Deva - 492, 535, // bo -> Tibt - 495, 100, // bph -> Cyrl - 499, 105, // bpx -> Deva - 503, 45, // bpy -> Beng - 507, 10, // bqi -> Arab - 511, 105, // bra -> Deva - 515, 235, // brb -> Khmr - 519, 105, // brd -> Deva - 523, 10, // brh -> Arab - 527, 10, // brk -> Arab - 531, 260, // brv -> Laoo - 535, 105, // brx -> Deva - 539, 10, // bsh -> Arab - 543, 10, // bsk -> Arab - 547, 35, // bsq -> Bass - 551, 120, // bst -> Ethi - 555, 40, // btd -> Batk - 559, 40, // btm -> Batk - 563, 105, // btv -> Deva - 567, 100, // bua -> Cyrl - 571, 345, // bwe -> Mymr - 575, 100, // bxm -> Cyrl - 579, 330, // bxu -> Mong - 583, 105, // byh -> Deva - 587, 120, // byn -> Ethi - 591, 105, // byw -> Deva - 595, 530, // bzi -> Thai - 599, 530, // cbn -> Thai - 603, 60, // ccp -> Cakm - 607, 515, // cde -> Telu - 611, 105, // cdh -> Deva - 615, 155, // cdi -> Gujr - 619, 105, // cdj -> Deva - 623, 105, // cdm -> Deva - 627, 175, // cdo -> Hans - 631, 45, // cdz -> Beng - 635, 100, // ce -> Cyrl - 638, 535, // cgk -> Tibt - 642, 10, // chg -> Arab - 646, 100, // chm -> Cyrl - 650, 80, // chr -> Cher - 654, 105, // chx -> Deva - 658, 105, // cih -> Deva - 662, 10, // cja -> Arab - 666, 100, // cji -> Cyrl - 670, 75, // cjm -> Cham - 674, 175, // cjy -> Hans - 678, 10, // ckb -> Arab - 682, 100, // ckt -> Cyrl - 686, 10, // clh -> Arab - 690, 100, // clw -> Cyrl - 694, 470, // cmg -> Soyo - 698, 535, // cna -> Tibt - 702, 175, // cnp -> Hans - 706, 530, // cog -> Thai - 710, 90, // cop -> Copt - 714, 150, // cpg -> Grek - 718, 65, // cr -> Cans - 721, 100, // crh -> Cyrl - 725, 65, // crj -> Cans - 729, 65, // crk -> Cans - 733, 65, // crl -> Cans - 737, 65, // crm -> Cans - 741, 345, // csh -> Mymr - 745, 175, // csp -> Hans - 749, 65, // csw -> Cans - 753, 395, // ctd -> Pauc - 757, 45, // ctg -> Beng - 761, 105, // ctn -> Deva - 765, 500, // ctt -> Taml - 769, 100, // cu -> Cyrl - 772, 255, // cuu -> Lana - 776, 100, // cv -> Cyrl - 779, 175, // czh -> Hans - 783, 185, // czk -> Hebr - 787, 105, // daq -> Deva - 791, 100, // dar -> Cyrl - 795, 10, // dcc -> Arab - 799, 100, // ddo -> Cyrl - 803, 10, // def -> Arab - 807, 10, // deh -> Arab - 811, 45, // der -> Beng - 815, 105, // dhi -> Deva - 819, 155, // dhn -> Gujr - 823, 105, // dho -> Deva - 827, 105, // dhw -> Deva - 831, 535, // dka -> Tibt - 835, 100, // dlg -> Cyrl - 839, 310, // dmf -> Medf - 843, 10, // dmk -> Arab - 847, 10, // dml -> Arab - 851, 100, // dng -> Cyrl - 855, 345, // dnu -> Mymr - 859, 345, // dnv -> Mymr - 863, 105, // doi -> Deva - 867, 120, // dox -> Ethi - 871, 535, // dre -> Tibt - 875, 105, // drq -> Deva - 879, 120, // drs -> Ethi - 883, 105, // dry -> Deva - 887, 385, // dso -> Orya - 891, 105, // dty -> Deva - 895, 155, // dub -> Gujr - 899, 105, // duh -> Deva - 903, 105, // dus -> Deva - 907, 525, // dv -> Thaa - 910, 385, // dwk -> Orya - 914, 105, // dwz -> Deva - 918, 535, // dz -> Tibt - 921, 535, // dzl -> Tibt - 925, 150, // ecr -> Grek - 929, 95, // ecy -> Cprt - 933, 110, // egy -> Egyp - 937, 215, // eky -> Kali - 941, 150, // el -> Grek - 944, 105, // emg -> Deva - 948, 105, // emu -> Deva - 952, 100, // enf -> Cyrl - 956, 100, // enh -> Cyrl - 960, 500, // era -> Taml - 964, 135, // esg -> Gonm - 968, 10, // esh -> Arab - 972, 200, // ett -> Ital - 976, 100, // eve -> Cyrl - 980, 100, // evn -> Cyrl - 984, 10, // fa -> Arab - 987, 10, // fay -> Arab - 991, 10, // faz -> Arab - 995, 10, // fia -> Arab - 999, 105, // fmu -> Deva - 1003, 10, // fub -> Arab - 1007, 175, // gan -> Hans - 1011, 385, // gaq -> Orya - 1015, 155, // gas -> Gujr - 1019, 515, // gau -> Telu - 1023, 385, // gbj -> Orya - 1027, 105, // gbk -> Deva - 1031, 155, // gbl -> Gujr - 1035, 105, // gbm -> Deva - 1039, 10, // gbz -> Arab - 1043, 385, // gdb -> Orya - 1047, 100, // gdo -> Cyrl - 1051, 105, // gdx -> Deva - 1055, 120, // gez -> Ethi - 1059, 10, // ggg -> Arab - 1063, 10, // gha -> Arab - 1067, 105, // ghe -> Deva - 1071, 10, // ghr -> Arab - 1075, 535, // ght -> Tibt - 1079, 10, // gig -> Arab - 1083, 100, // gin -> Cyrl - 1087, 10, // gjk -> Arab - 1091, 10, // gju -> Arab - 1095, 100, // gld -> Cyrl - 1099, 10, // glh -> Arab - 1103, 10, // glk -> Arab - 1107, 120, // gmv -> Ethi - 1111, 275, // gmy -> Linb - 1115, 535, // goe -> Tibt - 1119, 120, // gof -> Ethi - 1123, 105, // gok -> Deva - 1127, 105, // gom -> Deva - 1131, 515, // gon -> Telu - 1135, 140, // got -> Goth - 1139, 105, // gra -> Deva - 1143, 95, // grc -> Cprt - 1147, 45, // grt -> Beng - 1151, 120, // gru -> Ethi - 1155, 155, // gu -> Gujr - 1158, 105, // gvr -> Deva - 1162, 10, // gwc -> Arab - 1166, 10, // gwf -> Arab - 1170, 10, // gwt -> Arab - 1174, 105, // gyo -> Deva - 1178, 10, // gzi -> Arab - 1182, 10, // ha_CM -> Arab - 1188, 10, // ha_SD -> Arab - 1194, 10, // hac -> Arab - 1198, 175, // hak -> Hans - 1202, 120, // har -> Ethi - 1206, 10, // haz -> Arab - 1210, 185, // hbo -> Hebr - 1214, 120, // hdy -> Ethi - 1218, 185, // he -> Hebr - 1221, 105, // hi -> Deva - 1224, 485, // hii -> Takr - 1228, 570, // hit -> Xsux - 1232, 10, // hkh -> Arab - 1236, 105, // hlb -> Deva - 1240, 190, // hlu -> Hluw - 1244, 410, // hmd -> Plrd - 1248, 50, // hmj -> Bopo - 1252, 50, // hmq -> Bopo - 1256, 10, // hnd -> Arab - 1260, 105, // hne -> Deva - 1264, 195, // hnj -> Hmnp - 1268, 260, // hnj_AU -> Laoo - 1275, 260, // hnj_CN -> Laoo - 1282, 260, // hnj_FR -> Laoo - 1289, 260, // hnj_GF -> Laoo - 1296, 260, // hnj_LA -> Laoo - 1303, 260, // hnj_MM -> Laoo - 1310, 260, // hnj_SR -> Laoo - 1317, 260, // hnj_TH -> Laoo - 1324, 260, // hnj_VN -> Laoo - 1331, 10, // hno -> Arab - 1335, 105, // hoc -> Deva - 1339, 10, // hoh -> Arab - 1343, 105, // hoj -> Deva - 1347, 170, // how -> Hani - 1351, 105, // hoy -> Deva - 1355, 345, // hpo -> Mymr - 1359, 475, // hrt -> Syrc - 1363, 10, // hrz -> Arab - 1367, 175, // hsn -> Hans - 1371, 10, // hss -> Arab - 1375, 570, // htx -> Xsux - 1379, 105, // hut -> Deva - 1383, 185, // huy -> Hebr - 1387, 100, // huz -> Cyrl - 1391, 20, // hy -> Armn - 1394, 20, // hyw -> Armn - 1398, 575, // ii -> Yiii - 1401, 285, // imy -> Lyci - 1405, 100, // inh -> Cyrl - 1409, 345, // int -> Mymr - 1413, 120, // ior -> Ethi - 1417, 500, // iru -> Taml - 1421, 10, // isk -> Arab - 1425, 185, // itk -> Hebr - 1429, 100, // itl -> Cyrl - 1433, 65, // iu -> Cans - 1436, 185, // iw -> Hebr - 1439, 210, // ja -> Jpan - 1442, 10, // jad -> Arab - 1446, 10, // jat -> Arab - 1450, 185, // jbe -> Hebr - 1454, 10, // jbn -> Arab - 1458, 100, // jct -> Cyrl - 1462, 535, // jda -> Tibt - 1466, 10, // jdg -> Arab - 1470, 100, // jdt -> Cyrl - 1474, 105, // jee -> Deva - 1478, 125, // jge -> Geor - 1482, 185, // ji -> Hebr - 1485, 165, // jje -> Hang - 1489, 345, // jkm -> Mymr - 1493, 105, // jml -> Deva - 1497, 485, // jna -> Takr - 1501, 10, // jnd -> Arab - 1505, 105, // jnl -> Deva - 1509, 105, // jns -> Deva - 1513, 10, // jog -> Arab - 1517, 185, // jpa -> Hebr - 1521, 185, // jpr -> Hebr - 1525, 185, // jrb -> Hebr - 1529, 10, // jrb_MA -> Arab - 1536, 105, // jul -> Deva - 1540, 385, // jun -> Orya - 1544, 385, // juy -> Orya - 1548, 535, // jya -> Tibt - 1552, 185, // jye -> Hebr - 1556, 125, // ka -> Geor - 1559, 100, // kaa -> Cyrl - 1563, 100, // kap -> Cyrl - 1567, 225, // kaw -> Kawi - 1571, 100, // kbd -> Cyrl - 1575, 10, // kbu -> Arab - 1579, 10, // kby -> Arab - 1583, 100, // kca -> Cyrl - 1587, 45, // kdq -> Beng - 1591, 530, // kdt -> Thai - 1595, 100, // ket -> Cyrl - 1599, 105, // kex -> Deva - 1603, 515, // key -> Telu - 1607, 245, // kfa -> Knda - 1611, 105, // kfb -> Deva - 1615, 515, // kfc -> Telu - 1619, 245, // kfd -> Knda - 1623, 500, // kfe -> Taml - 1627, 320, // kfh -> Mlym - 1631, 500, // kfi -> Taml - 1635, 105, // kfk -> Deva - 1639, 10, // kfm -> Arab - 1643, 105, // kfp -> Deva - 1647, 105, // kfq -> Deva - 1651, 105, // kfr -> Deva - 1655, 105, // kfs -> Deva - 1659, 105, // kfx -> Deva - 1663, 105, // kfy -> Deva - 1667, 105, // kgj -> Deva - 1671, 105, // kgy -> Deva - 1675, 495, // khb -> Talu - 1679, 530, // khf -> Thai - 1683, 535, // khg -> Tibt - 1687, 105, // khn -> Deva - 1691, 345, // kht -> Mymr - 1695, 100, // khv -> Cyrl - 1699, 10, // khw -> Arab - 1703, 105, // kif -> Deva - 1707, 100, // kim -> Cyrl - 1711, 105, // kip -> Deva - 1715, 260, // kjg -> Laoo - 1719, 100, // kjh -> Cyrl - 1723, 105, // kjl -> Deva - 1727, 105, // kjo -> Deva - 1731, 345, // kjp -> Mymr - 1735, 530, // kjt -> Thai - 1739, 100, // kk -> Cyrl - 1742, 10, // kk_AF -> Arab - 1748, 10, // kk_CN -> Arab - 1754, 10, // kk_IR -> Arab - 1760, 10, // kk_MN -> Arab - 1766, 535, // kkf -> Tibt - 1770, 255, // kkh -> Lana - 1774, 105, // kkt -> Deva - 1778, 105, // kle -> Deva - 1782, 10, // klj -> Arab - 1786, 105, // klr -> Deva - 1790, 235, // km -> Khmr - 1793, 105, // kmj -> Deva - 1797, 10, // kmz -> Arab - 1801, 245, // kn -> Knda - 1804, 250, // ko -> Kore - 1807, 100, // koi -> Cyrl - 1811, 105, // kok -> Deva - 1815, 100, // kpt -> Cyrl - 1819, 100, // kpy -> Cyrl - 1823, 475, // kqd -> Syrc - 1827, 120, // kqy -> Ethi - 1831, 105, // kra -> Deva - 1835, 100, // krc -> Cyrl - 1839, 100, // krk -> Cyrl - 1843, 235, // krr -> Khmr - 1847, 105, // kru -> Deva - 1851, 235, // krv -> Khmr - 1855, 10, // ks -> Arab - 1858, 345, // ksu -> Mymr - 1862, 345, // ksw -> Mymr - 1866, 105, // ksz -> Deva - 1870, 120, // ktb -> Ethi - 1874, 10, // ktl -> Arab - 1878, 410, // ktp -> Plrd - 1882, 10, // ku_LB -> Arab - 1888, 260, // kuf -> Laoo - 1892, 100, // kum -> Cyrl - 1896, 100, // kv -> Cyrl - 1899, 100, // kva -> Cyrl - 1903, 345, // kvq -> Mymr - 1907, 345, // kvt -> Mymr - 1911, 10, // kvx -> Arab - 1915, 215, // kvy -> Kali - 1919, 345, // kxf -> Mymr - 1923, 345, // kxk -> Mymr - 1927, 530, // kxm -> Thai - 1931, 10, // kxp -> Arab - 1935, 100, // ky -> Cyrl - 1938, 10, // ky_CN -> Arab - 1944, 215, // kyu -> Kali - 1948, 105, // kyv -> Deva - 1952, 105, // kyw -> Deva - 1956, 270, // lab -> Lina - 1960, 185, // lad -> Hebr - 1964, 105, // lae -> Deva - 1968, 10, // lah -> Arab - 1972, 280, // lbc -> Lisu - 1976, 100, // lbe -> Cyrl - 1980, 105, // lbf -> Deva - 1984, 535, // lbj -> Tibt - 1988, 105, // lbm -> Deva - 1992, 260, // lbo -> Laoo - 1996, 105, // lbr -> Deva - 2000, 530, // lcp -> Thai - 2004, 265, // lep -> Lepc - 2008, 100, // lez -> Cyrl - 2012, 105, // lhm -> Deva - 2016, 475, // lhs -> Syrc - 2020, 105, // lif -> Deva - 2024, 280, // lis -> Lisu - 2028, 535, // lkh -> Tibt - 2032, 10, // lki -> Arab - 2036, 105, // lmh -> Deva - 2040, 515, // lmn -> Telu - 2044, 260, // lo -> Laoo - 2047, 105, // loy -> Deva - 2051, 410, // lpo -> Plrd - 2055, 10, // lrc -> Arab - 2059, 10, // lrk -> Arab - 2063, 10, // lrl -> Arab - 2067, 10, // lsa -> Arab - 2071, 185, // lsd -> Hebr - 2075, 10, // lss -> Arab - 2079, 535, // luk -> Tibt - 2083, 105, // luu -> Deva - 2087, 10, // luv -> Arab - 2091, 10, // luz -> Arab - 2095, 530, // lwl -> Thai - 2099, 530, // lwm -> Thai - 2103, 535, // lya -> Tibt - 2107, 175, // lzh -> Hans - 2111, 105, // mag -> Deva - 2115, 105, // mai -> Deva - 2119, 360, // man_GN -> Nkoo - 2126, 10, // mby -> Arab - 2130, 10, // mde -> Arab - 2134, 100, // mdf -> Cyrl - 2138, 120, // mdx -> Ethi - 2142, 120, // mdy -> Ethi - 2146, 10, // mfa -> Arab - 2150, 10, // mfi -> Arab - 2154, 105, // mgp -> Deva - 2158, 10, // mhj -> Arab - 2162, 295, // mid -> Mand - 2166, 105, // mjl -> Deva - 2170, 320, // mjq -> Mlym - 2174, 320, // mjr -> Mlym - 2178, 105, // mjt -> Deva - 2182, 515, // mju -> Telu - 2186, 320, // mjv -> Mlym - 2190, 105, // mjz -> Deva - 2194, 100, // mk -> Cyrl - 2197, 105, // mkb -> Deva - 2201, 105, // mke -> Deva - 2205, 10, // mki -> Arab - 2209, 530, // mkm -> Thai - 2213, 320, // ml -> Mlym - 2216, 530, // mlf -> Thai - 2220, 100, // mn -> Cyrl - 2223, 330, // mn_CN -> Mong - 2229, 45, // mni -> Beng - 2233, 10, // mnj -> Arab - 2237, 100, // mns -> Cyrl - 2241, 345, // mnw -> Mymr - 2245, 530, // mpz -> Thai - 2249, 105, // mr -> Deva - 2252, 530, // mra -> Thai - 2256, 105, // mrd -> Deva - 2260, 100, // mrj -> Cyrl - 2264, 335, // mro -> Mroo - 2268, 105, // mrr -> Deva - 2272, 10, // ms_CC -> Arab - 2278, 100, // mtm -> Cyrl - 2282, 105, // mtr -> Deva - 2286, 100, // mud -> Cyrl - 2290, 535, // muk -> Tibt - 2294, 105, // mut -> Deva - 2298, 500, // muv -> Taml - 2302, 120, // muz -> Ethi - 2306, 330, // mvf -> Mong - 2310, 10, // mvy -> Arab - 2314, 120, // mvz -> Ethi - 2318, 105, // mwr -> Deva - 2322, 345, // mwt -> Mymr - 2326, 195, // mww -> Hmnp - 2330, 345, // my -> Mymr - 2333, 120, // mym -> Ethi - 2337, 100, // myv -> Cyrl - 2341, 295, // myz -> Mand - 2345, 10, // mzn -> Arab - 2349, 175, // nan -> Hans - 2353, 105, // nao -> Deva - 2357, 105, // ncd -> Deva - 2361, 260, // ncq -> Laoo - 2365, 100, // ndf -> Cyrl - 2369, 105, // ne -> Deva - 2372, 100, // neg -> Cyrl - 2376, 535, // neh -> Tibt - 2380, 570, // nei -> Xsux - 2384, 105, // new -> Deva - 2388, 260, // ngt -> Laoo - 2392, 100, // nio -> Cyrl - 2396, 515, // nit -> Telu - 2400, 100, // niv -> Cyrl - 2404, 10, // nli -> Arab - 2408, 10, // nlm -> Arab - 2412, 105, // nlx -> Deva - 2416, 105, // nmm -> Deva - 2420, 560, // nnp -> Wcho - 2424, 255, // nod -> Lana - 2428, 105, // noe -> Deva - 2432, 100, // nog -> Cyrl - 2436, 105, // noi -> Deva - 2440, 430, // non -> Runr - 2444, 575, // nos -> Yiii - 2448, 535, // npb -> Tibt - 2452, 360, // nqo -> Nkoo - 2456, 575, // nsd -> Yiii - 2460, 575, // nsf -> Yiii - 2464, 65, // nsk -> Cans - 2468, 540, // nst -> Tnsa - 2472, 575, // nsv -> Yiii - 2476, 575, // nty -> Yiii - 2480, 10, // ntz -> Arab - 2484, 355, // nwc -> Newa - 2488, 105, // nwx -> Deva - 2492, 530, // nyl -> Thai - 2496, 10, // nyq -> Arab - 2500, 100, // oaa -> Cyrl - 2504, 100, // oac -> Cyrl - 2508, 475, // oar -> Syrc - 2512, 125, // oav -> Geor - 2516, 405, // obm -> Phnx - 2520, 345, // obr -> Mymr - 2524, 10, // odk -> Arab - 2528, 570, // oht -> Xsux - 2532, 65, // oj -> Cans - 2535, 65, // ojs -> Cans - 2539, 165, // okm -> Hang - 2543, 170, // oko -> Hani - 2547, 235, // okz -> Khmr - 2551, 105, // ola -> Deva - 2555, 535, // ole -> Tibt - 2559, 100, // omk -> Cyrl - 2563, 340, // omp -> Mtei - 2567, 325, // omr -> Modi - 2571, 105, // oon -> Deva - 2575, 385, // or -> Orya - 2578, 515, // ort -> Telu - 2582, 10, // oru -> Arab - 2586, 100, // orv -> Cyrl - 2590, 100, // os -> Cyrl - 2593, 390, // osa -> Osge - 2597, 200, // osc -> Ital - 2601, 205, // osi -> Java - 2605, 10, // ota -> Arab - 2609, 535, // otb -> Tibt - 2613, 380, // otk -> Orkh - 2617, 145, // oty -> Gran - 2621, 160, // pa -> Guru - 2624, 10, // pa_PK -> Arab - 2630, 400, // pal -> Phli - 2634, 100, // paq -> Cyrl - 2638, 10, // pbt -> Arab - 2642, 235, // pcb -> Khmr - 2646, 345, // pce -> Mymr - 2650, 320, // pcf -> Mlym - 2654, 320, // pcg -> Mlym - 2658, 105, // pch -> Deva - 2662, 105, // pci -> Deva - 2666, 515, // pcj -> Telu - 2670, 385, // peg -> Orya - 2674, 565, // peo -> Xpeo - 2678, 230, // pgd -> Khar - 2682, 105, // pgg -> Deva - 2686, 370, // pgl -> Ogam - 2690, 200, // pgn -> Ital - 2694, 105, // phd -> Deva - 2698, 345, // phk -> Mymr - 2702, 10, // phl -> Arab - 2706, 405, // phn -> Phnx - 2710, 260, // pho -> Laoo - 2714, 10, // phr -> Arab - 2718, 530, // pht -> Thai - 2722, 10, // phv -> Arab - 2726, 105, // phw -> Deva - 2730, 455, // pi -> Sinh - 2733, 55, // pka -> Brah - 2737, 320, // pkr -> Mlym - 2741, 10, // plk -> Arab - 2745, 345, // pll -> Mymr - 2749, 55, // pmh -> Brah - 2753, 150, // pnt -> Grek - 2757, 230, // pra -> Khar - 2761, 10, // prc -> Arab - 2765, 10, // prd -> Arab - 2769, 530, // prt -> Thai - 2773, 10, // prx -> Arab - 2777, 10, // ps -> Arab - 2780, 10, // psh -> Arab - 2784, 10, // psi -> Arab - 2788, 10, // pst -> Arab - 2792, 105, // pum -> Deva - 2796, 345, // pwo -> Mymr - 2800, 105, // pwr -> Deva - 2804, 530, // pww -> Thai - 2808, 345, // pyx -> Mymr - 2812, 10, // qxq -> Arab - 2816, 105, // raa -> Deva - 2820, 105, // rab -> Deva - 2824, 105, // raf -> Deva - 2828, 45, // rah -> Beng - 2832, 105, // raj -> Deva - 2836, 105, // rav -> Deva - 2840, 345, // rbb -> Mymr - 2844, 10, // rdb -> Arab - 2848, 385, // rei -> Orya - 2852, 425, // rhg -> Rohg - 2856, 105, // rji -> Deva - 2860, 105, // rjs -> Deva - 2864, 235, // rka -> Khmr - 2868, 345, // rki -> Mymr - 2872, 45, // rkt -> Beng - 2876, 20, // rmi -> Armn - 2880, 10, // rmt -> Arab - 2884, 345, // rmz -> Mymr - 2888, 100, // rom_BG -> Cyrl - 2895, 100, // rsk -> Cyrl - 2899, 105, // rtw -> Deva - 2903, 100, // ru -> Cyrl - 2906, 100, // rue -> Cyrl - 2910, 100, // rut -> Cyrl - 2914, 105, // rwr -> Deva - 2918, 220, // ryu -> Kana - 2922, 105, // sa -> Deva - 2925, 100, // sah -> Cyrl - 2929, 435, // sam -> Samr - 2933, 375, // sat -> Olck - 2937, 445, // saz -> Saur - 2941, 10, // sbn -> Arab - 2945, 535, // sbu -> Tibt - 2949, 105, // sck -> Deva - 2953, 10, // scl -> Arab - 2957, 10, // scl_IN -> Arab - 2964, 105, // scp -> Deva - 2968, 260, // sct -> Laoo - 2972, 485, // scu -> Takr - 2976, 150, // scx -> Grek - 2980, 10, // sd -> Arab - 2983, 105, // sd_IN -> Deva - 2989, 10, // sdb -> Arab - 2993, 10, // sdf -> Arab - 2997, 10, // sdg -> Arab - 3001, 10, // sdh -> Arab - 3005, 10, // sds -> Arab - 3009, 100, // sel -> Cyrl - 3013, 410, // sfm -> Plrd - 3017, 370, // sga -> Ogam - 3021, 100, // sgh -> Cyrl - 3025, 105, // sgj -> Deva - 3029, 10, // sgr -> Arab - 3033, 535, // sgt -> Tibt - 3037, 120, // sgw -> Ethi - 3041, 10, // sgy -> Arab - 3045, 10, // shd -> Arab - 3049, 520, // shi -> Tfng - 3053, 10, // shm -> Arab - 3057, 345, // shn -> Mymr - 3061, 10, // shu -> Arab - 3065, 10, // shv -> Arab - 3069, 455, // si -> Sinh - 3072, 100, // sia -> Cyrl - 3076, 535, // sip -> Tibt - 3080, 10, // siy -> Arab - 3084, 10, // siz -> Arab - 3088, 100, // sjd -> Cyrl - 3092, 105, // sjp -> Deva - 3096, 100, // sjt -> Cyrl - 3100, 530, // skb -> Thai - 3104, 105, // skj -> Deva - 3108, 10, // skr -> Arab - 3112, 575, // smh -> Yiii - 3116, 435, // smp -> Samr - 3120, 235, // smu -> Khmr - 3124, 10, // smy -> Arab - 3128, 510, // soa -> Tavt - 3132, 460, // sog -> Sogd - 3136, 105, // soi -> Deva - 3140, 530, // sou -> Thai - 3144, 535, // spt -> Tibt - 3148, 385, // spv -> Orya - 3152, 10, // sqo -> Arab - 3156, 260, // sqq -> Laoo - 3160, 10, // sqt -> Arab - 3164, 100, // sr -> Cyrl - 3167, 465, // srb -> Sora - 3171, 10, // srh -> Arab - 3175, 105, // srx -> Deva - 3179, 10, // srz -> Arab - 3183, 10, // ssh -> Arab - 3187, 260, // sss -> Laoo - 3191, 10, // sts -> Arab - 3195, 120, // stv -> Ethi - 3199, 100, // sty -> Cyrl - 3203, 105, // suz -> Deva - 3207, 125, // sva -> Geor - 3211, 10, // swb -> Arab - 3215, 170, // swi -> Hani - 3219, 105, // swv -> Deva - 3223, 475, // syc -> Syrc - 3227, 45, // syl -> Beng - 3231, 475, // syn -> Syrc - 3235, 475, // syr -> Syrc - 3239, 105, // syw -> Deva - 3243, 500, // ta -> Taml - 3246, 100, // tab -> Cyrl - 3250, 105, // taj -> Deva - 3254, 480, // tbk -> Tagb - 3258, 535, // tcn -> Tibt - 3262, 345, // tco -> Mymr - 3266, 500, // tcx -> Taml - 3270, 245, // tcy -> Knda - 3274, 520, // tda -> Tfng - 3278, 105, // tdb -> Deva - 3282, 490, // tdd -> Tale - 3286, 105, // tdg -> Deva - 3290, 105, // tdh -> Deva - 3294, 515, // te -> Telu - 3297, 205, // tes -> Java - 3301, 100, // tg -> Cyrl - 3304, 10, // tg_PK -> Arab - 3310, 105, // tge -> Deva - 3314, 535, // tgf -> Tibt - 3318, 530, // th -> Thai - 3321, 105, // the -> Deva - 3325, 105, // thf -> Deva - 3329, 490, // thi -> Tale - 3333, 105, // thl -> Deva - 3337, 530, // thm -> Thai - 3341, 105, // thq -> Deva - 3345, 105, // thr -> Deva - 3349, 105, // ths -> Deva - 3353, 120, // ti -> Ethi - 3356, 120, // tig -> Ethi - 3360, 105, // tij -> Deva - 3364, 100, // tin -> Cyrl - 3368, 345, // tjl -> Mymr - 3372, 10, // tjo -> Arab - 3376, 105, // tkb -> Deva - 3380, 10, // tks -> Arab - 3384, 105, // tkt -> Deva - 3388, 475, // tmr -> Syrc - 3392, 60, // tnv -> Cakm - 3396, 10, // tov -> Arab - 3400, 235, // tpu -> Khmr - 3404, 10, // tra -> Arab - 3408, 185, // trg -> Hebr - 3412, 10, // trm -> Arab - 3416, 10, // trw -> Arab - 3420, 150, // tsd -> Grek - 3424, 535, // tsj -> Tibt - 3428, 100, // tt -> Cyrl - 3431, 260, // tth -> Laoo - 3435, 260, // tto -> Laoo - 3439, 530, // tts -> Thai - 3443, 345, // tvn -> Mymr - 3447, 105, // twm -> Deva - 3451, 505, // txg -> Tang - 3455, 545, // txo -> Toto - 3459, 510, // tyr -> Tavt - 3463, 100, // tyv -> Cyrl - 3467, 100, // ude -> Cyrl - 3471, 320, // udg -> Mlym - 3475, 0, // udi -> Aghb - 3479, 100, // udm -> Cyrl - 3483, 10, // ug -> Arab - 3486, 100, // ug_KZ -> Cyrl - 3492, 100, // ug_MN -> Cyrl - 3498, 550, // uga -> Ugar - 3502, 100, // ugh -> Cyrl - 3506, 530, // ugo -> Thai - 3510, 100, // uk -> Cyrl - 3513, 385, // uki -> Orya - 3517, 100, // ulc -> Cyrl - 3521, 45, // unr -> Beng - 3525, 105, // unr_NP -> Deva - 3532, 45, // unx -> Beng - 3536, 10, // ur -> Arab - 3539, 530, // urk -> Thai - 3543, 10, // ush -> Arab - 3547, 150, // uum -> Grek - 3551, 10, // uz_AF -> Arab - 3557, 100, // uz_CN -> Cyrl - 3563, 10, // uzs -> Arab - 3567, 500, // vaa -> Taml - 3571, 10, // vaf -> Arab - 3575, 105, // vah -> Deva - 3579, 555, // vai -> Vaii - 3583, 105, // vas -> Deva - 3587, 105, // vav -> Deva - 3591, 105, // vay -> Deva - 3595, 10, // vgr -> Arab - 3599, 245, // vmd -> Knda - 3603, 10, // vmh -> Arab - 3607, 120, // wal -> Ethi - 3611, 10, // wbk -> Arab - 3615, 515, // wbq -> Telu - 3619, 105, // wbr -> Deva - 3623, 10, // wlo -> Arab - 3627, 105, // wme -> Deva - 3631, 10, // wne -> Arab - 3635, 10, // wni -> Arab - 3639, 130, // wsg -> Gong - 3643, 10, // wsv -> Arab - 3647, 105, // wtm -> Deva - 3651, 175, // wuu -> Hans - 3655, 100, // xal -> Cyrl - 3659, 120, // xan -> Ethi - 3663, 100, // xas -> Cyrl - 3667, 85, // xco -> Chrs - 3671, 70, // xcr -> Cari - 3675, 100, // xdq -> Cyrl - 3679, 10, // xhe -> Arab - 3683, 235, // xhm -> Khmr - 3687, 385, // xis -> Orya - 3691, 10, // xka -> Arab - 3695, 10, // xkc -> Arab - 3699, 10, // xkj -> Arab - 3703, 10, // xkp -> Arab - 3707, 285, // xlc -> Lyci - 3711, 290, // xld -> Lydi - 3715, 115, // xly -> Elym - 3719, 125, // xmf -> Geor - 3723, 300, // xmn -> Mani - 3727, 315, // xmr -> Merc - 3731, 350, // xna -> Narb - 3735, 105, // xnr -> Deva - 3739, 150, // xpg -> Grek - 3743, 370, // xpi -> Ogam - 3747, 100, // xpm -> Cyrl - 3751, 415, // xpr -> Prti - 3755, 100, // xrm -> Cyrl - 3759, 100, // xrn -> Cyrl - 3763, 440, // xsa -> Sarb - 3767, 105, // xsr -> Deva - 3771, 500, // xub -> Taml - 3775, 500, // xuj -> Taml - 3779, 200, // xve -> Ital - 3783, 10, // xvi -> Arab - 3787, 100, // xwo -> Cyrl - 3791, 305, // xzh -> Marc - 3795, 100, // yai -> Cyrl - 3799, 105, // ybh -> Deva - 3803, 105, // ybi -> Deva - 3807, 10, // ydg -> Arab - 3811, 320, // yea -> Mlym - 3815, 150, // yej -> Grek - 3819, 515, // yeu -> Telu - 3823, 410, // ygp -> Plrd - 3827, 185, // yhd -> Hebr - 3831, 185, // yi -> Hebr - 3834, 575, // yig -> Yiii - 3838, 185, // yih -> Hebr - 3842, 575, // yiv -> Yiii - 3846, 100, // ykg -> Cyrl - 3850, 410, // yna -> Plrd - 3854, 100, // ynk -> Cyrl - 3858, 210, // yoi -> Jpan - 3862, 530, // yoy -> Thai - 3866, 100, // yrk -> Cyrl - 3870, 575, // ysd -> Yiii - 3874, 575, // ysn -> Yiii - 3878, 575, // ysp -> Yiii - 3882, 100, // ysr -> Cyrl - 3886, 410, // ysy -> Plrd - 3890, 185, // yud -> Hebr - 3894, 180, // yue -> Hant - 3898, 175, // yue_CN -> Hans - 3905, 100, // yug -> Cyrl - 3909, 100, // yux -> Cyrl - 3913, 410, // ywq -> Plrd - 3917, 410, // ywu -> Plrd - 3921, 535, // zau -> Tibt - 3925, 10, // zba -> Arab - 3929, 170, // zch -> Hani - 3933, 10, // zdj -> Arab - 3937, 170, // zeh -> Hani - 3941, 520, // zen -> Tfng - 3945, 170, // zgb -> Hani - 3949, 520, // zgh -> Tfng - 3953, 170, // zgm -> Hani - 3957, 170, // zgn -> Hani - 3961, 175, // zh -> Hans - 3964, 180, // zh_AU -> Hant - 3970, 180, // zh_BN -> Hant - 3976, 180, // zh_GB -> Hant - 3982, 180, // zh_GF -> Hant - 3988, 180, // zh_HK -> Hant - 3994, 180, // zh_ID -> Hant - 4000, 180, // zh_MO -> Hant - 4006, 180, // zh_PA -> Hant - 4012, 180, // zh_PF -> Hant - 4018, 180, // zh_PH -> Hant - 4024, 180, // zh_SR -> Hant - 4030, 180, // zh_TH -> Hant - 4036, 180, // zh_TW -> Hant - 4042, 180, // zh_US -> Hant - 4048, 180, // zh_VN -> Hant - 4054, 170, // zhd -> Hani - 4058, 365, // zhx -> Nshu - 4062, 100, // zko -> Cyrl - 4066, 240, // zkt -> Kits - 4070, 100, // zkz -> Cyrl - 4074, 170, // zlj -> Hani - 4078, 170, // zln -> Hani - 4082, 170, // zlq -> Hani - 4086, 170, // zqe -> Hani - 4090, 185, // zrp -> Hebr - 4094, 10, // zum -> Arab - 4098, 170, // zyg -> Hani - 4102, 170, // zyn -> Hani - 4106, 170, // zzj -> Hani + 106, 495, // aii -> Syrc + 110, 185, // aij -> Hebr + 114, 220, // ain -> Kana + 118, 355, // aio -> Mymr + 122, 10, // aiq -> Arab + 126, 590, // akk -> Xsux + 130, 100, // akv -> Cyrl + 134, 260, // alk -> Laoo + 138, 330, // all -> Mlym + 142, 100, // alr -> Cyrl + 146, 100, // alt -> Cyrl + 150, 120, // alw -> Ethi + 154, 120, // am -> Ethi + 157, 210, // ams -> Jpan + 161, 495, // amw -> Syrc + 165, 100, // ani -> Cyrl + 169, 105, // anp -> Deva + 173, 105, // anq -> Deva + 177, 105, // anr -> Deva + 181, 120, // anu -> Ethi + 185, 45, // aot -> Beng + 189, 10, // apc -> Arab + 193, 10, // apd -> Arab + 197, 105, // aph -> Deva + 201, 100, // aqc -> Cyrl + 205, 10, // ar -> Arab + 208, 15, // arc -> Armi + 212, 10, // arq -> Arab + 216, 10, // ars -> Arab + 220, 10, // ary -> Arab + 224, 10, // arz -> Arab + 228, 45, // as -> Beng + 231, 465, // ase -> Sgnw + 235, 10, // ask -> Arab + 239, 105, // asr -> Deva + 243, 10, // atn -> Arab + 247, 100, // atv -> Cyrl + 251, 10, // auj -> Arab + 255, 10, // auz -> Arab + 259, 100, // av -> Cyrl + 262, 10, // avd -> Arab + 266, 10, // avl -> Arab + 270, 105, // awa -> Deva + 274, 120, // awn -> Ethi + 278, 20, // axm -> Armn + 282, 10, // ayh -> Arab + 286, 10, // ayl -> Arab + 290, 10, // ayn -> Arab + 294, 10, // ayp -> Arab + 298, 10, // az_IQ -> Arab + 304, 10, // az_IR -> Arab + 310, 100, // az_RU -> Cyrl + 316, 10, // azb -> Arab + 320, 100, // ba -> Cyrl + 323, 10, // bal -> Arab + 327, 105, // bap -> Deva + 331, 30, // bax -> Bamu + 335, 125, // bbl -> Geor + 339, 120, // bcq -> Ethi + 343, 395, // bdv -> Orya + 347, 10, // bdz -> Arab + 351, 100, // be -> Cyrl + 354, 105, // bee -> Deva + 358, 10, // bej -> Arab + 362, 105, // bfb -> Deva + 366, 520, // bfq -> Taml + 370, 10, // bft -> Arab + 374, 555, // bfu -> Tibt + 378, 395, // bfw -> Orya + 382, 105, // bfy -> Deva + 386, 105, // bfz -> Deva + 390, 100, // bg -> Cyrl + 393, 105, // bgc -> Deva + 397, 105, // bgd -> Deva + 401, 10, // bgn -> Arab + 405, 10, // bgp -> Arab + 409, 105, // bgq -> Deva + 413, 105, // bgw -> Deva + 417, 150, // bgx -> Grek + 421, 105, // bha -> Deva + 425, 105, // bhb -> Deva + 429, 105, // bhd -> Deva + 433, 10, // bhe -> Arab + 437, 100, // bhh -> Cyrl + 441, 105, // bhi -> Deva + 445, 105, // bhj -> Deva + 449, 10, // bhm -> Arab + 453, 495, // bhn -> Syrc + 457, 105, // bho -> Deva + 461, 105, // bht -> Deva + 465, 105, // bhu -> Deva + 469, 105, // biy -> Deva + 473, 495, // bjf -> Syrc + 477, 105, // bjj -> Deva + 481, 10, // bjm -> Arab + 485, 555, // bkk -> Tibt + 489, 355, // blk -> Mymr + 493, 530, // blt -> Tavt + 497, 105, // bmj -> Deva + 501, 45, // bn -> Beng + 504, 105, // bns -> Deva + 508, 555, // bo -> Tibt + 511, 100, // bph -> Cyrl + 515, 105, // bpx -> Deva + 519, 45, // bpy -> Beng + 523, 10, // bqi -> Arab + 527, 105, // bra -> Deva + 531, 235, // brb -> Khmr + 535, 105, // brd -> Deva + 539, 10, // brh -> Arab + 543, 10, // brk -> Arab + 547, 555, // bro -> Tibt + 551, 260, // brv -> Laoo + 555, 245, // brw -> Knda + 559, 105, // brx -> Deva + 563, 10, // bsh -> Arab + 567, 10, // bsk -> Arab + 571, 35, // bsq -> Bass + 575, 120, // bst -> Ethi + 579, 40, // btd -> Batk + 583, 40, // btm -> Batk + 587, 105, // btv -> Deva + 591, 100, // bua -> Cyrl + 595, 355, // bwe -> Mymr + 599, 100, // bxm -> Cyrl + 603, 340, // bxu -> Mong + 607, 105, // byh -> Deva + 611, 120, // byn -> Ethi + 615, 105, // byw -> Deva + 619, 550, // bzi -> Thai + 623, 550, // cbn -> Thai + 627, 60, // ccp -> Cakm + 631, 535, // cde -> Telu + 635, 105, // cdh -> Deva + 639, 155, // cdi -> Gujr + 643, 105, // cdj -> Deva + 647, 105, // cdm -> Deva + 651, 175, // cdo -> Hans + 655, 45, // cdz -> Beng + 659, 100, // ce -> Cyrl + 662, 555, // cgk -> Tibt + 666, 10, // chg -> Arab + 670, 100, // chm -> Cyrl + 674, 80, // chr -> Cher + 678, 105, // chx -> Deva + 682, 105, // cih -> Deva + 686, 10, // cja -> Arab + 690, 100, // cji -> Cyrl + 694, 75, // cjm -> Cham + 698, 175, // cjy -> Hans + 702, 10, // ckb -> Arab + 706, 100, // ckt -> Cyrl + 710, 10, // clh -> Arab + 714, 100, // clw -> Cyrl + 718, 485, // cmg -> Soyo + 722, 555, // cna -> Tibt + 726, 175, // cnp -> Hans + 730, 550, // cog -> Thai + 734, 90, // cop -> Copt + 738, 150, // cpg -> Grek + 742, 65, // cr -> Cans + 745, 100, // crh -> Cyrl + 749, 65, // crj -> Cans + 753, 65, // crk -> Cans + 757, 65, // crl -> Cans + 761, 65, // crm -> Cans + 765, 355, // csh -> Mymr + 769, 175, // csp -> Hans + 773, 65, // csw -> Cans + 777, 410, // ctd -> Pauc + 781, 45, // ctg -> Beng + 785, 105, // ctn -> Deva + 789, 520, // ctt -> Taml + 793, 520, // cty -> Taml + 797, 100, // cu -> Cyrl + 800, 255, // cuu -> Lana + 804, 100, // cv -> Cyrl + 807, 175, // czh -> Hans + 811, 185, // czk -> Hebr + 815, 105, // daq -> Deva + 819, 100, // dar -> Cyrl + 823, 10, // dcc -> Arab + 827, 100, // ddo -> Cyrl + 831, 10, // def -> Arab + 835, 10, // deh -> Arab + 839, 45, // der -> Beng + 843, 10, // dgl -> Arab + 847, 105, // dhi -> Deva + 851, 155, // dhn -> Gujr + 855, 105, // dho -> Deva + 859, 105, // dhw -> Deva + 863, 555, // dka -> Tibt + 867, 100, // dlg -> Cyrl + 871, 320, // dmf -> Medf + 875, 10, // dmk -> Arab + 879, 10, // dml -> Arab + 883, 100, // dng -> Cyrl + 887, 355, // dnu -> Mymr + 891, 355, // dnv -> Mymr + 895, 105, // doi -> Deva + 899, 120, // dox -> Ethi + 903, 555, // dre -> Tibt + 907, 105, // drq -> Deva + 911, 120, // drs -> Ethi + 915, 105, // dry -> Deva + 919, 395, // dso -> Orya + 923, 105, // dty -> Deva + 927, 155, // dub -> Gujr + 931, 105, // duh -> Deva + 935, 105, // dus -> Deva + 939, 545, // dv -> Thaa + 942, 395, // dwk -> Orya + 946, 105, // dwz -> Deva + 950, 555, // dz -> Tibt + 953, 555, // dzl -> Tibt + 957, 150, // ecr -> Grek + 961, 95, // ecy -> Cprt + 965, 110, // egy -> Egyp + 969, 215, // eky -> Kali + 973, 150, // el -> Grek + 976, 105, // emg -> Deva + 980, 105, // emu -> Deva + 984, 100, // enf -> Cyrl + 988, 100, // enh -> Cyrl + 992, 520, // era -> Taml + 996, 135, // esg -> Gonm + 1000, 10, // esh -> Arab + 1004, 200, // ett -> Ital + 1008, 100, // eve -> Cyrl + 1012, 100, // evn -> Cyrl + 1016, 10, // fa -> Arab + 1019, 10, // fay -> Arab + 1023, 10, // faz -> Arab + 1027, 10, // fia -> Arab + 1031, 105, // fmu -> Deva + 1035, 10, // fub -> Arab + 1039, 175, // gan -> Hans + 1043, 395, // gaq -> Orya + 1047, 155, // gas -> Gujr + 1051, 535, // gau -> Telu + 1055, 395, // gbj -> Orya + 1059, 105, // gbk -> Deva + 1063, 155, // gbl -> Gujr + 1067, 105, // gbm -> Deva + 1071, 10, // gbz -> Arab + 1075, 395, // gdb -> Orya + 1079, 100, // gdo -> Cyrl + 1083, 105, // gdx -> Deva + 1087, 120, // gez -> Ethi + 1091, 10, // ggg -> Arab + 1095, 10, // gha -> Arab + 1099, 105, // ghe -> Deva + 1103, 540, // gho -> Tfng + 1107, 10, // ghr -> Arab + 1111, 555, // ght -> Tibt + 1115, 10, // gig -> Arab + 1119, 100, // gin -> Cyrl + 1123, 10, // gjk -> Arab + 1127, 10, // gju -> Arab + 1131, 100, // gld -> Cyrl + 1135, 10, // glh -> Arab + 1139, 10, // glk -> Arab + 1143, 265, // gml -> Latf + 1147, 120, // gmv -> Ethi + 1151, 285, // gmy -> Linb + 1155, 555, // goe -> Tibt + 1159, 120, // gof -> Ethi + 1163, 105, // goj -> Deva + 1167, 105, // gok -> Deva + 1171, 105, // gon -> Deva + 1175, 140, // got -> Goth + 1179, 105, // gra -> Deva + 1183, 95, // grc -> Cprt + 1187, 45, // grt -> Beng + 1191, 120, // gru -> Ethi + 1195, 155, // gu -> Gujr + 1198, 105, // gvr -> Deva + 1202, 10, // gwc -> Arab + 1206, 10, // gwf -> Arab + 1210, 10, // gwt -> Arab + 1214, 105, // gyo -> Deva + 1218, 10, // gzi -> Arab + 1222, 10, // ha_CM -> Arab + 1228, 10, // ha_SD -> Arab + 1234, 10, // hac -> Arab + 1238, 175, // hak -> Hans + 1242, 120, // har -> Ethi + 1246, 10, // haz -> Arab + 1250, 185, // hbo -> Hebr + 1254, 120, // hdy -> Ethi + 1258, 185, // he -> Hebr + 1261, 105, // hi -> Deva + 1264, 105, // hif -> Deva + 1268, 505, // hii -> Takr + 1272, 590, // hit -> Xsux + 1276, 10, // hkh -> Arab + 1280, 105, // hlb -> Deva + 1284, 190, // hlu -> Hluw + 1288, 425, // hmd -> Plrd + 1292, 50, // hmj -> Bopo + 1296, 50, // hmq -> Bopo + 1300, 10, // hnd -> Arab + 1304, 105, // hne -> Deva + 1308, 195, // hnj -> Hmnp + 1312, 10, // hno -> Arab + 1316, 105, // hoc -> Deva + 1320, 10, // hoh -> Arab + 1324, 105, // hoj -> Deva + 1328, 170, // how -> Hani + 1332, 105, // hoy -> Deva + 1336, 355, // hpo -> Mymr + 1340, 495, // hrt -> Syrc + 1344, 10, // hrz -> Arab + 1348, 175, // hsn -> Hans + 1352, 10, // hss -> Arab + 1356, 590, // htx -> Xsux + 1360, 105, // hut -> Deva + 1364, 185, // huy -> Hebr + 1368, 100, // huz -> Cyrl + 1372, 20, // hy -> Armn + 1375, 20, // hyw -> Armn + 1379, 595, // ii -> Yiii + 1382, 295, // imy -> Lyci + 1386, 100, // inh -> Cyrl + 1390, 355, // int -> Mymr + 1394, 120, // ior -> Ethi + 1398, 520, // iru -> Taml + 1402, 10, // isk -> Arab + 1406, 185, // itk -> Hebr + 1410, 100, // itl -> Cyrl + 1414, 65, // iu -> Cans + 1417, 185, // iw -> Hebr + 1420, 210, // ja -> Jpan + 1423, 10, // jad -> Arab + 1427, 10, // jat -> Arab + 1431, 185, // jbe -> Hebr + 1435, 10, // jbn -> Arab + 1439, 100, // jct -> Cyrl + 1443, 555, // jda -> Tibt + 1447, 10, // jdg -> Arab + 1451, 100, // jdt -> Cyrl + 1455, 105, // jee -> Deva + 1459, 125, // jge -> Geor + 1463, 185, // ji -> Hebr + 1466, 165, // jje -> Hang + 1470, 355, // jkm -> Mymr + 1474, 105, // jml -> Deva + 1478, 505, // jna -> Takr + 1482, 10, // jnd -> Arab + 1486, 105, // jnl -> Deva + 1490, 105, // jns -> Deva + 1494, 10, // jog -> Arab + 1498, 185, // jpa -> Hebr + 1502, 185, // jpr -> Hebr + 1506, 185, // jrb -> Hebr + 1510, 105, // jul -> Deva + 1514, 395, // jun -> Orya + 1518, 395, // juy -> Orya + 1522, 555, // jya -> Tibt + 1526, 185, // jye -> Hebr + 1530, 125, // ka -> Geor + 1533, 100, // kaa -> Cyrl + 1537, 100, // kap -> Cyrl + 1541, 225, // kaw -> Kawi + 1545, 100, // kbd -> Cyrl + 1549, 555, // kbg -> Tibt + 1553, 10, // kbu -> Arab + 1557, 10, // kby -> Arab + 1561, 100, // kca -> Cyrl + 1565, 10, // kcy -> Arab + 1569, 45, // kdq -> Beng + 1573, 550, // kdt -> Thai + 1577, 100, // ket -> Cyrl + 1581, 330, // kev -> Mlym + 1585, 105, // kex -> Deva + 1589, 535, // key -> Telu + 1593, 245, // kfa -> Knda + 1597, 105, // kfb -> Deva + 1601, 535, // kfc -> Telu + 1605, 245, // kfd -> Knda + 1609, 520, // kfe -> Taml + 1613, 245, // kfg -> Knda + 1617, 330, // kfh -> Mlym + 1621, 520, // kfi -> Taml + 1625, 105, // kfk -> Deva + 1629, 10, // kfm -> Arab + 1633, 105, // kfp -> Deva + 1637, 105, // kfq -> Deva + 1641, 105, // kfr -> Deva + 1645, 105, // kfs -> Deva + 1649, 105, // kfu -> Deva + 1653, 105, // kfx -> Deva + 1657, 105, // kfy -> Deva + 1661, 105, // kgj -> Deva + 1665, 105, // kgy -> Deva + 1669, 515, // khb -> Talu + 1673, 550, // khf -> Thai + 1677, 555, // khg -> Tibt + 1681, 105, // khn -> Deva + 1685, 55, // kho -> Brah + 1689, 355, // kht -> Mymr + 1693, 100, // khv -> Cyrl + 1697, 10, // khw -> Arab + 1701, 105, // kif -> Deva + 1705, 100, // kim -> Cyrl + 1709, 105, // kip -> Deva + 1713, 260, // kjg -> Laoo + 1717, 100, // kjh -> Cyrl + 1721, 105, // kjl -> Deva + 1725, 105, // kjo -> Deva + 1729, 355, // kjp -> Mymr + 1733, 550, // kjt -> Thai + 1737, 555, // kjz -> Tibt + 1741, 100, // kk -> Cyrl + 1744, 10, // kk_AF -> Arab + 1750, 10, // kk_CN -> Arab + 1756, 10, // kk_IR -> Arab + 1762, 10, // kk_MN -> Arab + 1768, 555, // kkf -> Tibt + 1772, 255, // kkh -> Lana + 1776, 105, // kkt -> Deva + 1780, 105, // kle -> Deva + 1784, 10, // klj -> Arab + 1788, 105, // klr -> Deva + 1792, 235, // km -> Khmr + 1795, 105, // kmj -> Deva + 1799, 10, // kmz -> Arab + 1803, 245, // kn -> Knda + 1806, 105, // knn -> Deva + 1810, 250, // ko -> Kore + 1813, 100, // koi -> Cyrl + 1817, 105, // kok -> Deva + 1821, 100, // kpt -> Cyrl + 1825, 100, // kpy -> Cyrl + 1829, 495, // kqd -> Syrc + 1833, 120, // kqy -> Ethi + 1837, 105, // kra -> Deva + 1841, 100, // krc -> Cyrl + 1845, 100, // krk -> Cyrl + 1849, 235, // krr -> Khmr + 1853, 105, // kru -> Deva + 1857, 235, // krv -> Khmr + 1861, 10, // ks -> Arab + 1864, 355, // ksu -> Mymr + 1868, 355, // ksw -> Mymr + 1872, 105, // ksz -> Deva + 1876, 120, // ktb -> Ethi + 1880, 105, // kte -> Deva + 1884, 10, // ktl -> Arab + 1888, 425, // ktp -> Plrd + 1892, 10, // ku_LB -> Arab + 1898, 260, // kuf -> Laoo + 1902, 100, // kum -> Cyrl + 1906, 100, // kv -> Cyrl + 1909, 100, // kva -> Cyrl + 1913, 355, // kvq -> Mymr + 1917, 355, // kvt -> Mymr + 1921, 10, // kvx -> Arab + 1925, 215, // kvy -> Kali + 1929, 355, // kxf -> Mymr + 1933, 355, // kxk -> Mymr + 1937, 550, // kxm -> Thai + 1941, 10, // kxp -> Arab + 1945, 100, // ky -> Cyrl + 1948, 10, // ky_CN -> Arab + 1954, 215, // kyu -> Kali + 1958, 105, // kyv -> Deva + 1962, 105, // kyw -> Deva + 1966, 280, // lab -> Lina + 1970, 185, // lad -> Hebr + 1974, 105, // lae -> Deva + 1978, 10, // lah -> Arab + 1982, 100, // lbe -> Cyrl + 1986, 105, // lbf -> Deva + 1990, 555, // lbj -> Tibt + 1994, 105, // lbm -> Deva + 1998, 260, // lbo -> Laoo + 2002, 105, // lbr -> Deva + 2006, 550, // lcp -> Thai + 2010, 275, // lep -> Lepc + 2014, 100, // lez -> Cyrl + 2018, 105, // lhm -> Deva + 2022, 495, // lhs -> Syrc + 2026, 105, // lif -> Deva + 2030, 290, // lis -> Lisu + 2034, 555, // lkh -> Tibt + 2038, 10, // lki -> Arab + 2042, 105, // lmh -> Deva + 2046, 535, // lmn -> Telu + 2050, 260, // lo -> Laoo + 2053, 105, // loy -> Deva + 2057, 425, // lpo -> Plrd + 2061, 10, // lrc -> Arab + 2065, 10, // lrk -> Arab + 2069, 10, // lrl -> Arab + 2073, 10, // lsa -> Arab + 2077, 185, // lsd -> Hebr + 2081, 10, // lss -> Arab + 2085, 180, // ltc -> Hant + 2089, 555, // luk -> Tibt + 2093, 105, // luu -> Deva + 2097, 10, // luv -> Arab + 2101, 10, // luz -> Arab + 2105, 550, // lwl -> Thai + 2109, 550, // lwm -> Thai + 2113, 555, // lya -> Tibt + 2117, 175, // lzh -> Hans + 2121, 105, // mag -> Deva + 2125, 105, // mai -> Deva + 2129, 370, // man_GN -> Nkoo + 2136, 10, // mby -> Arab + 2140, 10, // mde -> Arab + 2144, 100, // mdf -> Cyrl + 2148, 120, // mdx -> Ethi + 2152, 120, // mdy -> Ethi + 2156, 10, // mfa -> Arab + 2160, 10, // mfi -> Arab + 2164, 270, // mga -> Latg + 2168, 105, // mgp -> Deva + 2172, 10, // mhj -> Arab + 2176, 305, // mid -> Mand + 2180, 105, // mjl -> Deva + 2184, 330, // mjq -> Mlym + 2188, 330, // mjr -> Mlym + 2192, 105, // mjt -> Deva + 2196, 535, // mju -> Telu + 2200, 330, // mjv -> Mlym + 2204, 105, // mjz -> Deva + 2208, 100, // mk -> Cyrl + 2211, 105, // mkb -> Deva + 2215, 105, // mke -> Deva + 2219, 10, // mki -> Arab + 2223, 550, // mkm -> Thai + 2227, 330, // ml -> Mlym + 2230, 550, // mlf -> Thai + 2234, 100, // mn -> Cyrl + 2237, 340, // mn_CN -> Mong + 2243, 340, // mnc -> Mong + 2247, 45, // mni -> Beng + 2251, 10, // mnj -> Arab + 2255, 100, // mns -> Cyrl + 2259, 355, // mnw -> Mymr + 2263, 550, // mpz -> Thai + 2267, 105, // mr -> Deva + 2270, 550, // mra -> Thai + 2274, 105, // mrd -> Deva + 2278, 100, // mrj -> Cyrl + 2282, 345, // mro -> Mroo + 2286, 105, // mrr -> Deva + 2290, 10, // ms_CC -> Arab + 2296, 100, // mtm -> Cyrl + 2300, 105, // mtr -> Deva + 2304, 100, // mud -> Cyrl + 2308, 555, // muk -> Tibt + 2312, 105, // mut -> Deva + 2316, 520, // muv -> Taml + 2320, 120, // muz -> Ethi + 2324, 10, // mve -> Arab + 2328, 340, // mvf -> Mong + 2332, 10, // mvy -> Arab + 2336, 120, // mvz -> Ethi + 2340, 105, // mwr -> Deva + 2344, 355, // mwt -> Mymr + 2348, 195, // mww -> Hmnp + 2352, 355, // my -> Mymr + 2355, 120, // mym -> Ethi + 2359, 100, // myv -> Cyrl + 2363, 305, // myz -> Mand + 2367, 10, // mzn -> Arab + 2371, 175, // nan -> Hans + 2375, 105, // nao -> Deva + 2379, 105, // ncd -> Deva + 2383, 260, // ncq -> Laoo + 2387, 100, // ndf -> Cyrl + 2391, 105, // ne -> Deva + 2394, 100, // neg -> Cyrl + 2398, 555, // neh -> Tibt + 2402, 590, // nei -> Xsux + 2406, 105, // new -> Deva + 2410, 260, // ngt -> Laoo + 2414, 100, // nio -> Cyrl + 2418, 535, // nit -> Telu + 2422, 100, // niv -> Cyrl + 2426, 10, // nli -> Arab + 2430, 10, // nlm -> Arab + 2434, 105, // nlx -> Deva + 2438, 105, // nmm -> Deva + 2442, 580, // nnp -> Wcho + 2446, 255, // nod -> Lana + 2450, 105, // noe -> Deva + 2454, 100, // nog -> Cyrl + 2458, 105, // noi -> Deva + 2462, 445, // non -> Runr + 2466, 595, // nos -> Yiii + 2470, 555, // npb -> Tibt + 2474, 370, // nqo -> Nkoo + 2478, 445, // nrn -> Runr + 2482, 595, // nsd -> Yiii + 2486, 595, // nsf -> Yiii + 2490, 65, // nsk -> Cans + 2494, 560, // nst -> Tnsa + 2498, 595, // nsv -> Yiii + 2502, 595, // nty -> Yiii + 2506, 10, // ntz -> Arab + 2510, 365, // nwc -> Newa + 2514, 105, // nwx -> Deva + 2518, 550, // nyl -> Thai + 2522, 10, // nyq -> Arab + 2526, 550, // nyw -> Thai + 2530, 100, // oaa -> Cyrl + 2534, 100, // oac -> Cyrl + 2538, 495, // oar -> Syrc + 2542, 125, // oav -> Geor + 2546, 420, // obm -> Phnx + 2550, 355, // obr -> Mymr + 2554, 10, // odk -> Arab + 2558, 590, // oht -> Xsux + 2562, 65, // oj -> Cans + 2565, 65, // ojs -> Cans + 2569, 165, // okm -> Hang + 2573, 170, // oko -> Hani + 2577, 235, // okz -> Khmr + 2581, 105, // ola -> Deva + 2585, 555, // ole -> Tibt + 2589, 100, // omk -> Cyrl + 2593, 350, // omp -> Mtei + 2597, 335, // omr -> Modi + 2601, 355, // omx -> Mymr + 2605, 105, // oon -> Deva + 2609, 395, // or -> Orya + 2612, 535, // ort -> Telu + 2616, 10, // oru -> Arab + 2620, 100, // orv -> Cyrl + 2624, 100, // os -> Cyrl + 2627, 400, // osa -> Osge + 2631, 200, // osc -> Ital + 2635, 205, // osi -> Java + 2639, 10, // ota -> Arab + 2643, 555, // otb -> Tibt + 2647, 390, // otk -> Orkh + 2651, 145, // oty -> Gran + 2655, 405, // oui -> Ougr + 2659, 160, // pa -> Guru + 2662, 10, // pa_PK -> Arab + 2668, 415, // pal -> Phli + 2672, 100, // paq -> Cyrl + 2676, 10, // pbt -> Arab + 2680, 235, // pcb -> Khmr + 2684, 355, // pce -> Mymr + 2688, 330, // pcf -> Mlym + 2692, 330, // pcg -> Mlym + 2696, 105, // pch -> Deva + 2700, 105, // pci -> Deva + 2704, 535, // pcj -> Telu + 2708, 395, // peg -> Orya + 2712, 585, // peo -> Xpeo + 2716, 230, // pgd -> Khar + 2720, 105, // pgg -> Deva + 2724, 380, // pgl -> Ogam + 2728, 200, // pgn -> Ital + 2732, 105, // phd -> Deva + 2736, 355, // phk -> Mymr + 2740, 10, // phl -> Arab + 2744, 420, // phn -> Phnx + 2748, 260, // pho -> Laoo + 2752, 10, // phr -> Arab + 2756, 550, // pht -> Thai + 2760, 550, // phu -> Thai + 2764, 10, // phv -> Arab + 2768, 105, // phw -> Deva + 2772, 470, // pi -> Sinh + 2775, 55, // pka -> Brah + 2779, 330, // pkr -> Mlym + 2783, 10, // plk -> Arab + 2787, 355, // pll -> Mymr + 2791, 55, // pmh -> Brah + 2795, 150, // pnt -> Grek + 2799, 230, // pra -> Khar + 2803, 10, // prc -> Arab + 2807, 10, // prd -> Arab + 2811, 550, // prt -> Thai + 2815, 10, // prx -> Arab + 2819, 10, // ps -> Arab + 2822, 10, // psh -> Arab + 2826, 10, // psi -> Arab + 2830, 10, // pst -> Arab + 2834, 55, // psu -> Brah + 2838, 105, // pum -> Deva + 2842, 355, // pwo -> Mymr + 2846, 105, // pwr -> Deva + 2850, 550, // pww -> Thai + 2854, 355, // pyx -> Mymr + 2858, 10, // qxq -> Arab + 2862, 105, // raa -> Deva + 2866, 105, // rab -> Deva + 2870, 105, // raf -> Deva + 2874, 45, // rah -> Beng + 2878, 105, // raj -> Deva + 2882, 105, // rav -> Deva + 2886, 355, // rbb -> Mymr + 2890, 10, // rdb -> Arab + 2894, 395, // rei -> Orya + 2898, 440, // rhg -> Rohg + 2902, 105, // rji -> Deva + 2906, 105, // rjs -> Deva + 2910, 235, // rka -> Khmr + 2914, 355, // rki -> Mymr + 2918, 45, // rkt -> Beng + 2922, 20, // rmi -> Armn + 2926, 10, // rmt -> Arab + 2930, 355, // rmz -> Mymr + 2934, 100, // rsk -> Cyrl + 2938, 105, // rtw -> Deva + 2942, 100, // ru -> Cyrl + 2945, 100, // rue -> Cyrl + 2949, 100, // rut -> Cyrl + 2953, 105, // rwr -> Deva + 2957, 220, // ryu -> Kana + 2961, 105, // sa -> Deva + 2964, 100, // sah -> Cyrl + 2968, 450, // sam -> Samr + 2972, 385, // sat -> Olck + 2976, 460, // saz -> Saur + 2980, 10, // sbn -> Arab + 2984, 555, // sbu -> Tibt + 2988, 105, // sck -> Deva + 2992, 10, // scl -> Arab + 2996, 105, // scp -> Deva + 3000, 260, // sct -> Laoo + 3004, 505, // scu -> Takr + 3008, 150, // scx -> Grek + 3012, 10, // sd -> Arab + 3015, 105, // sd_IN -> Deva + 3021, 10, // sdb -> Arab + 3025, 10, // sdf -> Arab + 3029, 10, // sdg -> Arab + 3033, 10, // sdh -> Arab + 3037, 45, // sdr -> Beng + 3041, 10, // sds -> Arab + 3045, 100, // sel -> Cyrl + 3049, 425, // sfm -> Plrd + 3053, 380, // sga -> Ogam + 3057, 100, // sgh -> Cyrl + 3061, 105, // sgj -> Deva + 3065, 10, // sgr -> Arab + 3069, 555, // sgt -> Tibt + 3073, 120, // sgw -> Ethi + 3077, 10, // sgy -> Arab + 3081, 10, // shd -> Arab + 3085, 540, // shi -> Tfng + 3089, 10, // shm -> Arab + 3093, 355, // shn -> Mymr + 3097, 10, // shu -> Arab + 3101, 10, // shv -> Arab + 3105, 470, // si -> Sinh + 3108, 100, // sia -> Cyrl + 3112, 555, // sip -> Tibt + 3116, 10, // siy -> Arab + 3120, 10, // siz -> Arab + 3124, 100, // sjd -> Cyrl + 3128, 105, // sjp -> Deva + 3132, 100, // sjt -> Cyrl + 3136, 550, // skb -> Thai + 3140, 105, // skj -> Deva + 3144, 10, // skr -> Arab + 3148, 595, // smh -> Yiii + 3152, 450, // smp -> Samr + 3156, 235, // smu -> Khmr + 3160, 10, // smy -> Arab + 3164, 530, // soa -> Tavt + 3168, 475, // sog -> Sogd + 3172, 105, // soi -> Deva + 3176, 550, // sou -> Thai + 3180, 555, // spt -> Tibt + 3184, 395, // spv -> Orya + 3188, 10, // sqo -> Arab + 3192, 260, // sqq -> Laoo + 3196, 10, // sqt -> Arab + 3200, 100, // sr -> Cyrl + 3203, 480, // srb -> Sora + 3207, 10, // srh -> Arab + 3211, 105, // srx -> Deva + 3215, 10, // srz -> Arab + 3219, 10, // ssh -> Arab + 3223, 260, // sss -> Laoo + 3227, 10, // sts -> Arab + 3231, 120, // stv -> Ethi + 3235, 100, // sty -> Cyrl + 3239, 490, // suz -> Sunu + 3243, 125, // sva -> Geor + 3247, 10, // swb -> Arab + 3251, 170, // swi -> Hani + 3255, 105, // swv -> Deva + 3259, 445, // sxu -> Runr + 3263, 495, // syc -> Syrc + 3267, 45, // syl -> Beng + 3271, 495, // syn -> Syrc + 3275, 495, // syr -> Syrc + 3279, 105, // syw -> Deva + 3283, 520, // ta -> Taml + 3286, 100, // tab -> Cyrl + 3290, 105, // taj -> Deva + 3294, 500, // tbk -> Tagb + 3298, 555, // tcn -> Tibt + 3302, 355, // tco -> Mymr + 3306, 520, // tcx -> Taml + 3310, 245, // tcy -> Knda + 3314, 540, // tda -> Tfng + 3318, 105, // tdb -> Deva + 3322, 510, // tdd -> Tale + 3326, 105, // tdg -> Deva + 3330, 105, // tdh -> Deva + 3334, 535, // te -> Telu + 3337, 205, // tes -> Java + 3341, 100, // tg -> Cyrl + 3344, 10, // tg_PK -> Arab + 3350, 105, // tge -> Deva + 3354, 555, // tgf -> Tibt + 3358, 550, // th -> Thai + 3361, 105, // the -> Deva + 3365, 105, // thf -> Deva + 3369, 510, // thi -> Tale + 3373, 105, // thl -> Deva + 3377, 550, // thm -> Thai + 3381, 105, // thq -> Deva + 3385, 105, // thr -> Deva + 3389, 105, // ths -> Deva + 3393, 120, // ti -> Ethi + 3396, 120, // tig -> Ethi + 3400, 105, // tij -> Deva + 3404, 100, // tin -> Cyrl + 3408, 355, // tjl -> Mymr + 3412, 10, // tjo -> Arab + 3416, 105, // tkb -> Deva + 3420, 10, // tks -> Arab + 3424, 105, // tkt -> Deva + 3428, 495, // tmr -> Syrc + 3432, 60, // tnv -> Cakm + 3436, 10, // tov -> Arab + 3440, 235, // tpu -> Khmr + 3444, 10, // tra -> Arab + 3448, 185, // trg -> Hebr + 3452, 10, // trm -> Arab + 3456, 10, // trw -> Arab + 3460, 150, // tsd -> Grek + 3464, 555, // tsj -> Tibt + 3468, 100, // tt -> Cyrl + 3471, 260, // tth -> Laoo + 3475, 260, // tto -> Laoo + 3479, 550, // tts -> Thai + 3483, 105, // ttz -> Deva + 3487, 355, // tvn -> Mymr + 3491, 105, // twm -> Deva + 3495, 525, // txg -> Tang + 3499, 565, // txo -> Toto + 3503, 530, // tyr -> Tavt + 3507, 100, // tyv -> Cyrl + 3511, 100, // ude -> Cyrl + 3515, 330, // udg -> Mlym + 3519, 100, // udi -> Cyrl + 3523, 100, // udm -> Cyrl + 3527, 10, // ug -> Arab + 3530, 100, // ug_KZ -> Cyrl + 3536, 100, // ug_MN -> Cyrl + 3542, 570, // uga -> Ugar + 3546, 100, // ugh -> Cyrl + 3550, 550, // ugo -> Thai + 3554, 100, // uk -> Cyrl + 3557, 395, // uki -> Orya + 3561, 100, // ulc -> Cyrl + 3565, 45, // unr -> Beng + 3569, 105, // unr_NP -> Deva + 3576, 45, // unx -> Beng + 3580, 10, // ur -> Arab + 3583, 550, // urk -> Thai + 3587, 10, // ush -> Arab + 3591, 150, // uum -> Grek + 3595, 10, // uz_AF -> Arab + 3601, 100, // uz_CN -> Cyrl + 3607, 10, // uzs -> Arab + 3611, 520, // vaa -> Taml + 3615, 10, // vaf -> Arab + 3619, 105, // vah -> Deva + 3623, 575, // vai -> Vaii + 3627, 105, // vas -> Deva + 3631, 105, // vav -> Deva + 3635, 105, // vay -> Deva + 3639, 10, // vgr -> Arab + 3643, 105, // vjk -> Deva + 3647, 245, // vmd -> Knda + 3651, 10, // vmh -> Arab + 3655, 120, // wal -> Ethi + 3659, 10, // wbk -> Arab + 3663, 535, // wbq -> Telu + 3667, 105, // wbr -> Deva + 3671, 120, // wle -> Ethi + 3675, 10, // wlo -> Arab + 3679, 105, // wme -> Deva + 3683, 10, // wne -> Arab + 3687, 10, // wni -> Arab + 3691, 130, // wsg -> Gong + 3695, 10, // wsv -> Arab + 3699, 105, // wtm -> Deva + 3703, 175, // wuu -> Hans + 3707, 0, // xag -> Aghb + 3711, 100, // xal -> Cyrl + 3715, 120, // xan -> Ethi + 3719, 100, // xas -> Cyrl + 3723, 85, // xco -> Chrs + 3727, 70, // xcr -> Cari + 3731, 100, // xdq -> Cyrl + 3735, 10, // xhe -> Arab + 3739, 235, // xhm -> Khmr + 3743, 395, // xis -> Orya + 3747, 10, // xka -> Arab + 3751, 10, // xkc -> Arab + 3755, 555, // xkf -> Tibt + 3759, 10, // xkj -> Arab + 3763, 10, // xkp -> Arab + 3767, 295, // xlc -> Lyci + 3771, 300, // xld -> Lydi + 3775, 115, // xly -> Elym + 3779, 125, // xmf -> Geor + 3783, 310, // xmn -> Mani + 3787, 325, // xmr -> Merc + 3791, 360, // xna -> Narb + 3795, 105, // xnr -> Deva + 3799, 150, // xpg -> Grek + 3803, 380, // xpi -> Ogam + 3807, 100, // xpm -> Cyrl + 3811, 430, // xpr -> Prti + 3815, 100, // xrm -> Cyrl + 3819, 100, // xrn -> Cyrl + 3823, 455, // xsa -> Sarb + 3827, 105, // xsr -> Deva + 3831, 55, // xtq -> Brah + 3835, 520, // xub -> Taml + 3839, 520, // xuj -> Taml + 3843, 200, // xve -> Ital + 3847, 10, // xvi -> Arab + 3851, 100, // xwo -> Cyrl + 3855, 315, // xzh -> Marc + 3859, 100, // yai -> Cyrl + 3863, 105, // ybh -> Deva + 3867, 105, // ybi -> Deva + 3871, 10, // ydg -> Arab + 3875, 330, // yea -> Mlym + 3879, 150, // yej -> Grek + 3883, 535, // yeu -> Telu + 3887, 425, // ygp -> Plrd + 3891, 185, // yhd -> Hebr + 3895, 185, // yi -> Hebr + 3898, 595, // yig -> Yiii + 3902, 185, // yih -> Hebr + 3906, 595, // yiv -> Yiii + 3910, 100, // ykg -> Cyrl + 3914, 100, // ykh -> Cyrl + 3918, 425, // yna -> Plrd + 3922, 100, // ynk -> Cyrl + 3926, 210, // yoi -> Jpan + 3930, 550, // yoy -> Thai + 3934, 100, // yrk -> Cyrl + 3938, 595, // ysd -> Yiii + 3942, 595, // ysn -> Yiii + 3946, 595, // ysp -> Yiii + 3950, 100, // ysr -> Cyrl + 3954, 425, // ysy -> Plrd + 3958, 185, // yud -> Hebr + 3962, 180, // yue -> Hant + 3966, 175, // yue_CN -> Hans + 3973, 100, // yug -> Cyrl + 3977, 100, // yux -> Cyrl + 3981, 425, // ywq -> Plrd + 3985, 425, // ywu -> Plrd + 3989, 555, // zau -> Tibt + 3993, 10, // zba -> Arab + 3997, 170, // zch -> Hani + 4001, 10, // zdj -> Arab + 4005, 170, // zeh -> Hani + 4009, 540, // zen -> Tfng + 4013, 170, // zgb -> Hani + 4017, 540, // zgh -> Tfng + 4021, 170, // zgm -> Hani + 4025, 170, // zgn -> Hani + 4029, 175, // zh -> Hans + 4032, 180, // zh_AU -> Hant + 4038, 180, // zh_BN -> Hant + 4044, 180, // zh_GB -> Hant + 4050, 180, // zh_GF -> Hant + 4056, 180, // zh_HK -> Hant + 4062, 180, // zh_ID -> Hant + 4068, 180, // zh_MO -> Hant + 4074, 180, // zh_PA -> Hant + 4080, 180, // zh_PF -> Hant + 4086, 180, // zh_PH -> Hant + 4092, 180, // zh_SR -> Hant + 4098, 180, // zh_TH -> Hant + 4104, 180, // zh_TW -> Hant + 4110, 180, // zh_US -> Hant + 4116, 180, // zh_VN -> Hant + 4122, 170, // zhd -> Hani + 4126, 375, // zhx -> Nshu + 4130, 100, // zko -> Cyrl + 4134, 240, // zkt -> Kits + 4138, 100, // zkz -> Cyrl + 4142, 170, // zlj -> Hani + 4146, 170, // zln -> Hani + 4150, 170, // zlq -> Hani + 4154, 170, // zqe -> Hani + 4158, 395, // zrg -> Orya + 4162, 185, // zrp -> Hebr + 4166, 10, // zum -> Arab + 4170, 120, // zwa -> Ethi + 4174, 170, // zyg -> Hani + 4178, 170, // zyn -> Hani + 4182, 170, // zzj -> Hani }; //====================================================================== @@ -1142,26 +1171,26 @@ const char parentLocaleChars[] = "en_ZM\0en_ZW\0es_419\0es_AR\0es_BO\0es_BR\0es_BZ\0es_CL\0es_CO\0" "es_CR\0es_CU\0es_DO\0es_EC\0es_GT\0es_HN\0es_JP\0es_MX\0es_NI\0" "es_PA\0es_PE\0es_PR\0es_PY\0es_SV\0es_US\0es_UY\0es_VE\0ff_Adlm\0" - "ff_Arab\0fr_HT\0ha_Arab\0hi_Latn\0ht\0iu_Latn\0kk_Arab\0ks_Deva\0" - "ku_Arab\0kxv_Deva\0kxv_Orya\0kxv_Telu\0ky_Arab\0ky_Latn\0ml_Arab\0" - "mn_Mong\0mni_Mtei\0ms_Arab\0nb\0nn\0no\0no_NO\0pa_Arab\0pt_AO\0" - "pt_CH\0pt_CV\0pt_FR\0pt_GQ\0pt_GW\0pt_LU\0pt_MO\0pt_MZ\0pt_PT\0" - "pt_ST\0pt_TL\0root\0sat_Deva\0sd_Deva\0sd_Khoj\0sd_Sind\0shi_Latn\0" - "so_Arab\0sr_Latn\0sw_Arab\0tg_Arab\0ug_Cyrl\0uz_Arab\0uz_Cyrl\0" - "vai_Latn\0wo_Arab\0yo_Arab\0yue_Hans\0zh_Hant\0zh_Hant_HK\0zh_Hant_MO\0" - ""; + "ff_Arab\0fr_HT\0ha_Arab\0hi_Latn\0ht\0iu_Latn\0kaa_Latn\0kk_Arab\0" + "kok_Latn\0ks_Deva\0ku_Arab\0kxv_Deva\0kxv_Orya\0kxv_Telu\0ky_Arab\0" + "ky_Latn\0ml_Arab\0mn_Mong\0mni_Mtei\0ms_Arab\0nb\0nn\0no\0no_NO\0" + "pa_Arab\0pt_AO\0pt_CH\0pt_CV\0pt_FR\0pt_GQ\0pt_GW\0pt_LU\0pt_MO\0" + "pt_MZ\0pt_PT\0pt_ST\0pt_TL\0root\0sat_Deva\0sd_Deva\0sd_Khoj\0" + "sd_Sind\0shi_Latn\0so_Arab\0sr_Latn\0sw_Arab\0tg_Arab\0ug_Cyrl\0" + "uz_Arab\0uz_Cyrl\0vai_Latn\0wo_Arab\0yo_Arab\0yue_Hans\0zh_Hant\0" + "zh_Hant_HK\0zh_Hant_MO\0"; const int32_t parentLocaleTable[] = { - 0, 1062, // az_Arab -> root - 8, 1062, // az_Cyrl -> root - 16, 1062, // bal_Latn -> root - 25, 1062, // blt_Latn -> root - 34, 1062, // bm_Nkoo -> root - 42, 1062, // bs_Cyrl -> root - 50, 1062, // byn_Latn -> root - 59, 1062, // cu_Glag -> root - 67, 1062, // dje_Arab -> root - 76, 1062, // dyo_Arab -> root + 0, 1080, // az_Arab -> root + 8, 1080, // az_Cyrl -> root + 16, 1080, // bal_Latn -> root + 25, 1080, // blt_Latn -> root + 34, 1080, // bm_Nkoo -> root + 42, 1080, // bs_Cyrl -> root + 50, 1080, // byn_Latn -> root + 59, 1080, // cu_Glag -> root + 67, 1080, // dje_Arab -> root + 76, 1080, // dyo_Arab -> root 92, 85, // en_150 -> en_001 99, 85, // en_AG -> en_001 105, 85, // en_AI -> en_001 @@ -1183,7 +1212,7 @@ const int32_t parentLocaleTable[] = { 201, 85, // en_DG -> en_001 207, 92, // en_DK -> en_150 213, 85, // en_DM -> en_001 - 219, 1062, // en_Dsrt -> root + 219, 1080, // en_Dsrt -> root 227, 85, // en_ER -> en_001 233, 92, // en_FI -> en_150 239, 85, // en_FJ -> en_001 @@ -1243,7 +1272,7 @@ const int32_t parentLocaleTable[] = { 563, 85, // en_SS -> en_001 569, 85, // en_SX -> en_001 575, 85, // en_SZ -> en_001 - 581, 1062, // en_Shaw -> root + 581, 1080, // en_Shaw -> root 589, 85, // en_TC -> en_001 595, 85, // en_TK -> en_001 601, 85, // en_TO -> en_001 @@ -1281,57 +1310,59 @@ const int32_t parentLocaleTable[] = { 800, 673, // es_US -> es_419 806, 673, // es_UY -> es_419 812, 673, // es_VE -> es_419 - 818, 1062, // ff_Adlm -> root - 826, 1062, // ff_Arab -> root - 840, 1062, // ha_Arab -> root + 818, 1080, // ff_Adlm -> root + 826, 1080, // ff_Arab -> root + 840, 1080, // ha_Arab -> root 848, 329, // hi_Latn -> en_IN 856, 834, // ht -> fr_HT - 859, 1062, // iu_Latn -> root - 867, 1062, // kk_Arab -> root - 875, 1062, // ks_Deva -> root - 883, 1062, // ku_Arab -> root - 891, 1062, // kxv_Deva -> root - 900, 1062, // kxv_Orya -> root - 909, 1062, // kxv_Telu -> root - 918, 1062, // ky_Arab -> root - 926, 1062, // ky_Latn -> root - 934, 1062, // ml_Arab -> root - 942, 1062, // mn_Mong -> root - 950, 1062, // mni_Mtei -> root - 959, 1062, // ms_Arab -> root - 967, 973, // nb -> no - 970, 973, // nn -> no - 976, 973, // no_NO -> no - 982, 1062, // pa_Arab -> root - 990, 1044, // pt_AO -> pt_PT - 996, 1044, // pt_CH -> pt_PT - 1002, 1044, // pt_CV -> pt_PT - 1008, 1044, // pt_FR -> pt_PT - 1014, 1044, // pt_GQ -> pt_PT - 1020, 1044, // pt_GW -> pt_PT - 1026, 1044, // pt_LU -> pt_PT - 1032, 1044, // pt_MO -> pt_PT - 1038, 1044, // pt_MZ -> pt_PT - 1050, 1044, // pt_ST -> pt_PT - 1056, 1044, // pt_TL -> pt_PT - 1067, 1062, // sat_Deva -> root - 1076, 1062, // sd_Deva -> root - 1084, 1062, // sd_Khoj -> root - 1092, 1062, // sd_Sind -> root - 1100, 1062, // shi_Latn -> root - 1109, 1062, // so_Arab -> root - 1117, 1062, // sr_Latn -> root - 1125, 1062, // sw_Arab -> root - 1133, 1062, // tg_Arab -> root - 1141, 1062, // ug_Cyrl -> root - 1149, 1062, // uz_Arab -> root - 1157, 1062, // uz_Cyrl -> root - 1165, 1062, // vai_Latn -> root - 1174, 1062, // wo_Arab -> root - 1182, 1062, // yo_Arab -> root - 1190, 1062, // yue_Hans -> root - 1199, 1062, // zh_Hant -> root - 1218, 1207, // zh_Hant_MO -> zh_Hant_HK + 859, 1080, // iu_Latn -> root + 867, 1080, // kaa_Latn -> root + 876, 1080, // kk_Arab -> root + 884, 1080, // kok_Latn -> root + 893, 1080, // ks_Deva -> root + 901, 1080, // ku_Arab -> root + 909, 1080, // kxv_Deva -> root + 918, 1080, // kxv_Orya -> root + 927, 1080, // kxv_Telu -> root + 936, 1080, // ky_Arab -> root + 944, 1080, // ky_Latn -> root + 952, 1080, // ml_Arab -> root + 960, 1080, // mn_Mong -> root + 968, 1080, // mni_Mtei -> root + 977, 1080, // ms_Arab -> root + 985, 991, // nb -> no + 988, 991, // nn -> no + 994, 991, // no_NO -> no + 1000, 1080, // pa_Arab -> root + 1008, 1062, // pt_AO -> pt_PT + 1014, 1062, // pt_CH -> pt_PT + 1020, 1062, // pt_CV -> pt_PT + 1026, 1062, // pt_FR -> pt_PT + 1032, 1062, // pt_GQ -> pt_PT + 1038, 1062, // pt_GW -> pt_PT + 1044, 1062, // pt_LU -> pt_PT + 1050, 1062, // pt_MO -> pt_PT + 1056, 1062, // pt_MZ -> pt_PT + 1068, 1062, // pt_ST -> pt_PT + 1074, 1062, // pt_TL -> pt_PT + 1085, 1080, // sat_Deva -> root + 1094, 1080, // sd_Deva -> root + 1102, 1080, // sd_Khoj -> root + 1110, 1080, // sd_Sind -> root + 1118, 1080, // shi_Latn -> root + 1127, 1080, // so_Arab -> root + 1135, 1080, // sr_Latn -> root + 1143, 1080, // sw_Arab -> root + 1151, 1080, // tg_Arab -> root + 1159, 1080, // ug_Cyrl -> root + 1167, 1080, // uz_Arab -> root + 1175, 1080, // uz_Cyrl -> root + 1183, 1080, // vai_Latn -> root + 1192, 1080, // wo_Arab -> root + 1200, 1080, // yo_Arab -> root + 1208, 1080, // yue_Hans -> root + 1217, 1080, // zh_Hant -> root + 1236, 1225, // zh_Hant_MO -> zh_Hant_HK }; diff --git a/thirdparty/icu4c/common/localematcher.cpp b/thirdparty/icu4c/common/localematcher.cpp index 8aae596bc8..1e74dd1f14 100644 --- a/thirdparty/icu4c/common/localematcher.cpp +++ b/thirdparty/icu4c/common/localematcher.cpp @@ -780,7 +780,7 @@ int32_t acceptLanguage(UEnumeration &supportedLocales, Locale::Iterator &desired ULOC_ACCEPT_VALID : ULOC_ACCEPT_FALLBACK; } const char *bestStr = result.getSupportedLocale()->getName(); - int32_t bestLength = (int32_t)uprv_strlen(bestStr); + int32_t bestLength = static_cast<int32_t>(uprv_strlen(bestStr)); if (bestLength <= capacity) { uprv_memcpy(dest, bestStr, bestLength); } diff --git a/thirdparty/icu4c/common/locbased.h b/thirdparty/icu4c/common/locbased.h index 45738863b5..2d260b5278 100644 --- a/thirdparty/icu4c/common/locbased.h +++ b/thirdparty/icu4c/common/locbased.h @@ -99,7 +99,7 @@ inline LocaleBased::LocaleBased(char* validAlias, char* actualAlias) : inline LocaleBased::LocaleBased(const char* validAlias, const char* actualAlias) : // ugh: cast away const - valid((char*)validAlias), actual((char*)actualAlias) { + valid(const_cast<char*>(validAlias)), actual(const_cast<char*>(actualAlias)) { } U_NAMESPACE_END diff --git a/thirdparty/icu4c/common/locdispnames.cpp b/thirdparty/icu4c/common/locdispnames.cpp index 0be069357a..ddf7687a2b 100644 --- a/thirdparty/icu4c/common/locdispnames.cpp +++ b/thirdparty/icu4c/common/locdispnames.cpp @@ -245,7 +245,7 @@ Locale::getDisplayName(const Locale &displayLocale, return result; } -#if ! UCONFIG_NO_BREAK_ITERATION +#if !UCONFIG_NO_BREAK_ITERATION // ------------------------------------- // Gets the objectLocale display name in the default locale language. @@ -351,7 +351,7 @@ _getStringOrCopyKey(const char *path, const char *locale, } } else { /* no string from a resource bundle: convert the substitute */ - length=(int32_t)uprv_strlen(substitute); + length = static_cast<int32_t>(uprv_strlen(substitute)); u_charsToUChars(substitute, dest, uprv_min(length, destCapacity)); errorCode = U_USING_DEFAULT_WARNING; } @@ -835,7 +835,10 @@ uloc_getDisplayKeywordValue( const char* locale, } /* get the keyword value */ - CharString keywordValue = ulocimp_getKeywordValue(locale, keyword, *status); + CharString keywordValue; + if (keyword != nullptr && *keyword != '\0') { + keywordValue = ulocimp_getKeywordValue(locale, keyword, *status); + } /* * if the keyword is equal to currency .. then to get the display name diff --git a/thirdparty/icu4c/common/locdspnm.cpp b/thirdparty/icu4c/common/locdspnm.cpp index c65a349dbd..270684341c 100644 --- a/thirdparty/icu4c/common/locdspnm.cpp +++ b/thirdparty/icu4c/common/locdspnm.cpp @@ -336,10 +336,11 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, { while (length-- > 0) { UDisplayContext value = *contexts++; - UDisplayContextType selector = (UDisplayContextType)((uint32_t)value >> 8); + UDisplayContextType selector = + static_cast<UDisplayContextType>(static_cast<uint32_t>(value) >> 8); switch (selector) { case UDISPCTX_TYPE_DIALECT_HANDLING: - dialectHandling = (UDialectHandling)value; + dialectHandling = static_cast<UDialectHandling>(value); break; case UDISPCTX_TYPE_CAPITALIZATION: capitalizationContext = value; @@ -407,7 +408,7 @@ LocaleDisplayNamesImpl::CapitalizationContextSink::~CapitalizationContextSink() void LocaleDisplayNamesImpl::initialize() { - LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this; + LocaleDisplayNamesImpl* nonConstThis = this; nonConstThis->locale = langData.getLocale() == Locale::getRoot() ? regionData.getLocale() : langData.getLocale(); @@ -426,16 +427,16 @@ LocaleDisplayNamesImpl::initialize() { pattern = UnicodeString("{0} ({1})", -1, US_INV); } format.applyPatternMinMaxArguments(pattern, 2, 2, status); - if (pattern.indexOf((char16_t)0xFF08) >= 0) { - formatOpenParen.setTo((char16_t)0xFF08); // fullwidth ( - formatReplaceOpenParen.setTo((char16_t)0xFF3B); // fullwidth [ - formatCloseParen.setTo((char16_t)0xFF09); // fullwidth ) - formatReplaceCloseParen.setTo((char16_t)0xFF3D); // fullwidth ] + if (pattern.indexOf(static_cast<char16_t>(0xFF08)) >= 0) { + formatOpenParen.setTo(static_cast<char16_t>(0xFF08)); // fullwidth ( + formatReplaceOpenParen.setTo(static_cast<char16_t>(0xFF3B)); // fullwidth [ + formatCloseParen.setTo(static_cast<char16_t>(0xFF09)); // fullwidth ) + formatReplaceCloseParen.setTo(static_cast<char16_t>(0xFF3D)); // fullwidth ] } else { - formatOpenParen.setTo((char16_t)0x0028); // ( - formatReplaceOpenParen.setTo((char16_t)0x005B); // [ - formatCloseParen.setTo((char16_t)0x0029); // ) - formatReplaceCloseParen.setTo((char16_t)0x005D); // ] + formatOpenParen.setTo(static_cast<char16_t>(0x0028)); // ( + formatReplaceOpenParen.setTo(static_cast<char16_t>(0x005B)); // [ + formatCloseParen.setTo(static_cast<char16_t>(0x0029)); // ) + formatReplaceCloseParen.setTo(static_cast<char16_t>(0x005D)); // ] } UnicodeString ktPattern; @@ -495,7 +496,7 @@ UDisplayContext LocaleDisplayNamesImpl::getContext(UDisplayContextType type) const { switch (type) { case UDISPCTX_TYPE_DIALECT_HANDLING: - return (UDisplayContext)dialectHandling; + return static_cast<UDisplayContext>(dialectHandling); case UDISPCTX_TYPE_CAPITALIZATION: return capitalizationContext; case UDISPCTX_TYPE_DISPLAY_LENGTH: @@ -505,7 +506,7 @@ LocaleDisplayNamesImpl::getContext(UDisplayContextType type) const { default: break; } - return (UDisplayContext)0; + return static_cast<UDisplayContext>(0); } UnicodeString& @@ -652,7 +653,7 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, appendWithSep(resultRemainder, temp3); } else { appendWithSep(resultRemainder, temp) - .append((char16_t)0x3d /* = */) + .append(static_cast<char16_t>(0x3d) /* = */) .append(temp2); } } diff --git a/thirdparty/icu4c/common/locid.cpp b/thirdparty/icu4c/common/locid.cpp index 37bbe4ba94..4a73f55920 100644 --- a/thirdparty/icu4c/common/locid.cpp +++ b/thirdparty/icu4c/common/locid.cpp @@ -31,6 +31,8 @@ ****************************************************************************** */ +#include <optional> +#include <string_view> #include <utility> #include "unicode/bytestream.h" @@ -109,7 +111,7 @@ namespace { // void U_CALLCONV deleteLocale(void *obj) { - delete (icu::Locale *) obj; + delete static_cast<icu::Locale*>(obj); } UBool U_CALLCONV locale_cleanup() @@ -132,7 +134,7 @@ void U_CALLCONV locale_init(UErrorCode &status) { U_NAMESPACE_USE U_ASSERT(gLocaleCache == nullptr); - gLocaleCache = new Locale[(int)eMAX_LOCALES]; + gLocaleCache = new Locale[static_cast<int>(eMAX_LOCALES)]; if (gLocaleCache == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; @@ -194,7 +196,7 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) { ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); } - Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf.data()); + Locale* newDefault = static_cast<Locale*>(uhash_get(gDefaultLocalesHashT, localeNameBuf.data())); if (newDefault == nullptr) { newDefault = new Locale(Locale::eBOGUS); if (newDefault == nullptr) { @@ -202,7 +204,7 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) { return gDefaultLocale; } newDefault->init(localeNameBuf.data(), false); - uhash_put(gDefaultLocalesHashT, (char*) newDefault->getName(), newDefault, &status); + uhash_put(gDefaultLocalesHashT, const_cast<char*>(newDefault->getName()), newDefault, &status); if (U_FAILURE(status)) { return gDefaultLocale; } @@ -296,7 +298,7 @@ Locale::Locale( const char * newLanguage, // Language if ( newLanguage != nullptr ) { - lsize = (int32_t)uprv_strlen(newLanguage); + lsize = static_cast<int32_t>(uprv_strlen(newLanguage)); if ( lsize < 0 || lsize > ULOC_STRING_LIMIT ) { // int32 wrap setToBogus(); return; @@ -308,7 +310,7 @@ Locale::Locale( const char * newLanguage, // _Country if ( newCountry != nullptr ) { - csize = (int32_t)uprv_strlen(newCountry); + csize = static_cast<int32_t>(uprv_strlen(newCountry)); if ( csize < 0 || csize > ULOC_STRING_LIMIT ) { // int32 wrap setToBogus(); return; @@ -325,7 +327,7 @@ Locale::Locale( const char * newLanguage, } // remove trailing _'s - vsize = (int32_t)uprv_strlen(newVariant); + vsize = static_cast<int32_t>(uprv_strlen(newVariant)); if ( vsize < 0 || vsize > ULOC_STRING_LIMIT ) { // int32 wrap setToBogus(); return; @@ -338,7 +340,7 @@ Locale::Locale( const char * newLanguage, if ( newKeywords != nullptr) { - ksize = (int32_t)uprv_strlen(newKeywords); + ksize = static_cast<int32_t>(uprv_strlen(newKeywords)); if ( ksize < 0 || ksize > ULOC_STRING_LIMIT ) { setToBogus(); return; @@ -1200,8 +1202,8 @@ AliasReplacer::parseLanguageReplacement( return; } // We have multiple field so we have to allocate and parse - CharString* str = new CharString( - replacement, (int32_t)uprv_strlen(replacement), status); + CharString* str = + new CharString(replacement, static_cast<int32_t>(uprv_strlen(replacement)), status); LocalPointer<CharString> lpStr(str, status); toBeFreed.adoptElement(lpStr.orphan(), status); if (U_FAILURE(status)) { @@ -1213,7 +1215,7 @@ AliasReplacer::parseLanguageReplacement( *endOfField = '\0'; // null terminiate it. endOfField++; const char* start = endOfField; - endOfField = (char*) uprv_strchr(start, '_'); + endOfField = const_cast<char*>(uprv_strchr(start, '_')); size_t len = 0; if (endOfField == nullptr) { len = uprv_strlen(start); @@ -1228,7 +1230,7 @@ AliasReplacer::parseLanguageReplacement( return; } start = endOfField++; - endOfField = (char*)uprv_strchr(start, '_'); + endOfField = const_cast<char*>(uprv_strchr(start, '_')); if (endOfField == nullptr) { len = uprv_strlen(start); } else { @@ -1243,7 +1245,7 @@ AliasReplacer::parseLanguageReplacement( return; } start = endOfField++; - endOfField = (char*)uprv_strchr(start, '_'); + endOfField = const_cast<char*>(uprv_strchr(start, '_')); if (endOfField == nullptr) { len = uprv_strlen(start); } else { @@ -1285,7 +1287,7 @@ AliasReplacer::replaceLanguage( variant_index++) { if (checkVariants) { U_ASSERT(variant_index < variant_size); - searchVariant = (const char*)(variants.elementAt(variant_index)); + searchVariant = static_cast<const char*>(variants.elementAt(variant_index)); } if (searchVariant != nullptr && uprv_strlen(searchVariant) < 4) { @@ -1406,13 +1408,13 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status) U_ASSERT(foundInReplacement[len] == ' ' || foundInReplacement[len] == '\0'); item.adoptInsteadAndCheckErrorCode( - new CharString(foundInReplacement, (int32_t)len, status), status); + new CharString(foundInReplacement, static_cast<int32_t>(len), status), status); } } if (item.isNull() && U_SUCCESS(status)) { item.adoptInsteadAndCheckErrorCode( new CharString(replacement, - (int32_t)(firstSpace - replacement), status), status); + static_cast<int32_t>(firstSpace - replacement), status), status); } if (U_FAILURE(status)) { return false; } replacedRegion = item->data(); @@ -1454,7 +1456,7 @@ AliasReplacer::replaceVariant(UErrorCode& status) } // Since we may have more than one variant, we need to loop through them. for (int32_t i = 0; i < variants.size(); i++) { - const char *variant = (const char*)(variants.elementAt(i)); + const char* variant = static_cast<const char*>(variants.elementAt(i)); const char *replacement = data->variantMap().get(variant); if (replacement == nullptr) { // Found no replacement data for this variant. @@ -1496,7 +1498,7 @@ AliasReplacer::replaceSubdivision( size_t len = (firstSpace != nullptr) ? (firstSpace - replacement) : uprv_strlen(replacement); if (2 <= len && len <= 8) { - output.append(replacement, (int32_t)len, status); + output.append(replacement, static_cast<int32_t>(len), status); if (2 == len) { // Add 'zzzz' based on changes to UTS #35 for CLDR-14312. output.append("zzzz", 4, status); @@ -1546,7 +1548,7 @@ AliasReplacer::replaceTransformedExtensions( } const char* nextTKey = ultag_getTKeyStart(tvalue); if (nextTKey != nullptr) { - *((char*)(nextTKey-1)) = '\0'; // NUL terminate tvalue + *const_cast<char*>(nextTKey - 1) = '\0'; // NUL terminate tvalue } tfields.insertElementAt((void*)tkey, tfields.size(), status); if (U_FAILURE(status)) { @@ -1561,17 +1563,17 @@ AliasReplacer::replaceTransformedExtensions( if (output.length() > 0) { output.append('-', status); } - const char* tfield = (const char*) tfields.elementAt(i); + const char* tfield = static_cast<const char*>(tfields.elementAt(i)); const char* tvalue = uprv_strchr(tfield, '-'); if (tvalue == nullptr) { status = U_ILLEGAL_ARGUMENT_ERROR; return false; } // Split the "tkey-tvalue" pair string so that we can canonicalize the tvalue. - *((char*)tvalue++) = '\0'; // NUL terminate tkey + *const_cast<char*>(tvalue++) = '\0'; // NUL terminate tkey output.append(tfield, status).append('-', status); - const char* bcpTValue = ulocimp_toBcpType(tfield, tvalue, nullptr, nullptr); - output.append((bcpTValue == nullptr) ? tvalue : bcpTValue, status); + std::optional<std::string_view> bcpTValue = ulocimp_toBcpType(tfield, tvalue); + output.append(bcpTValue.has_value() ? *bcpTValue : tvalue, status); } } if (U_FAILURE(status)) { @@ -1604,7 +1606,7 @@ AliasReplacer::outputToString( int32_t variantsStart = out.length(); for (int32_t i = 0; i < variants.size(); i++) { out.append(SEP_CHAR, status) - .append((const char*)(variants.elementAt(i)), + .append(static_cast<const char*>(variants.elementAt(i)), status); } T_CString_toUpperCase(out.data() + variantsStart); @@ -1673,7 +1675,7 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status int changed = 0; // A UVector to to hold CharString allocated by the replace* method // and freed when out of scope from his function. - UVector stringsToBeFreed([](void *obj){ delete ((CharString*) obj); }, + UVector stringsToBeFreed([](void *obj) { delete static_cast<CharString*>(obj); }, nullptr, 10, status); while (U_SUCCESS(status)) { // Something wrong with the data cause looping here more than 10 times @@ -1866,14 +1868,14 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) uloc_canonicalize(localeID, fullName, sizeof(fullNameBuffer), &err) : uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err); - if(err == U_BUFFER_OVERFLOW_ERROR || length >= (int32_t)sizeof(fullNameBuffer)) { + if (err == U_BUFFER_OVERFLOW_ERROR || length >= static_cast<int32_t>(sizeof(fullNameBuffer))) { U_ASSERT(baseName == nullptr); /*Go to heap for the fullName if necessary*/ - fullName = (char *)uprv_malloc(sizeof(char)*(length + 1)); - if (fullName == nullptr) { - fullName = fullNameBuffer; + char* newFullName = static_cast<char*>(uprv_malloc(sizeof(char) * (length + 1))); + if (newFullName == nullptr) { break; // error: out of memory } + fullName = newFullName; err = U_ZERO_ERROR; length = canonicalize ? uloc_canonicalize(localeID, fullName, length+1, &err) : @@ -1895,7 +1897,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) fieldIdx < UPRV_LENGTHOF(field)-1 && (at == nullptr || separator < at)) { field[fieldIdx] = separator + 1; - fieldLen[fieldIdx-1] = (int32_t)(separator - field[fieldIdx-1]); + fieldLen[fieldIdx - 1] = static_cast<int32_t>(separator - field[fieldIdx - 1]); fieldIdx++; } // variant may contain @foo or .foo POSIX cruft; remove it @@ -1905,12 +1907,12 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) if (separator==nullptr || (sep2!=nullptr && separator > sep2)) { separator = sep2; } - fieldLen[fieldIdx-1] = (int32_t)(separator - field[fieldIdx-1]); + fieldLen[fieldIdx - 1] = static_cast<int32_t>(separator - field[fieldIdx - 1]); } else { - fieldLen[fieldIdx-1] = length - (int32_t)(field[fieldIdx-1] - fullName); + fieldLen[fieldIdx - 1] = length - static_cast<int32_t>(field[fieldIdx - 1] - fullName); } - if (fieldLen[0] >= (int32_t)(sizeof(language))) + if (fieldLen[0] >= static_cast<int32_t>(sizeof(language))) { break; // error: the language field is too long } @@ -1941,7 +1943,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) if (fieldLen[variantField] > 0) { /* We have a variant */ - variantBegin = (int32_t)(field[variantField] - fullName); + variantBegin = static_cast<int32_t>(field[variantField] - fullName); } err = U_ZERO_ERROR; @@ -1991,12 +1993,13 @@ Locale::initBaseName(UErrorCode &status) { const char *eqPtr = uprv_strchr(fullName, '='); if (atPtr && eqPtr && atPtr < eqPtr) { // Key words exist. - int32_t baseNameLength = (int32_t)(atPtr - fullName); - baseName = (char *)uprv_malloc(baseNameLength + 1); - if (baseName == nullptr) { + int32_t baseNameLength = static_cast<int32_t>(atPtr - fullName); + char* newBaseName = static_cast<char*>(uprv_malloc(baseNameLength + 1)); + if (newBaseName == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } + baseName = newBaseName; uprv_strncpy(baseName, fullName, baseNameLength); baseName[baseNameLength] = 0; @@ -2434,7 +2437,7 @@ public: UErrorCode status = U_ZERO_ERROR; return new KeywordEnumeration( keywords.data(), keywords.length(), - (int32_t)(current - keywords.data()), status); + static_cast<int32_t>(current - keywords.data()), status); } virtual int32_t count(UErrorCode& status) const override { @@ -2453,7 +2456,7 @@ public: int32_t len; if(U_SUCCESS(status) && *current != 0) { result = current; - len = (int32_t)uprv_strlen(current); + len = static_cast<int32_t>(uprv_strlen(current)); current += len+1; if(resultLength != nullptr) { *resultLength = len; @@ -2596,13 +2599,7 @@ Locale::getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& sta return; } - // TODO: Remove the need for a const char* to a NUL terminated buffer. - const CharString keywordName_nul(keywordName, status); - if (U_FAILURE(status)) { - return; - } - - ulocimp_getKeywordValue(fullName, keywordName_nul.data(), sink, status); + ulocimp_getKeywordValue(fullName, keywordName, sink, status); } void @@ -2613,89 +2610,90 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName, return; } - // TODO: Remove the need for a const char* to a NUL terminated buffer. - const CharString keywordName_nul(keywordName, status); - if (U_FAILURE(status)) { - return; - } - - const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); - if (legacy_key == nullptr) { + std::optional<std::string_view> legacy_key = ulocimp_toLegacyKeyWithFallback(keywordName); + if (!legacy_key.has_value()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } - auto legacy_value = getKeywordValue<CharString>(legacy_key, status); + auto legacy_value = getKeywordValue<CharString>(*legacy_key, status); if (U_FAILURE(status)) { return; } - const char* unicode_value = uloc_toUnicodeLocaleType( - keywordName_nul.data(), legacy_value.data()); - - if (unicode_value == nullptr) { + std::optional<std::string_view> unicode_value = + ulocimp_toBcpTypeWithFallback(keywordName, legacy_value.toStringPiece()); + if (!unicode_value.has_value()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } - sink.Append(unicode_value, static_cast<int32_t>(uprv_strlen(unicode_value))); + sink.Append(unicode_value->data(), static_cast<int32_t>(unicode_value->size())); } void -Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status) -{ - if (U_FAILURE(status)) { +Locale::setKeywordValue(StringPiece keywordName, + StringPiece keywordValue, + UErrorCode& status) { + if (U_FAILURE(status)) { return; } + if (keywordName.empty()) { + status = U_ILLEGAL_ARGUMENT_ERROR; return; } if (status == U_STRING_NOT_TERMINATED_WARNING) { status = U_ZERO_ERROR; } - int32_t bufferLength = uprv_max((int32_t)(uprv_strlen(fullName) + 1), ULOC_FULLNAME_CAPACITY); - int32_t newLength = uloc_setKeywordValue(keywordName, keywordValue, fullName, - bufferLength, &status) + 1; - U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING); - /* Handle the case the current buffer is not enough to hold the new id */ - if (status == U_BUFFER_OVERFLOW_ERROR) { - U_ASSERT(newLength > bufferLength); - char* newFullName = (char *)uprv_malloc(newLength); - if (newFullName == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - uprv_strcpy(newFullName, fullName); - if (fullName != fullNameBuffer) { - // if full Name is already on the heap, need to free it. - uprv_free(fullName); - if (baseName == fullName) { - baseName = newFullName; // baseName should not point to freed memory. + + int32_t length = static_cast<int32_t>(uprv_strlen(fullName)); + int32_t capacity = fullName == fullNameBuffer ? ULOC_FULLNAME_CAPACITY : length + 1; + + const char* start = locale_getKeywordsStart(fullName); + int32_t offset = start == nullptr ? length : start - fullName; + + for (;;) { + // Remove -1 from the capacity so that this function can guarantee NUL termination. + CheckedArrayByteSink sink(fullName + offset, capacity - offset - 1); + + int32_t reslen = ulocimp_setKeywordValue( + {fullName + offset, static_cast<std::string_view::size_type>(length - offset)}, + keywordName, + keywordValue, + sink, + status); + + if (status == U_BUFFER_OVERFLOW_ERROR) { + capacity = reslen + offset + 1; + char* newFullName = static_cast<char*>(uprv_malloc(capacity)); + if (newFullName == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + uprv_memcpy(newFullName, fullName, length + 1); + if (fullName != fullNameBuffer) { + if (baseName == fullName) { + baseName = newFullName; // baseName should not point to freed memory. + } + // if fullName is already on the heap, need to free it. + uprv_free(fullName); } + fullName = newFullName; + status = U_ZERO_ERROR; + continue; } - fullName = newFullName; - status = U_ZERO_ERROR; - uloc_setKeywordValue(keywordName, keywordValue, fullName, newLength, &status); - U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING); - } else { - U_ASSERT(newLength <= bufferLength); + + if (U_FAILURE(status)) { return; } + u_terminateChars(fullName, capacity, reslen + offset, &status); + break; } - if (U_SUCCESS(status) && baseName == fullName) { + + if (baseName == fullName) { // May have added the first keyword, meaning that the fullName is no longer also the baseName. initBaseName(status); } } void -Locale::setKeywordValue(StringPiece keywordName, - StringPiece keywordValue, - UErrorCode& status) { - if (U_FAILURE(status)) { return; } - // TODO: Remove the need for a const char* to a NUL terminated buffer. - const CharString keywordName_nul(keywordName, status); - const CharString keywordValue_nul(keywordValue, status); - setKeywordValue(keywordName_nul.data(), keywordValue_nul.data(), status); -} - -void Locale::setUnicodeKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status) { @@ -2703,32 +2701,25 @@ Locale::setUnicodeKeywordValue(StringPiece keywordName, return; } - // TODO: Remove the need for a const char* to a NUL terminated buffer. - const CharString keywordName_nul(keywordName, status); - const CharString keywordValue_nul(keywordValue, status); - if (U_FAILURE(status)) { - return; - } - - const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); - if (legacy_key == nullptr) { + std::optional<std::string_view> legacy_key = ulocimp_toLegacyKeyWithFallback(keywordName); + if (!legacy_key.has_value()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } - const char* legacy_value = nullptr; - - if (!keywordValue_nul.isEmpty()) { - legacy_value = - uloc_toLegacyType(keywordName_nul.data(), keywordValue_nul.data()); + std::string_view value; - if (legacy_value == nullptr) { + if (!keywordValue.empty()) { + std::optional<std::string_view> legacy_value = + ulocimp_toLegacyTypeWithFallback(keywordName, keywordValue); + if (!legacy_value.has_value()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } + value = *legacy_value; } - setKeywordValue(legacy_key, legacy_value, status); + setKeywordValue(*legacy_key, value, status); } const char * diff --git a/thirdparty/icu4c/common/loclikely.cpp b/thirdparty/icu4c/common/loclikely.cpp index 5aa929dc4b..ccbcbfa7a5 100644 --- a/thirdparty/icu4c/common/loclikely.cpp +++ b/thirdparty/icu4c/common/loclikely.cpp @@ -19,6 +19,7 @@ * that then do not depend on resource bundle code and likely-subtags data. */ +#include <string_view> #include <utility> #include "unicode/bytestream.h" @@ -170,7 +171,7 @@ _uloc_addLikelySubtags(const char* localeID, return; } - int32_t trailingLength = (int32_t)uprv_strlen(trailing); + int32_t trailingLength = static_cast<int32_t>(uprv_strlen(trailing)); const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err); if (U_FAILURE(err)) { @@ -193,11 +194,11 @@ _uloc_addLikelySubtags(const char* localeID, } createTagStringWithAlternates( language, - (int32_t)uprv_strlen(language), + static_cast<int32_t>(uprv_strlen(language)), lsr.script, - (int32_t)uprv_strlen(lsr.script), + static_cast<int32_t>(uprv_strlen(lsr.script)), lsr.region, - (int32_t)uprv_strlen(lsr.region), + static_cast<int32_t>(uprv_strlen(lsr.region)), variant.data(), variant.length(), trailing, @@ -235,7 +236,7 @@ _uloc_minimizeSubtags(const char* localeID, return; } - int32_t trailingLength = (int32_t)uprv_strlen(trailing); + int32_t trailingLength = static_cast<int32_t>(uprv_strlen(trailing)); const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err); if (U_FAILURE(err)) { @@ -256,11 +257,11 @@ _uloc_minimizeSubtags(const char* localeID, } createTagStringWithAlternates( language, - (int32_t)uprv_strlen(language), + static_cast<int32_t>(uprv_strlen(language)), lsr.script, - (int32_t)uprv_strlen(lsr.script), + static_cast<int32_t>(uprv_strlen(lsr.script)), lsr.region, - (int32_t)uprv_strlen(lsr.region), + static_cast<int32_t>(uprv_strlen(lsr.region)), variant.data(), variant.length(), trailing, @@ -388,21 +389,32 @@ U_NAMESPACE_END namespace { icu::CharString -GetRegionFromKey(const char* localeID, const char* key, UErrorCode& status) { +GetRegionFromKey(const char* localeID, std::string_view key, UErrorCode& status) { icu::CharString result; - // First check for keyword value icu::CharString kw = ulocimp_getKeywordValue(localeID, key, status); int32_t len = kw.length(); - if (U_SUCCESS(status) && len >= 3 && len <= 7) { - // chop off the subdivision code (which will generally be "zzzz" anyway) - const char* const data = kw.data(); - if (uprv_isASCIILetter(data[0])) { - result.append(uprv_toupper(data[0]), status); - result.append(uprv_toupper(data[1]), status); - } else { - // assume three-digit region code - result.append(data, 3, status); + // In UTS35 + // type = alphanum{3,8} (sep alphanum{3,8})* ; + // so we know the subdivision must fit the type already. + // + // unicode_subdivision_id = unicode_region_subtag unicode_subdivision_suffix ; + // unicode_region_subtag = (alpha{2} | digit{3}) ; + // unicode_subdivision_suffix = alphanum{1,4} ; + // But we also know there are no id in start with digit{3} in + // https://github.com/unicode-org/cldr/blob/main/common/validity/subdivision.xml + // Therefore we can simplify as + // unicode_subdivision_id = alpha{2} alphanum{1,4} + // + // and only need to accept/reject the code based on the alpha{2} and the length. + if (U_SUCCESS(status) && len >= 3 && len <= 6 && + uprv_isASCIILetter(kw[0]) && uprv_isASCIILetter(kw[1])) { + // Additional Check + static icu::RegionValidateMap valid; + const char region[] = {kw[0], kw[1], '\0'}; + if (valid.isSet(region)) { + result.append(uprv_toupper(kw[0]), status); + result.append(uprv_toupper(kw[1]), status); } } return result; @@ -435,3 +447,55 @@ ulocimp_getRegionForSupplementalData(const char *localeID, bool inferRegion, return rgBuf; } + +namespace { + +// The following data is generated by unit test code inside +// test/intltest/regiontst.cpp from the resource data while +// the test failed. +const uint32_t gValidRegionMap[] = { + 0xeedf597c, 0xdeddbdef, 0x15943f3f, 0x0e00d580, + 0xb0095c00, 0x0015fb9f, 0x781c068d, 0x0340400f, + 0xf42b1d00, 0xfd4f8141, 0x25d7fffc, 0x0100084b, + 0x538f3c40, 0x40000001, 0xfdf15100, 0x9fbb7ae7, + 0x0410419a, 0x00408557, 0x00004002, 0x00100001, + 0x00400408, 0x00000001, +}; + +} // namespace + // +U_NAMESPACE_BEGIN +RegionValidateMap::RegionValidateMap() { + uprv_memcpy(map, gValidRegionMap, sizeof(map)); +} + +RegionValidateMap::~RegionValidateMap() { +} + +bool RegionValidateMap::isSet(const char* region) const { + int32_t index = value(region); + if (index < 0) { + return false; + } + return 0 != (map[index / 32] & (1L << (index % 32))); +} + +bool RegionValidateMap::equals(const RegionValidateMap& that) const { + return uprv_memcmp(map, that.map, sizeof(map)) == 0; +} + +// The code transform two letter a-z to a integer valued between -1, 26x26. +// -1 indicate the region is outside the range of two letter a-z +// the rest of value is between 0 and 676 (= 26x26) and used as an index +// the the bigmap in map. The map is an array of 22 int32_t. +// since 32x21 < 676/32 < 32x22 we store this 676 bits bitmap into 22 int32_t. +int32_t RegionValidateMap::value(const char* region) const { + if (uprv_isASCIILetter(region[0]) && uprv_isASCIILetter(region[1]) && + region[2] == '\0') { + return (uprv_toupper(region[0])-'A') * 26 + + (uprv_toupper(region[1])-'A'); + } + return -1; +} + +U_NAMESPACE_END diff --git a/thirdparty/icu4c/common/loclikelysubtags.cpp b/thirdparty/icu4c/common/loclikelysubtags.cpp index c182191057..7c6131197d 100644 --- a/thirdparty/icu4c/common/loclikelysubtags.cpp +++ b/thirdparty/icu4c/common/loclikelysubtags.cpp @@ -564,47 +564,40 @@ LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, co // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. // They should match only themselves, // not other locales with what looks like the same language and script subtags. - char c1; - if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) { - switch (c1) { - case 'A': - if (returnInputIfUnmatch) { - return LSR(language, script, region, LSR::EXPLICIT_LSR); - } - return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, - LSR::EXPLICIT_LSR, errorCode); - case 'B': - if (returnInputIfUnmatch) { - return LSR(language, script, region, LSR::EXPLICIT_LSR); - } - return LSR(PSEUDO_BIDI_PREFIX, language, script, region, - LSR::EXPLICIT_LSR, errorCode); - case 'C': - if (returnInputIfUnmatch) { - return LSR(language, script, region, LSR::EXPLICIT_LSR); + if (!returnInputIfUnmatch) { + char c1; + if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) { + switch (c1) { + case 'A': + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); + case 'B': + return LSR(PSEUDO_BIDI_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); + case 'C': + return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); + default: // normal locale + break; } - return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, - LSR::EXPLICIT_LSR, errorCode); - default: // normal locale - break; } - } - if (variant[0] == 'P' && variant[1] == 'S') { - int32_t lsrFlags = *region == 0 ? - LSR::EXPLICIT_LANGUAGE | LSR::EXPLICIT_SCRIPT : LSR::EXPLICIT_LSR; - if (uprv_strcmp(variant, "PSACCENT") == 0) { - return LSR(PSEUDO_ACCENTS_PREFIX, language, script, - *region == 0 ? "XA" : region, lsrFlags, errorCode); - } else if (uprv_strcmp(variant, "PSBIDI") == 0) { - return LSR(PSEUDO_BIDI_PREFIX, language, script, - *region == 0 ? "XB" : region, lsrFlags, errorCode); - } else if (uprv_strcmp(variant, "PSCRACK") == 0) { - return LSR(PSEUDO_CRACKED_PREFIX, language, script, - *region == 0 ? "XC" : region, lsrFlags, errorCode); + if (variant[0] == 'P' && variant[1] == 'S') { + int32_t lsrFlags = *region == 0 ? + LSR::EXPLICIT_LANGUAGE | LSR::EXPLICIT_SCRIPT : LSR::EXPLICIT_LSR; + if (uprv_strcmp(variant, "PSACCENT") == 0) { + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, + *region == 0 ? "XA" : region, lsrFlags, errorCode); + } else if (uprv_strcmp(variant, "PSBIDI") == 0) { + return LSR(PSEUDO_BIDI_PREFIX, language, script, + *region == 0 ? "XB" : region, lsrFlags, errorCode); + } else if (uprv_strcmp(variant, "PSCRACK") == 0) { + return LSR(PSEUDO_CRACKED_PREFIX, language, script, + *region == 0 ? "XC" : region, lsrFlags, errorCode); + } + // else normal locale } - // else normal locale - } + } // end of if (!returnInputIfUnmatch) language = getCanonical(languageAliases, language); // (We have no script mappings.) @@ -616,9 +609,9 @@ LSR LikelySubtags::maximize(const char *language, const char *script, const char bool returnInputIfUnmatch, UErrorCode &errorCode) const { if (U_FAILURE(errorCode)) { return {}; } - return maximize({language, (int32_t)uprv_strlen(language)}, - {script, (int32_t)uprv_strlen(script)}, - {region, (int32_t)uprv_strlen(region)}, + return maximize({language, static_cast<int32_t>(uprv_strlen(language))}, + {script, static_cast<int32_t>(uprv_strlen(script))}, + {region, static_cast<int32_t>(uprv_strlen(region))}, returnInputIfUnmatch, errorCode); } diff --git a/thirdparty/icu4c/common/locmap.cpp b/thirdparty/icu4c/common/locmap.cpp index b95eb04428..da78c7716a 100644 --- a/thirdparty/icu4c/common/locmap.cpp +++ b/thirdparty/icu4c/common/locmap.cpp @@ -979,7 +979,7 @@ getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status) if (U_FAILURE(status)) { return locmap_root->hostID; } int32_t bestIdx = 0; int32_t bestIdxDiff = 0; - int32_t posixIDlen = (int32_t)uprv_strlen(posixID); + int32_t posixIDlen = static_cast<int32_t>(uprv_strlen(posixID)); uint32_t idx; for (idx = 0; idx < this_0->numRegions; idx++ ) { diff --git a/thirdparty/icu4c/common/locutil.cpp b/thirdparty/icu4c/common/locutil.cpp index 1abecef1c5..a257ec593a 100644 --- a/thirdparty/icu4c/common/locutil.cpp +++ b/thirdparty/icu4c/common/locutil.cpp @@ -171,7 +171,7 @@ LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result) prev = 0; UErrorCode status = U_ZERO_ERROR; do { - i = id.indexOf((char16_t)0x40, prev); + i = id.indexOf(static_cast<char16_t>(0x40), prev); if(i < 0) { // no @ between prev and the rest of the string buffer.appendInvariantChars(id.tempSubString(prev), status); @@ -224,7 +224,7 @@ LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID) Hashtable* htp; umtx_lock(nullptr); - htp = (Hashtable*) cache->get(bundleID); + htp = static_cast<Hashtable*>(cache->get(bundleID)); umtx_unlock(nullptr); if (htp == nullptr) { diff --git a/thirdparty/icu4c/common/lstmbe.cpp b/thirdparty/icu4c/common/lstmbe.cpp index fb8eb01761..c1a142469c 100644 --- a/thirdparty/icu4c/common/lstmbe.cpp +++ b/thirdparty/icu4c/common/lstmbe.cpp @@ -164,7 +164,7 @@ public: Array1D() : memory_(nullptr), data_(nullptr), d1_(0) {} Array1D(int32_t d1, UErrorCode &status) : memory_(uprv_malloc(d1 * sizeof(float))), - data_((float*)memory_), d1_(d1) { + data_(static_cast<float*>(memory_)), d1_(d1) { if (U_SUCCESS(status)) { if (memory_ == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; @@ -301,7 +301,7 @@ public: Array2D() : memory_(nullptr), data_(nullptr), d1_(0), d2_(0) {} Array2D(int32_t d1, int32_t d2, UErrorCode &status) : memory_(uprv_malloc(d1 * d2 * sizeof(float))), - data_((float*)memory_), d1_(d1), d2_(d2) { + data_(static_cast<float*>(memory_)), d1_(d1), d2_(d2) { if (U_SUCCESS(status)) { if (memory_ == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; @@ -526,11 +526,11 @@ void CodePointsVectorizer::vectorize( int32_t current; char16_t str[2] = {0, 0}; while (U_SUCCESS(status) && - (current = (int32_t)utext_getNativeIndex(text)) < endPos) { + (current = static_cast<int32_t>(utext_getNativeIndex(text))) < endPos) { // Since the LSTMBreakEngine is currently only accept chars in BMP, // we can ignore the possibility of hitting supplementary code // point. - str[0] = (char16_t) utext_next32(text); + str[0] = static_cast<char16_t>(utext_next32(text)); U_ASSERT(!U_IS_SURROGATE(str[0])); offsets.addElement(current, status); indices.addElement(stringToIndex(str), status); @@ -733,7 +733,7 @@ LSTMBreakEngine::divideUpDictionaryRange( UText *text, #endif // LSTM_DEBUG // current = argmax(logp) - LSTMClass current = (LSTMClass)logp.maxIndex(); + LSTMClass current = static_cast<LSTMClass>(logp.maxIndex()); // BIES logic. if (current == BEGIN || current == SINGLE) { if (i != 0) { diff --git a/thirdparty/icu4c/common/messagepattern.cpp b/thirdparty/icu4c/common/messagepattern.cpp index 9e318295f9..96555ce8ae 100644 --- a/thirdparty/icu4c/common/messagepattern.cpp +++ b/thirdparty/icu4c/common/messagepattern.cpp @@ -351,7 +351,7 @@ MessagePattern::autoQuoteApostropheDeep() const { for(int32_t i=count; i>0;) { const Part &part=getPart(--i); if(part.getType()==UMSGPAT_PART_TYPE_INSERT_CHAR) { - modified.insert(part.index, (char16_t)part.value); + modified.insert(part.index, static_cast<char16_t>(part.value)); } } return modified; @@ -437,7 +437,7 @@ MessagePattern::parseMessage(int32_t index, int32_t msgStartLength, if(U_FAILURE(errorCode)) { return 0; } - if(nestingLevel>Part::MAX_VALUE) { + if(nestingLevel>Part::MAX_NESTED_LEVELS) { errorCode=U_INDEX_OUTOFBOUNDS_ERROR; return 0; } @@ -628,7 +628,7 @@ MessagePattern::parseArg(int32_t index, int32_t argStartLength, int32_t nestingL } } // change the ARG_START type from NONE to argType - partsList->a[argStart].value=(int16_t)argType; + partsList->a[argStart].value = static_cast<int16_t>(argType); if(argType==UMSGPAT_ARG_TYPE_SIMPLE) { addPart(UMSGPAT_PART_TYPE_ARG_TYPE, typeIndex, length, 0, errorCode); } @@ -980,13 +980,13 @@ MessagePattern::parseDouble(int32_t start, int32_t limit, UBool allowInfinity, } // Let Double.parseDouble() throw a NumberFormatException. char numberChars[128]; - int32_t capacity=(int32_t)sizeof(numberChars); + int32_t capacity = static_cast<int32_t>(sizeof(numberChars)); int32_t length=limit-start; if(length>=capacity) { break; // number too long } msg.extract(start, length, numberChars, capacity, US_INV); - if((int32_t)uprv_strlen(numberChars)<length) { + if (static_cast<int32_t>(uprv_strlen(numberChars)) < length) { break; // contains non-invariant character that was turned into NUL } char *end; @@ -1006,7 +1006,7 @@ MessagePattern::skipWhiteSpace(int32_t index) { const char16_t *s=msg.getBuffer(); int32_t msgLength=msg.length(); const char16_t *t=PatternProps::skipWhiteSpace(s+index, msgLength-index); - return (int32_t)(t-s); + return static_cast<int32_t>(t - s); } int32_t @@ -1014,7 +1014,7 @@ MessagePattern::skipIdentifier(int32_t index) { const char16_t *s=msg.getBuffer(); int32_t msgLength=msg.length(); const char16_t *t=PatternProps::skipIdentifier(s+index, msgLength-index); - return (int32_t)(t-s); + return static_cast<int32_t>(t - s); } int32_t @@ -1105,8 +1105,8 @@ MessagePattern::addPart(UMessagePatternPartType type, int32_t index, int32_t len Part &part=partsList->a[partsLength++]; part.type=type; part.index=index; - part.length=(uint16_t)length; - part.value=(int16_t)value; + part.length = static_cast<uint16_t>(length); + part.value = static_cast<int16_t>(value); part.limitPartIndex=0; } } diff --git a/thirdparty/icu4c/common/mlbe.cpp b/thirdparty/icu4c/common/mlbe.cpp index 7e734f2c8a..b5385428e0 100644 --- a/thirdparty/icu4c/common/mlbe.cpp +++ b/thirdparty/icu4c/common/mlbe.cpp @@ -57,12 +57,12 @@ int32_t MlBreakEngine::divideUpRange(UText *inText, int32_t rangeStart, int32_t // moving forward, finally the last six values in the indexList are // [length-4, length-3, length-2, length-1, -1, -1]. The "+4" here means four extra "-1". int32_t indexSize = codePointLength + 4; - int32_t *indexList = (int32_t *)uprv_malloc(indexSize * sizeof(int32_t)); - if (indexList == nullptr) { + LocalMemory<int32_t> indexList(static_cast<int32_t*>(uprv_malloc(indexSize * sizeof(int32_t)))); + if (indexList.isNull()) { status = U_MEMORY_ALLOCATION_ERROR; return 0; } - int32_t numCodeUnits = initIndexList(inString, indexList, status); + int32_t numCodeUnits = initIndexList(inString, indexList.getAlias(), status); // Add a break for the start. boundary.addElement(0, status); @@ -71,13 +71,12 @@ int32_t MlBreakEngine::divideUpRange(UText *inText, int32_t rangeStart, int32_t for (int32_t idx = 0; idx + 1 < codePointLength && U_SUCCESS(status); idx++) { numBreaks = - evaluateBreakpoint(inString, indexList, idx, numCodeUnits, numBreaks, boundary, status); + evaluateBreakpoint(inString, indexList.getAlias(), idx, numCodeUnits, numBreaks, boundary, status); if (idx + 4 < codePointLength) { indexList[idx + 6] = numCodeUnits; numCodeUnits += U16_LENGTH(inString.char32At(indexList[idx + 6])); } } - uprv_free(indexList); if (U_FAILURE(status)) return 0; diff --git a/thirdparty/icu4c/common/norm2_nfc_data.h b/thirdparty/icu4c/common/norm2_nfc_data.h index 3dada06c57..89d0287c54 100644 --- a/thirdparty/icu4c/common/norm2_nfc_data.h +++ b/thirdparty/icu4c/common/norm2_nfc_data.h @@ -9,28 +9,28 @@ #ifdef INCLUDED_FROM_NORMALIZER2_CPP -static const UVersionInfo norm2_nfc_data_formatVersion={4,0,0,0}; -static const UVersionInfo norm2_nfc_data_dataVersion={0xf,1,0,0}; +static const UVersionInfo norm2_nfc_data_formatVersion={5,0,0,0}; +static const UVersionInfo norm2_nfc_data_dataVersion={0x10,0,0,0}; static const int32_t norm2_nfc_data_indexes[Normalizer2Impl::IX_COUNT]={ -0x50,0x4cb8,0x8920,0x8a20,0x8a20,0x8a20,0x8a20,0x8a20,0xc0,0x300,0xae2,0x29e0,0x3c66,0xfc00,0x1288,0x3b9c, -0x3c34,0x3c66,0x300,0 +0x58,0x4e84,0x8c60,0x8d60,0x8d60,0x8d60,0x8d60,0x8d60,0xc0,0x300,0xb0c,0x2a6a,0x3cf0,0xfbc4,0x12c2,0x3c26, +0x3cbe,0x3cf0,0x300,0,0xfb10,0xfb9e }; -static const uint16_t norm2_nfc_data_trieIndex[1788]={ +static const uint16_t norm2_nfc_data_trieIndex[1869]={ 0,0x40,0x7b,0xbb,0xfb,0x13a,0x17a,0x1b2,0x1f2,0x226,0x254,0x226,0x294,0x2d4,0x313,0x353, 0x393,0x3d2,0x40f,0x44e,0x226,0x226,0x488,0x4c8,0x4f8,0x530,0x226,0x570,0x59f,0x5de,0x226,0x5f3, -0x631,0x65f,0x687,0x6bd,0x6fd,0x73a,0x75a,0x799,0x7d8,0x815,0x834,0x871,0x75a,0x8aa,0x8d8,0x917, -0x834,0x951,0x968,0x9a8,0x9bf,0x9fe,0x226,0xa34,0xa54,0xa8f,0xa9b,0xad6,0xafe,0xb3b,0xb7b,0xbb5, -0xbd0,0x226,0xc0b,0x226,0xc4b,0xc6a,0xca0,0xcdd,0x226,0x226,0x226,0x226,0x226,0xd00,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xd2c,0x226,0x226,0xd61, -0x226,0x226,0xd7f,0x226,0xda9,0x226,0x226,0x226,0xde5,0xe05,0xe45,0xe84,0xebf,0xeff,0xf33,0xf5f, -0x839,0x226,0x226,0xf93,0x226,0x226,0x226,0xfd3,0x1013,0x1053,0x1093,0x10d3,0x1113,0x1153,0x1193,0x11d3, -0x1213,0x226,0x226,0x1243,0x1274,0x226,0x12a4,0x12d7,0x1314,0x1353,0x1393,0x13c9,0x13f7,0x226,0x226,0x226, +0x631,0x65f,0x688,0x6be,0x6fe,0x73b,0x75b,0x79a,0x7d9,0x816,0x835,0x872,0x75b,0x8ab,0x8d9,0x918, +0x835,0x952,0x969,0x9a9,0x9c0,0x9ff,0x226,0xa35,0xa55,0xa90,0xa9c,0xad7,0xaff,0xb3c,0xb7c,0xbb6, +0xbd1,0x226,0xc0c,0x226,0xc4c,0xc6b,0xca1,0xcde,0x226,0x226,0x226,0x226,0x226,0xd01,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xd2d,0x226,0x226,0xd62, +0x226,0x226,0xd80,0x226,0xdaa,0x226,0x226,0x226,0xde6,0xe06,0xe46,0xe85,0xec0,0xf00,0xf34,0xf60, +0x83a,0x226,0x226,0xf94,0x226,0x226,0x226,0xfd4,0x1014,0x1054,0x1094,0x10d4,0x1114,0x1154,0x1194,0x11d4, +0x1214,0x226,0x226,0x1244,0x1275,0x226,0x12a5,0x12d8,0x1315,0x1354,0x1394,0x13ca,0x13f8,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1422,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0xcee,0x226,0x143f,0x226,0x147f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x14bf,0x14f9,0x1537,0x1577,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1423,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0xcef,0x226,0x1440,0x226,0x1480,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x14c0,0x14fa,0x1538,0x1578,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, @@ -59,20 +59,20 @@ static const uint16_t norm2_nfc_data_trieIndex[1788]={ 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x15b6,0x15f4,0x1614,0x226,0x226,0x226,0x226, -0x164e,0x226,0x226,0x1676,0x16a8,0x16d6,0x83d,0x16e9,0x226,0x226,0x16f9,0x1739,0x226,0x226,0x226,0x1451, -0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781, -0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791, -0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785, -0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779, -0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789, -0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d, -0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d, -0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781, -0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791, -0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785, -0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x178d,0x1779,0x1781,0x1789,0x1791,0x177d,0x1785,0x17c5,0x226, -0x1805,0x1840,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x15b7,0x15f5,0x1615,0x226,0x226,0x226,0x226, +0x164f,0x226,0x226,0x1677,0x16a9,0x16d7,0x83e,0x16ea,0x226,0x226,0x16fa,0x173a,0x226,0x226,0x226,0x1452, +0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782, +0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792, +0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786, +0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a, +0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a, +0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e, +0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e, +0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782, +0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792, +0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786, +0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x178e,0x177a,0x1782,0x178a,0x1792,0x177e,0x1786,0x17c6,0x226, +0x1806,0x1841,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, @@ -80,59 +80,64 @@ static const uint16_t norm2_nfc_data_trieIndex[1788]={ 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x1880,0x18c0,0x1900,0x1940,0x1980,0x19c0,0x1a00,0x1a40,0x1a63,0x1aa3,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ac3,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x67e,0x68e,0x6a6,0x6c5,0x6da,0x6da,0x6da,0x6de,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x1881,0x18c1,0x1901,0x1941,0x1981,0x19c1,0x1a01,0x1a41,0x1a64,0x1aa4,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ac4,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x6cf,0x6df,0x6f7,0x716,0x72b,0x72b,0x72b,0x72f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xc0b,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xc0c,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x54f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x40c, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1af6,0x226,0x226,0x1b06,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0xdf7,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1b16,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1607,0x226,0x226,0x226,0x226,0x66b,0x226,0x226,0x226, -0x226,0x1b20,0x54f,0x226,0x226,0x1b30,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x81c,0x226,0x226, -0x1b40,0x226,0x1b50,0x1b5d,0x1b69,0x226,0x226,0x226,0x226,0x414,0x226,0x1b74,0x1b84,0x226,0x226,0x226, -0x811,0x226,0x226,0x226,0x226,0x1b94,0x226,0x226,0x226,0x1b9f,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x1ba6,0x226,0x226,0x226,0x226,0x1bb1,0x1bc0,0x927,0x1bce,0x412,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x1bdc,0x7c9,0x226,0x226,0x226,0x226,0x226,0x1bec,0x1bfb,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x907,0x1c03,0x1c13,0x226, -0x226,0x226,0x9eb,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c1d,0x226,0x226,0x226,0x226,0x226, -0x226,0x817,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c1a, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c2d, -0x811,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x87e,0x226,0x226,0x226,0x81e,0x81b, -0x226,0x226,0x226,0x226,0x819,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x9eb,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xc05,0x226,0x226,0x226, -0x226,0x81b,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0xc08,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x1c3d,0x226,0x226,0x226,0xf2c,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c4d,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x1c4f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c5e,0x1c6e,0x1c7c,0x1c89,0x226, -0x1c95,0x1ca3,0x1cb3,0x226,0x226,0x226,0x226,0xd1b,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1afb,0x1b09,0x1b15,0x226, +0x1b1a,0x226,0x226,0x1b2a,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xdf8,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x1cc3,0x1ccb,0x1cd9,0x226,0x226,0x226,0x226,0x226,0x4f9,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0xf2c,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x7c9,0x226,0x226,0x226,0x4fc,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ce4,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1cf4,0x226,0x226,0x226,0x226, -0x226,0x226,0x1d00,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1d10,0x1d20, -0x1d30,0x1d40,0x1d50,0x1d60,0x1d70,0x1d80,0x1d90,0x1da0,0x1db0,0x1dc0,0x1dd0,0x1de0,0x1df0,0x1e00,0x1e10,0x1e20, -0x1e30,0x1e40,0x1e50,0x1e60,0x1e70,0x1e80,0x1e90,0x1ea0,0x1eb0,0x1ec0,0x1ed0,0x1ee0,0x1ef0,0x1f00,0x1f10,0x1f20, +0x226,0x1b3a,0x226,0x226,0x226,0x1b42,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x1608,0x226,0x226,0x226,0x226,0x66b,0x226,0x226,0x226,0x226,0x1b50,0x54f,0x226,0x226,0x1b60,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x81d,0x226,0x226,0x1b70,0x226,0x1b80,0x1b8d,0x1b99,0x226,0x226, +0x226,0x226,0x414,0x226,0x1ba4,0x1bb4,0x226,0x226,0x226,0x812,0x226,0x226,0x226,0x226,0x1bc4,0x226, +0x226,0x226,0x1bcf,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bd6,0x226,0x226, +0x226,0x226,0x1be1,0x1bf0,0x928,0x1bfe,0x412,0x1c0c,0x1c1c,0x226,0x1c24,0x1c32,0x87f,0x226,0x226,0x226, +0x226,0x1c42,0x7ca,0x226,0x226,0x226,0x226,0x226,0x1c52,0x1c61,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x908,0x1c69,0x1c79,0x226,0x226,0x226,0x9ec,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x1c83,0x226,0x226,0x226,0x226,0x226,0x226,0x818,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c80,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c93,0x812,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x87f,0x226,0x226,0x226,0x81f,0x81c,0x226,0x226,0x226,0x226,0x81a, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x408,0x428, -0xc4,0xc4,0xc4,0x448,0x457,0x46d,0x489,0x4a6,0x4c2,0x4df,0x4fc,0x51b,0x538,0x552,0xc4,0xc4, -0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, -0xc4,0xc4,0xc4,0x567,0xc4,0x57b,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0x226,0x226,0x226,0x226,0x226,0x226,0x9ec,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xc06,0x226,0x226,0x226,0x226,0x81c,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0xc09,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x1ca2,0x1cb1,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x1cc1,0x226,0x226,0x226,0xf2d,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1cce, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1cde, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ce0,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x1cef,0x1cff,0x1d0d,0x1d1a,0x226,0x1d26,0x1d34,0x1d44,0x226,0x226,0x226,0x226,0xd1c,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1d54,0x1d5c,0x1d6a,0x226,0x226,0x226,0x226,0x226, +0x4f9,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xf2d,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x7ca,0x226,0x226,0x226,0x4fc,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1d75,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x5c1,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1d85,0x226,0x226,0x226, +0x226,0x226,0x226,0x1d91,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1da1, +0x1db1,0x1dc1,0x1dd1,0x1de1,0x1df1,0x1e01,0x1e11,0x1e21,0x1e31,0x1e41,0x1e51,0x1e61,0x1e71,0x1e81,0x1e91,0x1ea1, +0x1eb1,0x1ec1,0x1ed1,0x1ee1,0x1ef1,0x1f01,0x1f11,0x1f21,0x1f31,0x1f41,0x1f51,0x1f61,0x1f71,0x1f81,0x1f91,0x1fa1, +0x1fb1,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x408, +0x428,0x440,0xc4,0xc4,0x460,0x46f,0x486,0x4a2,0x4bf,0x4dd,0x4fa,0x517,0x536,0x553,0x56d,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x582, +0xc4,0xc4,0xc4,0xc4,0x595,0x5a9,0x5c0,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, 0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, -0xc4,0xc4,0xc4,0xc4,0x59b,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x5a6,0x5c3,0xc4, -0xc4,0xc4,0xc4,0xc4,0xc4,0x5e3,0x5f9,0x60b,0xc4,0x61e,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0x5e0,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x5eb,0x608, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x628,0x63e,0x650,0xc4,0x66f,0xc4,0xc4,0xc4,0xc4,0xc4, 0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, -0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x63e,0x65e +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x68f,0x6af }; -static const uint16_t norm2_nfc_data_trieData[7984]={ +static const uint16_t norm2_nfc_data_trieData[8129]={ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -144,30 +149,30 @@ static const uint16_t norm2_nfc_data_trieData[7984]={ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,0x5e8,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x128a,0x1290,0xae4,0x1296,0xafa, -0xb04,0x5f4,0xb0e,0x129c,0x12a2,0xb18,0x12a8,0x12ae,0x12b4,0x12ba,0xb2e,1,0x12c0,0x12c6,0x12cc,0xb38, -0xb4e,0xb60,1,0x5fc,0x12d2,0x12d8,0x12de,0xb6a,0x12e4,1,1,0x12ea,0x12f0,0xb80,0x12f6,0xb96, -0xba0,0x600,0xbaa,0x12fc,0x1302,0xbb4,0x1308,0x130e,0x1314,0x131a,0xbca,1,0x1320,0x1326,0x132c,0xbd4, -0xbea,0xbfc,1,0x608,0x1332,0x1338,0x133e,0xc06,0x1344,1,0x134a,0x1350,0x1356,0xc1c,0xc32,0x135d, -0x1363,0x1368,0x136e,0x1374,0x137a,0x1380,0x1386,0x138c,0x1392,0x1398,0x139e,1,1,0xc48,0xc56,0x13a4, -0x13aa,0x13b0,0x13b6,0x13bd,0x13c3,0x13c8,0x13ce,0x13d4,0x13da,0x13e0,0x13e6,0x13ec,0x13f2,0x13f9,0x13ff,0x1404, -0x140a,1,1,0x1410,0x1416,0x141c,0x1422,0x1428,0x142e,0x1435,0x143b,0x1440,1,1,1,0x1447, -0x144d,0x1453,0x1459,1,0x145e,0x1464,0x146b,0x1471,0x1476,0x147c,1,1,1,0x1482,0x1488,0x148f, -0x1495,0x149a,0x14a0,1,1,1,0xc64,0xc72,0x14a6,0x14ac,0x14b2,0x14b8,1,1,0x14be,0x14c4, -0x14cb,0x14d1,0x14d6,0x14dc,0xc80,0xc8a,0x14e2,0x14e8,0x14ef,0x14f5,0xc94,0xc9e,0x14fb,0x1501,0x1506,0x150c, -1,1,0xca8,0xcb2,0xcbc,0xcc6,0x1512,0x1518,0x151e,0x1524,0x152a,0x1530,0x1537,0x153d,0x1542,0x1548, -0x154e,0x1554,0x155a,0x1560,0x1566,0x156c,0x1572,0x1578,0x157e,0x60c,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xcd0,0xcea,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xd04,0xd1e,1,1,1,1,1, -1,0x610,1,1,1,1,1,1,1,1,1,1,1,1,1,0x1584, -0x158a,0x1590,0x1596,0x159c,0x15a2,0x15a8,0x15ae,0x15b6,0x15c0,0x15ca,0x15d4,0x15de,0x15e8,0x15f2,0x15fc,1, -0x1606,0x1610,0x161a,0x1624,0x162d,0x1633,1,1,0x1638,0x163e,0x1644,0x164a,0xd38,0xd42,0x1653,0x165d, -0x1665,0x166b,0x1671,1,1,1,0x1676,0x167c,1,1,0x1682,0x1688,0x1690,0x169a,0x16a3,0x16a9, -0x16af,0x16b5,0x16ba,0x16c0,0x16c6,0x16cc,0x16d2,0x16d8,0x16de,0x16e4,0x16ea,0x16f0,0x16f6,0x16fc,0x1702,0x1708, -0x170e,0x1714,0x171a,0x1720,0x1726,0x172c,0x1732,0x1738,0x173e,0x1744,0x174a,0x1750,0x1756,0x175c,1,1, -0x1762,0x1768,1,1,1,1,1,1,0xd4c,0xd56,0xd60,0xd6a,0x1770,0x177a,0x1784,0x178e, -0xd74,0xd7e,0x1798,0x17a2,0x17aa,0x17b0,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x12c4,0x12ca,0xb0e,0x12d0,0xb24, +0xb2e,0x5f4,0xb38,0x12d6,0x12dc,0xb42,0x12e2,0x12e8,0x12ee,0x12f4,0xb58,1,0x12fa,0x1300,0x1306,0xb62, +0xb78,0xb8a,1,0x5fc,0x130c,0x1312,0x1318,0xb94,0x131e,1,1,0x1324,0x132a,0xbaa,0x1330,0xbc0, +0xbca,0x600,0xbd4,0x1336,0x133c,0xbde,0x1342,0x1348,0x134e,0x1354,0xbf4,1,0x135a,0x1360,0x1366,0xbfe, +0xc14,0xc26,1,0x608,0x136c,0x1372,0x1378,0xc30,0x137e,1,0x1384,0x138a,0x1390,0xc46,0xc5c,0x1397, +0x139d,0x13a2,0x13a8,0x13ae,0x13b4,0x13ba,0x13c0,0x13c6,0x13cc,0x13d2,0x13d8,1,1,0xc72,0xc80,0x13de, +0x13e4,0x13ea,0x13f0,0x13f7,0x13fd,0x1402,0x1408,0x140e,0x1414,0x141a,0x1420,0x1426,0x142c,0x1433,0x1439,0x143e, +0x1444,1,1,0x144a,0x1450,0x1456,0x145c,0x1462,0x1468,0x146f,0x1475,0x147a,1,1,1,0x1481, +0x1487,0x148d,0x1493,1,0x1498,0x149e,0x14a5,0x14ab,0x14b0,0x14b6,1,1,1,0x14bc,0x14c2,0x14c9, +0x14cf,0x14d4,0x14da,1,1,1,0xc8e,0xc9c,0x14e0,0x14e6,0x14ec,0x14f2,1,1,0x14f8,0x14fe, +0x1505,0x150b,0x1510,0x1516,0xcaa,0xcb4,0x151c,0x1522,0x1529,0x152f,0xcbe,0xcc8,0x1535,0x153b,0x1540,0x1546, +1,1,0xcd2,0xcdc,0xce6,0xcf0,0x154c,0x1552,0x1558,0x155e,0x1564,0x156a,0x1571,0x1577,0x157c,0x1582, +0x1588,0x158e,0x1594,0x159a,0x15a0,0x15a6,0x15ac,0x15b2,0x15b8,0x60c,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0xcfa,0xd14,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xd2e,0xd48,1,1,1,1,1, +1,0x610,1,1,1,1,1,1,1,1,1,1,1,1,1,0x15be, +0x15c4,0x15ca,0x15d0,0x15d6,0x15dc,0x15e2,0x15e8,0x15f0,0x15fa,0x1604,0x160e,0x1618,0x1622,0x162c,0x1636,1, +0x1640,0x164a,0x1654,0x165e,0x1667,0x166d,1,1,0x1672,0x1678,0x167e,0x1684,0xd62,0xd6c,0x168d,0x1697, +0x169f,0x16a5,0x16ab,1,1,1,0x16b0,0x16b6,1,1,0x16bc,0x16c2,0x16ca,0x16d4,0x16dd,0x16e3, +0x16e9,0x16ef,0x16f4,0x16fa,0x1700,0x1706,0x170c,0x1712,0x1718,0x171e,0x1724,0x172a,0x1730,0x1736,0x173c,0x1742, +0x1748,0x174e,0x1754,0x175a,0x1760,0x1766,0x176c,0x1772,0x1778,0x177e,0x1784,0x178a,0x1790,0x1796,1,1, +0x179c,0x17a2,1,1,1,1,1,1,0xd76,0xd80,0xd8a,0xd94,0x17aa,0x17b4,0x17be,0x17c8, +0xd9e,0xda8,0x17d2,0x17dc,0x17e4,0x17ea,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -178,34 +183,34 @@ static const uint16_t norm2_nfc_data_trieData[7984]={ 0xfdcc,0xffcc,0xffcc,0xfdcc,0xffcc,0xfdcc,0xffcc,0xfdcc,0xfdcc,0xffd0,0xffb8,0xffb8,0xffb8,0xffb8,0xffd0,0xfdb0, 0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xff94,0xff94,0xfdb8,0xfdb8,0xfdb8,0xfdb8,0xfd94,0xfd94,0xffb8,0xffb8,0xffb8, 0xffb8,0xfdb8,0xfdb8,0xffb8,0xfdb8,0xfdb8,0xffb8,0xffb8,0xfe02,0xfe02,0xfe02,0xfe02,0xfc02,0xffb8,0xffb8,0xffb8, -0xffb8,0xffcc,0xffcc,0xffcc,0x3c36,0x3c3c,0xfdcc,0x3c42,0x3c48,0xfde0,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, +0xffb8,0xffcc,0xffcc,0xffcc,0x3cc0,0x3cc6,0xfdcc,0x3ccc,0x3cd2,0xfde0,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, 0xffcc,0xffb8,0xffb8,1,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffd0,0xffb8,0xffb8,0xffcc, 0xffd2,0xffd4,0xffd4,0xffd2,0xffd4,0xffd4,0xffd2,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,0x29e1,1,1,1,1,1,1,1, -1,1,0x29e5,1,1,1,1,1,0x17b7,0x17bd,0x29e9,0x17c3,0x17c9,0x17cf,1,0x17d5, -1,0x17db,0x17e1,0x17e9,0x618,1,1,1,0x634,1,0x644,1,0x658,1,1,1, -1,1,0x674,1,0x684,1,1,1,0x688,1,1,1,0x6a0,0x17f1,0x17f7,0xd88, -0x17fd,0xd92,0x1803,0x180b,0x6b4,1,1,1,0x6d4,1,0x6e4,1,0x6fc,1,1,1, -1,1,0x71c,1,0x72c,1,1,1,0x734,1,1,1,0x754,0xd9c,0xdae,0x1813, -0x1819,0xdc0,1,1,1,0x76c,0x181f,0x1825,1,1,1,1,1,1,1,1, +0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,0x2a6b,1,1,1,1,1,1,1, +1,1,0x2a6f,1,1,1,1,1,0x17f1,0x17f7,0x2a73,0x17fd,0x1803,0x1809,1,0x180f, +1,0x1815,0x181b,0x1823,0x618,1,1,1,0x634,1,0x644,1,0x658,1,1,1, +1,1,0x674,1,0x684,1,1,1,0x688,1,1,1,0x6a0,0x182b,0x1831,0xdb2, +0x1837,0xdbc,0x183d,0x1845,0x6b4,1,1,1,0x6d4,1,0x6e4,1,0x6fc,1,1,1, +1,1,0x71c,1,0x72c,1,1,1,0x734,1,1,1,0x754,0xdc6,0xdd8,0x184d, +0x1853,0xdea,1,1,1,0x76c,0x1859,0x185f,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0x182b,0x1831,1,0x1837,1,1,0x774,0x183d,1,1,1,1,0x1843, -0x1849,0x184f,1,0x778,1,1,0x780,1,0x784,0x790,0x798,0x79c,0x1855,0x7ac,1,1, +1,1,1,0x1865,0x186b,1,0x1871,1,1,0x774,0x1877,1,1,1,1,0x187d, +0x1883,0x1889,1,0x778,1,1,0x780,1,0x784,0x790,0x798,0x79c,0x188f,0x7ac,1,1, 1,0x7b0,1,1,1,1,0x7b4,1,1,1,0x7c4,1,1,1,0x7c8,1, -0x7cc,1,1,0x7d0,1,1,0x7d8,1,0x7dc,0x7e8,0x7f0,0x7f4,0x185b,0x804,1,1, +0x7cc,1,1,0x7d0,1,1,0x7d8,1,0x7dc,0x7e8,0x7f0,0x7f4,0x1895,0x804,1,1, 1,0x808,1,1,1,0x80c,1,1,1,0x81c,1,1,1,0x820,1,0x824, -1,1,0x1861,0x1867,1,0x186d,1,1,0x828,0x1873,1,1,1,1,0x1879,0x187f, -0x1885,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x82c,0x830,0x188b,0x1891,1,1,1,1,1,1, +1,1,0x189b,0x18a1,1,0x18a7,1,1,0x828,0x18ad,1,1,1,1,0x18b3,0x18b9, +0x18bf,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x82c,0x830,0x18c5,0x18cb,1,1,1,1,1,1, 1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x1897, -0x189d,1,1,1,1,1,1,1,1,1,1,1,1,1,0x18a3,0x18a9, -0x18af,0x18b5,1,1,0x18bb,0x18c1,0x834,0x838,0x18c7,0x18cd,0x18d3,0x18d9,0x18df,0x18e5,1,1, -0x18eb,0x18f1,0x18f7,0x18fd,0x1903,0x1909,0x83c,0x840,0x190f,0x1915,0x191b,0x1921,0x1927,0x192d,0x1933,0x1939, -0x193f,0x1945,0x194b,0x1951,1,1,0x1957,0x195d,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x18d1, +0x18d7,1,1,1,1,1,1,1,1,1,1,1,1,1,0x18dd,0x18e3, +0x18e9,0x18ef,1,1,0x18f5,0x18fb,0x834,0x838,0x1901,0x1907,0x190d,0x1913,0x1919,0x191f,1,1, +0x1925,0x192b,0x1931,0x1937,0x193d,0x1943,0x83c,0x840,0x1949,0x194f,0x1955,0x195b,0x1961,0x1967,0x196d,0x1973, +0x1979,0x197f,0x1985,0x198b,1,1,0x1991,0x1997,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc, 0xffcc,0xffcc,0xffbc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, 0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffbc,0xffc8,0xffcc,0xfe14,0xfe16,0xfe18,0xfe1a,0xfe1c,0xfe1e,0xfe20,0xfe22, @@ -214,14 +219,14 @@ static const uint16_t norm2_nfc_data_trieData[7984]={ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xfe3c,0xfe3e,0xfe40,1,1,1,1,1,1,1,0x1962,0x1968,0x196f,0x1975,0x197b,0x844, +0xfe3c,0xfe3e,0xfe40,1,1,1,1,1,1,1,0x199c,0x19a2,0x19a9,0x19af,0x19b5,0x844, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,0x850,1,0x854,0xfe36,0xfe38,0xfe3a,0xfe3c,0xfe3e, 0xfe40,0xfe42,0xfe44,0xfdcc,0xfdcc,0xfdb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0xfe46,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x1981,0x858,0x1987,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0x85c,0x198d,1,0x860,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc, +0x19bb,0x858,0x19c1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0x85c,0x19c7,1,0x860,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc, 0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,1,1,0xffcc,0xffcc,1,0xffb8,0xffcc,0xffcc,0xffb8,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0xfe48,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -239,405 +244,415 @@ static const uint16_t norm2_nfc_data_trieData[7984]={ 1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc, -0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1, +0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8, -0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1, -0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xfe36,0xfe38,0xfe3a, -0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1, +1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8, +0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +1,0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xfe36,0xfe38, +0xfe3a,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x864,0x1993,1,1,1,1,1,1,0x868,0x1999,1, -0x86c,0x199f,1,1,1,1,1,1,1,0xfc0e,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xfe12,1,1,1,0xffcc,0xffb8,0xffcc,0xffcc,1, -1,1,0x29ec,0x29f2,0x29f8,0x29fe,0x2a04,0x2a0a,0x2a10,0x2a16,1,1,1,1,1,1, +1,1,1,1,1,1,0x864,0x19cd,1,1,1,1,1,1,0x868,0x19d3, +1,0x86c,0x19d9,1,1,1,1,1,1,1,0xfc0e,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xfe12,1,1,1,0xffcc,0xffb8,0xffcc,0xffcc, +1,1,1,0x2a76,0x2a7c,0x2a82,0x2a88,0x2a8e,0x2a94,0x2a9a,0x2aa0,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xfe0e,1,0xfc00,1,1,1,1,1,1,1, -0x870,1,1,1,0x19a5,0x19ab,0xfe12,1,1,1,1,1,1,1,1,1, -0xfc00,1,1,1,1,0x2a1c,0x2a22,1,0x2a28,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0xfe0e,1,0xfc00,1,1,1,1,1,1, +1,0x870,1,1,1,0x19df,0x19e5,0xfe12,1,1,1,1,1,1,1,1, +1,0xfc00,1,1,1,1,0x2aa6,0x2aac,1,0x2ab2,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xffcc,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xffcc,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x2a2e,1,1,0x2a34,1, -1,1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,1,0x2a3a,0x2a40, -0x2a46,1,1,0x2a4c,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0x2ab8,1,1,0x2abe, +1,1,1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1, +1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,1,0x2ac4, +0x2aca,0x2ad0,1,1,0x2ad6,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1, +1,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0x878,0x19b1,1,1,0x19b7,0x19bd,0xfe12,1,1,1,1,1,1,1,1, -0xfc00,0xfc00,1,1,1,1,0x2a52,0x2a58,1,1,1,1,1,1,1,1, +1,1,0x878,0x19eb,1,1,0x19f1,0x19f7,0xfe12,1,1,1,1,1,1,1, +1,0xfc00,0xfc00,1,1,1,1,0x2adc,0x2ae2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0x884,1,0x19c3,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x884,1,0x19fd,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xfc00,1,1,1,1,1,1,0x888,0x890,1, -1,0x19c9,0x19cf,0x19d5,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00,1, +1,1,1,1,1,1,1,0xfc00,1,1,1,1,1,1,0x888,0x890, +1,1,0x1a03,0x1a09,0x1a0f,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x894,1,0x19db,1,1,1,1,0xfe12,1, -1,1,1,1,1,1,0xfea8,0xfcb6,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x894,1,0x1a15,1,1,1,1,0xfe12, +1,1,1,1,1,1,1,0xfea8,0xfcb6,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xfe0e,1,1,0x898,0x19e1,1,0xfc00,1,1,1,0x89c,0x19e7, -0x19ed,1,0xdca,0x19f5,1,0xfe12,1,1,1,1,1,1,1,0xfc00,0xfc00,1, +1,1,1,1,1,0xfe0e,1,1,0x898,0x1a1b,1,0xfc00,1,1,1,0x89c, +0x1a21,0x1a27,1,0xdf4,0x1a2f,1,0xfe12,1,1,1,1,1,1,1,0xfc00,0xfc00, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xfe12,0xfe12,1,0xfc00,1,1, -1,1,1,1,0x8a8,0x8b0,1,1,0x19fd,0x1a03,0x1a09,0xfe12,1,1,1,1, -1,1,1,1,1,0xfc00,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0xfe12,0xfe12,1,0xfc00,1, +1,1,1,1,1,0x8a8,0x8b0,1,1,0x1a37,0x1a3d,0x1a43,0xfe12,1,1,1, +1,1,1,1,1,1,0xfc00,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfc12,1, -1,1,1,0xfc00,1,1,1,1,1,1,1,1,1,0x8b4,0x1a0f,1, -0xdd4,0x1a17,0x1a1f,0xfc00,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfc12, +1,1,1,1,0xfc00,1,1,1,1,1,1,1,1,1,0x8b4,0x1a49, +1,0xdfe,0x1a51,0x1a59,0xfc00,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xfece,0xfece,0xfe12,1, -1,1,1,1,1,1,1,0xfed6,0xfed6,0xfed6,0xfed6,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0xfece,0xfece,0xfe12, +1,1,1,1,1,1,1,1,0xfed6,0xfed6,0xfed6,0xfed6,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xfeec,0xfeec,0xfe12,1,1,1,1,1,1,1,1,0xfef4,0xfef4, -0xfef4,0xfef4,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xfeec,0xfeec,0xfe12,1,1,1,1,1,1,1,1,0xfef4, +0xfef4,0xfef4,0xfef4,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xffb8,0xffb8,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0xffb8,0xffb8,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffb8,1,0xffb8,1,0xffb0,1,1,1,1,1,1,0x2a5f,1, -1,1,1,1,1,1,1,1,0x2a65,1,1,1,1,0x2a6b,1,1, -1,1,0x2a71,1,1,1,1,0x2a77,1,1,1,1,1,1,1,1, -1,1,1,1,0x2a7d,1,1,1,1,1,1,1,0xff02,0xff04,0x3c50,0xff08, -0x3c58,0x2a82,1,0x2a88,1,0xff04,0xff04,0xff04,0xff04,1,1,0xff04,0x3c60,0xffcc,0xffcc,0xfe12, -1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x2a8f,1, -1,1,1,1,1,1,1,1,0x2a95,1,1,1,1,0x2a9b,1,1, -1,1,0x2aa1,1,1,1,1,0x2aa7,1,1,1,1,1,1,1,1, -1,1,1,1,0x2aad,1,1,1,1,1,1,0xffb8,1,1,1,1, +1,1,1,1,0xffb8,1,0xffb8,1,0xffb0,1,1,1,1,1,1,0x2ae9, +1,1,1,1,1,1,1,1,1,0x2aef,1,1,1,1,0x2af5,1, +1,1,1,0x2afb,1,1,1,1,0x2b01,1,1,1,1,1,1,1, +1,1,1,1,1,0x2b07,1,1,1,1,1,1,1,0xff02,0xff04,0x3cda, +0xff08,0x3ce2,0x2b0c,1,0x2b12,1,0xff04,0xff04,0xff04,0xff04,1,1,0xff04,0x3cea,0xffcc,0xffcc, +0xfe12,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x2b19, +1,1,1,1,1,1,1,1,1,0x2b1f,1,1,1,1,0x2b25,1, +1,1,1,0x2b2b,1,1,1,1,0x2b31,1,1,1,1,1,1,1, +1,1,1,1,1,0x2b37,1,1,1,1,1,1,0xffb8,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x8c0,0x1a25,1,1,1,1,1,1,1,0xfc00,1, -1,1,1,1,1,1,1,0xfe0e,1,0xfe12,0xfe12,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffb8,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x8c0,0x1a5f,1,1,1,1,1,1,1,0xfc00, +1,1,1,1,1,1,1,1,0xfe0e,1,0xfe12,0xfe12,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xffb8,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, +1,1,1,1,1,1,1,1,1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00, 0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, +0xfe00,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, +1,1,1,1,1,1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, 0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, +0xfe00,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc, +0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc, +1,0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,0xffcc, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,0xffcc,1, +1,1,1,1,1,1,1,1,1,0xffc8,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffc8,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0xffbc,0xffcc,0xffb8,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffb8,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xffbc,0xffcc,0xffb8,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffb8,1,1, +1,1,1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,1,1,0xffb8,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,1,1,0xffb8,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, +0xffb8,0xffcc,0xffcc,0xffb8,1,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8, +0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, -0xffcc,0xffcc,0xffb8,1,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc, -0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0x8c4,0x1a65,0x8c8,0x1a6b,0x8cc,0x1a71,0x8d0,0x1a77,0x8d4,0x1a7d,1, +1,0x8d8,0x1a83,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xfe0e,0xfc00,1,1,1,1,0x8dc,0x1a89,0x8e0,0x1a8f,0x8e4,0x8e8, +0x1a95,0x1a9b,0x8ec,0x1aa1,0xfe12,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x8c4,0x1a2b,0x8c8,0x1a31,0x8cc,0x1a37,0x8d0,0x1a3d,0x8d4,0x1a43,1,1, -0x8d8,0x1a49,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xfe0e,0xfc00,1,1,1,1,0x8dc,0x1a4f,0x8e0,0x1a55,0x8e4,0x8e8,0x1a5b, -0x1a61,0x8ec,0x1a67,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,0xfe12, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,0xfe12,1, +1,1,1,1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1, +1,1,0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xffcc,0xffcc,0xffcc,1,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, +0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1, +1,0xffb8,1,1,1,1,1,1,0xffcc,1,1,1,0xffcc,0xffcc,1,1, +1,1,1,1,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc, +0xffcc,0xffd4,0xffac,0xffb8,0xff94,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffd0,0xffc8,0xffc8,0xffb8,0xffb4,0xffcc, +0xffd2,0xffb8,0xffcc,0xffb8,0x1aa6,0x1aac,0x1ab2,0x1ab8,0x1abf,0x1ac5,0x1acb,0x1ad1,0x1ad9,0x1ae3,0x1aea,0x1af0, +0x1af6,0x1afc,0x1b02,0x1b08,0x1b0f,0x1b15,0x1b1a,0x1b20,0x1b28,0x1b32,0x1b3c,0x1b46,0x1b4e,0x1b54,0x1b5a,0x1b60, +0x1b69,0x1b73,0x1b7b,0x1b81,0x1b86,0x1b8c,0x1b92,0x1b98,0x1b9e,0x1ba4,0x1baa,0x1bb0,0x1bb7,0x1bbd,0x1bc2,0x1bc8, +0x1bce,0x1bd4,0x1bdc,0x1be6,0x1bee,0x1bf4,0x1bfa,0x1c00,0x1c06,0x1c0c,0xe08,0xe12,0x1c14,0x1c1e,0x1c26,0x1c2c, +0x1c32,0x1c38,0x1c3e,0x1c44,0x1c4a,0x1c50,0x1c57,0x1c5d,0x1c62,0x1c68,0x1c6e,0x1c74,0x1c7a,0x1c80,0x1c86,0x1c8c, +0x1c94,0x1c9e,0x1ca8,0x1cb2,0x1cbc,0x1cc6,0x1cd0,0x1cda,0x1ce3,0x1ce9,0x1cef,0x1cf5,0x1cfa,0x1d00,0xe1c,0xe26, +0x1d08,0x1d12,0x1d1a,0x1d20,0x1d26,0x1d2c,0xe30,0xe3a,0x1d34,0x1d3e,0x1d48,0x1d52,0x1d5c,0x1d66,0x1d6e,0x1d74, +0x1d7a,0x1d80,0x1d86,0x1d8c,0x1d92,0x1d98,0x1d9e,0x1da4,0x1daa,0x1db0,0x1db6,0x1dbc,0x1dc4,0x1dce,0x1dd8,0x1de2, +0x1dea,0x1df0,0x1df7,0x1dfd,0x1e02,0x1e08,0x1e0e,0x1e14,0x1e1a,0x1e20,0x1e26,0x1e2c,0x1e33,0x1e39,0x1e3f,0x1e45, +0x1e4b,0x1e51,0x1e56,0x1e5c,0x1e62,0x1e68,0x1e6f,0x1e75,0x1e7b,0x1e81,0x1e86,0x1e8c,0x1e92,0x1e98,1,0x1e9f, +1,1,1,1,0xe44,0xe52,0x1ea4,0x1eaa,0x1eb2,0x1ebc,0x1ec6,0x1ed0,0x1eda,0x1ee4,0x1eee,0x1ef8, +0x1f02,0x1f0c,0x1f16,0x1f20,0x1f2a,0x1f34,0x1f3e,0x1f48,0x1f52,0x1f5c,0x1f66,0x1f70,0xe60,0xe6a,0x1f78,0x1f7e, +0x1f84,0x1f8a,0x1f92,0x1f9c,0x1fa6,0x1fb0,0x1fba,0x1fc4,0x1fce,0x1fd8,0x1fe2,0x1fec,0x1ff4,0x1ffa,0x2000,0x2006, +0xe74,0xe7e,0x200c,0x2012,0x201a,0x2024,0x202e,0x2038,0x2042,0x204c,0x2056,0x2060,0x206a,0x2074,0x207e,0x2088, +0x2092,0x209c,0x20a6,0x20b0,0x20ba,0x20c4,0x20ce,0x20d8,0x20e0,0x20e6,0x20ec,0x20f2,0x20fa,0x2104,0x210e,0x2118, +0x2122,0x212c,0x2136,0x2140,0x214a,0x2154,0x215c,0x2162,0x2169,0x216f,0x2174,0x217a,0x2180,0x2186,1,1, +1,1,1,1,0xe88,0xe9e,0xeb6,0xec4,0xed2,0xee0,0xeee,0xefc,0xf08,0xf1e,0xf36,0xf44, +0xf52,0xf60,0xf6e,0xf7c,0xf88,0xf96,0x218f,0x2199,0x21a3,0x21ad,1,1,0xfa4,0xfb2,0x21b7,0x21c1, +0x21cb,0x21d5,1,1,0xfc0,0xfd6,0xfee,0xffc,0x100a,0x1018,0x1026,0x1034,0x1040,0x1056,0x106e,0x107c, +0x108a,0x1098,0x10a6,0x10b4,0x10c0,0x10d2,0x21df,0x21e9,0x21f3,0x21fd,0x2207,0x2211,0x10e4,0x10f6,0x221b,0x2225, +0x222f,0x2239,0x2243,0x224d,0x1108,0x1116,0x2257,0x2261,0x226b,0x2275,1,1,0x1124,0x1132,0x227f,0x2289, +0x2293,0x229d,1,1,0x1140,0x1152,0x22a7,0x22b1,0x22bb,0x22c5,0x22cf,0x22d9,1,0x1164,1,0x22e3, +1,0x22ed,1,0x22f7,0x1176,0x118c,0x11a4,0x11b2,0x11c0,0x11ce,0x11dc,0x11ea,0x11f6,0x120c,0x1224,0x1232, +0x1240,0x124e,0x125c,0x126a,0x1276,0x3c28,0x22ff,0x3c30,0x1280,0x3c38,0x2305,0x3c40,0x230b,0x3c48,0x2311,0x3c50, +0x128a,0x3c58,1,1,0x2318,0x2322,0x2331,0x2341,0x2351,0x2361,0x2371,0x2381,0x238c,0x2396,0x23a5,0x23b5, +0x23c5,0x23d5,0x23e5,0x23f5,0x2400,0x240a,0x2419,0x2429,0x2439,0x2449,0x2459,0x2469,0x2474,0x247e,0x248d,0x249d, +0x24ad,0x24bd,0x24cd,0x24dd,0x24e8,0x24f2,0x2501,0x2511,0x2521,0x2531,0x2541,0x2551,0x255c,0x2566,0x2575,0x2585, +0x2595,0x25a5,0x25b5,0x25c5,0x25cf,0x25d5,0x25dd,0x25e4,0x25ed,1,0x1294,0x25f7,0x25ff,0x2605,0x260b,0x3c60, +0x2610,1,0x2b3c,0x8f0,1,0x2617,0x261f,0x2626,0x262f,1,0x129e,0x2639,0x2641,0x3c68,0x2647,0x3c70, +0x264c,0x2653,0x2659,0x265f,0x2665,0x266b,0x2673,0x3c7a,1,1,0x267b,0x2683,0x268b,0x2691,0x2697,0x3c84, +1,0x269d,0x26a3,0x26a9,0x26af,0x26b5,0x26bd,0x3c8e,0x26c5,0x26cb,0x26d1,0x26d9,0x26e1,0x26e7,0x26ed,0x3c98, +0x26f3,0x26f9,0x3ca0,0x2b41,1,1,0x2701,0x2708,0x2711,1,0x12a8,0x271b,0x2723,0x3ca8,0x2729,0x3cb0, +0x272e,0x2b45,0x8fc,1,0xf919,0xf919,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xffcc,0xffcc,0xfe02,0xfe02,0xffcc,0xffcc,0xffcc,0xffcc,0xfe02,0xfe02,0xfe02,0xffcc, +0xffcc,1,1,1,1,0xffcc,1,1,1,0xfe02,0xfe02,0xffcc,0xffb8,0xffcc,0xfe02,0xfe02, +0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x2b48,1,1,1,0x2b4c, +0x3cb8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0x908,1,0x90c,1,0x910,1,1,1,1,1,0x2735, +0x273b,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x2741,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0x2747,0x274d,0x2753,0x914,1,0x918,1,0x91c,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x920,0x2759,1,1,1,0x924,0x275f,1, +0x928,0x2765,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x92c,0x276b,0x930,0x2771,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x934,1,1,1,0x2777,1,0x938,0x277d,0x93c,1,0x2783,0x940,0x2789,1,1, +1,0x944,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0x278f,0x948,0x2795,1,0x94c,0x950,1,1,1,1,1,1, +1,0x279b,0x27a1,0x27a7,0x27ad,0x27b3,0x954,0x958,0x27b9,0x27bf,0x95c,0x960,0x27c5,0x27cb,0x964,0x968, +0x96c,0x970,1,1,0x27d1,0x27d7,0x974,0x978,0x27dd,0x27e3,0x97c,0x980,0x27e9,0x27ef,1,1, +1,1,1,1,1,0x984,0x988,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x98c,1,1,1,1,1,0x990,0x994,1,0x998, +0x27f5,0x27fb,0x2801,0x2807,1,1,0x99c,0x9a0,0x9a4,0x9a8,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0x280d,0x2813,0x2819,0x281f,1,1, +1,1,1,1,0x2825,0x282b,0x2831,0x2837,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x2b51,0x2b55,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x2b59, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1, -1,0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffcc,0xffcc,0xffcc,1,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,0xffb8, -0xffb8,0xffb8,0xffb8,0xffcc,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1,1, -0xffb8,1,1,1,1,1,1,0xffcc,1,1,1,0xffcc,0xffcc,1,1,1, -1,1,1,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc, -0xffd4,0xffac,0xffb8,0xff94,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffd0,0xffc8,0xffc8,0xffb8,0xffb4,0xffcc,0xffd2, -0xffb8,0xffcc,0xffb8,0x1a6c,0x1a72,0x1a78,0x1a7e,0x1a85,0x1a8b,0x1a91,0x1a97,0x1a9f,0x1aa9,0x1ab0,0x1ab6,0x1abc, -0x1ac2,0x1ac8,0x1ace,0x1ad5,0x1adb,0x1ae0,0x1ae6,0x1aee,0x1af8,0x1b02,0x1b0c,0x1b14,0x1b1a,0x1b20,0x1b26,0x1b2f, -0x1b39,0x1b41,0x1b47,0x1b4c,0x1b52,0x1b58,0x1b5e,0x1b64,0x1b6a,0x1b70,0x1b76,0x1b7d,0x1b83,0x1b88,0x1b8e,0x1b94, -0x1b9a,0x1ba2,0x1bac,0x1bb4,0x1bba,0x1bc0,0x1bc6,0x1bcc,0x1bd2,0xdde,0xde8,0x1bda,0x1be4,0x1bec,0x1bf2,0x1bf8, -0x1bfe,0x1c04,0x1c0a,0x1c10,0x1c16,0x1c1d,0x1c23,0x1c28,0x1c2e,0x1c34,0x1c3a,0x1c40,0x1c46,0x1c4c,0x1c52,0x1c5a, -0x1c64,0x1c6e,0x1c78,0x1c82,0x1c8c,0x1c96,0x1ca0,0x1ca9,0x1caf,0x1cb5,0x1cbb,0x1cc0,0x1cc6,0xdf2,0xdfc,0x1cce, -0x1cd8,0x1ce0,0x1ce6,0x1cec,0x1cf2,0xe06,0xe10,0x1cfa,0x1d04,0x1d0e,0x1d18,0x1d22,0x1d2c,0x1d34,0x1d3a,0x1d40, -0x1d46,0x1d4c,0x1d52,0x1d58,0x1d5e,0x1d64,0x1d6a,0x1d70,0x1d76,0x1d7c,0x1d82,0x1d8a,0x1d94,0x1d9e,0x1da8,0x1db0, -0x1db6,0x1dbd,0x1dc3,0x1dc8,0x1dce,0x1dd4,0x1dda,0x1de0,0x1de6,0x1dec,0x1df2,0x1df9,0x1dff,0x1e05,0x1e0b,0x1e11, -0x1e17,0x1e1c,0x1e22,0x1e28,0x1e2e,0x1e35,0x1e3b,0x1e41,0x1e47,0x1e4c,0x1e52,0x1e58,0x1e5e,1,0x1e65,1, -1,1,1,0xe1a,0xe28,0x1e6a,0x1e70,0x1e78,0x1e82,0x1e8c,0x1e96,0x1ea0,0x1eaa,0x1eb4,0x1ebe,0x1ec8, -0x1ed2,0x1edc,0x1ee6,0x1ef0,0x1efa,0x1f04,0x1f0e,0x1f18,0x1f22,0x1f2c,0x1f36,0xe36,0xe40,0x1f3e,0x1f44,0x1f4a, -0x1f50,0x1f58,0x1f62,0x1f6c,0x1f76,0x1f80,0x1f8a,0x1f94,0x1f9e,0x1fa8,0x1fb2,0x1fba,0x1fc0,0x1fc6,0x1fcc,0xe4a, -0xe54,0x1fd2,0x1fd8,0x1fe0,0x1fea,0x1ff4,0x1ffe,0x2008,0x2012,0x201c,0x2026,0x2030,0x203a,0x2044,0x204e,0x2058, -0x2062,0x206c,0x2076,0x2080,0x208a,0x2094,0x209e,0x20a6,0x20ac,0x20b2,0x20b8,0x20c0,0x20ca,0x20d4,0x20de,0x20e8, -0x20f2,0x20fc,0x2106,0x2110,0x211a,0x2122,0x2128,0x212f,0x2135,0x213a,0x2140,0x2146,0x214c,1,1,1, -1,1,1,0xe5e,0xe74,0xe8c,0xe9a,0xea8,0xeb6,0xec4,0xed2,0xede,0xef4,0xf0c,0xf1a,0xf28, -0xf36,0xf44,0xf52,0xf5e,0xf6c,0x2155,0x215f,0x2169,0x2173,1,1,0xf7a,0xf88,0x217d,0x2187,0x2191, -0x219b,1,1,0xf96,0xfac,0xfc4,0xfd2,0xfe0,0xfee,0xffc,0x100a,0x1016,0x102c,0x1044,0x1052,0x1060, -0x106e,0x107c,0x108a,0x1096,0x10a8,0x21a5,0x21af,0x21b9,0x21c3,0x21cd,0x21d7,0x10ba,0x10cc,0x21e1,0x21eb,0x21f5, -0x21ff,0x2209,0x2213,0x10de,0x10ec,0x221d,0x2227,0x2231,0x223b,1,1,0x10fa,0x1108,0x2245,0x224f,0x2259, -0x2263,1,1,0x1116,0x1128,0x226d,0x2277,0x2281,0x228b,0x2295,0x229f,1,0x113a,1,0x22a9,1, -0x22b3,1,0x22bd,0x114c,0x1162,0x117a,0x1188,0x1196,0x11a4,0x11b2,0x11c0,0x11cc,0x11e2,0x11fa,0x1208,0x1216, -0x1224,0x1232,0x1240,0x124c,0x3b9e,0x22c5,0x3ba6,0x1256,0x3bae,0x22cb,0x3bb6,0x22d1,0x3bbe,0x22d7,0x3bc6,0x1260, -0x3bce,1,1,0x22de,0x22e8,0x22f7,0x2307,0x2317,0x2327,0x2337,0x2347,0x2352,0x235c,0x236b,0x237b,0x238b, -0x239b,0x23ab,0x23bb,0x23c6,0x23d0,0x23df,0x23ef,0x23ff,0x240f,0x241f,0x242f,0x243a,0x2444,0x2453,0x2463,0x2473, -0x2483,0x2493,0x24a3,0x24ae,0x24b8,0x24c7,0x24d7,0x24e7,0x24f7,0x2507,0x2517,0x2522,0x252c,0x253b,0x254b,0x255b, -0x256b,0x257b,0x258b,0x2595,0x259b,0x25a3,0x25aa,0x25b3,1,0x126a,0x25bd,0x25c5,0x25cb,0x25d1,0x3bd6,0x25d6, -1,0x2ab2,0x8f0,1,0x25dd,0x25e5,0x25ec,0x25f5,1,0x1274,0x25ff,0x2607,0x3bde,0x260d,0x3be6,0x2612, -0x2619,0x261f,0x2625,0x262b,0x2631,0x2639,0x3bf0,1,1,0x2641,0x2649,0x2651,0x2657,0x265d,0x3bfa,1, -0x2663,0x2669,0x266f,0x2675,0x267b,0x2683,0x3c04,0x268b,0x2691,0x2697,0x269f,0x26a7,0x26ad,0x26b3,0x3c0e,0x26b9, -0x26bf,0x3c16,0x2ab7,1,1,0x26c7,0x26ce,0x26d7,1,0x127e,0x26e1,0x26e9,0x3c1e,0x26ef,0x3c26,0x26f4, -0x2abb,0x8fc,1,0xfa09,0xfa09,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffcc,0xffcc,0xfe02,0xfe02,0xffcc,0xffcc,0xffcc,0xffcc,0xfe02,0xfe02,0xfe02,0xffcc,0xffcc, -1,1,1,1,0xffcc,1,1,1,0xfe02,0xfe02,0xffcc,0xffb8,0xffcc,0xfe02,0xfe02,0xffb8, -0xffb8,0xffb8,0xffb8,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0x2abe,1,1,1,0x2ac2,0x3c2e, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x908,1,0x90c,1,0x910,1,1,1,1,1,0x26fb,0x2701, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0x2707,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x270d,0x2713,0x2719,0x914,1,0x918,1,0x91c,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x920,0x271f,1,1,1,0x924,0x2725,1,0x928, -0x272b,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x92c,0x2731,0x930,0x2737,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x934,1,1,1,0x273d,1,0x938,0x2743,0x93c,1,0x2749,0x940,0x274f,1,1,1, -0x944,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0x2755,0x948,0x275b,1,0x94c,0x950,1,1,1,1,1,1,1, -0x2761,0x2767,0x276d,0x2773,0x2779,0x954,0x958,0x277f,0x2785,0x95c,0x960,0x278b,0x2791,0x964,0x968,0x96c, -0x970,1,1,0x2797,0x279d,0x974,0x978,0x27a3,0x27a9,0x97c,0x980,0x27af,0x27b5,1,1,1, -1,1,1,1,0x984,0x988,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x98c,1,1,1,1,1,0x990,0x994,1,0x998,0x27bb, -0x27c1,0x27c7,0x27cd,1,1,0x99c,0x9a0,0x9a4,0x9a8,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0x27d3,0x27d9,0x27df,0x27e5,1,1,1, -1,1,1,0x27eb,0x27f1,0x27f7,0x27fd,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x2ac7,0x2acb,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x2acf,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, 0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xffb4,0xffc8,0xffd0,0xffbc,0xffc0,0xffc0,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x9ac, -1,1,1,1,0x9b0,0x2803,0x9b4,0x2809,0x9b8,0x280f,0x9bc,0x2815,0x9c0,0x281b,0x9c4,0x2821, -0x9c8,0x2827,0x9cc,0x282d,0x9d0,0x2833,0x9d4,0x2839,0x9d8,0x283f,0x9dc,0x2845,1,0x9e0,0x284b,0x9e4, -0x2851,0x9e8,0x2857,1,1,1,1,1,0x9ec,0x285d,0x2863,0x9f4,0x2869,0x286f,0x9fc,0x2875, -0x287b,0xa04,0x2881,0x2887,0xa0c,0x288d,0x2893,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x2899,1,1,1,1, -0xfc10,0xfc10,1,1,0xa14,0x289f,1,1,1,1,1,1,1,0xa18,1,1, -1,1,0xa1c,0x28a5,0xa20,0x28ab,0xa24,0x28b1,0xa28,0x28b7,0xa2c,0x28bd,0xa30,0x28c3,0xa34,0x28c9, -0xa38,0x28cf,0xa3c,0x28d5,0xa40,0x28db,0xa44,0x28e1,0xa48,0x28e7,1,0xa4c,0x28ed,0xa50,0x28f3,0xa54, -0x28f9,1,1,1,1,1,0xa58,0x28ff,0x2905,0xa60,0x290b,0x2911,0xa68,0x2917,0x291d,0xa70, -0x2923,0x2929,0xa78,0x292f,0x2935,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xa80,0xa84,0xa88,0xa8c,1,0x293b,1,1,0x2941,0x2947, -0x294d,0x2953,1,1,0xa90,0x2959,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xffcc,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0xffb4,0xffc8,0xffd0,0xffbc,0xffc0,0xffc0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,1, +0x9ac,1,1,1,1,0x9b0,0x283d,0x9b4,0x2843,0x9b8,0x2849,0x9bc,0x284f,0x9c0,0x2855,0x9c4, +0x285b,0x9c8,0x2861,0x9cc,0x2867,0x9d0,0x286d,0x9d4,0x2873,0x9d8,0x2879,0x9dc,0x287f,1,0x9e0,0x2885, +0x9e4,0x288b,0x9e8,0x2891,1,1,1,1,1,0x9ec,0x2897,0x289d,0x9f4,0x28a3,0x28a9,0x9fc, +0x28af,0x28b5,0xa04,0x28bb,0x28c1,0xa0c,0x28c7,0x28cd,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0x28d3,1,1,1, +1,0xfc10,0xfc10,1,1,0xa14,0x28d9,1,1,1,1,1,1,1,0xa18,1, +1,1,1,0xa1c,0x28df,0xa20,0x28e5,0xa24,0x28eb,0xa28,0x28f1,0xa2c,0x28f7,0xa30,0x28fd,0xa34, +0x2903,0xa38,0x2909,0xa3c,0x290f,0xa40,0x2915,0xa44,0x291b,0xa48,0x2921,1,0xa4c,0x2927,0xa50,0x292d, +0xa54,0x2933,1,1,1,1,1,0xa58,0x2939,0x293f,0xa60,0x2945,0x294b,0xa68,0x2951,0x2957, +0xa70,0x295d,0x2963,0xa78,0x2969,0x296f,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0xa80,0xa84,0xa88,0xa8c,1,0x2975,1,1,0x297b, +0x2981,0x2987,0x298d,1,1,0xa90,0x2993,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xffcc,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xffcc,1,0xffcc,0xffcc,0xffb8,1,1, -0xffcc,0xffcc,1,1,1,1,1,0xffcc,0xffcc,1,0xffcc,1,1,1,1,1, +1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12, -1,1,1,1,1,1,1,1,1,0xae2,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, -0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, -0x1289,0x1289,0x1289,0x1289,0x1289,0xae2,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, -0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, -0x1289,0xae2,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, -0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0xae2,0x1289,0x1289, -0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, -0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x3c66,1,0x3c66,0x3c66,0x3c66,0x3c66,0x3c66,0x3c66,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x3c66, -0x3c66,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x3c66,1,1,1,1,0x3c66,1,1,1,0x3c66,0x3c66,0x3c66, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x3b97,1, -0x2ad5,0x2ad9,0x2add,0x2ae1,0x2ae5,0x2ae9,0x2aed,0x2af1,0x2af1,0x2af5,0x2af9,0x2afd,0x2b01,0x2b05,0x2b09,0x2b0d, -0x2b11,0x2b15,0x2b19,0x2b1d,0x2b21,0x2b25,0x2b29,0x2b2d,0x2b31,0x2b35,0x2b39,0x2b3d,0x2b41,0x2b45,0x2b49,0x2b4d, -0x2b51,0x2b55,0x2b59,0x2b5d,0x2b61,0x2b65,0x2b69,0x2b6d,0x2b71,0x2b75,0x2b79,0x2b7d,0x2b81,0x2b85,0x2b89,0x2b8d, -0x2b91,0x2b95,0x2b99,0x2b9d,0x2ba1,0x2ba5,0x2ba9,0x2bad,0x2bb1,0x2bb5,0x2bb9,0x2bbd,0x2bc1,0x2bc5,0x2bc9,0x2bcd, -0x2bd1,0x2bd5,0x2bd9,0x2bdd,0x2be1,0x2be5,0x2be9,0x2bed,0x2bf1,0x2bf5,0x2bf9,0x2bfd,0x2c01,0x2c05,0x2c09,0x2c0d, -0x2c11,0x2c15,0x2c19,0x2c1d,0x2c21,0x2c25,0x2c29,0x2c2d,0x2c31,0x2c35,0x2c39,0x2c3d,0x2b21,0x2c41,0x2c45,0x2c49, -0x2c4d,0x2c51,0x2c55,0x2c59,0x2c5d,0x2c61,0x2c65,0x2c69,0x2c6d,0x2c71,0x2c75,0x2c79,0x2c7d,0x2c81,0x2c85,0x2c89, -0x2c8d,0x2c91,0x2c95,0x2c99,0x2c9d,0x2ca1,0x2ca5,0x2ca9,0x2cad,0x2cb1,0x2cb5,0x2cb9,0x2cbd,0x2cc1,0x2cc5,0x2cc9, -0x2ccd,0x2cd1,0x2cd5,0x2cd9,0x2cdd,0x2ce1,0x2ce5,0x2ce9,0x2ced,0x2cf1,0x2cf5,0x2cf9,0x2cfd,0x2d01,0x2d05,0x2d09, -0x2d0d,0x2d11,0x2d15,0x2d19,0x2d1d,0x2d21,0x2d25,0x2d29,0x2d2d,0x2d31,0x2d35,0x2d39,0x2d3d,0x2d41,0x2d45,0x2d49, -0x2d4d,0x2c89,0x2d51,0x2d55,0x2d59,0x2d5d,0x2d61,0x2d65,0x2d69,0x2d6d,0x2c49,0x2d71,0x2d75,0x2d79,0x2d7d,0x2d81, -0x2d85,0x2d89,0x2d8d,0x2d91,0x2d95,0x2d99,0x2d9d,0x2da1,0x2da5,0x2da9,0x2dad,0x2db1,0x2db5,0x2db9,0x2dbd,0x2b21, -0x2dc1,0x2dc5,0x2dc9,0x2dcd,0x2dd1,0x2dd5,0x2dd9,0x2ddd,0x2de1,0x2de5,0x2de9,0x2ded,0x2df1,0x2df5,0x2df9,0x2dfd, -0x2e01,0x2e05,0x2e09,0x2e0d,0x2e11,0x2e15,0x2e19,0x2e1d,0x2e21,0x2e25,0x2e29,0x2c51,0x2e2d,0x2e31,0x2e35,0x2e39, -0x2e3d,0x2e41,0x2e45,0x2e49,0x2e4d,0x2e51,0x2e55,0x2e59,0x2e5d,0x2e61,0x2e65,0x2e69,0x2e6d,0x2e71,0x2e75,0x2e79, -0x2e7d,0x2e81,0x2e85,0x2e89,0x2e8d,0x2e91,0x2e95,0x2e99,0x2e9d,0x2ea1,0x2ea5,0x2ea9,0x2ead,0x2eb1,0x2eb5,0x2eb9, -0x2ebd,0x2ec1,0x2ec5,0x2ec9,0x2ecd,0x2ed1,0x2ed5,0x2ed9,0x2edd,0x2ee1,0x2ee5,0x2ee9,0x2eed,0x2ef1,1,1, -0x2ef5,1,0x2ef9,1,1,0x2efd,0x2f01,0x2f05,0x2f09,0x2f0d,0x2f11,0x2f15,0x2f19,0x2f1d,0x2f21,1, -0x2f25,1,0x2f29,1,1,0x2f2d,0x2f31,1,1,1,0x2f35,0x2f39,0x2f3d,0x2f41,0x2f45,0x2f49, -0x2f4d,0x2f51,0x2f55,0x2f59,0x2f5d,0x2f61,0x2f65,0x2f69,0x2f6d,0x2f71,0x2f75,0x2f79,0x2f7d,0x2f81,0x2f85,0x2f89, -0x2f8d,0x2f91,0x2f95,0x2f99,0x2f9d,0x2fa1,0x2fa5,0x2fa9,0x2fad,0x2fb1,0x2fb5,0x2fb9,0x2fbd,0x2fc1,0x2fc5,0x2fc9, -0x2fcd,0x2fd1,0x2fd5,0x2fd9,0x2fdd,0x2fe1,0x2fe5,0x2d25,0x2fe9,0x2fed,0x2ff1,0x2ff5,0x2ff9,0x2ffd,0x2ffd,0x3001, -0x3005,0x3009,0x300d,0x3011,0x3015,0x3019,0x301d,0x2f2d,0x3021,0x3025,0x3029,0x302d,0x3031,0x3037,1,1, -0x303b,0x303f,0x3043,0x3047,0x304b,0x304f,0x3053,0x3057,0x2f65,0x305b,0x305f,0x3063,0x2ef5,0x3067,0x306b,0x306f, -0x3073,0x3077,0x307b,0x307f,0x3083,0x3087,0x308b,0x308f,0x3093,0x2f89,0x3097,0x2f8d,0x309b,0x309f,0x30a3,0x30a7, -0x30ab,0x2ef9,0x2b75,0x30af,0x30b3,0x30b7,0x2c8d,0x2de9,0x30bb,0x30bf,0x2fa9,0x30c3,0x2fad,0x30c7,0x30cb,0x30cf, -0x2f01,0x30d3,0x30d7,0x30db,0x30df,0x30e3,0x2f05,0x30e7,0x30eb,0x30ef,0x30f3,0x30f7,0x30fb,0x2fe5,0x30ff,0x3103, -0x2d25,0x3107,0x2ff5,0x310b,0x310f,0x3113,0x3117,0x311b,0x3009,0x311f,0x2f29,0x3123,0x300d,0x2c41,0x3127,0x3011, -0x312b,0x3019,0x312f,0x3133,0x3137,0x313b,0x313f,0x3021,0x2f19,0x3143,0x3025,0x3147,0x3029,0x314b,0x2af1,0x314f, -0x3155,0x315b,0x3161,0x3165,0x3169,0x316d,0x3173,0x3179,0x317f,0x3183,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x3186,0xfe34,0x318c,1,1,1,1,1,1,1,1,1,1,0x3192,0x3198,0x31a0, -0x31aa,0x31b2,0x31b8,0x31be,0x31c4,0x31ca,0x31d0,0x31d6,0x31dc,0x31e2,1,0x31e8,0x31ee,0x31f4,0x31fa,0x3200, -1,0x3206,1,0x320c,0x3212,1,0x3218,0x321e,1,0x3224,0x322a,0x3230,0x3236,0x323c,0x3242,0x3248, -0x324e,0x3254,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, -0xffb8,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffb8,1,0xffcc,1,1,1,1,1,1,1,1,0xffcc,0xfe02, -0xffb8,1,1,1,1,0xfe12,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,1,1, +1,1,1,1,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0xffcc,1,0xffcc,0xffcc,0xffb8,1, +1,0xffcc,0xffcc,1,1,1,1,1,0xffcc,0xffcc,1,0xffcc,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0xfe12,1,1,1,1,1,1,1,1,1,0xb0c,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3, +0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3, +0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0xb0c,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3, +0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3, +0x12c3,0x12c3,0xb0c,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3, +0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0xb0c,0x12c3, +0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3, +0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,0x12c3,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x3cf0,0x29a0,0x3cf0,0x3cf0,0x3cf0,0x3cf0,0x3cf0,0x3cf0,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x3cf0,1, +0x3cf0,0x3cf0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0x3cf0,1,1,1,1,0x3cf0,1,1,1,0x3cf0,0x3cf0, +0x3cf0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x3c21, +1,0x2b5f,0x2b63,0x2b67,0x2b6b,0x2b6f,0x2b73,0x2b77,0x2b7b,0x2b7b,0x2b7f,0x2b83,0x2b87,0x2b8b,0x2b8f,0x2b93, +0x2b97,0x2b9b,0x2b9f,0x2ba3,0x2ba7,0x2bab,0x2baf,0x2bb3,0x2bb7,0x2bbb,0x2bbf,0x2bc3,0x2bc7,0x2bcb,0x2bcf,0x2bd3, +0x2bd7,0x2bdb,0x2bdf,0x2be3,0x2be7,0x2beb,0x2bef,0x2bf3,0x2bf7,0x2bfb,0x2bff,0x2c03,0x2c07,0x2c0b,0x2c0f,0x2c13, +0x2c17,0x2c1b,0x2c1f,0x2c23,0x2c27,0x2c2b,0x2c2f,0x2c33,0x2c37,0x2c3b,0x2c3f,0x2c43,0x2c47,0x2c4b,0x2c4f,0x2c53, +0x2c57,0x2c5b,0x2c5f,0x2c63,0x2c67,0x2c6b,0x2c6f,0x2c73,0x2c77,0x2c7b,0x2c7f,0x2c83,0x2c87,0x2c8b,0x2c8f,0x2c93, +0x2c97,0x2c9b,0x2c9f,0x2ca3,0x2ca7,0x2cab,0x2caf,0x2cb3,0x2cb7,0x2cbb,0x2cbf,0x2cc3,0x2cc7,0x2bab,0x2ccb,0x2ccf, +0x2cd3,0x2cd7,0x2cdb,0x2cdf,0x2ce3,0x2ce7,0x2ceb,0x2cef,0x2cf3,0x2cf7,0x2cfb,0x2cff,0x2d03,0x2d07,0x2d0b,0x2d0f, +0x2d13,0x2d17,0x2d1b,0x2d1f,0x2d23,0x2d27,0x2d2b,0x2d2f,0x2d33,0x2d37,0x2d3b,0x2d3f,0x2d43,0x2d47,0x2d4b,0x2d4f, +0x2d53,0x2d57,0x2d5b,0x2d5f,0x2d63,0x2d67,0x2d6b,0x2d6f,0x2d73,0x2d77,0x2d7b,0x2d7f,0x2d83,0x2d87,0x2d8b,0x2d8f, +0x2d93,0x2d97,0x2d9b,0x2d9f,0x2da3,0x2da7,0x2dab,0x2daf,0x2db3,0x2db7,0x2dbb,0x2dbf,0x2dc3,0x2dc7,0x2dcb,0x2dcf, +0x2dd3,0x2dd7,0x2d13,0x2ddb,0x2ddf,0x2de3,0x2de7,0x2deb,0x2def,0x2df3,0x2df7,0x2cd3,0x2dfb,0x2dff,0x2e03,0x2e07, +0x2e0b,0x2e0f,0x2e13,0x2e17,0x2e1b,0x2e1f,0x2e23,0x2e27,0x2e2b,0x2e2f,0x2e33,0x2e37,0x2e3b,0x2e3f,0x2e43,0x2e47, +0x2bab,0x2e4b,0x2e4f,0x2e53,0x2e57,0x2e5b,0x2e5f,0x2e63,0x2e67,0x2e6b,0x2e6f,0x2e73,0x2e77,0x2e7b,0x2e7f,0x2e83, +0x2e87,0x2e8b,0x2e8f,0x2e93,0x2e97,0x2e9b,0x2e9f,0x2ea3,0x2ea7,0x2eab,0x2eaf,0x2eb3,0x2cdb,0x2eb7,0x2ebb,0x2ebf, +0x2ec3,0x2ec7,0x2ecb,0x2ecf,0x2ed3,0x2ed7,0x2edb,0x2edf,0x2ee3,0x2ee7,0x2eeb,0x2eef,0x2ef3,0x2ef7,0x2efb,0x2eff, +0x2f03,0x2f07,0x2f0b,0x2f0f,0x2f13,0x2f17,0x2f1b,0x2f1f,0x2f23,0x2f27,0x2f2b,0x2f2f,0x2f33,0x2f37,0x2f3b,0x2f3f, +0x2f43,0x2f47,0x2f4b,0x2f4f,0x2f53,0x2f57,0x2f5b,0x2f5f,0x2f63,0x2f67,0x2f6b,0x2f6f,0x2f73,0x2f77,0x2f7b,1, +1,0x2f7f,1,0x2f83,1,1,0x2f87,0x2f8b,0x2f8f,0x2f93,0x2f97,0x2f9b,0x2f9f,0x2fa3,0x2fa7,0x2fab, +1,0x2faf,1,0x2fb3,1,1,0x2fb7,0x2fbb,1,1,1,0x2fbf,0x2fc3,0x2fc7,0x2fcb,0x2fcf, +0x2fd3,0x2fd7,0x2fdb,0x2fdf,0x2fe3,0x2fe7,0x2feb,0x2fef,0x2ff3,0x2ff7,0x2ffb,0x2fff,0x3003,0x3007,0x300b,0x300f, +0x3013,0x3017,0x301b,0x301f,0x3023,0x3027,0x302b,0x302f,0x3033,0x3037,0x303b,0x303f,0x3043,0x3047,0x304b,0x304f, +0x3053,0x3057,0x305b,0x305f,0x3063,0x3067,0x306b,0x306f,0x2daf,0x3073,0x3077,0x307b,0x307f,0x3083,0x3087,0x3087, +0x308b,0x308f,0x3093,0x3097,0x309b,0x309f,0x30a3,0x30a7,0x2fb7,0x30ab,0x30af,0x30b3,0x30b7,0x30bb,0x30c1,1, +1,0x30c5,0x30c9,0x30cd,0x30d1,0x30d5,0x30d9,0x30dd,0x30e1,0x2fef,0x30e5,0x30e9,0x30ed,0x2f7f,0x30f1,0x30f5, +0x30f9,0x30fd,0x3101,0x3105,0x3109,0x310d,0x3111,0x3115,0x3119,0x311d,0x3013,0x3121,0x3017,0x3125,0x3129,0x312d, +0x3131,0x3135,0x2f83,0x2bff,0x3139,0x313d,0x3141,0x2d17,0x2e73,0x3145,0x3149,0x3033,0x314d,0x3037,0x3151,0x3155, +0x3159,0x2f8b,0x315d,0x3161,0x3165,0x3169,0x316d,0x2f8f,0x3171,0x3175,0x3179,0x317d,0x3181,0x3185,0x306f,0x3189, +0x318d,0x2daf,0x3191,0x307f,0x3195,0x3199,0x319d,0x31a1,0x31a5,0x3093,0x31a9,0x2fb3,0x31ad,0x3097,0x2ccb,0x31b1, +0x309b,0x31b5,0x30a3,0x31b9,0x31bd,0x31c1,0x31c5,0x31c9,0x30ab,0x2fa3,0x31cd,0x30af,0x31d1,0x30b3,0x31d5,0x2b7b, +0x31d9,0x31df,0x31e5,0x31eb,0x31ef,0x31f3,0x31f7,0x31fd,0x3203,0x3209,0x320d,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x3210,0xfe34,0x3216,1,1,1,1,1,1,1,1,1,1,0x321c,0x3222, +0x322a,0x3234,0x323c,0x3242,0x3248,0x324e,0x3254,0x325a,0x3260,0x3266,0x326c,1,0x3272,0x3278,0x327e,0x3284, +0x328a,1,0x3290,1,0x3296,0x329c,1,0x32a2,0x32a8,1,0x32ae,0x32b4,0x32ba,0x32c0,0x32c6,0x32cc, +0x32d2,0x32d8,0x32de,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, +0xffb8,0xffb8,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0x2999,1,1,1,1,1,1,0xa94,1,1,1,1, +1,1,1,0xa9a,1,1,1,1,1,0x29a1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0xffb8,1,0xffcc,1,1,1,1,1,1, +1,1,0xffcc,0xfe02,0xffb8,1,1,1,1,0xfe12,1,1,1,1,0xffcc,0xffcc, +0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, 1,1,1,1,1,1,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffb8,0xffb8,0xffb8, 1,1,0xffcc,0xffb8,0xffcc,0xffb8,1,1,1,1,1,1,1,1,1,1, 0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12, -1,1,1,1,1,1,1,1,1,0xa94,0x295f,0xa9a,0x2969,1,1,1, -1,1,0xaa0,1,1,1,1,1,0x2973,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xaa0,0x29a9,0xaa6,0x29b3,1,1,1, +1,1,0xaac,1,1,1,1,1,0x29bd,1,1,1,1,1,1,1, 1,1,0xfe12,0xfc0e,1,1,1,1,1,1,1,0xfc00,1,1,1,1, -1,1,0x297d,0x2987,1,0xaa6,0xaac,0xfe12,0xfe12,1,1,1,1,1,1,1, +1,1,0x29c7,0x29d1,1,0xab2,0xab8,0xfe12,0xfe12,1,1,1,1,1,1,1, 1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,0xfe0e,1, 1,1,1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,0xfe0e, 0xfe12,1,1,1,1,1,1,1,1,1,1,1,0xfe0e,0xfe0e,1,0xfc00, -1,1,1,1,1,1,1,0xab2,1,1,1,0x2991,0x299b,0xfe12,1,1, -1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,0xfe12,1, -1,1,0xfe0e,1,1,1,1,1,1,1,1,1,0xfc00,1,1,1, -1,1,1,1,1,0xabe,0xfc00,0x29a5,0x29af,0xfc00,0x29b9,1,1,0xfe12,0xfe0e,1, -1,1,1,1,1,1,1,1,1,1,1,0xad0,0xad6,0x29c3,0x29cd,1, -1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,0xfc00,1,1, -1,1,0xadc,1,1,0x29d7,1,1,1,1,0xfe12,0xfe12,1,0xfe02,0xfe02,0xfe02, -0xfe02,0xfe02,1,1,1,1,1,1,1,1,1,1,1,0xfe0c,0xfe0c,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe02,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0x325a,0x3264,0x3278,0x3290, -0x32a8,0x32c0,0x32d8,0xffb0,0xffb0,0xfe02,0xfe02,0xfe02,1,1,1,0xffc4,0xffb0,0xffb0,0xffb0,1, -1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1,0xffcc, -0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x32e6,0x32f0, -0x3304,0x331c,0x3334,0x334c,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,1,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, -0xffd0,0xffd0,0xffb8,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,1,1,1, -1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xfe0e,1,1,1,1,1, -0x335b,0x335f,0x3363,0x3367,0x336d,0x2f4d,0x3371,0x3375,0x3379,0x337d,0x2f51,0x3381,0x3385,0x3389,0x2f55,0x338f, -0x3393,0x3397,0x339b,0x33a1,0x33a5,0x33a9,0x33ad,0x33b3,0x33b7,0x33bb,0x33bf,0x303f,0x33c3,0x33c9,0x33cd,0x33d1, -0x33d5,0x33d9,0x33dd,0x33e1,0x33e5,0x3053,0x2f59,0x2f5d,0x3057,0x33e9,0x33ed,0x2c59,0x33f1,0x2f61,0x33f5,0x33f9, -0x33fd,0x3401,0x3401,0x3401,0x3405,0x340b,0x340f,0x3413,0x3417,0x341d,0x3421,0x3425,0x3429,0x342d,0x3431,0x3435, -0x3439,0x343d,0x3441,0x3445,0x3449,0x344d,0x344d,0x305f,0x3451,0x3455,0x3459,0x345d,0x2f69,0x3461,0x3465,0x3469, -0x2ebd,0x346d,0x3471,0x3475,0x3479,0x347d,0x3481,0x3485,0x3489,0x348d,0x3493,0x3497,0x349b,0x349f,0x34a3,0x34a7, -0x34ab,0x34b1,0x34b7,0x34bb,0x34bf,0x34c3,0x34c7,0x34cb,0x34cf,0x34d3,0x34d7,0x34d7,0x34db,0x34e1,0x34e5,0x2c49, -0x34e9,0x34ed,0x34f3,0x34f7,0x34fb,0x34ff,0x3503,0x3507,0x2f7d,0x350b,0x350f,0x3513,0x3519,0x351d,0x3523,0x3527, -0x352b,0x352f,0x3533,0x3537,0x353b,0x353f,0x3543,0x3547,0x354b,0x354f,0x3555,0x3559,0x355d,0x3561,0x2b71,0x3565, -0x356b,0x356f,0x356f,0x3575,0x3579,0x3579,0x357d,0x3581,0x3587,0x358d,0x3591,0x3595,0x3599,0x359d,0x35a1,0x35a5, -0x35a9,0x35ad,0x35b1,0x2f81,0x35b5,0x35bb,0x35bf,0x35c3,0x308f,0x35c3,0x35c7,0x2f89,0x35cb,0x35cf,0x35d3,0x35d7, -0x2f8d,0x2b05,0x35db,0x35df,0x35e3,0x35e7,0x35eb,0x35ef,0x35f3,0x35f9,0x35fd,0x3601,0x3605,0x3609,0x360d,0x3613, -0x3617,0x361b,0x361f,0x3623,0x3627,0x362b,0x362f,0x3633,0x2f91,0x3637,0x363b,0x3641,0x3645,0x3649,0x364d,0x2f99, -0x3651,0x3655,0x3659,0x365d,0x3661,0x3665,0x3669,0x366d,0x2b75,0x30af,0x3671,0x3675,0x3679,0x367d,0x3683,0x3687, -0x368b,0x368f,0x2f9d,0x3693,0x3699,0x369d,0x36a1,0x3161,0x36a5,0x36a9,0x36ad,0x36b1,0x36b5,0x36bb,0x36bf,0x36c3, -0x36c7,0x36cd,0x36d1,0x36d5,0x36d9,0x2c8d,0x36dd,0x36e1,0x36e7,0x36ed,0x36f3,0x36f7,0x36fd,0x3701,0x3705,0x3709, -0x370d,0x2fa1,0x2de9,0x3711,0x3715,0x3719,0x371d,0x3723,0x3727,0x372b,0x372f,0x30bf,0x3733,0x3737,0x373d,0x3741, -0x3745,0x374b,0x3751,0x3755,0x30c3,0x3759,0x375d,0x3761,0x3765,0x3769,0x376d,0x3771,0x3777,0x377b,0x3781,0x3785, -0x378b,0x30cb,0x378f,0x3793,0x3799,0x379d,0x37a1,0x37a7,0x37ad,0x37b1,0x37b5,0x37b9,0x37bd,0x37bd,0x37c1,0x37c5, -0x30d3,0x37c9,0x37cd,0x37d1,0x37d5,0x37d9,0x37df,0x37e3,0x2c55,0x37e9,0x37ef,0x37f3,0x37f9,0x37ff,0x3805,0x3809, -0x30eb,0x380d,0x3813,0x3819,0x381f,0x3825,0x3829,0x3829,0x30ef,0x3169,0x382d,0x3831,0x3835,0x3839,0x383f,0x2bbd, -0x30f7,0x3843,0x3847,0x2fcd,0x384d,0x3853,0x2f15,0x3859,0x385d,0x2fdd,0x3861,0x3865,0x3869,0x386f,0x386f,0x3875, -0x3879,0x387d,0x3883,0x3887,0x388b,0x388f,0x3895,0x3899,0x389d,0x38a1,0x38a5,0x38a9,0x38af,0x38b3,0x38b7,0x38bb, -0x38bf,0x38c3,0x38c7,0x38cd,0x38d3,0x38d7,0x38dd,0x38e1,0x38e7,0x38eb,0x2ff5,0x38ef,0x38f5,0x38fb,0x38ff,0x3905, -0x3909,0x390f,0x3913,0x3917,0x391b,0x391f,0x3923,0x3927,0x392d,0x3933,0x3939,0x3575,0x393f,0x3943,0x3947,0x394b, -0x394f,0x3953,0x3957,0x395b,0x395f,0x3963,0x3967,0x396b,0x2c9d,0x3971,0x3975,0x3979,0x397d,0x3981,0x3985,0x3001, -0x3989,0x398d,0x3991,0x3995,0x3999,0x399f,0x39a5,0x39ab,0x39af,0x39b3,0x39b7,0x39bb,0x39c1,0x39c5,0x39cb,0x39cf, -0x39d3,0x39d9,0x39df,0x39e3,0x2ba9,0x39e7,0x39eb,0x39ef,0x39f3,0x39f7,0x39fb,0x3113,0x39ff,0x3a03,0x3a07,0x3a0b, -0x3a0f,0x3a13,0x3a17,0x3a1b,0x3a1f,0x3a23,0x3a29,0x3a2d,0x3a31,0x3a35,0x3a39,0x3a3d,0x3a43,0x3a49,0x3a4d,0x3a51, -0x3127,0x312b,0x3a55,0x3a59,0x3a5f,0x3a63,0x3a67,0x3a6b,0x3a6f,0x3a75,0x3a7b,0x3a7f,0x3a83,0x3a87,0x3a8d,0x312f, -0x3a91,0x3a97,0x3a9d,0x3aa1,0x3aa5,0x3aa9,0x3aaf,0x3ab3,0x3ab7,0x3abb,0x3abf,0x3ac3,0x3ac7,0x3acb,0x3ad1,0x3ad5, -0x3ad9,0x3add,0x3ae3,0x3ae7,0x3aeb,0x3aef,0x3af3,0x3af9,0x3aff,0x3b03,0x3b07,0x3b0b,0x3b11,0x3b15,0x3147,0x3147, -0x3b1b,0x3b1f,0x3b25,0x3b29,0x3b2d,0x3b31,0x3b35,0x3b39,0x3b3d,0x3b41,0x314b,0x3b47,0x3b4b,0x3b4f,0x3b53,0x3b57, -0x3b5b,0x3b61,0x3b65,0x3b6b,0x3b71,0x3b77,0x3b7b,0x3b7f,0x3b83,0x3b87,0x3b8b,0x3b8f,0x3b93,0x3b97,1,1 +1,1,1,1,1,1,1,0xabe,1,1,1,0x29db,0x29e5,0xfe12,1,1, +1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,0xaca,0x29ef, +0xad0,0x29f9,1,1,1,1,1,0xad6,1,1,0x2a03,1,0xadc,0x2a0d,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0xfc00,1,1,0xfc00, +1,1,1,1,0xfbc4,1,1,0xfb10,1,0xfb1a,0xfb24,0xfc00,1,1,1,1, +0xfe12,0xfe12,1,1,0xfe12,1,1,1,0xfe0e,1,1,1,1,1,1,1, +1,1,0xfc00,1,1,1,1,1,1,1,1,0xae2,0xfc00,0x2a17,0x2a21,0xfc00, +0x2a2b,1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,1,1, +1,0xaf4,0xafa,0x2a35,0x2a3f,1,1,1,0xfe12,0xfe0e,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xfe12,0xfe0e,1,1,1,1,1, +1,1,1,0xfc00,1,1,1,1,0xb00,1,1,0x2a49,1,1,1,1, +0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0xfbd6,0xfc00,0xfb9e,0xfbb4,0xfb2e,0xfb38,0xfb42,0xfb56,0xfb6e,0xfb86,0xfbee,1,1,1,1,1, +0xfe12,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1,1,1,1,1,1,1,1, +1,0xb06,1,1,1,0xfbf4,0xfb94,0x12b2,0x2a5d,1,1,1,1,1,0xfe0c,0xfe0c, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe02,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0x32e4,0x32ee,0x3302, +0x331a,0x3332,0x334a,0x3362,0xffb0,0xffb0,0xfe02,0xfe02,0xfe02,1,1,1,0xffc4,0xffb0,0xffb0,0xffb0, +1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1, +0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x3370, +0x337a,0x338e,0x33a6,0x33be,0x33d6,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,1, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1, +1,0xffd0,0xffd0,0xffb8,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,1,1, +1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xfe0e,1,1,1,1, +1,0x33e5,0x33e9,0x33ed,0x33f1,0x33f7,0x2fd7,0x33fb,0x33ff,0x3403,0x3407,0x2fdb,0x340b,0x340f,0x3413,0x2fdf, +0x3419,0x341d,0x3421,0x3425,0x342b,0x342f,0x3433,0x3437,0x343d,0x3441,0x3445,0x3449,0x30c9,0x344d,0x3453,0x3457, +0x345b,0x345f,0x3463,0x3467,0x346b,0x346f,0x30dd,0x2fe3,0x2fe7,0x30e1,0x3473,0x3477,0x2ce3,0x347b,0x2feb,0x347f, +0x3483,0x3487,0x348b,0x348b,0x348b,0x348f,0x3495,0x3499,0x349d,0x34a1,0x34a7,0x34ab,0x34af,0x34b3,0x34b7,0x34bb, +0x34bf,0x34c3,0x34c7,0x34cb,0x34cf,0x34d3,0x34d7,0x34d7,0x30e9,0x34db,0x34df,0x34e3,0x34e7,0x2ff3,0x34eb,0x34ef, +0x34f3,0x2f47,0x34f7,0x34fb,0x34ff,0x3503,0x3507,0x350b,0x350f,0x3513,0x3517,0x351d,0x3521,0x3525,0x3529,0x352d, +0x3531,0x3535,0x353b,0x3541,0x3545,0x3549,0x354d,0x3551,0x3555,0x3559,0x355d,0x3561,0x3561,0x3565,0x356b,0x356f, +0x2cd3,0x3573,0x3577,0x357d,0x3581,0x3585,0x3589,0x358d,0x3591,0x3007,0x3595,0x3599,0x359d,0x35a3,0x35a7,0x35ad, +0x35b1,0x35b5,0x35b9,0x35bd,0x35c1,0x35c5,0x35c9,0x35cd,0x35d1,0x35d5,0x35d9,0x35df,0x35e3,0x35e7,0x35eb,0x2bfb, +0x35ef,0x35f5,0x35f9,0x35f9,0x35ff,0x3603,0x3603,0x3607,0x360b,0x3611,0x3617,0x361b,0x361f,0x3623,0x3627,0x362b, +0x362f,0x3633,0x3637,0x363b,0x300b,0x363f,0x3645,0x3649,0x364d,0x3119,0x364d,0x3651,0x3013,0x3655,0x3659,0x365d, +0x3661,0x3017,0x2b8f,0x3665,0x3669,0x366d,0x3671,0x3675,0x3679,0x367d,0x3683,0x3687,0x368b,0x368f,0x3693,0x3697, +0x369d,0x36a1,0x36a5,0x36a9,0x36ad,0x36b1,0x36b5,0x36b9,0x36bd,0x301b,0x36c1,0x36c5,0x36cb,0x36cf,0x36d3,0x36d7, +0x3023,0x36db,0x36df,0x36e3,0x36e7,0x36eb,0x36ef,0x36f3,0x36f7,0x2bff,0x3139,0x36fb,0x36ff,0x3703,0x3707,0x370d, +0x3711,0x3715,0x3719,0x3027,0x371d,0x3723,0x3727,0x372b,0x31eb,0x372f,0x3733,0x3737,0x373b,0x373f,0x3745,0x3749, +0x374d,0x3751,0x3757,0x375b,0x375f,0x3763,0x2d17,0x3767,0x376b,0x3771,0x3777,0x377d,0x3781,0x3787,0x378b,0x378f, +0x3793,0x3797,0x302b,0x2e73,0x379b,0x379f,0x37a3,0x37a7,0x37ad,0x37b1,0x37b5,0x37b9,0x3149,0x37bd,0x37c1,0x37c7, +0x37cb,0x37cf,0x37d5,0x37db,0x37df,0x314d,0x37e3,0x37e7,0x37eb,0x37ef,0x37f3,0x37f7,0x37fb,0x3801,0x3805,0x380b, +0x380f,0x3815,0x3155,0x3819,0x381d,0x3823,0x3827,0x382b,0x3831,0x3837,0x383b,0x383f,0x3843,0x3847,0x3847,0x384b, +0x384f,0x315d,0x3853,0x3857,0x385b,0x385f,0x3863,0x3869,0x386d,0x2cdf,0x3873,0x3879,0x387d,0x3883,0x3889,0x388f, +0x3893,0x3175,0x3897,0x389d,0x38a3,0x38a9,0x38af,0x38b3,0x38b3,0x3179,0x31f3,0x38b7,0x38bb,0x38bf,0x38c3,0x38c9, +0x2c47,0x3181,0x38cd,0x38d1,0x3057,0x38d7,0x38dd,0x2f9f,0x38e3,0x38e7,0x3067,0x38eb,0x38ef,0x38f3,0x38f9,0x38f9, +0x38ff,0x3903,0x3907,0x390d,0x3911,0x3915,0x3919,0x391f,0x3923,0x3927,0x392b,0x392f,0x3933,0x3939,0x393d,0x3941, +0x3945,0x3949,0x394d,0x3951,0x3957,0x395d,0x3961,0x3967,0x396b,0x3971,0x3975,0x307f,0x3979,0x397f,0x3985,0x3989, +0x398f,0x3993,0x3999,0x399d,0x39a1,0x39a5,0x39a9,0x39ad,0x39b1,0x39b7,0x39bd,0x39c3,0x35ff,0x39c9,0x39cd,0x39d1, +0x39d5,0x39d9,0x39dd,0x39e1,0x39e5,0x39e9,0x39ed,0x39f1,0x39f5,0x2d27,0x39fb,0x39ff,0x3a03,0x3a07,0x3a0b,0x3a0f, +0x308b,0x3a13,0x3a17,0x3a1b,0x3a1f,0x3a23,0x3a29,0x3a2f,0x3a35,0x3a39,0x3a3d,0x3a41,0x3a45,0x3a4b,0x3a4f,0x3a55, +0x3a59,0x3a5d,0x3a63,0x3a69,0x3a6d,0x2c33,0x3a71,0x3a75,0x3a79,0x3a7d,0x3a81,0x3a85,0x319d,0x3a89,0x3a8d,0x3a91, +0x3a95,0x3a99,0x3a9d,0x3aa1,0x3aa5,0x3aa9,0x3aad,0x3ab3,0x3ab7,0x3abb,0x3abf,0x3ac3,0x3ac7,0x3acd,0x3ad3,0x3ad7, +0x3adb,0x31b1,0x31b5,0x3adf,0x3ae3,0x3ae9,0x3aed,0x3af1,0x3af5,0x3af9,0x3aff,0x3b05,0x3b09,0x3b0d,0x3b11,0x3b17, +0x31b9,0x3b1b,0x3b21,0x3b27,0x3b2b,0x3b2f,0x3b33,0x3b39,0x3b3d,0x3b41,0x3b45,0x3b49,0x3b4d,0x3b51,0x3b55,0x3b5b, +0x3b5f,0x3b63,0x3b67,0x3b6d,0x3b71,0x3b75,0x3b79,0x3b7d,0x3b83,0x3b89,0x3b8d,0x3b91,0x3b95,0x3b9b,0x3b9f,0x31d1, +0x31d1,0x3ba5,0x3ba9,0x3baf,0x3bb3,0x3bb7,0x3bbb,0x3bbf,0x3bc3,0x3bc7,0x3bcb,0x31d5,0x3bd1,0x3bd5,0x3bd9,0x3bdd, +0x3be1,0x3be5,0x3beb,0x3bef,0x3bf5,0x3bfb,0x3c01,0x3c05,0x3c09,0x3c0d,0x3c11,0x3c15,0x3c19,0x3c1d,0x3c21,1, +1 }; static const UCPTrie norm2_nfc_data_trie={ norm2_nfc_data_trieIndex, { norm2_nfc_data_trieData }, - 1788, 7984, + 1869, 8129, 0x2fc00, 0x30, 0, 0, 0, 0, @@ -645,7 +660,7 @@ static const UCPTrie norm2_nfc_data_trie={ 0x1, }; -static const uint16_t norm2_nfc_data_extraData[7732]={ +static const uint16_t norm2_nfc_data_extraData[7918]={ 0xffff,0xffff,0x8670,0x44dc,0x8670,0x44c0,0x8670,0x44de,0x600,0x180,0x602,0x182,0x604,0x185,0x606,0x186, 0x608,0x200,0x60c,0x205,0x60e,0x44d,0x610,0x189,0x612,0x3d44,0x614,0x18b,0x618,0x39a,0x61e,0x400, 0x622,0x404,0x646,0x3d41,0x64a,0x3c00,0x8650,0x208,0x60e,0x3c04,0x646,0x3c08,0x8662,0x3c0c,0x602,0x20c, @@ -730,406 +745,417 @@ static const uint16_t norm2_nfc_data_extraData[7732]={ 0xe132,0x615c,0xe132,0x6160,0xe132,0x6164,0xe132,0x6168,0xe132,0x616c,0xe132,0x6170,0xe132,0x6174,0xe132,0x6178, 0xe132,0x617c,0xe132,0x6180,0xe132,0x6184,0xe132,0x618a,0xe132,0x618e,0xe132,0x6192,0x6132,0x61a0,0xe134,0x61a2, 0x6132,0x61a6,0xe134,0x61a8,0x6132,0x61ac,0xe134,0x61ae,0x6132,0x61b2,0xe134,0x61b4,0x6132,0x61b8,0xe134,0x61ba, -0xe132,0x61ee,0xe132,0x61f0,0xe132,0x61f2,0xe132,0x61f4,0xe132,0x61fc,0xb489,0x2e82,0x2134,0xb489,0x2e82,0x2138, -0xb489,0x2e82,0x2156,0xb489,0x49c2,0x225c,0xb489,0x49c2,0x225e,0x3489,0xcf82,0x2696,0xb489,0xd5c2,0x2698,0x348b, -0x2c02,0x2978,0x348b,0x2e82,0x2976,0xb48b,0x2f42,0x297c,0xb48b,0x6bc2,0x2b74,0xb48b,0x6bc2,0x2b76,0xb48d,0x4c02, -0x3270,2,0xe602,0x41,0x302,0x600,0x3d4c,0x602,0x3d48,0x606,0x3d54,0x8612,0x3d50,0xe602,0x41,0x308, -0x8608,0x3bc,0xe602,0x41,0x30a,0x8602,0x3f4,0xca02,0x43,0x327,0x8602,0x3c10,0xe602,0x45,0x302,0x600, -0x3d80,0x602,0x3d7c,0x606,0x3d88,0x8612,0x3d84,0xe602,0x49,0x308,0x8602,0x3c5c,0xe602,0x4f,0x302,0x600, -0x3da4,0x602,0x3da0,0x606,0x3dac,0x8612,0x3da8,0xe602,0x4f,0x303,0x602,0x3c98,0x608,0x458,0x8610,0x3c9c, -0xe602,0x4f,0x308,0x8608,0x454,0xe602,0x55,0x308,0x600,0x3b6,0x602,0x3ae,0x608,0x3aa,0x8618,0x3b2, -0xe602,0x61,0x302,0x600,0x3d4e,0x602,0x3d4a,0x606,0x3d56,0x8612,0x3d52,0xe602,0x61,0x308,0x8608,0x3be, -0xe602,0x61,0x30a,0x8602,0x3f6,0xca02,0x63,0x327,0x8602,0x3c12,0xe602,0x65,0x302,0x600,0x3d82,0x602, -0x3d7e,0x606,0x3d8a,0x8612,0x3d86,0xe602,0x69,0x308,0x8602,0x3c5e,0xe602,0x6f,0x302,0x600,0x3da6,0x602, -0x3da2,0x606,0x3dae,0x8612,0x3daa,0xe602,0x6f,0x303,0x602,0x3c9a,0x608,0x45a,0x8610,0x3c9e,0xe602,0x6f, -0x308,0x8608,0x456,0xe602,0x75,0x308,0x600,0x3b8,0x602,0x3b0,0x608,0x3ac,0x8618,0x3b4,0xe602,0x41, -0x306,0x600,0x3d60,0x602,0x3d5c,0x606,0x3d68,0x8612,0x3d64,0xe602,0x61,0x306,0x600,0x3d62,0x602,0x3d5e, -0x606,0x3d6a,0x8612,0x3d66,0xe602,0x45,0x304,0x600,0x3c28,0x8602,0x3c2c,0xe602,0x65,0x304,0x600,0x3c2a, -0x8602,0x3c2e,0xe602,0x4f,0x304,0x600,0x3ca0,0x8602,0x3ca4,0xe602,0x6f,0x304,0x600,0x3ca2,0x8602,0x3ca6, -0xe602,0x53,0x301,0x860e,0x3cc8,0xe602,0x73,0x301,0x860e,0x3cca,0xe602,0x53,0x30c,0x860e,0x3ccc,0xe602, -0x73,0x30c,0x860e,0x3cce,0xe602,0x55,0x303,0x8602,0x3cf0,0xe602,0x75,0x303,0x8602,0x3cf2,0xe602,0x55, -0x304,0x8610,0x3cf4,0xe602,0x75,0x304,0x8610,0x3cf6,0xd802,0x4f,0x31b,0x600,0x3db8,0x602,0x3db4,0x606, -0x3dc0,0x612,0x3dbc,0x8646,0x3dc4,0xd802,0x6f,0x31b,0x600,0x3dba,0x602,0x3db6,0x606,0x3dc2,0x612,0x3dbe, -0x8646,0x3dc6,0xd802,0x55,0x31b,0x600,0x3dd4,0x602,0x3dd0,0x606,0x3ddc,0x612,0x3dd8,0x8646,0x3de0,0xd802, -0x75,0x31b,0x600,0x3dd6,0x602,0x3dd2,0x606,0x3dde,0x612,0x3dda,0x8646,0x3de2,0xca02,0x4f,0x328,0x8608, -0x3d8,0xca02,0x6f,0x328,0x8608,0x3da,0xe602,0x41,0x307,0x8608,0x3c0,0xe602,0x61,0x307,0x8608,0x3c2, -0xca02,0x45,0x327,0x860c,0x3c38,0xca02,0x65,0x327,0x860c,0x3c3a,0xe602,0x4f,0x307,0x8608,0x460,0xe602, -0x6f,0x307,0x8608,0x462,0xe602,0x3b1,0x301,0x868a,0x3f68,0xe602,0x3b7,0x301,0x868a,0x3f88,0xe602,0x3b9, -0x308,0x600,0x3fa4,0x602,0x720,0x8684,0x3fae,0xe602,0x3c5,0x308,0x600,0x3fc4,0x602,0x760,0x8684,0x3fce, -0xe602,0x3c9,0x301,0x868a,0x3fe8,2,0xcc6,0xcc2,0x99aa,0x1996,2,0xdd9,0xdcf,0x9b94,0x1bba,0xdc02, -0x4c,0x323,0x8608,0x3c70,0xdc02,0x6c,0x323,0x8608,0x3c72,0xdc02,0x52,0x323,0x8608,0x3cb8,0xdc02,0x72, -0x323,0x8608,0x3cba,0xdc02,0x53,0x323,0x860e,0x3cd0,0xdc02,0x73,0x323,0x860e,0x3cd2,0xdc02,0x41,0x323, -0x604,0x3d58,0x860c,0x3d6c,0xdc02,0x61,0x323,0x604,0x3d5a,0x860c,0x3d6e,0xdc02,0x45,0x323,0x8604,0x3d8c, -0xdc02,0x65,0x323,0x8604,0x3d8e,0xdc02,0x4f,0x323,0x8604,0x3db0,0xdc02,0x6f,0x323,0x8604,0x3db2,0xe602, -0x3b1,0x313,0x600,0x3e05,0x602,0x3e09,0x684,0x3e0d,0x868a,0x3f00,0xe602,0x3b1,0x314,0x600,0x3e07,0x602, -0x3e0b,0x684,0x3e0f,0x868a,0x3f02,0x1f00,0xe643,0x3b1,0x313,0x300,0x868a,0x3f04,0x1f01,0xe643,0x3b1,0x314, -0x300,0x868a,0x3f06,0x1f00,0xe643,0x3b1,0x313,0x301,0x868a,0x3f08,0x1f01,0xe643,0x3b1,0x314,0x301,0x868a, -0x3f0a,0x1f00,0xe643,0x3b1,0x313,0x342,0x868a,0x3f0c,0x1f01,0xe643,0x3b1,0x314,0x342,0x868a,0x3f0e,0xe602, -0x391,0x313,0x600,0x3e15,0x602,0x3e19,0x684,0x3e1d,0x868a,0x3f10,0xe602,0x391,0x314,0x600,0x3e17,0x602, -0x3e1b,0x684,0x3e1f,0x868a,0x3f12,0x1f08,0xe643,0x391,0x313,0x300,0x868a,0x3f14,0x1f09,0xe643,0x391,0x314, -0x300,0x868a,0x3f16,0x1f08,0xe643,0x391,0x313,0x301,0x868a,0x3f18,0x1f09,0xe643,0x391,0x314,0x301,0x868a, -0x3f1a,0x1f08,0xe643,0x391,0x313,0x342,0x868a,0x3f1c,0x1f09,0xe643,0x391,0x314,0x342,0x868a,0x3f1e,0xe602, -0x3b5,0x313,0x600,0x3e24,0x8602,0x3e28,0xe602,0x3b5,0x314,0x600,0x3e26,0x8602,0x3e2a,0xe602,0x395,0x313, -0x600,0x3e34,0x8602,0x3e38,0xe602,0x395,0x314,0x600,0x3e36,0x8602,0x3e3a,0xe602,0x3b7,0x313,0x600,0x3e45, -0x602,0x3e49,0x684,0x3e4d,0x868a,0x3f20,0xe602,0x3b7,0x314,0x600,0x3e47,0x602,0x3e4b,0x684,0x3e4f,0x868a, -0x3f22,0x1f20,0xe643,0x3b7,0x313,0x300,0x868a,0x3f24,0x1f21,0xe643,0x3b7,0x314,0x300,0x868a,0x3f26,0x1f20, -0xe643,0x3b7,0x313,0x301,0x868a,0x3f28,0x1f21,0xe643,0x3b7,0x314,0x301,0x868a,0x3f2a,0x1f20,0xe643,0x3b7, -0x313,0x342,0x868a,0x3f2c,0x1f21,0xe643,0x3b7,0x314,0x342,0x868a,0x3f2e,0xe602,0x397,0x313,0x600,0x3e55, -0x602,0x3e59,0x684,0x3e5d,0x868a,0x3f30,0xe602,0x397,0x314,0x600,0x3e57,0x602,0x3e5b,0x684,0x3e5f,0x868a, -0x3f32,0x1f28,0xe643,0x397,0x313,0x300,0x868a,0x3f34,0x1f29,0xe643,0x397,0x314,0x300,0x868a,0x3f36,0x1f28, -0xe643,0x397,0x313,0x301,0x868a,0x3f38,0x1f29,0xe643,0x397,0x314,0x301,0x868a,0x3f3a,0x1f28,0xe643,0x397, -0x313,0x342,0x868a,0x3f3c,0x1f29,0xe643,0x397,0x314,0x342,0x868a,0x3f3e,0xe602,0x3b9,0x313,0x600,0x3e64, -0x602,0x3e68,0x8684,0x3e6c,0xe602,0x3b9,0x314,0x600,0x3e66,0x602,0x3e6a,0x8684,0x3e6e,0xe602,0x399,0x313, -0x600,0x3e74,0x602,0x3e78,0x8684,0x3e7c,0xe602,0x399,0x314,0x600,0x3e76,0x602,0x3e7a,0x8684,0x3e7e,0xe602, -0x3bf,0x313,0x600,0x3e84,0x8602,0x3e88,0xe602,0x3bf,0x314,0x600,0x3e86,0x8602,0x3e8a,0xe602,0x39f,0x313, -0x600,0x3e94,0x8602,0x3e98,0xe602,0x39f,0x314,0x600,0x3e96,0x8602,0x3e9a,0xe602,0x3c5,0x313,0x600,0x3ea4, -0x602,0x3ea8,0x8684,0x3eac,0xe602,0x3c5,0x314,0x600,0x3ea6,0x602,0x3eaa,0x8684,0x3eae,0xe602,0x3a5,0x314, -0x600,0x3eb6,0x602,0x3eba,0x8684,0x3ebe,0xe602,0x3c9,0x313,0x600,0x3ec5,0x602,0x3ec9,0x684,0x3ecd,0x868a, -0x3f40,0xe602,0x3c9,0x314,0x600,0x3ec7,0x602,0x3ecb,0x684,0x3ecf,0x868a,0x3f42,0x1f60,0xe643,0x3c9,0x313, -0x300,0x868a,0x3f44,0x1f61,0xe643,0x3c9,0x314,0x300,0x868a,0x3f46,0x1f60,0xe643,0x3c9,0x313,0x301,0x868a, -0x3f48,0x1f61,0xe643,0x3c9,0x314,0x301,0x868a,0x3f4a,0x1f60,0xe643,0x3c9,0x313,0x342,0x868a,0x3f4c,0x1f61, -0xe643,0x3c9,0x314,0x342,0x868a,0x3f4e,0xe602,0x3a9,0x313,0x600,0x3ed5,0x602,0x3ed9,0x684,0x3edd,0x868a, -0x3f50,0xe602,0x3a9,0x314,0x600,0x3ed7,0x602,0x3edb,0x684,0x3edf,0x868a,0x3f52,0x1f68,0xe643,0x3a9,0x313, -0x300,0x868a,0x3f54,0x1f69,0xe643,0x3a9,0x314,0x300,0x868a,0x3f56,0x1f68,0xe643,0x3a9,0x313,0x301,0x868a, -0x3f58,0x1f69,0xe643,0x3a9,0x314,0x301,0x868a,0x3f5a,0x1f68,0xe643,0x3a9,0x313,0x342,0x868a,0x3f5c,0x1f69, -0xe643,0x3a9,0x314,0x342,0x868a,0x3f5e,0xe602,0x3b1,0x300,0x868a,0x3f64,0xe602,0x3b7,0x300,0x868a,0x3f84, -0xe602,0x3c9,0x300,0x868a,0x3fe4,0xe602,0x3b1,0x342,0x868a,0x3f6e,0xe602,0x3b7,0x342,0x868a,0x3f8e,0xe602, -0x3c9,0x342,0x868a,0x3fee,3,0xe602,0x41,0x300,0xe602,0x41,0x301,0xe602,0x41,0x303,0xe602,0x45, -0x300,0xe602,0x45,0x301,0xe602,0x45,0x308,0xe602,0x49,0x300,0xe602,0x49,0x301,0xe602,0x49,0x302, -0xe602,0x4e,0x303,0xe602,0x4f,0x300,0xe602,0x4f,0x301,0xe602,0x55,0x300,0xe602,0x55,0x301,0xe602, -0x55,0x302,0xe602,0x59,0x301,0xe602,0x61,0x300,0xe602,0x61,0x301,0xe602,0x61,0x303,0xe602,0x65, -0x300,0xe602,0x65,0x301,0xe602,0x65,0x308,0xe602,0x69,0x300,0xe602,0x69,0x301,0xe602,0x69,0x302, -0xe602,0x6e,0x303,0xe602,0x6f,0x300,0xe602,0x6f,0x301,0xe602,0x75,0x300,0xe602,0x75,0x301,0xe602, -0x75,0x302,0xe602,0x79,0x301,0xe602,0x79,0x308,0xe602,0x41,0x304,0xe602,0x61,0x304,0xca02,0x41, -0x328,0xca02,0x61,0x328,0xe602,0x43,0x301,0xe602,0x63,0x301,0xe602,0x43,0x302,0xe602,0x63,0x302, -0xe602,0x43,0x307,0xe602,0x63,0x307,0xe602,0x43,0x30c,0xe602,0x63,0x30c,0xe602,0x44,0x30c,0xe602, -0x64,0x30c,0xe602,0x45,0x306,0xe602,0x65,0x306,0xe602,0x45,0x307,0xe602,0x65,0x307,0xca02,0x45, -0x328,0xca02,0x65,0x328,0xe602,0x45,0x30c,0xe602,0x65,0x30c,0xe602,0x47,0x302,0xe602,0x67,0x302, -0xe602,0x47,0x306,0xe602,0x67,0x306,0xe602,0x47,0x307,0xe602,0x67,0x307,0xca02,0x47,0x327,0xca02, -0x67,0x327,0xe602,0x48,0x302,0xe602,0x68,0x302,0xe602,0x49,0x303,0xe602,0x69,0x303,0xe602,0x49, -0x304,0xe602,0x69,0x304,0xe602,0x49,0x306,0xe602,0x69,0x306,0xca02,0x49,0x328,0xca02,0x69,0x328, -0xe602,0x49,0x307,0xe602,0x4a,0x302,0xe602,0x6a,0x302,0xca02,0x4b,0x327,0xca02,0x6b,0x327,0xe602, -0x4c,0x301,0xe602,0x6c,0x301,0xca02,0x4c,0x327,0xca02,0x6c,0x327,0xe602,0x4c,0x30c,0xe602,0x6c, -0x30c,0xe602,0x4e,0x301,0xe602,0x6e,0x301,0xca02,0x4e,0x327,0xca02,0x6e,0x327,0xe602,0x4e,0x30c, -0xe602,0x6e,0x30c,0xe602,0x4f,0x306,0xe602,0x6f,0x306,0xe602,0x4f,0x30b,0xe602,0x6f,0x30b,0xe602, -0x52,0x301,0xe602,0x72,0x301,0xca02,0x52,0x327,0xca02,0x72,0x327,0xe602,0x52,0x30c,0xe602,0x72, -0x30c,0xe602,0x53,0x302,0xe602,0x73,0x302,0xca02,0x53,0x327,0xca02,0x73,0x327,0xca02,0x54,0x327, -0xca02,0x74,0x327,0xe602,0x54,0x30c,0xe602,0x74,0x30c,0xe602,0x55,0x306,0xe602,0x75,0x306,0xe602, -0x55,0x30a,0xe602,0x75,0x30a,0xe602,0x55,0x30b,0xe602,0x75,0x30b,0xca02,0x55,0x328,0xca02,0x75, -0x328,0xe602,0x57,0x302,0xe602,0x77,0x302,0xe602,0x59,0x302,0xe602,0x79,0x302,0xe602,0x59,0x308, -0xe602,0x5a,0x301,0xe602,0x7a,0x301,0xe602,0x5a,0x307,0xe602,0x7a,0x307,0xe602,0x5a,0x30c,0xe602, -0x7a,0x30c,0xe602,0x41,0x30c,0xe602,0x61,0x30c,0xe602,0x49,0x30c,0xe602,0x69,0x30c,0xe602,0x4f, -0x30c,0xe602,0x6f,0x30c,0xe602,0x55,0x30c,0xe602,0x75,0x30c,0xdc,0xe643,0x55,0x308,0x304,0xfc, -0xe643,0x75,0x308,0x304,0xdc,0xe643,0x55,0x308,0x301,0xfc,0xe643,0x75,0x308,0x301,0xdc,0xe643, -0x55,0x308,0x30c,0xfc,0xe643,0x75,0x308,0x30c,0xdc,0xe643,0x55,0x308,0x300,0xfc,0xe643,0x75, -0x308,0x300,0xc4,0xe643,0x41,0x308,0x304,0xe4,0xe643,0x61,0x308,0x304,0x226,0xe643,0x41,0x307, -0x304,0x227,0xe643,0x61,0x307,0x304,0xe602,0xc6,0x304,0xe602,0xe6,0x304,0xe602,0x47,0x30c,0xe602, -0x67,0x30c,0xe602,0x4b,0x30c,0xe602,0x6b,0x30c,0x1ea,0xe643,0x4f,0x328,0x304,0x1eb,0xe643,0x6f, -0x328,0x304,0xe602,0x1b7,0x30c,0xe602,0x292,0x30c,0xe602,0x6a,0x30c,0xe602,0x47,0x301,0xe602,0x67, -0x301,0xe602,0x4e,0x300,0xe602,0x6e,0x300,0xc5,0xe643,0x41,0x30a,0x301,0xe5,0xe643,0x61,0x30a, -0x301,0xe602,0xc6,0x301,0xe602,0xe6,0x301,0xe602,0xd8,0x301,0xe602,0xf8,0x301,0xe602,0x41,0x30f, -0xe602,0x61,0x30f,0xe602,0x41,0x311,0xe602,0x61,0x311,0xe602,0x45,0x30f,0xe602,0x65,0x30f,0xe602, -0x45,0x311,0xe602,0x65,0x311,0xe602,0x49,0x30f,0xe602,0x69,0x30f,0xe602,0x49,0x311,0xe602,0x69, -0x311,0xe602,0x4f,0x30f,0xe602,0x6f,0x30f,0xe602,0x4f,0x311,0xe602,0x6f,0x311,0xe602,0x52,0x30f, -0xe602,0x72,0x30f,0xe602,0x52,0x311,0xe602,0x72,0x311,0xe602,0x55,0x30f,0xe602,0x75,0x30f,0xe602, -0x55,0x311,0xe602,0x75,0x311,0xdc02,0x53,0x326,0xdc02,0x73,0x326,0xdc02,0x54,0x326,0xdc02,0x74, -0x326,0xe602,0x48,0x30c,0xe602,0x68,0x30c,0xd6,0xe643,0x4f,0x308,0x304,0xf6,0xe643,0x6f,0x308, -0x304,0xd5,0xe643,0x4f,0x303,0x304,0xf5,0xe643,0x6f,0x303,0x304,0x22e,0xe643,0x4f,0x307,0x304, -0x22f,0xe643,0x6f,0x307,0x304,0xe602,0x59,0x304,0xe602,0x79,0x304,0xe602,0xa8,0x301,0xe602,0x391, -0x301,0xe602,0x395,0x301,0xe602,0x397,0x301,0xe602,0x399,0x301,0xe602,0x39f,0x301,0xe602,0x3a5,0x301, -0xe602,0x3a9,0x301,0x3ca,0xe643,0x3b9,0x308,0x301,0xe602,0x399,0x308,0xe602,0x3a5,0x308,0xe602,0x3b5, -0x301,0xe602,0x3b9,0x301,0x3cb,0xe643,0x3c5,0x308,0x301,0xe602,0x3bf,0x301,0xe602,0x3c5,0x301,0xe602, -0x3d2,0x301,0xe602,0x3d2,0x308,0xe602,0x415,0x300,0xe602,0x415,0x308,0xe602,0x413,0x301,0xe602,0x406, -0x308,0xe602,0x41a,0x301,0xe602,0x418,0x300,0xe602,0x423,0x306,0xe602,0x418,0x306,0xe602,0x438,0x306, -0xe602,0x435,0x300,0xe602,0x435,0x308,0xe602,0x433,0x301,0xe602,0x456,0x308,0xe602,0x43a,0x301,0xe602, -0x438,0x300,0xe602,0x443,0x306,0xe602,0x474,0x30f,0xe602,0x475,0x30f,0xe602,0x416,0x306,0xe602,0x436, -0x306,0xe602,0x410,0x306,0xe602,0x430,0x306,0xe602,0x410,0x308,0xe602,0x430,0x308,0xe602,0x415,0x306, -0xe602,0x435,0x306,0xe602,0x4d8,0x308,0xe602,0x4d9,0x308,0xe602,0x416,0x308,0xe602,0x436,0x308,0xe602, -0x417,0x308,0xe602,0x437,0x308,0xe602,0x418,0x304,0xe602,0x438,0x304,0xe602,0x418,0x308,0xe602,0x438, -0x308,0xe602,0x41e,0x308,0xe602,0x43e,0x308,0xe602,0x4e8,0x308,0xe602,0x4e9,0x308,0xe602,0x42d,0x308, -0xe602,0x44d,0x308,0xe602,0x423,0x304,0xe602,0x443,0x304,0xe602,0x423,0x308,0xe602,0x443,0x308,0xe602, -0x423,0x30b,0xe602,0x443,0x30b,0xe602,0x427,0x308,0xe602,0x447,0x308,0xe602,0x42b,0x308,0xe602,0x44b, -0x308,0xe602,0x627,0x653,0xe602,0x627,0x654,0xe602,0x648,0x654,0xdc02,0x627,0x655,0xe602,0x64a,0x654, -0xe602,0x6d5,0x654,0xe602,0x6c1,0x654,0xe602,0x6d2,0x654,0x702,0x928,0x93c,0x702,0x930,0x93c,0x702, -0x933,0x93c,2,0x9c7,0x9be,2,0x9c7,0x9d7,2,0xb47,0xb56,2,0xb47,0xb3e,2,0xb47, -0xb57,2,0xb92,0xbd7,2,0xbc6,0xbbe,2,0xbc7,0xbbe,2,0xbc6,0xbd7,0x5b02,0xc46,0xc56, -2,0xcbf,0xcd5,2,0xcc6,0xcd5,2,0xcc6,0xcd6,0xcca,0x43,0xcc6,0xcc2,0xcd5,2,0xd46, -0xd3e,2,0xd47,0xd3e,2,0xd46,0xd57,0x902,0xdd9,0xdca,0xddc,0x943,0xdd9,0xdcf,0xdca,2, -0xdd9,0xddf,2,0x1025,0x102e,2,0x1b05,0x1b35,2,0x1b07,0x1b35,2,0x1b09,0x1b35,2,0x1b0b, -0x1b35,2,0x1b0d,0x1b35,2,0x1b11,0x1b35,2,0x1b3a,0x1b35,2,0x1b3c,0x1b35,2,0x1b3e,0x1b35, -2,0x1b3f,0x1b35,2,0x1b42,0x1b35,0xdc02,0x41,0x325,0xdc02,0x61,0x325,0xe602,0x42,0x307,0xe602, -0x62,0x307,0xdc02,0x42,0x323,0xdc02,0x62,0x323,0xdc02,0x42,0x331,0xdc02,0x62,0x331,0xc7,0xe643, -0x43,0x327,0x301,0xe7,0xe643,0x63,0x327,0x301,0xe602,0x44,0x307,0xe602,0x64,0x307,0xdc02,0x44, -0x323,0xdc02,0x64,0x323,0xdc02,0x44,0x331,0xdc02,0x64,0x331,0xca02,0x44,0x327,0xca02,0x64,0x327, -0xdc02,0x44,0x32d,0xdc02,0x64,0x32d,0x112,0xe643,0x45,0x304,0x300,0x113,0xe643,0x65,0x304,0x300, -0x112,0xe643,0x45,0x304,0x301,0x113,0xe643,0x65,0x304,0x301,0xdc02,0x45,0x32d,0xdc02,0x65,0x32d, -0xdc02,0x45,0x330,0xdc02,0x65,0x330,0x228,0xe643,0x45,0x327,0x306,0x229,0xe643,0x65,0x327,0x306, -0xe602,0x46,0x307,0xe602,0x66,0x307,0xe602,0x47,0x304,0xe602,0x67,0x304,0xe602,0x48,0x307,0xe602, -0x68,0x307,0xdc02,0x48,0x323,0xdc02,0x68,0x323,0xe602,0x48,0x308,0xe602,0x68,0x308,0xca02,0x48, -0x327,0xca02,0x68,0x327,0xdc02,0x48,0x32e,0xdc02,0x68,0x32e,0xdc02,0x49,0x330,0xdc02,0x69,0x330, -0xcf,0xe643,0x49,0x308,0x301,0xef,0xe643,0x69,0x308,0x301,0xe602,0x4b,0x301,0xe602,0x6b,0x301, -0xdc02,0x4b,0x323,0xdc02,0x6b,0x323,0xdc02,0x4b,0x331,0xdc02,0x6b,0x331,0x1e36,0xe643,0x4c,0x323, -0x304,0x1e37,0xe643,0x6c,0x323,0x304,0xdc02,0x4c,0x331,0xdc02,0x6c,0x331,0xdc02,0x4c,0x32d,0xdc02, -0x6c,0x32d,0xe602,0x4d,0x301,0xe602,0x6d,0x301,0xe602,0x4d,0x307,0xe602,0x6d,0x307,0xdc02,0x4d, -0x323,0xdc02,0x6d,0x323,0xe602,0x4e,0x307,0xe602,0x6e,0x307,0xdc02,0x4e,0x323,0xdc02,0x6e,0x323, -0xdc02,0x4e,0x331,0xdc02,0x6e,0x331,0xdc02,0x4e,0x32d,0xdc02,0x6e,0x32d,0xd5,0xe643,0x4f,0x303, -0x301,0xf5,0xe643,0x6f,0x303,0x301,0xd5,0xe643,0x4f,0x303,0x308,0xf5,0xe643,0x6f,0x303,0x308, -0x14c,0xe643,0x4f,0x304,0x300,0x14d,0xe643,0x6f,0x304,0x300,0x14c,0xe643,0x4f,0x304,0x301,0x14d, -0xe643,0x6f,0x304,0x301,0xe602,0x50,0x301,0xe602,0x70,0x301,0xe602,0x50,0x307,0xe602,0x70,0x307, -0xe602,0x52,0x307,0xe602,0x72,0x307,0x1e5a,0xe643,0x52,0x323,0x304,0x1e5b,0xe643,0x72,0x323,0x304, -0xdc02,0x52,0x331,0xdc02,0x72,0x331,0xe602,0x53,0x307,0xe602,0x73,0x307,0x15a,0xe643,0x53,0x301, -0x307,0x15b,0xe643,0x73,0x301,0x307,0x160,0xe643,0x53,0x30c,0x307,0x161,0xe643,0x73,0x30c,0x307, -0x1e62,0xe643,0x53,0x323,0x307,0x1e63,0xe643,0x73,0x323,0x307,0xe602,0x54,0x307,0xe602,0x74,0x307, -0xdc02,0x54,0x323,0xdc02,0x74,0x323,0xdc02,0x54,0x331,0xdc02,0x74,0x331,0xdc02,0x54,0x32d,0xdc02, -0x74,0x32d,0xdc02,0x55,0x324,0xdc02,0x75,0x324,0xdc02,0x55,0x330,0xdc02,0x75,0x330,0xdc02,0x55, -0x32d,0xdc02,0x75,0x32d,0x168,0xe643,0x55,0x303,0x301,0x169,0xe643,0x75,0x303,0x301,0x16a,0xe643, -0x55,0x304,0x308,0x16b,0xe643,0x75,0x304,0x308,0xe602,0x56,0x303,0xe602,0x76,0x303,0xdc02,0x56, -0x323,0xdc02,0x76,0x323,0xe602,0x57,0x300,0xe602,0x77,0x300,0xe602,0x57,0x301,0xe602,0x77,0x301, -0xe602,0x57,0x308,0xe602,0x77,0x308,0xe602,0x57,0x307,0xe602,0x77,0x307,0xdc02,0x57,0x323,0xdc02, -0x77,0x323,0xe602,0x58,0x307,0xe602,0x78,0x307,0xe602,0x58,0x308,0xe602,0x78,0x308,0xe602,0x59, -0x307,0xe602,0x79,0x307,0xe602,0x5a,0x302,0xe602,0x7a,0x302,0xdc02,0x5a,0x323,0xdc02,0x7a,0x323, -0xdc02,0x5a,0x331,0xdc02,0x7a,0x331,0xdc02,0x68,0x331,0xe602,0x74,0x308,0xe602,0x77,0x30a,0xe602, -0x79,0x30a,0xe602,0x17f,0x307,0xe602,0x41,0x309,0xe602,0x61,0x309,0xc2,0xe643,0x41,0x302,0x301, -0xe2,0xe643,0x61,0x302,0x301,0xc2,0xe643,0x41,0x302,0x300,0xe2,0xe643,0x61,0x302,0x300,0xc2, -0xe643,0x41,0x302,0x309,0xe2,0xe643,0x61,0x302,0x309,0xc2,0xe643,0x41,0x302,0x303,0xe2,0xe643, -0x61,0x302,0x303,0x1ea0,0xe643,0x41,0x323,0x302,0x1ea1,0xe643,0x61,0x323,0x302,0x102,0xe643,0x41, -0x306,0x301,0x103,0xe643,0x61,0x306,0x301,0x102,0xe643,0x41,0x306,0x300,0x103,0xe643,0x61,0x306, -0x300,0x102,0xe643,0x41,0x306,0x309,0x103,0xe643,0x61,0x306,0x309,0x102,0xe643,0x41,0x306,0x303, -0x103,0xe643,0x61,0x306,0x303,0x1ea0,0xe643,0x41,0x323,0x306,0x1ea1,0xe643,0x61,0x323,0x306,0xe602, -0x45,0x309,0xe602,0x65,0x309,0xe602,0x45,0x303,0xe602,0x65,0x303,0xca,0xe643,0x45,0x302,0x301, -0xea,0xe643,0x65,0x302,0x301,0xca,0xe643,0x45,0x302,0x300,0xea,0xe643,0x65,0x302,0x300,0xca, -0xe643,0x45,0x302,0x309,0xea,0xe643,0x65,0x302,0x309,0xca,0xe643,0x45,0x302,0x303,0xea,0xe643, -0x65,0x302,0x303,0x1eb8,0xe643,0x45,0x323,0x302,0x1eb9,0xe643,0x65,0x323,0x302,0xe602,0x49,0x309, -0xe602,0x69,0x309,0xdc02,0x49,0x323,0xdc02,0x69,0x323,0xe602,0x4f,0x309,0xe602,0x6f,0x309,0xd4, -0xe643,0x4f,0x302,0x301,0xf4,0xe643,0x6f,0x302,0x301,0xd4,0xe643,0x4f,0x302,0x300,0xf4,0xe643, -0x6f,0x302,0x300,0xd4,0xe643,0x4f,0x302,0x309,0xf4,0xe643,0x6f,0x302,0x309,0xd4,0xe643,0x4f, -0x302,0x303,0xf4,0xe643,0x6f,0x302,0x303,0x1ecc,0xe643,0x4f,0x323,0x302,0x1ecd,0xe643,0x6f,0x323, -0x302,0x1a0,0xe643,0x4f,0x31b,0x301,0x1a1,0xe643,0x6f,0x31b,0x301,0x1a0,0xe643,0x4f,0x31b,0x300, -0x1a1,0xe643,0x6f,0x31b,0x300,0x1a0,0xe643,0x4f,0x31b,0x309,0x1a1,0xe643,0x6f,0x31b,0x309,0x1a0, -0xe643,0x4f,0x31b,0x303,0x1a1,0xe643,0x6f,0x31b,0x303,0x1a0,0xdc43,0x4f,0x31b,0x323,0x1a1,0xdc43, -0x6f,0x31b,0x323,0xdc02,0x55,0x323,0xdc02,0x75,0x323,0xe602,0x55,0x309,0xe602,0x75,0x309,0x1af, -0xe643,0x55,0x31b,0x301,0x1b0,0xe643,0x75,0x31b,0x301,0x1af,0xe643,0x55,0x31b,0x300,0x1b0,0xe643, -0x75,0x31b,0x300,0x1af,0xe643,0x55,0x31b,0x309,0x1b0,0xe643,0x75,0x31b,0x309,0x1af,0xe643,0x55, -0x31b,0x303,0x1b0,0xe643,0x75,0x31b,0x303,0x1af,0xdc43,0x55,0x31b,0x323,0x1b0,0xdc43,0x75,0x31b, -0x323,0xe602,0x59,0x300,0xe602,0x79,0x300,0xdc02,0x59,0x323,0xdc02,0x79,0x323,0xe602,0x59,0x309, -0xe602,0x79,0x309,0xe602,0x59,0x303,0xe602,0x79,0x303,0x1f10,0xe643,0x3b5,0x313,0x300,0x1f11,0xe643, -0x3b5,0x314,0x300,0x1f10,0xe643,0x3b5,0x313,0x301,0x1f11,0xe643,0x3b5,0x314,0x301,0x1f18,0xe643,0x395, -0x313,0x300,0x1f19,0xe643,0x395,0x314,0x300,0x1f18,0xe643,0x395,0x313,0x301,0x1f19,0xe643,0x395,0x314, -0x301,0x1f30,0xe643,0x3b9,0x313,0x300,0x1f31,0xe643,0x3b9,0x314,0x300,0x1f30,0xe643,0x3b9,0x313,0x301, -0x1f31,0xe643,0x3b9,0x314,0x301,0x1f30,0xe643,0x3b9,0x313,0x342,0x1f31,0xe643,0x3b9,0x314,0x342,0x1f38, -0xe643,0x399,0x313,0x300,0x1f39,0xe643,0x399,0x314,0x300,0x1f38,0xe643,0x399,0x313,0x301,0x1f39,0xe643, -0x399,0x314,0x301,0x1f38,0xe643,0x399,0x313,0x342,0x1f39,0xe643,0x399,0x314,0x342,0x1f40,0xe643,0x3bf, -0x313,0x300,0x1f41,0xe643,0x3bf,0x314,0x300,0x1f40,0xe643,0x3bf,0x313,0x301,0x1f41,0xe643,0x3bf,0x314, -0x301,0x1f48,0xe643,0x39f,0x313,0x300,0x1f49,0xe643,0x39f,0x314,0x300,0x1f48,0xe643,0x39f,0x313,0x301, -0x1f49,0xe643,0x39f,0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x300,0x1f51,0xe643,0x3c5,0x314,0x300,0x1f50, -0xe643,0x3c5,0x313,0x301,0x1f51,0xe643,0x3c5,0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x342,0x1f51,0xe643, -0x3c5,0x314,0x342,0x1f59,0xe643,0x3a5,0x314,0x300,0x1f59,0xe643,0x3a5,0x314,0x301,0x1f59,0xe643,0x3a5, -0x314,0x342,0xe602,0x3b5,0x300,0xe602,0x3b9,0x300,0xe602,0x3bf,0x300,0xe602,0x3c5,0x300,0x1f00,0xf043, -0x3b1,0x313,0x345,0x1f01,0xf043,0x3b1,0x314,0x345,0x1f02,0x345,2,0xf044,0x3b1,0x313,0x300,0x345, -0x1f03,0x345,2,0xf044,0x3b1,0x314,0x300,0x345,0x1f04,0x345,2,0xf044,0x3b1,0x313,0x301,0x345, -0x1f05,0x345,2,0xf044,0x3b1,0x314,0x301,0x345,0x1f06,0x345,2,0xf044,0x3b1,0x313,0x342,0x345, -0x1f07,0x345,2,0xf044,0x3b1,0x314,0x342,0x345,0x1f08,0xf043,0x391,0x313,0x345,0x1f09,0xf043,0x391, -0x314,0x345,0x1f0a,0x345,2,0xf044,0x391,0x313,0x300,0x345,0x1f0b,0x345,2,0xf044,0x391,0x314, -0x300,0x345,0x1f0c,0x345,2,0xf044,0x391,0x313,0x301,0x345,0x1f0d,0x345,2,0xf044,0x391,0x314, -0x301,0x345,0x1f0e,0x345,2,0xf044,0x391,0x313,0x342,0x345,0x1f0f,0x345,2,0xf044,0x391,0x314, -0x342,0x345,0x1f20,0xf043,0x3b7,0x313,0x345,0x1f21,0xf043,0x3b7,0x314,0x345,0x1f22,0x345,2,0xf044, -0x3b7,0x313,0x300,0x345,0x1f23,0x345,2,0xf044,0x3b7,0x314,0x300,0x345,0x1f24,0x345,2,0xf044, -0x3b7,0x313,0x301,0x345,0x1f25,0x345,2,0xf044,0x3b7,0x314,0x301,0x345,0x1f26,0x345,2,0xf044, -0x3b7,0x313,0x342,0x345,0x1f27,0x345,2,0xf044,0x3b7,0x314,0x342,0x345,0x1f28,0xf043,0x397,0x313, -0x345,0x1f29,0xf043,0x397,0x314,0x345,0x1f2a,0x345,2,0xf044,0x397,0x313,0x300,0x345,0x1f2b,0x345, -2,0xf044,0x397,0x314,0x300,0x345,0x1f2c,0x345,2,0xf044,0x397,0x313,0x301,0x345,0x1f2d,0x345, -2,0xf044,0x397,0x314,0x301,0x345,0x1f2e,0x345,2,0xf044,0x397,0x313,0x342,0x345,0x1f2f,0x345, -2,0xf044,0x397,0x314,0x342,0x345,0x1f60,0xf043,0x3c9,0x313,0x345,0x1f61,0xf043,0x3c9,0x314,0x345, -0x1f62,0x345,2,0xf044,0x3c9,0x313,0x300,0x345,0x1f63,0x345,2,0xf044,0x3c9,0x314,0x300,0x345, -0x1f64,0x345,2,0xf044,0x3c9,0x313,0x301,0x345,0x1f65,0x345,2,0xf044,0x3c9,0x314,0x301,0x345, -0x1f66,0x345,2,0xf044,0x3c9,0x313,0x342,0x345,0x1f67,0x345,2,0xf044,0x3c9,0x314,0x342,0x345, -0x1f68,0xf043,0x3a9,0x313,0x345,0x1f69,0xf043,0x3a9,0x314,0x345,0x1f6a,0x345,2,0xf044,0x3a9,0x313, -0x300,0x345,0x1f6b,0x345,2,0xf044,0x3a9,0x314,0x300,0x345,0x1f6c,0x345,2,0xf044,0x3a9,0x313, -0x301,0x345,0x1f6d,0x345,2,0xf044,0x3a9,0x314,0x301,0x345,0x1f6e,0x345,2,0xf044,0x3a9,0x313, -0x342,0x345,0x1f6f,0x345,2,0xf044,0x3a9,0x314,0x342,0x345,0xe602,0x3b1,0x306,0xe602,0x3b1,0x304, -0x1f70,0xf043,0x3b1,0x300,0x345,0xf002,0x3b1,0x345,0x3ac,0xf043,0x3b1,0x301,0x345,0x1fb6,0xf043,0x3b1, -0x342,0x345,0xe602,0x391,0x306,0xe602,0x391,0x304,0xe602,0x391,0x300,0xf002,0x391,0x345,0xe602,0xa8, -0x342,0x1f74,0xf043,0x3b7,0x300,0x345,0xf002,0x3b7,0x345,0x3ae,0xf043,0x3b7,0x301,0x345,0x1fc6,0xf043, -0x3b7,0x342,0x345,0xe602,0x395,0x300,0xe602,0x397,0x300,0xf002,0x397,0x345,0xe602,0x1fbf,0x300,0xe602, -0x1fbf,0x301,0xe602,0x1fbf,0x342,0xe602,0x3b9,0x306,0xe602,0x3b9,0x304,0x3ca,0xe643,0x3b9,0x308,0x300, -0xe602,0x3b9,0x342,0x3ca,0xe643,0x3b9,0x308,0x342,0xe602,0x399,0x306,0xe602,0x399,0x304,0xe602,0x399, -0x300,0xe602,0x1ffe,0x300,0xe602,0x1ffe,0x301,0xe602,0x1ffe,0x342,0xe602,0x3c5,0x306,0xe602,0x3c5,0x304, -0x3cb,0xe643,0x3c5,0x308,0x300,0xe602,0x3c1,0x313,0xe602,0x3c1,0x314,0xe602,0x3c5,0x342,0x3cb,0xe643, -0x3c5,0x308,0x342,0xe602,0x3a5,0x306,0xe602,0x3a5,0x304,0xe602,0x3a5,0x300,0xe602,0x3a1,0x314,0xe602, -0xa8,0x300,0x1f7c,0xf043,0x3c9,0x300,0x345,0xf002,0x3c9,0x345,0x3ce,0xf043,0x3c9,0x301,0x345,0x1ff6, -0xf043,0x3c9,0x342,0x345,0xe602,0x39f,0x300,0xe602,0x3a9,0x300,0xf002,0x3a9,0x345,0x102,0x2190,0x338, -0x102,0x2192,0x338,0x102,0x2194,0x338,0x102,0x21d0,0x338,0x102,0x21d4,0x338,0x102,0x21d2,0x338,0x102, -0x2203,0x338,0x102,0x2208,0x338,0x102,0x220b,0x338,0x102,0x2223,0x338,0x102,0x2225,0x338,0x102,0x223c, -0x338,0x102,0x2243,0x338,0x102,0x2245,0x338,0x102,0x2248,0x338,0x102,0x3d,0x338,0x102,0x2261,0x338, -0x102,0x224d,0x338,0x102,0x3c,0x338,0x102,0x3e,0x338,0x102,0x2264,0x338,0x102,0x2265,0x338,0x102, -0x2272,0x338,0x102,0x2273,0x338,0x102,0x2276,0x338,0x102,0x2277,0x338,0x102,0x227a,0x338,0x102,0x227b, -0x338,0x102,0x2282,0x338,0x102,0x2283,0x338,0x102,0x2286,0x338,0x102,0x2287,0x338,0x102,0x22a2,0x338, -0x102,0x22a8,0x338,0x102,0x22a9,0x338,0x102,0x22ab,0x338,0x102,0x227c,0x338,0x102,0x227d,0x338,0x102, -0x2291,0x338,0x102,0x2292,0x338,0x102,0x22b2,0x338,0x102,0x22b3,0x338,0x102,0x22b4,0x338,0x102,0x22b5, -0x338,0x802,0x304b,0x3099,0x802,0x304d,0x3099,0x802,0x304f,0x3099,0x802,0x3051,0x3099,0x802,0x3053,0x3099, -0x802,0x3055,0x3099,0x802,0x3057,0x3099,0x802,0x3059,0x3099,0x802,0x305b,0x3099,0x802,0x305d,0x3099,0x802, -0x305f,0x3099,0x802,0x3061,0x3099,0x802,0x3064,0x3099,0x802,0x3066,0x3099,0x802,0x3068,0x3099,0x802,0x306f, -0x3099,0x802,0x306f,0x309a,0x802,0x3072,0x3099,0x802,0x3072,0x309a,0x802,0x3075,0x3099,0x802,0x3075,0x309a, -0x802,0x3078,0x3099,0x802,0x3078,0x309a,0x802,0x307b,0x3099,0x802,0x307b,0x309a,0x802,0x3046,0x3099,0x802, -0x309d,0x3099,0x802,0x30ab,0x3099,0x802,0x30ad,0x3099,0x802,0x30af,0x3099,0x802,0x30b1,0x3099,0x802,0x30b3, -0x3099,0x802,0x30b5,0x3099,0x802,0x30b7,0x3099,0x802,0x30b9,0x3099,0x802,0x30bb,0x3099,0x802,0x30bd,0x3099, -0x802,0x30bf,0x3099,0x802,0x30c1,0x3099,0x802,0x30c4,0x3099,0x802,0x30c6,0x3099,0x802,0x30c8,0x3099,0x802, -0x30cf,0x3099,0x802,0x30cf,0x309a,0x802,0x30d2,0x3099,0x802,0x30d2,0x309a,0x802,0x30d5,0x3099,0x802,0x30d5, -0x309a,0x802,0x30d8,0x3099,0x802,0x30d8,0x309a,0x802,0x30db,0x3099,0x802,0x30db,0x309a,0x802,0x30a6,0x3099, -0x802,0x30ef,0x3099,0x802,0x30f0,0x3099,0x802,0x30f1,0x3099,0x802,0x30f2,0x3099,0x802,0x30fd,0x3099,0x704, -0xd804,0xdc99,0xd804,0xdcba,0x704,0xd804,0xdc9b,0xd804,0xdcba,0x704,0xd804,0xdca5,0xd804,0xdcba,4,0xd804, -0xdd31,0xd804,0xdd27,4,0xd804,0xdd32,0xd804,0xdd27,4,0xd804,0xdf47,0xd804,0xdf3e,4,0xd804,0xdf47, -0xd804,0xdf57,4,0xd805,0xdcb9,0xd805,0xdcba,4,0xd805,0xdcb9,0xd805,0xdcb0,4,0xd805,0xdcb9,0xd805, -0xdcbd,4,0xd805,0xddb8,0xd805,0xddaf,4,0xd805,0xddb9,0xd805,0xddaf,4,0xd806,0xdd35,0xd806,0xdd30, -1,0x2b9,1,0x3b,1,0xb7,0x702,0x915,0x93c,0x702,0x916,0x93c,0x702,0x917,0x93c,0x702, -0x91c,0x93c,0x702,0x921,0x93c,0x702,0x922,0x93c,0x702,0x92b,0x93c,0x702,0x92f,0x93c,0x702,0x9a1, -0x9bc,0x702,0x9a2,0x9bc,0x702,0x9af,0x9bc,0x702,0xa32,0xa3c,0x702,0xa38,0xa3c,0x702,0xa16,0xa3c, -0x702,0xa17,0xa3c,0x702,0xa1c,0xa3c,0x702,0xa2b,0xa3c,0x702,0xb21,0xb3c,0x702,0xb22,0xb3c,2, -0xf42,0xfb7,2,0xf4c,0xfb7,2,0xf51,0xfb7,2,0xf56,0xfb7,2,0xf5b,0xfb7,2,0xf40, -0xfb5,0x8202,0xfb2,0xf80,0x8202,0xfb3,0xf80,2,0xf92,0xfb7,2,0xf9c,0xfb7,2,0xfa1,0xfb7, -2,0xfa6,0xfb7,2,0xfab,0xfb7,2,0xf90,0xfb5,1,0x3b9,1,0x60,1,0xb4,1, -0x3a9,1,0x4b,1,0x3008,1,0x3009,0x102,0x2add,0x338,1,0x8c48,1,0x66f4,1,0x8eca, -1,0x8cc8,1,0x6ed1,1,0x4e32,1,0x53e5,1,0x9f9c,1,0x5951,1,0x91d1,1,0x5587, -1,0x5948,1,0x61f6,1,0x7669,1,0x7f85,1,0x863f,1,0x87ba,1,0x88f8,1,0x908f, -1,0x6a02,1,0x6d1b,1,0x70d9,1,0x73de,1,0x843d,1,0x916a,1,0x99f1,1,0x4e82, -1,0x5375,1,0x6b04,1,0x721b,1,0x862d,1,0x9e1e,1,0x5d50,1,0x6feb,1,0x85cd, -1,0x8964,1,0x62c9,1,0x81d8,1,0x881f,1,0x5eca,1,0x6717,1,0x6d6a,1,0x72fc, -1,0x90ce,1,0x4f86,1,0x51b7,1,0x52de,1,0x64c4,1,0x6ad3,1,0x7210,1,0x76e7, -1,0x8001,1,0x8606,1,0x865c,1,0x8def,1,0x9732,1,0x9b6f,1,0x9dfa,1,0x788c, -1,0x797f,1,0x7da0,1,0x83c9,1,0x9304,1,0x9e7f,1,0x8ad6,1,0x58df,1,0x5f04, -1,0x7c60,1,0x807e,1,0x7262,1,0x78ca,1,0x8cc2,1,0x96f7,1,0x58d8,1,0x5c62, -1,0x6a13,1,0x6dda,1,0x6f0f,1,0x7d2f,1,0x7e37,1,0x964b,1,0x52d2,1,0x808b, -1,0x51dc,1,0x51cc,1,0x7a1c,1,0x7dbe,1,0x83f1,1,0x9675,1,0x8b80,1,0x62cf, -1,0x8afe,1,0x4e39,1,0x5be7,1,0x6012,1,0x7387,1,0x7570,1,0x5317,1,0x78fb, -1,0x4fbf,1,0x5fa9,1,0x4e0d,1,0x6ccc,1,0x6578,1,0x7d22,1,0x53c3,1,0x585e, -1,0x7701,1,0x8449,1,0x8aaa,1,0x6bba,1,0x8fb0,1,0x6c88,1,0x62fe,1,0x82e5, -1,0x63a0,1,0x7565,1,0x4eae,1,0x5169,1,0x51c9,1,0x6881,1,0x7ce7,1,0x826f, -1,0x8ad2,1,0x91cf,1,0x52f5,1,0x5442,1,0x5973,1,0x5eec,1,0x65c5,1,0x6ffe, -1,0x792a,1,0x95ad,1,0x9a6a,1,0x9e97,1,0x9ece,1,0x529b,1,0x66c6,1,0x6b77, -1,0x8f62,1,0x5e74,1,0x6190,1,0x6200,1,0x649a,1,0x6f23,1,0x7149,1,0x7489, -1,0x79ca,1,0x7df4,1,0x806f,1,0x8f26,1,0x84ee,1,0x9023,1,0x934a,1,0x5217, -1,0x52a3,1,0x54bd,1,0x70c8,1,0x88c2,1,0x5ec9,1,0x5ff5,1,0x637b,1,0x6bae, -1,0x7c3e,1,0x7375,1,0x4ee4,1,0x56f9,1,0x5dba,1,0x601c,1,0x73b2,1,0x7469, -1,0x7f9a,1,0x8046,1,0x9234,1,0x96f6,1,0x9748,1,0x9818,1,0x4f8b,1,0x79ae, -1,0x91b4,1,0x96b8,1,0x60e1,1,0x4e86,1,0x50da,1,0x5bee,1,0x5c3f,1,0x6599, -1,0x71ce,1,0x7642,1,0x84fc,1,0x907c,1,0x9f8d,1,0x6688,1,0x962e,1,0x5289, -1,0x677b,1,0x67f3,1,0x6d41,1,0x6e9c,1,0x7409,1,0x7559,1,0x786b,1,0x7d10, -1,0x985e,1,0x516d,1,0x622e,1,0x9678,1,0x502b,1,0x5d19,1,0x6dea,1,0x8f2a, -1,0x5f8b,1,0x6144,1,0x6817,1,0x9686,1,0x5229,1,0x540f,1,0x5c65,1,0x6613, -1,0x674e,1,0x68a8,1,0x6ce5,1,0x7406,1,0x75e2,1,0x7f79,1,0x88cf,1,0x88e1, -1,0x91cc,1,0x96e2,1,0x533f,1,0x6eba,1,0x541d,1,0x71d0,1,0x7498,1,0x85fa, -1,0x96a3,1,0x9c57,1,0x9e9f,1,0x6797,1,0x6dcb,1,0x81e8,1,0x7acb,1,0x7b20, -1,0x7c92,1,0x72c0,1,0x7099,1,0x8b58,1,0x4ec0,1,0x8336,1,0x523a,1,0x5207, -1,0x5ea6,1,0x62d3,1,0x7cd6,1,0x5b85,1,0x6d1e,1,0x66b4,1,0x8f3b,1,0x884c, -1,0x964d,1,0x898b,1,0x5ed3,1,0x5140,1,0x55c0,1,0x585a,1,0x6674,1,0x51de, -1,0x732a,1,0x76ca,1,0x793c,1,0x795e,1,0x7965,1,0x798f,1,0x9756,1,0x7cbe, -1,0x7fbd,1,0x8612,1,0x8af8,1,0x9038,1,0x90fd,1,0x98ef,1,0x98fc,1,0x9928, -1,0x9db4,1,0x90de,1,0x96b7,1,0x4fae,1,0x50e7,1,0x514d,1,0x52c9,1,0x52e4, -1,0x5351,1,0x559d,1,0x5606,1,0x5668,1,0x5840,1,0x58a8,1,0x5c64,1,0x5c6e, -1,0x6094,1,0x6168,1,0x618e,1,0x61f2,1,0x654f,1,0x65e2,1,0x6691,1,0x6885, -1,0x6d77,1,0x6e1a,1,0x6f22,1,0x716e,1,0x722b,1,0x7422,1,0x7891,1,0x793e, -1,0x7949,1,0x7948,1,0x7950,1,0x7956,1,0x795d,1,0x798d,1,0x798e,1,0x7a40, -1,0x7a81,1,0x7bc0,1,0x7e09,1,0x7e41,1,0x7f72,1,0x8005,1,0x81ed,1,0x8279, -1,0x8457,1,0x8910,1,0x8996,1,0x8b01,1,0x8b39,1,0x8cd3,1,0x8d08,1,0x8fb6, -1,0x96e3,1,0x97ff,1,0x983b,1,0x6075,2,0xd850,0xdeee,1,0x8218,1,0x4e26,1, -0x51b5,1,0x5168,1,0x4f80,1,0x5145,1,0x5180,1,0x52c7,1,0x52fa,1,0x5555,1, -0x5599,1,0x55e2,1,0x58b3,1,0x5944,1,0x5954,1,0x5a62,1,0x5b28,1,0x5ed2,1, -0x5ed9,1,0x5f69,1,0x5fad,1,0x60d8,1,0x614e,1,0x6108,1,0x6160,1,0x6234,1, -0x63c4,1,0x641c,1,0x6452,1,0x6556,1,0x671b,1,0x6756,1,0x6b79,1,0x6edb,1, -0x6ecb,1,0x701e,1,0x77a7,1,0x7235,1,0x72af,1,0x7471,1,0x7506,1,0x753b,1, -0x761d,1,0x761f,1,0x76db,1,0x76f4,1,0x774a,1,0x7740,1,0x78cc,1,0x7ab1,1, -0x7c7b,1,0x7d5b,1,0x7f3e,1,0x8352,1,0x83ef,1,0x8779,1,0x8941,1,0x8986,1, -0x8abf,1,0x8acb,1,0x8aed,1,0x8b8a,1,0x8f38,1,0x9072,1,0x9199,1,0x9276,1, -0x967c,1,0x97db,1,0x980b,1,0x9b12,2,0xd84a,0xdc4a,2,0xd84a,0xdc44,2,0xd84c,0xdfd5, -1,0x3b9d,1,0x4018,1,0x4039,2,0xd854,0xde49,2,0xd857,0xdcd0,2,0xd85f,0xded3,1, -0x9f43,1,0x9f8e,0xe02,0x5d9,0x5b4,0x1102,0x5f2,0x5b7,0x1802,0x5e9,0x5c1,0x1902,0x5e9,0x5c2,0xfb49, -0x1843,0x5e9,0x5bc,0x5c1,0xfb49,0x1943,0x5e9,0x5bc,0x5c2,0x1102,0x5d0,0x5b7,0x1202,0x5d0,0x5b8,0x1502, -0x5d0,0x5bc,0x1502,0x5d1,0x5bc,0x1502,0x5d2,0x5bc,0x1502,0x5d3,0x5bc,0x1502,0x5d4,0x5bc,0x1502,0x5d5, -0x5bc,0x1502,0x5d6,0x5bc,0x1502,0x5d8,0x5bc,0x1502,0x5d9,0x5bc,0x1502,0x5da,0x5bc,0x1502,0x5db,0x5bc, -0x1502,0x5dc,0x5bc,0x1502,0x5de,0x5bc,0x1502,0x5e0,0x5bc,0x1502,0x5e1,0x5bc,0x1502,0x5e3,0x5bc,0x1502, -0x5e4,0x5bc,0x1502,0x5e6,0x5bc,0x1502,0x5e7,0x5bc,0x1502,0x5e8,0x5bc,0x1502,0x5e9,0x5bc,0x1502,0x5ea, -0x5bc,0x1302,0x5d5,0x5b9,0x1702,0x5d1,0x5bf,0x1702,0x5db,0x5bf,0x1702,0x5e4,0x5bf,0xd804,0xd834,0xdd57, -0xd834,0xdd65,0xd804,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd5f,0xd834,0xdd6e,4,0xd846,0xd834,0xdd58,0xd834, -0xdd65,0xd834,0xdd6e,0xd834,0xdd5f,0xd834,0xdd6f,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd6f,0xd834, -0xdd5f,0xd834,0xdd70,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd70,0xd834,0xdd5f,0xd834,0xdd71,4, -0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd71,0xd834,0xdd5f,0xd834,0xdd72,4,0xd846,0xd834,0xdd58,0xd834, -0xdd65,0xd834,0xdd72,0xd804,0xd834,0xddb9,0xd834,0xdd65,0xd804,0xd834,0xddba,0xd834,0xdd65,0xd834,0xddbb,0xd834, -0xdd6e,4,0xd846,0xd834,0xddb9,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xddbc,0xd834,0xdd6e,4,0xd846,0xd834, -0xddba,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xddbb,0xd834,0xdd6f,4,0xd846,0xd834,0xddb9,0xd834,0xdd65,0xd834, -0xdd6f,0xd834,0xddbc,0xd834,0xdd6f,4,0xd846,0xd834,0xddba,0xd834,0xdd65,0xd834,0xdd6f,1,0x4e3d,1, -0x4e38,1,0x4e41,2,0xd840,0xdd22,1,0x4f60,1,0x4fbb,1,0x5002,1,0x507a,1,0x5099, -1,0x50cf,1,0x349e,2,0xd841,0xde3a,1,0x5154,1,0x5164,1,0x5177,2,0xd841,0xdd1c, -1,0x34b9,1,0x5167,1,0x518d,2,0xd841,0xdd4b,1,0x5197,1,0x51a4,1,0x4ecc,1, -0x51ac,2,0xd864,0xdddf,1,0x51f5,1,0x5203,1,0x34df,1,0x523b,1,0x5246,1,0x5272, -1,0x5277,1,0x3515,1,0x5305,1,0x5306,1,0x5349,1,0x535a,1,0x5373,1,0x537d, -1,0x537f,2,0xd842,0xde2c,1,0x7070,1,0x53ca,1,0x53df,2,0xd842,0xdf63,1,0x53eb, -1,0x53f1,1,0x5406,1,0x549e,1,0x5438,1,0x5448,1,0x5468,1,0x54a2,1,0x54f6, -1,0x5510,1,0x5553,1,0x5563,1,0x5584,1,0x55ab,1,0x55b3,1,0x55c2,1,0x5716, -1,0x5717,1,0x5651,1,0x5674,1,0x58ee,1,0x57ce,1,0x57f4,1,0x580d,1,0x578b, -1,0x5832,1,0x5831,1,0x58ac,2,0xd845,0xdce4,1,0x58f2,1,0x58f7,1,0x5906,1, -0x591a,1,0x5922,1,0x5962,2,0xd845,0xdea8,2,0xd845,0xdeea,1,0x59ec,1,0x5a1b,1, -0x5a27,1,0x59d8,1,0x5a66,1,0x36ee,1,0x36fc,1,0x5b08,1,0x5b3e,2,0xd846,0xddc8, -1,0x5bc3,1,0x5bd8,1,0x5bf3,2,0xd846,0xdf18,1,0x5bff,1,0x5c06,1,0x5f53,1, -0x5c22,1,0x3781,1,0x5c60,1,0x5cc0,1,0x5c8d,2,0xd847,0xdde4,1,0x5d43,2,0xd847, -0xdde6,1,0x5d6e,1,0x5d6b,1,0x5d7c,1,0x5de1,1,0x5de2,1,0x382f,1,0x5dfd,1, -0x5e28,1,0x5e3d,1,0x5e69,1,0x3862,2,0xd848,0xdd83,1,0x387c,1,0x5eb0,1,0x5eb3, -1,0x5eb6,2,0xd868,0xdf92,1,0x5efe,2,0xd848,0xdf31,1,0x8201,1,0x5f22,1,0x38c7, -2,0xd84c,0xdeb8,2,0xd858,0xddda,1,0x5f62,1,0x5f6b,1,0x38e3,1,0x5f9a,1,0x5fcd, -1,0x5fd7,1,0x5ff9,1,0x6081,1,0x393a,1,0x391c,2,0xd849,0xded4,1,0x60c7,1, -0x6148,1,0x614c,1,0x617a,1,0x61b2,1,0x61a4,1,0x61af,1,0x61de,1,0x6210,1, -0x621b,1,0x625d,1,0x62b1,1,0x62d4,1,0x6350,2,0xd84a,0xdf0c,1,0x633d,1,0x62fc, -1,0x6368,1,0x6383,1,0x63e4,2,0xd84a,0xdff1,1,0x6422,1,0x63c5,1,0x63a9,1, -0x3a2e,1,0x6469,1,0x647e,1,0x649d,1,0x6477,1,0x3a6c,1,0x656c,2,0xd84c,0xdc0a, -1,0x65e3,1,0x66f8,1,0x6649,1,0x3b19,1,0x3b08,1,0x3ae4,1,0x5192,1,0x5195, -1,0x6700,1,0x669c,1,0x80ad,1,0x43d9,1,0x6721,1,0x675e,1,0x6753,2,0xd84c, -0xdfc3,1,0x3b49,1,0x67fa,1,0x6785,1,0x6852,2,0xd84d,0xdc6d,1,0x688e,1,0x681f, -1,0x6914,1,0x6942,1,0x69a3,1,0x69ea,1,0x6aa8,2,0xd84d,0xdea3,1,0x6adb,1, -0x3c18,1,0x6b21,2,0xd84e,0xdca7,1,0x6b54,1,0x3c4e,1,0x6b72,1,0x6b9f,1,0x6bbb, -2,0xd84e,0xde8d,2,0xd847,0xdd0b,2,0xd84e,0xdefa,1,0x6c4e,2,0xd84f,0xdcbc,1,0x6cbf, -1,0x6ccd,1,0x6c67,1,0x6d16,1,0x6d3e,1,0x6d69,1,0x6d78,1,0x6d85,2,0xd84f, -0xdd1e,1,0x6d34,1,0x6e2f,1,0x6e6e,1,0x3d33,1,0x6ec7,2,0xd84f,0xded1,1,0x6df9, -1,0x6f6e,2,0xd84f,0xdf5e,2,0xd84f,0xdf8e,1,0x6fc6,1,0x7039,1,0x701b,1,0x3d96, -1,0x704a,1,0x707d,1,0x7077,1,0x70ad,2,0xd841,0xdd25,1,0x7145,2,0xd850,0xde63, -1,0x719c,2,0xd850,0xdfab,1,0x7228,1,0x7250,2,0xd851,0xde08,1,0x7280,1,0x7295, -2,0xd851,0xdf35,2,0xd852,0xdc14,1,0x737a,1,0x738b,1,0x3eac,1,0x73a5,1,0x3eb8, -1,0x7447,1,0x745c,1,0x7485,1,0x74ca,1,0x3f1b,1,0x7524,2,0xd853,0xdc36,1, -0x753e,2,0xd853,0xdc92,2,0xd848,0xdd9f,1,0x7610,2,0xd853,0xdfa1,2,0xd853,0xdfb8,2, -0xd854,0xdc44,1,0x3ffc,1,0x4008,2,0xd854,0xdcf3,2,0xd854,0xdcf2,2,0xd854,0xdd19,2, -0xd854,0xdd33,1,0x771e,1,0x771f,1,0x778b,1,0x4046,1,0x4096,2,0xd855,0xdc1d,1, -0x784e,1,0x40e3,2,0xd855,0xde26,2,0xd855,0xde9a,2,0xd855,0xdec5,1,0x79eb,1,0x412f, -1,0x7a4a,1,0x7a4f,2,0xd856,0xdd7c,2,0xd856,0xdea7,1,0x7aee,1,0x4202,2,0xd856, -0xdfab,1,0x7bc6,1,0x7bc9,1,0x4227,2,0xd857,0xdc80,1,0x7cd2,1,0x42a0,1,0x7ce8, -1,0x7ce3,1,0x7d00,2,0xd857,0xdf86,1,0x7d63,1,0x4301,1,0x7dc7,1,0x7e02,1, -0x7e45,1,0x4334,2,0xd858,0xde28,2,0xd858,0xde47,1,0x4359,2,0xd858,0xded9,1,0x7f7a, -2,0xd858,0xdf3e,1,0x7f95,1,0x7ffa,2,0xd859,0xdcda,2,0xd859,0xdd23,1,0x8060,2, -0xd859,0xdda8,1,0x8070,2,0xd84c,0xdf5f,1,0x43d5,1,0x80b2,1,0x8103,1,0x440b,1, -0x813e,1,0x5ab5,2,0xd859,0xdfa7,2,0xd859,0xdfb5,2,0xd84c,0xdf93,2,0xd84c,0xdf9c,1, -0x8204,1,0x8f9e,1,0x446b,1,0x8291,1,0x828b,1,0x829d,1,0x52b3,1,0x82b1,1, -0x82b3,1,0x82bd,1,0x82e6,2,0xd85a,0xdf3c,1,0x831d,1,0x8363,1,0x83ad,1,0x8323, -1,0x83bd,1,0x83e7,1,0x8353,1,0x83ca,1,0x83cc,1,0x83dc,2,0xd85b,0xdc36,2, -0xd85b,0xdd6b,2,0xd85b,0xdcd5,1,0x452b,1,0x84f1,1,0x84f3,1,0x8516,2,0xd85c,0xdfca, -1,0x8564,2,0xd85b,0xdf2c,1,0x455d,1,0x4561,2,0xd85b,0xdfb1,2,0xd85c,0xdcd2,1, -0x456b,1,0x8650,1,0x8667,1,0x8669,1,0x86a9,1,0x8688,1,0x870e,1,0x86e2,1, -0x8728,1,0x876b,1,0x8786,1,0x45d7,1,0x87e1,1,0x8801,1,0x45f9,1,0x8860,1, -0x8863,2,0xd85d,0xde67,1,0x88d7,1,0x88de,1,0x4635,1,0x88fa,1,0x34bb,2,0xd85e, -0xdcae,2,0xd85e,0xdd66,1,0x46be,1,0x46c7,1,0x8aa0,1,0x8c55,2,0xd85f,0xdca8,1, -0x8cab,1,0x8cc1,1,0x8d1b,1,0x8d77,2,0xd85f,0xdf2f,2,0xd842,0xdc04,1,0x8dcb,1, -0x8dbc,1,0x8df0,2,0xd842,0xdcde,1,0x8ed4,2,0xd861,0xddd2,2,0xd861,0xdded,1,0x9094, -1,0x90f1,1,0x9111,2,0xd861,0xdf2e,1,0x911b,1,0x9238,1,0x92d7,1,0x92d8,1, -0x927c,1,0x93f9,1,0x9415,2,0xd862,0xdffa,1,0x958b,1,0x4995,1,0x95b7,2,0xd863, -0xdd77,1,0x49e6,1,0x96c3,1,0x5db2,1,0x9723,2,0xd864,0xdd45,2,0xd864,0xde1a,1, -0x4a6e,1,0x4a76,1,0x97e0,2,0xd865,0xdc0a,1,0x4ab2,2,0xd865,0xdc96,1,0x9829,2, -0xd865,0xddb6,1,0x98e2,1,0x4b33,1,0x9929,1,0x99a7,1,0x99c2,1,0x99fe,1,0x4bce, -2,0xd866,0xdf30,1,0x9c40,1,0x9cfd,1,0x4cce,1,0x4ced,1,0x9d67,2,0xd868,0xdcce, -1,0x4cf8,2,0xd868,0xdd05,2,0xd868,0xde0e,2,0xd868,0xde91,1,0x9ebb,1,0x4d56,1, -0x9ef9,1,0x9efe,1,0x9f05,1,0x9f0f,1,0x9f16,1,0x9f3b,2,0xd869,0xde00,0x3ac,0xe642, -0x3b1,0x301,0x3ad,0xe642,0x3b5,0x301,0x3ae,0xe642,0x3b7,0x301,0x3af,0xe642,0x3b9,0x301,0x3cc,0xe642, -0x3bf,0x301,0x3cd,0xe642,0x3c5,0x301,0x3ce,0xe642,0x3c9,0x301,0x386,0xe642,0x391,0x301,0x388,0xe642, -0x395,0x301,0x389,0xe642,0x397,0x301,0x390,1,0xe643,0x3b9,0x308,0x301,0x38a,0xe642,0x399,0x301, -0x3b0,1,0xe643,0x3c5,0x308,0x301,0x38e,0xe642,0x3a5,0x301,0x385,0xe642,0xa8,0x301,0x38c,0xe642, -0x39f,0x301,0x38f,0xe642,0x3a9,0x301,0xc5,0xe642,0x41,0x30a,0xe6e6,0xe681,0x300,0xe6e6,0xe681,0x301, -0xe6e6,0xe681,0x313,0xe6e6,0xe682,0x308,0x301,0x8100,0x8282,0xf71,0xf72,0x8100,0x8482,0xf71,0xf74,0x8100, -0x8282,0xf71,0xf80,0 +0xe132,0x61ee,0xe132,0x61f0,0xe132,0x61f2,0xe132,0x61f4,0xe132,0x61fc,0x860f,2,0xb92,0x860f,2,0xbc8, +0xb489,0x2e82,0x2134,0xb489,0x2e82,0x2138,0xb489,0x2e82,0x2156,0xb489,0x49c2,0x225c,0xb489,0x49c2,0x225e,0x3489, +0xcf82,0x2696,0xb489,0xd5c2,0x2698,0xb489,0xf242,0x2706,0xb489,0xeec2,0x270a,0xb489,0xf082,0x271c,0xb489,0xf242, +0x2722,0x348b,0x2c02,0x2978,0x348b,0x2e82,0x2976,0xb48b,0x2f42,0x297c,0xb48b,0x6bc2,0x2b74,0xb48b,0x6bc2,0x2b76, +0xb48d,0x4c02,0x3270,0xb4b7,0x59c2,0xdad3,2,0xe602,0x41,0x302,0x600,0x3d4c,0x602,0x3d48,0x606,0x3d54, +0x8612,0x3d50,0xe602,0x41,0x308,0x8608,0x3bc,0xe602,0x41,0x30a,0x8602,0x3f4,0xca02,0x43,0x327,0x8602, +0x3c10,0xe602,0x45,0x302,0x600,0x3d80,0x602,0x3d7c,0x606,0x3d88,0x8612,0x3d84,0xe602,0x49,0x308,0x8602, +0x3c5c,0xe602,0x4f,0x302,0x600,0x3da4,0x602,0x3da0,0x606,0x3dac,0x8612,0x3da8,0xe602,0x4f,0x303,0x602, +0x3c98,0x608,0x458,0x8610,0x3c9c,0xe602,0x4f,0x308,0x8608,0x454,0xe602,0x55,0x308,0x600,0x3b6,0x602, +0x3ae,0x608,0x3aa,0x8618,0x3b2,0xe602,0x61,0x302,0x600,0x3d4e,0x602,0x3d4a,0x606,0x3d56,0x8612,0x3d52, +0xe602,0x61,0x308,0x8608,0x3be,0xe602,0x61,0x30a,0x8602,0x3f6,0xca02,0x63,0x327,0x8602,0x3c12,0xe602, +0x65,0x302,0x600,0x3d82,0x602,0x3d7e,0x606,0x3d8a,0x8612,0x3d86,0xe602,0x69,0x308,0x8602,0x3c5e,0xe602, +0x6f,0x302,0x600,0x3da6,0x602,0x3da2,0x606,0x3dae,0x8612,0x3daa,0xe602,0x6f,0x303,0x602,0x3c9a,0x608, +0x45a,0x8610,0x3c9e,0xe602,0x6f,0x308,0x8608,0x456,0xe602,0x75,0x308,0x600,0x3b8,0x602,0x3b0,0x608, +0x3ac,0x8618,0x3b4,0xe602,0x41,0x306,0x600,0x3d60,0x602,0x3d5c,0x606,0x3d68,0x8612,0x3d64,0xe602,0x61, +0x306,0x600,0x3d62,0x602,0x3d5e,0x606,0x3d6a,0x8612,0x3d66,0xe602,0x45,0x304,0x600,0x3c28,0x8602,0x3c2c, +0xe602,0x65,0x304,0x600,0x3c2a,0x8602,0x3c2e,0xe602,0x4f,0x304,0x600,0x3ca0,0x8602,0x3ca4,0xe602,0x6f, +0x304,0x600,0x3ca2,0x8602,0x3ca6,0xe602,0x53,0x301,0x860e,0x3cc8,0xe602,0x73,0x301,0x860e,0x3cca,0xe602, +0x53,0x30c,0x860e,0x3ccc,0xe602,0x73,0x30c,0x860e,0x3cce,0xe602,0x55,0x303,0x8602,0x3cf0,0xe602,0x75, +0x303,0x8602,0x3cf2,0xe602,0x55,0x304,0x8610,0x3cf4,0xe602,0x75,0x304,0x8610,0x3cf6,0xd802,0x4f,0x31b, +0x600,0x3db8,0x602,0x3db4,0x606,0x3dc0,0x612,0x3dbc,0x8646,0x3dc4,0xd802,0x6f,0x31b,0x600,0x3dba,0x602, +0x3db6,0x606,0x3dc2,0x612,0x3dbe,0x8646,0x3dc6,0xd802,0x55,0x31b,0x600,0x3dd4,0x602,0x3dd0,0x606,0x3ddc, +0x612,0x3dd8,0x8646,0x3de0,0xd802,0x75,0x31b,0x600,0x3dd6,0x602,0x3dd2,0x606,0x3dde,0x612,0x3dda,0x8646, +0x3de2,0xca02,0x4f,0x328,0x8608,0x3d8,0xca02,0x6f,0x328,0x8608,0x3da,0xe602,0x41,0x307,0x8608,0x3c0, +0xe602,0x61,0x307,0x8608,0x3c2,0xca02,0x45,0x327,0x860c,0x3c38,0xca02,0x65,0x327,0x860c,0x3c3a,0xe602, +0x4f,0x307,0x8608,0x460,0xe602,0x6f,0x307,0x8608,0x462,0xe602,0x3b1,0x301,0x868a,0x3f68,0xe602,0x3b7, +0x301,0x868a,0x3f88,0xe602,0x3b9,0x308,0x600,0x3fa4,0x602,0x720,0x8684,0x3fae,0xe602,0x3c5,0x308,0x600, +0x3fc4,0x602,0x760,0x8684,0x3fce,0xe602,0x3c9,0x301,0x868a,0x3fe8,2,0xcc6,0xcc2,0x99aa,0x1996,2, +0xdd9,0xdcf,0x9b94,0x1bba,0xdc02,0x4c,0x323,0x8608,0x3c70,0xdc02,0x6c,0x323,0x8608,0x3c72,0xdc02,0x52, +0x323,0x8608,0x3cb8,0xdc02,0x72,0x323,0x8608,0x3cba,0xdc02,0x53,0x323,0x860e,0x3cd0,0xdc02,0x73,0x323, +0x860e,0x3cd2,0xdc02,0x41,0x323,0x604,0x3d58,0x860c,0x3d6c,0xdc02,0x61,0x323,0x604,0x3d5a,0x860c,0x3d6e, +0xdc02,0x45,0x323,0x8604,0x3d8c,0xdc02,0x65,0x323,0x8604,0x3d8e,0xdc02,0x4f,0x323,0x8604,0x3db0,0xdc02, +0x6f,0x323,0x8604,0x3db2,0xe602,0x3b1,0x313,0x600,0x3e05,0x602,0x3e09,0x684,0x3e0d,0x868a,0x3f00,0xe602, +0x3b1,0x314,0x600,0x3e07,0x602,0x3e0b,0x684,0x3e0f,0x868a,0x3f02,0x1f00,0xe643,0x3b1,0x313,0x300,0x868a, +0x3f04,0x1f01,0xe643,0x3b1,0x314,0x300,0x868a,0x3f06,0x1f00,0xe643,0x3b1,0x313,0x301,0x868a,0x3f08,0x1f01, +0xe643,0x3b1,0x314,0x301,0x868a,0x3f0a,0x1f00,0xe643,0x3b1,0x313,0x342,0x868a,0x3f0c,0x1f01,0xe643,0x3b1, +0x314,0x342,0x868a,0x3f0e,0xe602,0x391,0x313,0x600,0x3e15,0x602,0x3e19,0x684,0x3e1d,0x868a,0x3f10,0xe602, +0x391,0x314,0x600,0x3e17,0x602,0x3e1b,0x684,0x3e1f,0x868a,0x3f12,0x1f08,0xe643,0x391,0x313,0x300,0x868a, +0x3f14,0x1f09,0xe643,0x391,0x314,0x300,0x868a,0x3f16,0x1f08,0xe643,0x391,0x313,0x301,0x868a,0x3f18,0x1f09, +0xe643,0x391,0x314,0x301,0x868a,0x3f1a,0x1f08,0xe643,0x391,0x313,0x342,0x868a,0x3f1c,0x1f09,0xe643,0x391, +0x314,0x342,0x868a,0x3f1e,0xe602,0x3b5,0x313,0x600,0x3e24,0x8602,0x3e28,0xe602,0x3b5,0x314,0x600,0x3e26, +0x8602,0x3e2a,0xe602,0x395,0x313,0x600,0x3e34,0x8602,0x3e38,0xe602,0x395,0x314,0x600,0x3e36,0x8602,0x3e3a, +0xe602,0x3b7,0x313,0x600,0x3e45,0x602,0x3e49,0x684,0x3e4d,0x868a,0x3f20,0xe602,0x3b7,0x314,0x600,0x3e47, +0x602,0x3e4b,0x684,0x3e4f,0x868a,0x3f22,0x1f20,0xe643,0x3b7,0x313,0x300,0x868a,0x3f24,0x1f21,0xe643,0x3b7, +0x314,0x300,0x868a,0x3f26,0x1f20,0xe643,0x3b7,0x313,0x301,0x868a,0x3f28,0x1f21,0xe643,0x3b7,0x314,0x301, +0x868a,0x3f2a,0x1f20,0xe643,0x3b7,0x313,0x342,0x868a,0x3f2c,0x1f21,0xe643,0x3b7,0x314,0x342,0x868a,0x3f2e, +0xe602,0x397,0x313,0x600,0x3e55,0x602,0x3e59,0x684,0x3e5d,0x868a,0x3f30,0xe602,0x397,0x314,0x600,0x3e57, +0x602,0x3e5b,0x684,0x3e5f,0x868a,0x3f32,0x1f28,0xe643,0x397,0x313,0x300,0x868a,0x3f34,0x1f29,0xe643,0x397, +0x314,0x300,0x868a,0x3f36,0x1f28,0xe643,0x397,0x313,0x301,0x868a,0x3f38,0x1f29,0xe643,0x397,0x314,0x301, +0x868a,0x3f3a,0x1f28,0xe643,0x397,0x313,0x342,0x868a,0x3f3c,0x1f29,0xe643,0x397,0x314,0x342,0x868a,0x3f3e, +0xe602,0x3b9,0x313,0x600,0x3e64,0x602,0x3e68,0x8684,0x3e6c,0xe602,0x3b9,0x314,0x600,0x3e66,0x602,0x3e6a, +0x8684,0x3e6e,0xe602,0x399,0x313,0x600,0x3e74,0x602,0x3e78,0x8684,0x3e7c,0xe602,0x399,0x314,0x600,0x3e76, +0x602,0x3e7a,0x8684,0x3e7e,0xe602,0x3bf,0x313,0x600,0x3e84,0x8602,0x3e88,0xe602,0x3bf,0x314,0x600,0x3e86, +0x8602,0x3e8a,0xe602,0x39f,0x313,0x600,0x3e94,0x8602,0x3e98,0xe602,0x39f,0x314,0x600,0x3e96,0x8602,0x3e9a, +0xe602,0x3c5,0x313,0x600,0x3ea4,0x602,0x3ea8,0x8684,0x3eac,0xe602,0x3c5,0x314,0x600,0x3ea6,0x602,0x3eaa, +0x8684,0x3eae,0xe602,0x3a5,0x314,0x600,0x3eb6,0x602,0x3eba,0x8684,0x3ebe,0xe602,0x3c9,0x313,0x600,0x3ec5, +0x602,0x3ec9,0x684,0x3ecd,0x868a,0x3f40,0xe602,0x3c9,0x314,0x600,0x3ec7,0x602,0x3ecb,0x684,0x3ecf,0x868a, +0x3f42,0x1f60,0xe643,0x3c9,0x313,0x300,0x868a,0x3f44,0x1f61,0xe643,0x3c9,0x314,0x300,0x868a,0x3f46,0x1f60, +0xe643,0x3c9,0x313,0x301,0x868a,0x3f48,0x1f61,0xe643,0x3c9,0x314,0x301,0x868a,0x3f4a,0x1f60,0xe643,0x3c9, +0x313,0x342,0x868a,0x3f4c,0x1f61,0xe643,0x3c9,0x314,0x342,0x868a,0x3f4e,0xe602,0x3a9,0x313,0x600,0x3ed5, +0x602,0x3ed9,0x684,0x3edd,0x868a,0x3f50,0xe602,0x3a9,0x314,0x600,0x3ed7,0x602,0x3edb,0x684,0x3edf,0x868a, +0x3f52,0x1f68,0xe643,0x3a9,0x313,0x300,0x868a,0x3f54,0x1f69,0xe643,0x3a9,0x314,0x300,0x868a,0x3f56,0x1f68, +0xe643,0x3a9,0x313,0x301,0x868a,0x3f58,0x1f69,0xe643,0x3a9,0x314,0x301,0x868a,0x3f5a,0x1f68,0xe643,0x3a9, +0x313,0x342,0x868a,0x3f5c,0x1f69,0xe643,0x3a9,0x314,0x342,0x868a,0x3f5e,0xe602,0x3b1,0x300,0x868a,0x3f64, +0xe602,0x3b7,0x300,0x868a,0x3f84,0xe602,0x3c9,0x300,0x868a,0x3fe4,0xe602,0x3b1,0x342,0x868a,0x3f6e,0xe602, +0x3b7,0x342,0x868a,0x3f8e,0xe602,0x3c9,0x342,0x868a,0x3fee,4,0xd81b,0xdd63,0xd81b,0xdd67,0xb4b7,0x59c2, +0xdad4,3,0xe602,0x41,0x300,0xe602,0x41,0x301,0xe602,0x41,0x303,0xe602,0x45,0x300,0xe602,0x45, +0x301,0xe602,0x45,0x308,0xe602,0x49,0x300,0xe602,0x49,0x301,0xe602,0x49,0x302,0xe602,0x4e,0x303, +0xe602,0x4f,0x300,0xe602,0x4f,0x301,0xe602,0x55,0x300,0xe602,0x55,0x301,0xe602,0x55,0x302,0xe602, +0x59,0x301,0xe602,0x61,0x300,0xe602,0x61,0x301,0xe602,0x61,0x303,0xe602,0x65,0x300,0xe602,0x65, +0x301,0xe602,0x65,0x308,0xe602,0x69,0x300,0xe602,0x69,0x301,0xe602,0x69,0x302,0xe602,0x6e,0x303, +0xe602,0x6f,0x300,0xe602,0x6f,0x301,0xe602,0x75,0x300,0xe602,0x75,0x301,0xe602,0x75,0x302,0xe602, +0x79,0x301,0xe602,0x79,0x308,0xe602,0x41,0x304,0xe602,0x61,0x304,0xca02,0x41,0x328,0xca02,0x61, +0x328,0xe602,0x43,0x301,0xe602,0x63,0x301,0xe602,0x43,0x302,0xe602,0x63,0x302,0xe602,0x43,0x307, +0xe602,0x63,0x307,0xe602,0x43,0x30c,0xe602,0x63,0x30c,0xe602,0x44,0x30c,0xe602,0x64,0x30c,0xe602, +0x45,0x306,0xe602,0x65,0x306,0xe602,0x45,0x307,0xe602,0x65,0x307,0xca02,0x45,0x328,0xca02,0x65, +0x328,0xe602,0x45,0x30c,0xe602,0x65,0x30c,0xe602,0x47,0x302,0xe602,0x67,0x302,0xe602,0x47,0x306, +0xe602,0x67,0x306,0xe602,0x47,0x307,0xe602,0x67,0x307,0xca02,0x47,0x327,0xca02,0x67,0x327,0xe602, +0x48,0x302,0xe602,0x68,0x302,0xe602,0x49,0x303,0xe602,0x69,0x303,0xe602,0x49,0x304,0xe602,0x69, +0x304,0xe602,0x49,0x306,0xe602,0x69,0x306,0xca02,0x49,0x328,0xca02,0x69,0x328,0xe602,0x49,0x307, +0xe602,0x4a,0x302,0xe602,0x6a,0x302,0xca02,0x4b,0x327,0xca02,0x6b,0x327,0xe602,0x4c,0x301,0xe602, +0x6c,0x301,0xca02,0x4c,0x327,0xca02,0x6c,0x327,0xe602,0x4c,0x30c,0xe602,0x6c,0x30c,0xe602,0x4e, +0x301,0xe602,0x6e,0x301,0xca02,0x4e,0x327,0xca02,0x6e,0x327,0xe602,0x4e,0x30c,0xe602,0x6e,0x30c, +0xe602,0x4f,0x306,0xe602,0x6f,0x306,0xe602,0x4f,0x30b,0xe602,0x6f,0x30b,0xe602,0x52,0x301,0xe602, +0x72,0x301,0xca02,0x52,0x327,0xca02,0x72,0x327,0xe602,0x52,0x30c,0xe602,0x72,0x30c,0xe602,0x53, +0x302,0xe602,0x73,0x302,0xca02,0x53,0x327,0xca02,0x73,0x327,0xca02,0x54,0x327,0xca02,0x74,0x327, +0xe602,0x54,0x30c,0xe602,0x74,0x30c,0xe602,0x55,0x306,0xe602,0x75,0x306,0xe602,0x55,0x30a,0xe602, +0x75,0x30a,0xe602,0x55,0x30b,0xe602,0x75,0x30b,0xca02,0x55,0x328,0xca02,0x75,0x328,0xe602,0x57, +0x302,0xe602,0x77,0x302,0xe602,0x59,0x302,0xe602,0x79,0x302,0xe602,0x59,0x308,0xe602,0x5a,0x301, +0xe602,0x7a,0x301,0xe602,0x5a,0x307,0xe602,0x7a,0x307,0xe602,0x5a,0x30c,0xe602,0x7a,0x30c,0xe602, +0x41,0x30c,0xe602,0x61,0x30c,0xe602,0x49,0x30c,0xe602,0x69,0x30c,0xe602,0x4f,0x30c,0xe602,0x6f, +0x30c,0xe602,0x55,0x30c,0xe602,0x75,0x30c,0xdc,0xe643,0x55,0x308,0x304,0xfc,0xe643,0x75,0x308, +0x304,0xdc,0xe643,0x55,0x308,0x301,0xfc,0xe643,0x75,0x308,0x301,0xdc,0xe643,0x55,0x308,0x30c, +0xfc,0xe643,0x75,0x308,0x30c,0xdc,0xe643,0x55,0x308,0x300,0xfc,0xe643,0x75,0x308,0x300,0xc4, +0xe643,0x41,0x308,0x304,0xe4,0xe643,0x61,0x308,0x304,0x226,0xe643,0x41,0x307,0x304,0x227,0xe643, +0x61,0x307,0x304,0xe602,0xc6,0x304,0xe602,0xe6,0x304,0xe602,0x47,0x30c,0xe602,0x67,0x30c,0xe602, +0x4b,0x30c,0xe602,0x6b,0x30c,0x1ea,0xe643,0x4f,0x328,0x304,0x1eb,0xe643,0x6f,0x328,0x304,0xe602, +0x1b7,0x30c,0xe602,0x292,0x30c,0xe602,0x6a,0x30c,0xe602,0x47,0x301,0xe602,0x67,0x301,0xe602,0x4e, +0x300,0xe602,0x6e,0x300,0xc5,0xe643,0x41,0x30a,0x301,0xe5,0xe643,0x61,0x30a,0x301,0xe602,0xc6, +0x301,0xe602,0xe6,0x301,0xe602,0xd8,0x301,0xe602,0xf8,0x301,0xe602,0x41,0x30f,0xe602,0x61,0x30f, +0xe602,0x41,0x311,0xe602,0x61,0x311,0xe602,0x45,0x30f,0xe602,0x65,0x30f,0xe602,0x45,0x311,0xe602, +0x65,0x311,0xe602,0x49,0x30f,0xe602,0x69,0x30f,0xe602,0x49,0x311,0xe602,0x69,0x311,0xe602,0x4f, +0x30f,0xe602,0x6f,0x30f,0xe602,0x4f,0x311,0xe602,0x6f,0x311,0xe602,0x52,0x30f,0xe602,0x72,0x30f, +0xe602,0x52,0x311,0xe602,0x72,0x311,0xe602,0x55,0x30f,0xe602,0x75,0x30f,0xe602,0x55,0x311,0xe602, +0x75,0x311,0xdc02,0x53,0x326,0xdc02,0x73,0x326,0xdc02,0x54,0x326,0xdc02,0x74,0x326,0xe602,0x48, +0x30c,0xe602,0x68,0x30c,0xd6,0xe643,0x4f,0x308,0x304,0xf6,0xe643,0x6f,0x308,0x304,0xd5,0xe643, +0x4f,0x303,0x304,0xf5,0xe643,0x6f,0x303,0x304,0x22e,0xe643,0x4f,0x307,0x304,0x22f,0xe643,0x6f, +0x307,0x304,0xe602,0x59,0x304,0xe602,0x79,0x304,0xe602,0xa8,0x301,0xe602,0x391,0x301,0xe602,0x395, +0x301,0xe602,0x397,0x301,0xe602,0x399,0x301,0xe602,0x39f,0x301,0xe602,0x3a5,0x301,0xe602,0x3a9,0x301, +0x3ca,0xe643,0x3b9,0x308,0x301,0xe602,0x399,0x308,0xe602,0x3a5,0x308,0xe602,0x3b5,0x301,0xe602,0x3b9, +0x301,0x3cb,0xe643,0x3c5,0x308,0x301,0xe602,0x3bf,0x301,0xe602,0x3c5,0x301,0xe602,0x3d2,0x301,0xe602, +0x3d2,0x308,0xe602,0x415,0x300,0xe602,0x415,0x308,0xe602,0x413,0x301,0xe602,0x406,0x308,0xe602,0x41a, +0x301,0xe602,0x418,0x300,0xe602,0x423,0x306,0xe602,0x418,0x306,0xe602,0x438,0x306,0xe602,0x435,0x300, +0xe602,0x435,0x308,0xe602,0x433,0x301,0xe602,0x456,0x308,0xe602,0x43a,0x301,0xe602,0x438,0x300,0xe602, +0x443,0x306,0xe602,0x474,0x30f,0xe602,0x475,0x30f,0xe602,0x416,0x306,0xe602,0x436,0x306,0xe602,0x410, +0x306,0xe602,0x430,0x306,0xe602,0x410,0x308,0xe602,0x430,0x308,0xe602,0x415,0x306,0xe602,0x435,0x306, +0xe602,0x4d8,0x308,0xe602,0x4d9,0x308,0xe602,0x416,0x308,0xe602,0x436,0x308,0xe602,0x417,0x308,0xe602, +0x437,0x308,0xe602,0x418,0x304,0xe602,0x438,0x304,0xe602,0x418,0x308,0xe602,0x438,0x308,0xe602,0x41e, +0x308,0xe602,0x43e,0x308,0xe602,0x4e8,0x308,0xe602,0x4e9,0x308,0xe602,0x42d,0x308,0xe602,0x44d,0x308, +0xe602,0x423,0x304,0xe602,0x443,0x304,0xe602,0x423,0x308,0xe602,0x443,0x308,0xe602,0x423,0x30b,0xe602, +0x443,0x30b,0xe602,0x427,0x308,0xe602,0x447,0x308,0xe602,0x42b,0x308,0xe602,0x44b,0x308,0xe602,0x627, +0x653,0xe602,0x627,0x654,0xe602,0x648,0x654,0xdc02,0x627,0x655,0xe602,0x64a,0x654,0xe602,0x6d5,0x654, +0xe602,0x6c1,0x654,0xe602,0x6d2,0x654,0x702,0x928,0x93c,0x702,0x930,0x93c,0x702,0x933,0x93c,2, +0x9c7,0x9be,2,0x9c7,0x9d7,2,0xb47,0xb56,2,0xb47,0xb3e,2,0xb47,0xb57,2,0xb92, +0xbd7,2,0xbc6,0xbbe,2,0xbc7,0xbbe,2,0xbc6,0xbd7,0x5b02,0xc46,0xc56,2,0xcbf,0xcd5, +2,0xcc6,0xcd5,2,0xcc6,0xcd6,0xcca,0x43,0xcc6,0xcc2,0xcd5,2,0xd46,0xd3e,2,0xd47, +0xd3e,2,0xd46,0xd57,0x902,0xdd9,0xdca,0xddc,0x943,0xdd9,0xdcf,0xdca,2,0xdd9,0xddf,2, +0x1025,0x102e,2,0x1b05,0x1b35,2,0x1b07,0x1b35,2,0x1b09,0x1b35,2,0x1b0b,0x1b35,2,0x1b0d, +0x1b35,2,0x1b11,0x1b35,2,0x1b3a,0x1b35,2,0x1b3c,0x1b35,2,0x1b3e,0x1b35,2,0x1b3f,0x1b35, +2,0x1b42,0x1b35,0xdc02,0x41,0x325,0xdc02,0x61,0x325,0xe602,0x42,0x307,0xe602,0x62,0x307,0xdc02, +0x42,0x323,0xdc02,0x62,0x323,0xdc02,0x42,0x331,0xdc02,0x62,0x331,0xc7,0xe643,0x43,0x327,0x301, +0xe7,0xe643,0x63,0x327,0x301,0xe602,0x44,0x307,0xe602,0x64,0x307,0xdc02,0x44,0x323,0xdc02,0x64, +0x323,0xdc02,0x44,0x331,0xdc02,0x64,0x331,0xca02,0x44,0x327,0xca02,0x64,0x327,0xdc02,0x44,0x32d, +0xdc02,0x64,0x32d,0x112,0xe643,0x45,0x304,0x300,0x113,0xe643,0x65,0x304,0x300,0x112,0xe643,0x45, +0x304,0x301,0x113,0xe643,0x65,0x304,0x301,0xdc02,0x45,0x32d,0xdc02,0x65,0x32d,0xdc02,0x45,0x330, +0xdc02,0x65,0x330,0x228,0xe643,0x45,0x327,0x306,0x229,0xe643,0x65,0x327,0x306,0xe602,0x46,0x307, +0xe602,0x66,0x307,0xe602,0x47,0x304,0xe602,0x67,0x304,0xe602,0x48,0x307,0xe602,0x68,0x307,0xdc02, +0x48,0x323,0xdc02,0x68,0x323,0xe602,0x48,0x308,0xe602,0x68,0x308,0xca02,0x48,0x327,0xca02,0x68, +0x327,0xdc02,0x48,0x32e,0xdc02,0x68,0x32e,0xdc02,0x49,0x330,0xdc02,0x69,0x330,0xcf,0xe643,0x49, +0x308,0x301,0xef,0xe643,0x69,0x308,0x301,0xe602,0x4b,0x301,0xe602,0x6b,0x301,0xdc02,0x4b,0x323, +0xdc02,0x6b,0x323,0xdc02,0x4b,0x331,0xdc02,0x6b,0x331,0x1e36,0xe643,0x4c,0x323,0x304,0x1e37,0xe643, +0x6c,0x323,0x304,0xdc02,0x4c,0x331,0xdc02,0x6c,0x331,0xdc02,0x4c,0x32d,0xdc02,0x6c,0x32d,0xe602, +0x4d,0x301,0xe602,0x6d,0x301,0xe602,0x4d,0x307,0xe602,0x6d,0x307,0xdc02,0x4d,0x323,0xdc02,0x6d, +0x323,0xe602,0x4e,0x307,0xe602,0x6e,0x307,0xdc02,0x4e,0x323,0xdc02,0x6e,0x323,0xdc02,0x4e,0x331, +0xdc02,0x6e,0x331,0xdc02,0x4e,0x32d,0xdc02,0x6e,0x32d,0xd5,0xe643,0x4f,0x303,0x301,0xf5,0xe643, +0x6f,0x303,0x301,0xd5,0xe643,0x4f,0x303,0x308,0xf5,0xe643,0x6f,0x303,0x308,0x14c,0xe643,0x4f, +0x304,0x300,0x14d,0xe643,0x6f,0x304,0x300,0x14c,0xe643,0x4f,0x304,0x301,0x14d,0xe643,0x6f,0x304, +0x301,0xe602,0x50,0x301,0xe602,0x70,0x301,0xe602,0x50,0x307,0xe602,0x70,0x307,0xe602,0x52,0x307, +0xe602,0x72,0x307,0x1e5a,0xe643,0x52,0x323,0x304,0x1e5b,0xe643,0x72,0x323,0x304,0xdc02,0x52,0x331, +0xdc02,0x72,0x331,0xe602,0x53,0x307,0xe602,0x73,0x307,0x15a,0xe643,0x53,0x301,0x307,0x15b,0xe643, +0x73,0x301,0x307,0x160,0xe643,0x53,0x30c,0x307,0x161,0xe643,0x73,0x30c,0x307,0x1e62,0xe643,0x53, +0x323,0x307,0x1e63,0xe643,0x73,0x323,0x307,0xe602,0x54,0x307,0xe602,0x74,0x307,0xdc02,0x54,0x323, +0xdc02,0x74,0x323,0xdc02,0x54,0x331,0xdc02,0x74,0x331,0xdc02,0x54,0x32d,0xdc02,0x74,0x32d,0xdc02, +0x55,0x324,0xdc02,0x75,0x324,0xdc02,0x55,0x330,0xdc02,0x75,0x330,0xdc02,0x55,0x32d,0xdc02,0x75, +0x32d,0x168,0xe643,0x55,0x303,0x301,0x169,0xe643,0x75,0x303,0x301,0x16a,0xe643,0x55,0x304,0x308, +0x16b,0xe643,0x75,0x304,0x308,0xe602,0x56,0x303,0xe602,0x76,0x303,0xdc02,0x56,0x323,0xdc02,0x76, +0x323,0xe602,0x57,0x300,0xe602,0x77,0x300,0xe602,0x57,0x301,0xe602,0x77,0x301,0xe602,0x57,0x308, +0xe602,0x77,0x308,0xe602,0x57,0x307,0xe602,0x77,0x307,0xdc02,0x57,0x323,0xdc02,0x77,0x323,0xe602, +0x58,0x307,0xe602,0x78,0x307,0xe602,0x58,0x308,0xe602,0x78,0x308,0xe602,0x59,0x307,0xe602,0x79, +0x307,0xe602,0x5a,0x302,0xe602,0x7a,0x302,0xdc02,0x5a,0x323,0xdc02,0x7a,0x323,0xdc02,0x5a,0x331, +0xdc02,0x7a,0x331,0xdc02,0x68,0x331,0xe602,0x74,0x308,0xe602,0x77,0x30a,0xe602,0x79,0x30a,0xe602, +0x17f,0x307,0xe602,0x41,0x309,0xe602,0x61,0x309,0xc2,0xe643,0x41,0x302,0x301,0xe2,0xe643,0x61, +0x302,0x301,0xc2,0xe643,0x41,0x302,0x300,0xe2,0xe643,0x61,0x302,0x300,0xc2,0xe643,0x41,0x302, +0x309,0xe2,0xe643,0x61,0x302,0x309,0xc2,0xe643,0x41,0x302,0x303,0xe2,0xe643,0x61,0x302,0x303, +0x1ea0,0xe643,0x41,0x323,0x302,0x1ea1,0xe643,0x61,0x323,0x302,0x102,0xe643,0x41,0x306,0x301,0x103, +0xe643,0x61,0x306,0x301,0x102,0xe643,0x41,0x306,0x300,0x103,0xe643,0x61,0x306,0x300,0x102,0xe643, +0x41,0x306,0x309,0x103,0xe643,0x61,0x306,0x309,0x102,0xe643,0x41,0x306,0x303,0x103,0xe643,0x61, +0x306,0x303,0x1ea0,0xe643,0x41,0x323,0x306,0x1ea1,0xe643,0x61,0x323,0x306,0xe602,0x45,0x309,0xe602, +0x65,0x309,0xe602,0x45,0x303,0xe602,0x65,0x303,0xca,0xe643,0x45,0x302,0x301,0xea,0xe643,0x65, +0x302,0x301,0xca,0xe643,0x45,0x302,0x300,0xea,0xe643,0x65,0x302,0x300,0xca,0xe643,0x45,0x302, +0x309,0xea,0xe643,0x65,0x302,0x309,0xca,0xe643,0x45,0x302,0x303,0xea,0xe643,0x65,0x302,0x303, +0x1eb8,0xe643,0x45,0x323,0x302,0x1eb9,0xe643,0x65,0x323,0x302,0xe602,0x49,0x309,0xe602,0x69,0x309, +0xdc02,0x49,0x323,0xdc02,0x69,0x323,0xe602,0x4f,0x309,0xe602,0x6f,0x309,0xd4,0xe643,0x4f,0x302, +0x301,0xf4,0xe643,0x6f,0x302,0x301,0xd4,0xe643,0x4f,0x302,0x300,0xf4,0xe643,0x6f,0x302,0x300, +0xd4,0xe643,0x4f,0x302,0x309,0xf4,0xe643,0x6f,0x302,0x309,0xd4,0xe643,0x4f,0x302,0x303,0xf4, +0xe643,0x6f,0x302,0x303,0x1ecc,0xe643,0x4f,0x323,0x302,0x1ecd,0xe643,0x6f,0x323,0x302,0x1a0,0xe643, +0x4f,0x31b,0x301,0x1a1,0xe643,0x6f,0x31b,0x301,0x1a0,0xe643,0x4f,0x31b,0x300,0x1a1,0xe643,0x6f, +0x31b,0x300,0x1a0,0xe643,0x4f,0x31b,0x309,0x1a1,0xe643,0x6f,0x31b,0x309,0x1a0,0xe643,0x4f,0x31b, +0x303,0x1a1,0xe643,0x6f,0x31b,0x303,0x1a0,0xdc43,0x4f,0x31b,0x323,0x1a1,0xdc43,0x6f,0x31b,0x323, +0xdc02,0x55,0x323,0xdc02,0x75,0x323,0xe602,0x55,0x309,0xe602,0x75,0x309,0x1af,0xe643,0x55,0x31b, +0x301,0x1b0,0xe643,0x75,0x31b,0x301,0x1af,0xe643,0x55,0x31b,0x300,0x1b0,0xe643,0x75,0x31b,0x300, +0x1af,0xe643,0x55,0x31b,0x309,0x1b0,0xe643,0x75,0x31b,0x309,0x1af,0xe643,0x55,0x31b,0x303,0x1b0, +0xe643,0x75,0x31b,0x303,0x1af,0xdc43,0x55,0x31b,0x323,0x1b0,0xdc43,0x75,0x31b,0x323,0xe602,0x59, +0x300,0xe602,0x79,0x300,0xdc02,0x59,0x323,0xdc02,0x79,0x323,0xe602,0x59,0x309,0xe602,0x79,0x309, +0xe602,0x59,0x303,0xe602,0x79,0x303,0x1f10,0xe643,0x3b5,0x313,0x300,0x1f11,0xe643,0x3b5,0x314,0x300, +0x1f10,0xe643,0x3b5,0x313,0x301,0x1f11,0xe643,0x3b5,0x314,0x301,0x1f18,0xe643,0x395,0x313,0x300,0x1f19, +0xe643,0x395,0x314,0x300,0x1f18,0xe643,0x395,0x313,0x301,0x1f19,0xe643,0x395,0x314,0x301,0x1f30,0xe643, +0x3b9,0x313,0x300,0x1f31,0xe643,0x3b9,0x314,0x300,0x1f30,0xe643,0x3b9,0x313,0x301,0x1f31,0xe643,0x3b9, +0x314,0x301,0x1f30,0xe643,0x3b9,0x313,0x342,0x1f31,0xe643,0x3b9,0x314,0x342,0x1f38,0xe643,0x399,0x313, +0x300,0x1f39,0xe643,0x399,0x314,0x300,0x1f38,0xe643,0x399,0x313,0x301,0x1f39,0xe643,0x399,0x314,0x301, +0x1f38,0xe643,0x399,0x313,0x342,0x1f39,0xe643,0x399,0x314,0x342,0x1f40,0xe643,0x3bf,0x313,0x300,0x1f41, +0xe643,0x3bf,0x314,0x300,0x1f40,0xe643,0x3bf,0x313,0x301,0x1f41,0xe643,0x3bf,0x314,0x301,0x1f48,0xe643, +0x39f,0x313,0x300,0x1f49,0xe643,0x39f,0x314,0x300,0x1f48,0xe643,0x39f,0x313,0x301,0x1f49,0xe643,0x39f, +0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x300,0x1f51,0xe643,0x3c5,0x314,0x300,0x1f50,0xe643,0x3c5,0x313, +0x301,0x1f51,0xe643,0x3c5,0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x342,0x1f51,0xe643,0x3c5,0x314,0x342, +0x1f59,0xe643,0x3a5,0x314,0x300,0x1f59,0xe643,0x3a5,0x314,0x301,0x1f59,0xe643,0x3a5,0x314,0x342,0xe602, +0x3b5,0x300,0xe602,0x3b9,0x300,0xe602,0x3bf,0x300,0xe602,0x3c5,0x300,0x1f00,0xf043,0x3b1,0x313,0x345, +0x1f01,0xf043,0x3b1,0x314,0x345,0x1f02,0x345,2,0xf044,0x3b1,0x313,0x300,0x345,0x1f03,0x345,2, +0xf044,0x3b1,0x314,0x300,0x345,0x1f04,0x345,2,0xf044,0x3b1,0x313,0x301,0x345,0x1f05,0x345,2, +0xf044,0x3b1,0x314,0x301,0x345,0x1f06,0x345,2,0xf044,0x3b1,0x313,0x342,0x345,0x1f07,0x345,2, +0xf044,0x3b1,0x314,0x342,0x345,0x1f08,0xf043,0x391,0x313,0x345,0x1f09,0xf043,0x391,0x314,0x345,0x1f0a, +0x345,2,0xf044,0x391,0x313,0x300,0x345,0x1f0b,0x345,2,0xf044,0x391,0x314,0x300,0x345,0x1f0c, +0x345,2,0xf044,0x391,0x313,0x301,0x345,0x1f0d,0x345,2,0xf044,0x391,0x314,0x301,0x345,0x1f0e, +0x345,2,0xf044,0x391,0x313,0x342,0x345,0x1f0f,0x345,2,0xf044,0x391,0x314,0x342,0x345,0x1f20, +0xf043,0x3b7,0x313,0x345,0x1f21,0xf043,0x3b7,0x314,0x345,0x1f22,0x345,2,0xf044,0x3b7,0x313,0x300, +0x345,0x1f23,0x345,2,0xf044,0x3b7,0x314,0x300,0x345,0x1f24,0x345,2,0xf044,0x3b7,0x313,0x301, +0x345,0x1f25,0x345,2,0xf044,0x3b7,0x314,0x301,0x345,0x1f26,0x345,2,0xf044,0x3b7,0x313,0x342, +0x345,0x1f27,0x345,2,0xf044,0x3b7,0x314,0x342,0x345,0x1f28,0xf043,0x397,0x313,0x345,0x1f29,0xf043, +0x397,0x314,0x345,0x1f2a,0x345,2,0xf044,0x397,0x313,0x300,0x345,0x1f2b,0x345,2,0xf044,0x397, +0x314,0x300,0x345,0x1f2c,0x345,2,0xf044,0x397,0x313,0x301,0x345,0x1f2d,0x345,2,0xf044,0x397, +0x314,0x301,0x345,0x1f2e,0x345,2,0xf044,0x397,0x313,0x342,0x345,0x1f2f,0x345,2,0xf044,0x397, +0x314,0x342,0x345,0x1f60,0xf043,0x3c9,0x313,0x345,0x1f61,0xf043,0x3c9,0x314,0x345,0x1f62,0x345,2, +0xf044,0x3c9,0x313,0x300,0x345,0x1f63,0x345,2,0xf044,0x3c9,0x314,0x300,0x345,0x1f64,0x345,2, +0xf044,0x3c9,0x313,0x301,0x345,0x1f65,0x345,2,0xf044,0x3c9,0x314,0x301,0x345,0x1f66,0x345,2, +0xf044,0x3c9,0x313,0x342,0x345,0x1f67,0x345,2,0xf044,0x3c9,0x314,0x342,0x345,0x1f68,0xf043,0x3a9, +0x313,0x345,0x1f69,0xf043,0x3a9,0x314,0x345,0x1f6a,0x345,2,0xf044,0x3a9,0x313,0x300,0x345,0x1f6b, +0x345,2,0xf044,0x3a9,0x314,0x300,0x345,0x1f6c,0x345,2,0xf044,0x3a9,0x313,0x301,0x345,0x1f6d, +0x345,2,0xf044,0x3a9,0x314,0x301,0x345,0x1f6e,0x345,2,0xf044,0x3a9,0x313,0x342,0x345,0x1f6f, +0x345,2,0xf044,0x3a9,0x314,0x342,0x345,0xe602,0x3b1,0x306,0xe602,0x3b1,0x304,0x1f70,0xf043,0x3b1, +0x300,0x345,0xf002,0x3b1,0x345,0x3ac,0xf043,0x3b1,0x301,0x345,0x1fb6,0xf043,0x3b1,0x342,0x345,0xe602, +0x391,0x306,0xe602,0x391,0x304,0xe602,0x391,0x300,0xf002,0x391,0x345,0xe602,0xa8,0x342,0x1f74,0xf043, +0x3b7,0x300,0x345,0xf002,0x3b7,0x345,0x3ae,0xf043,0x3b7,0x301,0x345,0x1fc6,0xf043,0x3b7,0x342,0x345, +0xe602,0x395,0x300,0xe602,0x397,0x300,0xf002,0x397,0x345,0xe602,0x1fbf,0x300,0xe602,0x1fbf,0x301,0xe602, +0x1fbf,0x342,0xe602,0x3b9,0x306,0xe602,0x3b9,0x304,0x3ca,0xe643,0x3b9,0x308,0x300,0xe602,0x3b9,0x342, +0x3ca,0xe643,0x3b9,0x308,0x342,0xe602,0x399,0x306,0xe602,0x399,0x304,0xe602,0x399,0x300,0xe602,0x1ffe, +0x300,0xe602,0x1ffe,0x301,0xe602,0x1ffe,0x342,0xe602,0x3c5,0x306,0xe602,0x3c5,0x304,0x3cb,0xe643,0x3c5, +0x308,0x300,0xe602,0x3c1,0x313,0xe602,0x3c1,0x314,0xe602,0x3c5,0x342,0x3cb,0xe643,0x3c5,0x308,0x342, +0xe602,0x3a5,0x306,0xe602,0x3a5,0x304,0xe602,0x3a5,0x300,0xe602,0x3a1,0x314,0xe602,0xa8,0x300,0x1f7c, +0xf043,0x3c9,0x300,0x345,0xf002,0x3c9,0x345,0x3ce,0xf043,0x3c9,0x301,0x345,0x1ff6,0xf043,0x3c9,0x342, +0x345,0xe602,0x39f,0x300,0xe602,0x3a9,0x300,0xf002,0x3a9,0x345,0x102,0x2190,0x338,0x102,0x2192,0x338, +0x102,0x2194,0x338,0x102,0x21d0,0x338,0x102,0x21d4,0x338,0x102,0x21d2,0x338,0x102,0x2203,0x338,0x102, +0x2208,0x338,0x102,0x220b,0x338,0x102,0x2223,0x338,0x102,0x2225,0x338,0x102,0x223c,0x338,0x102,0x2243, +0x338,0x102,0x2245,0x338,0x102,0x2248,0x338,0x102,0x3d,0x338,0x102,0x2261,0x338,0x102,0x224d,0x338, +0x102,0x3c,0x338,0x102,0x3e,0x338,0x102,0x2264,0x338,0x102,0x2265,0x338,0x102,0x2272,0x338,0x102, +0x2273,0x338,0x102,0x2276,0x338,0x102,0x2277,0x338,0x102,0x227a,0x338,0x102,0x227b,0x338,0x102,0x2282, +0x338,0x102,0x2283,0x338,0x102,0x2286,0x338,0x102,0x2287,0x338,0x102,0x22a2,0x338,0x102,0x22a8,0x338, +0x102,0x22a9,0x338,0x102,0x22ab,0x338,0x102,0x227c,0x338,0x102,0x227d,0x338,0x102,0x2291,0x338,0x102, +0x2292,0x338,0x102,0x22b2,0x338,0x102,0x22b3,0x338,0x102,0x22b4,0x338,0x102,0x22b5,0x338,0x802,0x304b, +0x3099,0x802,0x304d,0x3099,0x802,0x304f,0x3099,0x802,0x3051,0x3099,0x802,0x3053,0x3099,0x802,0x3055,0x3099, +0x802,0x3057,0x3099,0x802,0x3059,0x3099,0x802,0x305b,0x3099,0x802,0x305d,0x3099,0x802,0x305f,0x3099,0x802, +0x3061,0x3099,0x802,0x3064,0x3099,0x802,0x3066,0x3099,0x802,0x3068,0x3099,0x802,0x306f,0x3099,0x802,0x306f, +0x309a,0x802,0x3072,0x3099,0x802,0x3072,0x309a,0x802,0x3075,0x3099,0x802,0x3075,0x309a,0x802,0x3078,0x3099, +0x802,0x3078,0x309a,0x802,0x307b,0x3099,0x802,0x307b,0x309a,0x802,0x3046,0x3099,0x802,0x309d,0x3099,0x802, +0x30ab,0x3099,0x802,0x30ad,0x3099,0x802,0x30af,0x3099,0x802,0x30b1,0x3099,0x802,0x30b3,0x3099,0x802,0x30b5, +0x3099,0x802,0x30b7,0x3099,0x802,0x30b9,0x3099,0x802,0x30bb,0x3099,0x802,0x30bd,0x3099,0x802,0x30bf,0x3099, +0x802,0x30c1,0x3099,0x802,0x30c4,0x3099,0x802,0x30c6,0x3099,0x802,0x30c8,0x3099,0x802,0x30cf,0x3099,0x802, +0x30cf,0x309a,0x802,0x30d2,0x3099,0x802,0x30d2,0x309a,0x802,0x30d5,0x3099,0x802,0x30d5,0x309a,0x802,0x30d8, +0x3099,0x802,0x30d8,0x309a,0x802,0x30db,0x3099,0x802,0x30db,0x309a,0x802,0x30a6,0x3099,0x802,0x30ef,0x3099, +0x802,0x30f0,0x3099,0x802,0x30f1,0x3099,0x802,0x30f2,0x3099,0x802,0x30fd,0x3099,0xe603,0xd801,0xddd2,0x307, +0xe603,0xd801,0xddda,0x307,0x704,0xd804,0xdc99,0xd804,0xdcba,0x704,0xd804,0xdc9b,0xd804,0xdcba,0x704,0xd804, +0xdca5,0xd804,0xdcba,4,0xd804,0xdd31,0xd804,0xdd27,4,0xd804,0xdd32,0xd804,0xdd27,4,0xd804,0xdf47, +0xd804,0xdf3e,4,0xd804,0xdf47,0xd804,0xdf57,4,0xd804,0xdf82,0xd804,0xdfc9,4,0xd804,0xdf84,0xd804, +0xdfbb,4,0xd804,0xdf8b,0xd804,0xdfc2,4,0xd804,0xdf90,0xd804,0xdfc9,4,0xd805,0xdcb9,0xd805,0xdcba, +4,0xd805,0xdcb9,0xd805,0xdcb0,4,0xd805,0xdcb9,0xd805,0xdcbd,4,0xd805,0xddb8,0xd805,0xddaf,4, +0xd805,0xddb9,0xd805,0xddaf,4,0xd806,0xdd35,0xd806,0xdd30,0xd81b,0xdd69,0xd81b,0xdd67,4,0x46,0xd81b, +0xdd63,0xd81b,0xdd67,0xd81b,0xdd67,1,0x2b9,1,0x3b,1,0xb7,0x702,0x915,0x93c,0x702,0x916, +0x93c,0x702,0x917,0x93c,0x702,0x91c,0x93c,0x702,0x921,0x93c,0x702,0x922,0x93c,0x702,0x92b,0x93c, +0x702,0x92f,0x93c,0x702,0x9a1,0x9bc,0x702,0x9a2,0x9bc,0x702,0x9af,0x9bc,0x702,0xa32,0xa3c,0x702, +0xa38,0xa3c,0x702,0xa16,0xa3c,0x702,0xa17,0xa3c,0x702,0xa1c,0xa3c,0x702,0xa2b,0xa3c,0x702,0xb21, +0xb3c,0x702,0xb22,0xb3c,2,0xf42,0xfb7,2,0xf4c,0xfb7,2,0xf51,0xfb7,2,0xf56,0xfb7, +2,0xf5b,0xfb7,2,0xf40,0xfb5,0x8202,0xfb2,0xf80,0x8202,0xfb3,0xf80,2,0xf92,0xfb7,2, +0xf9c,0xfb7,2,0xfa1,0xfb7,2,0xfa6,0xfb7,2,0xfab,0xfb7,2,0xf90,0xfb5,1,0x3b9, +1,0x60,1,0xb4,1,0x3a9,1,0x4b,1,0x3008,1,0x3009,0x102,0x2add,0x338,1, +0x8c48,1,0x66f4,1,0x8eca,1,0x8cc8,1,0x6ed1,1,0x4e32,1,0x53e5,1,0x9f9c,1, +0x5951,1,0x91d1,1,0x5587,1,0x5948,1,0x61f6,1,0x7669,1,0x7f85,1,0x863f,1, +0x87ba,1,0x88f8,1,0x908f,1,0x6a02,1,0x6d1b,1,0x70d9,1,0x73de,1,0x843d,1, +0x916a,1,0x99f1,1,0x4e82,1,0x5375,1,0x6b04,1,0x721b,1,0x862d,1,0x9e1e,1, +0x5d50,1,0x6feb,1,0x85cd,1,0x8964,1,0x62c9,1,0x81d8,1,0x881f,1,0x5eca,1, +0x6717,1,0x6d6a,1,0x72fc,1,0x90ce,1,0x4f86,1,0x51b7,1,0x52de,1,0x64c4,1, +0x6ad3,1,0x7210,1,0x76e7,1,0x8001,1,0x8606,1,0x865c,1,0x8def,1,0x9732,1, +0x9b6f,1,0x9dfa,1,0x788c,1,0x797f,1,0x7da0,1,0x83c9,1,0x9304,1,0x9e7f,1, +0x8ad6,1,0x58df,1,0x5f04,1,0x7c60,1,0x807e,1,0x7262,1,0x78ca,1,0x8cc2,1, +0x96f7,1,0x58d8,1,0x5c62,1,0x6a13,1,0x6dda,1,0x6f0f,1,0x7d2f,1,0x7e37,1, +0x964b,1,0x52d2,1,0x808b,1,0x51dc,1,0x51cc,1,0x7a1c,1,0x7dbe,1,0x83f1,1, +0x9675,1,0x8b80,1,0x62cf,1,0x8afe,1,0x4e39,1,0x5be7,1,0x6012,1,0x7387,1, +0x7570,1,0x5317,1,0x78fb,1,0x4fbf,1,0x5fa9,1,0x4e0d,1,0x6ccc,1,0x6578,1, +0x7d22,1,0x53c3,1,0x585e,1,0x7701,1,0x8449,1,0x8aaa,1,0x6bba,1,0x8fb0,1, +0x6c88,1,0x62fe,1,0x82e5,1,0x63a0,1,0x7565,1,0x4eae,1,0x5169,1,0x51c9,1, +0x6881,1,0x7ce7,1,0x826f,1,0x8ad2,1,0x91cf,1,0x52f5,1,0x5442,1,0x5973,1, +0x5eec,1,0x65c5,1,0x6ffe,1,0x792a,1,0x95ad,1,0x9a6a,1,0x9e97,1,0x9ece,1, +0x529b,1,0x66c6,1,0x6b77,1,0x8f62,1,0x5e74,1,0x6190,1,0x6200,1,0x649a,1, +0x6f23,1,0x7149,1,0x7489,1,0x79ca,1,0x7df4,1,0x806f,1,0x8f26,1,0x84ee,1, +0x9023,1,0x934a,1,0x5217,1,0x52a3,1,0x54bd,1,0x70c8,1,0x88c2,1,0x5ec9,1, +0x5ff5,1,0x637b,1,0x6bae,1,0x7c3e,1,0x7375,1,0x4ee4,1,0x56f9,1,0x5dba,1, +0x601c,1,0x73b2,1,0x7469,1,0x7f9a,1,0x8046,1,0x9234,1,0x96f6,1,0x9748,1, +0x9818,1,0x4f8b,1,0x79ae,1,0x91b4,1,0x96b8,1,0x60e1,1,0x4e86,1,0x50da,1, +0x5bee,1,0x5c3f,1,0x6599,1,0x71ce,1,0x7642,1,0x84fc,1,0x907c,1,0x9f8d,1, +0x6688,1,0x962e,1,0x5289,1,0x677b,1,0x67f3,1,0x6d41,1,0x6e9c,1,0x7409,1, +0x7559,1,0x786b,1,0x7d10,1,0x985e,1,0x516d,1,0x622e,1,0x9678,1,0x502b,1, +0x5d19,1,0x6dea,1,0x8f2a,1,0x5f8b,1,0x6144,1,0x6817,1,0x9686,1,0x5229,1, +0x540f,1,0x5c65,1,0x6613,1,0x674e,1,0x68a8,1,0x6ce5,1,0x7406,1,0x75e2,1, +0x7f79,1,0x88cf,1,0x88e1,1,0x91cc,1,0x96e2,1,0x533f,1,0x6eba,1,0x541d,1, +0x71d0,1,0x7498,1,0x85fa,1,0x96a3,1,0x9c57,1,0x9e9f,1,0x6797,1,0x6dcb,1, +0x81e8,1,0x7acb,1,0x7b20,1,0x7c92,1,0x72c0,1,0x7099,1,0x8b58,1,0x4ec0,1, +0x8336,1,0x523a,1,0x5207,1,0x5ea6,1,0x62d3,1,0x7cd6,1,0x5b85,1,0x6d1e,1, +0x66b4,1,0x8f3b,1,0x884c,1,0x964d,1,0x898b,1,0x5ed3,1,0x5140,1,0x55c0,1, +0x585a,1,0x6674,1,0x51de,1,0x732a,1,0x76ca,1,0x793c,1,0x795e,1,0x7965,1, +0x798f,1,0x9756,1,0x7cbe,1,0x7fbd,1,0x8612,1,0x8af8,1,0x9038,1,0x90fd,1, +0x98ef,1,0x98fc,1,0x9928,1,0x9db4,1,0x90de,1,0x96b7,1,0x4fae,1,0x50e7,1, +0x514d,1,0x52c9,1,0x52e4,1,0x5351,1,0x559d,1,0x5606,1,0x5668,1,0x5840,1, +0x58a8,1,0x5c64,1,0x5c6e,1,0x6094,1,0x6168,1,0x618e,1,0x61f2,1,0x654f,1, +0x65e2,1,0x6691,1,0x6885,1,0x6d77,1,0x6e1a,1,0x6f22,1,0x716e,1,0x722b,1, +0x7422,1,0x7891,1,0x793e,1,0x7949,1,0x7948,1,0x7950,1,0x7956,1,0x795d,1, +0x798d,1,0x798e,1,0x7a40,1,0x7a81,1,0x7bc0,1,0x7e09,1,0x7e41,1,0x7f72,1, +0x8005,1,0x81ed,1,0x8279,1,0x8457,1,0x8910,1,0x8996,1,0x8b01,1,0x8b39,1, +0x8cd3,1,0x8d08,1,0x8fb6,1,0x96e3,1,0x97ff,1,0x983b,1,0x6075,2,0xd850,0xdeee, +1,0x8218,1,0x4e26,1,0x51b5,1,0x5168,1,0x4f80,1,0x5145,1,0x5180,1,0x52c7, +1,0x52fa,1,0x5555,1,0x5599,1,0x55e2,1,0x58b3,1,0x5944,1,0x5954,1,0x5a62, +1,0x5b28,1,0x5ed2,1,0x5ed9,1,0x5f69,1,0x5fad,1,0x60d8,1,0x614e,1,0x6108, +1,0x6160,1,0x6234,1,0x63c4,1,0x641c,1,0x6452,1,0x6556,1,0x671b,1,0x6756, +1,0x6b79,1,0x6edb,1,0x6ecb,1,0x701e,1,0x77a7,1,0x7235,1,0x72af,1,0x7471, +1,0x7506,1,0x753b,1,0x761d,1,0x761f,1,0x76db,1,0x76f4,1,0x774a,1,0x7740, +1,0x78cc,1,0x7ab1,1,0x7c7b,1,0x7d5b,1,0x7f3e,1,0x8352,1,0x83ef,1,0x8779, +1,0x8941,1,0x8986,1,0x8abf,1,0x8acb,1,0x8aed,1,0x8b8a,1,0x8f38,1,0x9072, +1,0x9199,1,0x9276,1,0x967c,1,0x97db,1,0x980b,1,0x9b12,2,0xd84a,0xdc4a,2, +0xd84a,0xdc44,2,0xd84c,0xdfd5,1,0x3b9d,1,0x4018,1,0x4039,2,0xd854,0xde49,2,0xd857, +0xdcd0,2,0xd85f,0xded3,1,0x9f43,1,0x9f8e,0xe02,0x5d9,0x5b4,0x1102,0x5f2,0x5b7,0x1802,0x5e9, +0x5c1,0x1902,0x5e9,0x5c2,0xfb49,0x1843,0x5e9,0x5bc,0x5c1,0xfb49,0x1943,0x5e9,0x5bc,0x5c2,0x1102,0x5d0, +0x5b7,0x1202,0x5d0,0x5b8,0x1502,0x5d0,0x5bc,0x1502,0x5d1,0x5bc,0x1502,0x5d2,0x5bc,0x1502,0x5d3,0x5bc, +0x1502,0x5d4,0x5bc,0x1502,0x5d5,0x5bc,0x1502,0x5d6,0x5bc,0x1502,0x5d8,0x5bc,0x1502,0x5d9,0x5bc,0x1502, +0x5da,0x5bc,0x1502,0x5db,0x5bc,0x1502,0x5dc,0x5bc,0x1502,0x5de,0x5bc,0x1502,0x5e0,0x5bc,0x1502,0x5e1, +0x5bc,0x1502,0x5e3,0x5bc,0x1502,0x5e4,0x5bc,0x1502,0x5e6,0x5bc,0x1502,0x5e7,0x5bc,0x1502,0x5e8,0x5bc, +0x1502,0x5e9,0x5bc,0x1502,0x5ea,0x5bc,0x1302,0x5d5,0x5b9,0x1702,0x5d1,0x5bf,0x1702,0x5db,0x5bf,0x1702, +0x5e4,0x5bf,0xd804,0xd834,0xdd57,0xd834,0xdd65,0xd804,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd5f,0xd834,0xdd6e, +4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xdd5f,0xd834,0xdd6f,4,0xd846,0xd834,0xdd58, +0xd834,0xdd65,0xd834,0xdd6f,0xd834,0xdd5f,0xd834,0xdd70,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd70, +0xd834,0xdd5f,0xd834,0xdd71,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd71,0xd834,0xdd5f,0xd834,0xdd72, +4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd72,0xd804,0xd834,0xddb9,0xd834,0xdd65,0xd804,0xd834,0xddba, +0xd834,0xdd65,0xd834,0xddbb,0xd834,0xdd6e,4,0xd846,0xd834,0xddb9,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xddbc, +0xd834,0xdd6e,4,0xd846,0xd834,0xddba,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xddbb,0xd834,0xdd6f,4,0xd846, +0xd834,0xddb9,0xd834,0xdd65,0xd834,0xdd6f,0xd834,0xddbc,0xd834,0xdd6f,4,0xd846,0xd834,0xddba,0xd834,0xdd65, +0xd834,0xdd6f,1,0x4e3d,1,0x4e38,1,0x4e41,2,0xd840,0xdd22,1,0x4f60,1,0x4fbb,1, +0x5002,1,0x507a,1,0x5099,1,0x50cf,1,0x349e,2,0xd841,0xde3a,1,0x5154,1,0x5164, +1,0x5177,2,0xd841,0xdd1c,1,0x34b9,1,0x5167,1,0x518d,2,0xd841,0xdd4b,1,0x5197, +1,0x51a4,1,0x4ecc,1,0x51ac,2,0xd864,0xdddf,1,0x51f5,1,0x5203,1,0x34df,1, +0x523b,1,0x5246,1,0x5272,1,0x5277,1,0x3515,1,0x5305,1,0x5306,1,0x5349,1, +0x535a,1,0x5373,1,0x537d,1,0x537f,2,0xd842,0xde2c,1,0x7070,1,0x53ca,1,0x53df, +2,0xd842,0xdf63,1,0x53eb,1,0x53f1,1,0x5406,1,0x549e,1,0x5438,1,0x5448,1, +0x5468,1,0x54a2,1,0x54f6,1,0x5510,1,0x5553,1,0x5563,1,0x5584,1,0x55ab,1, +0x55b3,1,0x55c2,1,0x5716,1,0x5717,1,0x5651,1,0x5674,1,0x58ee,1,0x57ce,1, +0x57f4,1,0x580d,1,0x578b,1,0x5832,1,0x5831,1,0x58ac,2,0xd845,0xdce4,1,0x58f2, +1,0x58f7,1,0x5906,1,0x591a,1,0x5922,1,0x5962,2,0xd845,0xdea8,2,0xd845,0xdeea, +1,0x59ec,1,0x5a1b,1,0x5a27,1,0x59d8,1,0x5a66,1,0x36ee,1,0x36fc,1,0x5b08, +1,0x5b3e,2,0xd846,0xddc8,1,0x5bc3,1,0x5bd8,1,0x5bf3,2,0xd846,0xdf18,1,0x5bff, +1,0x5c06,1,0x5f53,1,0x5c22,1,0x3781,1,0x5c60,1,0x5cc0,1,0x5c8d,2,0xd847, +0xdde4,1,0x5d43,2,0xd847,0xdde6,1,0x5d6e,1,0x5d6b,1,0x5d7c,1,0x5de1,1,0x5de2, +1,0x382f,1,0x5dfd,1,0x5e28,1,0x5e3d,1,0x5e69,1,0x3862,2,0xd848,0xdd83,1, +0x387c,1,0x5eb0,1,0x5eb3,1,0x5eb6,2,0xd868,0xdf92,1,0x5efe,2,0xd848,0xdf31,1, +0x8201,1,0x5f22,1,0x38c7,2,0xd84c,0xdeb8,2,0xd858,0xddda,1,0x5f62,1,0x5f6b,1, +0x38e3,1,0x5f9a,1,0x5fcd,1,0x5fd7,1,0x5ff9,1,0x6081,1,0x393a,1,0x391c,2, +0xd849,0xded4,1,0x60c7,1,0x6148,1,0x614c,1,0x617a,1,0x61b2,1,0x61a4,1,0x61af, +1,0x61de,1,0x6210,1,0x621b,1,0x625d,1,0x62b1,1,0x62d4,1,0x6350,2,0xd84a, +0xdf0c,1,0x633d,1,0x62fc,1,0x6368,1,0x6383,1,0x63e4,2,0xd84a,0xdff1,1,0x6422, +1,0x63c5,1,0x63a9,1,0x3a2e,1,0x6469,1,0x647e,1,0x649d,1,0x6477,1,0x3a6c, +1,0x656c,2,0xd84c,0xdc0a,1,0x65e3,1,0x66f8,1,0x6649,1,0x3b19,1,0x3b08,1, +0x3ae4,1,0x5192,1,0x5195,1,0x6700,1,0x669c,1,0x80ad,1,0x43d9,1,0x6721,1, +0x675e,1,0x6753,2,0xd84c,0xdfc3,1,0x3b49,1,0x67fa,1,0x6785,1,0x6852,2,0xd84d, +0xdc6d,1,0x688e,1,0x681f,1,0x6914,1,0x6942,1,0x69a3,1,0x69ea,1,0x6aa8,2, +0xd84d,0xdea3,1,0x6adb,1,0x3c18,1,0x6b21,2,0xd84e,0xdca7,1,0x6b54,1,0x3c4e,1, +0x6b72,1,0x6b9f,1,0x6bbb,2,0xd84e,0xde8d,2,0xd847,0xdd0b,2,0xd84e,0xdefa,1,0x6c4e, +2,0xd84f,0xdcbc,1,0x6cbf,1,0x6ccd,1,0x6c67,1,0x6d16,1,0x6d3e,1,0x6d69,1, +0x6d78,1,0x6d85,2,0xd84f,0xdd1e,1,0x6d34,1,0x6e2f,1,0x6e6e,1,0x3d33,1,0x6ec7, +2,0xd84f,0xded1,1,0x6df9,1,0x6f6e,2,0xd84f,0xdf5e,2,0xd84f,0xdf8e,1,0x6fc6,1, +0x7039,1,0x701b,1,0x3d96,1,0x704a,1,0x707d,1,0x7077,1,0x70ad,2,0xd841,0xdd25, +1,0x7145,2,0xd850,0xde63,1,0x719c,2,0xd850,0xdfab,1,0x7228,1,0x7250,2,0xd851, +0xde08,1,0x7280,1,0x7295,2,0xd851,0xdf35,2,0xd852,0xdc14,1,0x737a,1,0x738b,1, +0x3eac,1,0x73a5,1,0x3eb8,1,0x7447,1,0x745c,1,0x7485,1,0x74ca,1,0x3f1b,1, +0x7524,2,0xd853,0xdc36,1,0x753e,2,0xd853,0xdc92,2,0xd848,0xdd9f,1,0x7610,2,0xd853, +0xdfa1,2,0xd853,0xdfb8,2,0xd854,0xdc44,1,0x3ffc,1,0x4008,2,0xd854,0xdcf3,2,0xd854, +0xdcf2,2,0xd854,0xdd19,2,0xd854,0xdd33,1,0x771e,1,0x771f,1,0x778b,1,0x4046,1, +0x4096,2,0xd855,0xdc1d,1,0x784e,1,0x40e3,2,0xd855,0xde26,2,0xd855,0xde9a,2,0xd855, +0xdec5,1,0x79eb,1,0x412f,1,0x7a4a,1,0x7a4f,2,0xd856,0xdd7c,2,0xd856,0xdea7,1, +0x7aee,1,0x4202,2,0xd856,0xdfab,1,0x7bc6,1,0x7bc9,1,0x4227,2,0xd857,0xdc80,1, +0x7cd2,1,0x42a0,1,0x7ce8,1,0x7ce3,1,0x7d00,2,0xd857,0xdf86,1,0x7d63,1,0x4301, +1,0x7dc7,1,0x7e02,1,0x7e45,1,0x4334,2,0xd858,0xde28,2,0xd858,0xde47,1,0x4359, +2,0xd858,0xded9,1,0x7f7a,2,0xd858,0xdf3e,1,0x7f95,1,0x7ffa,2,0xd859,0xdcda,2, +0xd859,0xdd23,1,0x8060,2,0xd859,0xdda8,1,0x8070,2,0xd84c,0xdf5f,1,0x43d5,1,0x80b2, +1,0x8103,1,0x440b,1,0x813e,1,0x5ab5,2,0xd859,0xdfa7,2,0xd859,0xdfb5,2,0xd84c, +0xdf93,2,0xd84c,0xdf9c,1,0x8204,1,0x8f9e,1,0x446b,1,0x8291,1,0x828b,1,0x829d, +1,0x52b3,1,0x82b1,1,0x82b3,1,0x82bd,1,0x82e6,2,0xd85a,0xdf3c,1,0x831d,1, +0x8363,1,0x83ad,1,0x8323,1,0x83bd,1,0x83e7,1,0x8353,1,0x83ca,1,0x83cc,1, +0x83dc,2,0xd85b,0xdc36,2,0xd85b,0xdd6b,2,0xd85b,0xdcd5,1,0x452b,1,0x84f1,1,0x84f3, +1,0x8516,2,0xd85c,0xdfca,1,0x8564,2,0xd85b,0xdf2c,1,0x455d,1,0x4561,2,0xd85b, +0xdfb1,2,0xd85c,0xdcd2,1,0x456b,1,0x8650,1,0x8667,1,0x8669,1,0x86a9,1,0x8688, +1,0x870e,1,0x86e2,1,0x8728,1,0x876b,1,0x8786,1,0x45d7,1,0x87e1,1,0x8801, +1,0x45f9,1,0x8860,1,0x8863,2,0xd85d,0xde67,1,0x88d7,1,0x88de,1,0x4635,1, +0x88fa,1,0x34bb,2,0xd85e,0xdcae,2,0xd85e,0xdd66,1,0x46be,1,0x46c7,1,0x8aa0,1, +0x8c55,2,0xd85f,0xdca8,1,0x8cab,1,0x8cc1,1,0x8d1b,1,0x8d77,2,0xd85f,0xdf2f,2, +0xd842,0xdc04,1,0x8dcb,1,0x8dbc,1,0x8df0,2,0xd842,0xdcde,1,0x8ed4,2,0xd861,0xddd2, +2,0xd861,0xdded,1,0x9094,1,0x90f1,1,0x9111,2,0xd861,0xdf2e,1,0x911b,1,0x9238, +1,0x92d7,1,0x92d8,1,0x927c,1,0x93f9,1,0x9415,2,0xd862,0xdffa,1,0x958b,1, +0x4995,1,0x95b7,2,0xd863,0xdd77,1,0x49e6,1,0x96c3,1,0x5db2,1,0x9723,2,0xd864, +0xdd45,2,0xd864,0xde1a,1,0x4a6e,1,0x4a76,1,0x97e0,2,0xd865,0xdc0a,1,0x4ab2,2, +0xd865,0xdc96,1,0x9829,2,0xd865,0xddb6,1,0x98e2,1,0x4b33,1,0x9929,1,0x99a7,1, +0x99c2,1,0x99fe,1,0x4bce,2,0xd866,0xdf30,1,0x9c40,1,0x9cfd,1,0x4cce,1,0x4ced, +1,0x9d67,2,0xd868,0xdcce,1,0x4cf8,2,0xd868,0xdd05,2,0xd868,0xde0e,2,0xd868,0xde91, +1,0x9ebb,1,0x4d56,1,0x9ef9,1,0x9efe,1,0x9f05,1,0x9f0f,1,0x9f16,1,0x9f3b, +2,0xd869,0xde00,0x3ac,0xe642,0x3b1,0x301,0x3ad,0xe642,0x3b5,0x301,0x3ae,0xe642,0x3b7,0x301,0x3af, +0xe642,0x3b9,0x301,0x3cc,0xe642,0x3bf,0x301,0x3cd,0xe642,0x3c5,0x301,0x3ce,0xe642,0x3c9,0x301,0x386, +0xe642,0x391,0x301,0x388,0xe642,0x395,0x301,0x389,0xe642,0x397,0x301,0x390,1,0xe643,0x3b9,0x308, +0x301,0x38a,0xe642,0x399,0x301,0x3b0,1,0xe643,0x3c5,0x308,0x301,0x38e,0xe642,0x3a5,0x301,0x385, +0xe642,0xa8,0x301,0x38c,0xe642,0x39f,0x301,0x38f,0xe642,0x3a9,0x301,0xc5,0xe642,0x41,0x30a,0xe6e6, +0xe681,0x300,0xe6e6,0xe681,0x301,0xe6e6,0xe681,0x313,0xe6e6,0xe682,0x308,0x301,0x8100,0x8282,0xf71,0xf72, +0x8100,0x8482,0xf71,0xf74,0x8100,0x8282,0xf71,0xf80,4,0xd804,0xdfc2,0xd804,0xdfc2,4,0xd804,0xdfc2, +0xd804,0xdfb8,4,0xd804,0xdfc2,0xd804,0xdfc9,4,0xd818,0xdd1e,0xd818,0xdd1f,4,0xd818,0xdd29,0xd818, +0xdd1f,4,0xd818,0xdd1e,0xd818,0xdd20,0xd818,0xdd21,0xd818,0xdd1f,4,0x46,0xd818,0xdd1e,0xd818,0xdd1e, +0xd818,0xdd1f,0xd818,0xdd22,0xd818,0xdd1f,4,0x46,0xd818,0xdd1e,0xd818,0xdd29,0xd818,0xdd1f,0xd818,0xdd21, +0xd818,0xdd20,4,0x46,0xd818,0xdd1e,0xd818,0xdd1e,0xd818,0xdd20,4,0xd81b,0xdd67,0xd81b,0xdd67,4, +0xd818,0xdd1e,0xd818,0xdd1e,0x34b1,0x47c2,0xc24c,0xb4b1,0x4802,0xc250,4,0xd818,0xdd1e,0xd818,0xdd29,0xb4b1, +0x47c2,0xc24e,0x3489,0xee02,0x278e,0x3489,0xf082,0x278a,0xb489,0xf242,0x2790,0x34b1,0x4782,0xc243,0x34b1,0x47c2, +0xc246,0x34b1,0x4802,0xc24a,0xb4b1,0x4a42,0xc245,0xb4b1,0x47c2,0xc248,0xb4b7,0x59c2,0xdad0,0 }; static const uint8_t norm2_nfc_data_smallFCD[256]={ diff --git a/thirdparty/icu4c/common/norm2allmodes.h b/thirdparty/icu4c/common/norm2allmodes.h index a2cfc89c1a..4b30d787e8 100644 --- a/thirdparty/icu4c/common/norm2allmodes.h +++ b/thirdparty/icu4c/common/norm2allmodes.h @@ -174,7 +174,7 @@ public: errorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } - return (int32_t)(spanQuickCheckYes(sArray, sArray+s.length(), errorCode)-sArray); + return static_cast<int32_t>(spanQuickCheckYes(sArray, sArray + s.length(), errorCode) - sArray); } virtual const char16_t * spanQuickCheckYes(const char16_t *src, const char16_t *limit, UErrorCode &errorCode) const = 0; diff --git a/thirdparty/icu4c/common/normalizer2.cpp b/thirdparty/icu4c/common/normalizer2.cpp index 6856736b88..dad3df4ede 100644 --- a/thirdparty/icu4c/common/normalizer2.cpp +++ b/thirdparty/icu4c/common/normalizer2.cpp @@ -380,8 +380,8 @@ normalizeSecondAndAppend(const UNormalizer2 *norm2, firstLength=firstString.length(); // In case it was -1. // secondLength==0: Nothing to do, and n2wi->normalizeAndAppend(nullptr, nullptr, buffer, ...) would crash. if(secondLength!=0) { - const Normalizer2 *n2=(const Normalizer2 *)norm2; - const Normalizer2WithImpl *n2wi=dynamic_cast<const Normalizer2WithImpl *>(n2); + const Normalizer2* n2 = reinterpret_cast<const Normalizer2*>(norm2); + const Normalizer2WithImpl* n2wi = dynamic_cast<const Normalizer2WithImpl*>(n2); if(n2wi!=nullptr) { // Avoid duplicate argument checking and support NUL-terminated src. UnicodeString safeMiddle; diff --git a/thirdparty/icu4c/common/normalizer2impl.cpp b/thirdparty/icu4c/common/normalizer2impl.cpp index 9c715ac3ef..758a84c110 100644 --- a/thirdparty/icu4c/common/normalizer2impl.cpp +++ b/thirdparty/icu4c/common/normalizer2impl.cpp @@ -53,9 +53,9 @@ namespace { */ inline uint8_t leadByteForCP(UChar32 c) { if (c <= 0x7f) { - return (uint8_t)c; + return static_cast<uint8_t>(c); } else if (c <= 0x7ff) { - return (uint8_t)(0xc0+(c>>6)); + return static_cast<uint8_t>(0xc0 + (c >> 6)); } else { // Should not occur because ccc(U+0300)!=0. return 0xe0; @@ -82,7 +82,7 @@ UChar32 codePointFromValidUTF8(const uint8_t *cpStart, const uint8_t *cpLimit) { return ((c&0x1f)<<6) | (cpStart[1]&0x3f); case 3: // no need for (c&0xf) because the upper bits are truncated after <<12 in the cast to (char16_t) - return (char16_t)((c<<12) | ((cpStart[1]&0x3f)<<6) | (cpStart[2]&0x3f)); + return static_cast<char16_t>((c << 12) | ((cpStart[1] & 0x3f) << 6) | (cpStart[2] & 0x3f)); case 4: return ((c&7)<<18) | ((cpStart[1]&0x3f)<<12) | ((cpStart[2]&0x3f)<<6) | (cpStart[3]&0x3f); default: @@ -100,8 +100,8 @@ UChar32 previousHangulOrJamo(const uint8_t *start, const uint8_t *p) { uint8_t l = *p; uint8_t t1, t2; if (0xe1 <= l && l <= 0xed && - (t1 = (uint8_t)(p[1] - 0x80)) <= 0x3f && - (t2 = (uint8_t)(p[2] - 0x80)) <= 0x3f && + (t1 = static_cast<uint8_t>(p[1] - 0x80)) <= 0x3f && + (t2 = static_cast<uint8_t>(p[2] - 0x80)) <= 0x3f && (l < 0xed || t1 <= 0x1f)) { return ((l & 0xf) << 12) | (t1 << 6) | t2; } @@ -125,7 +125,7 @@ int32_t getJamoTMinusBase(const uint8_t *src, const uint8_t *limit) { } } else if (src[1] == 0x87) { uint8_t t = src[2]; - if ((int8_t)t <= (int8_t)0x82u) { + if (static_cast<int8_t>(t) <= static_cast<int8_t>(0x82u)) { return t - (0xa7 - 0x40); } } @@ -138,10 +138,10 @@ appendCodePointDelta(const uint8_t *cpStart, const uint8_t *cpLimit, int32_t del ByteSink &sink, Edits *edits) { char buffer[U8_MAX_LENGTH]; int32_t length; - int32_t cpLength = (int32_t)(cpLimit - cpStart); + int32_t cpLength = static_cast<int32_t>(cpLimit - cpStart); if (cpLength == 1) { // The builder makes ASCII map to ASCII. - buffer[0] = (uint8_t)(*cpStart + delta); + buffer[0] = static_cast<uint8_t>(*cpStart + delta); length = 1; } else { int32_t trail = *(cpLimit-1) + delta; @@ -150,7 +150,7 @@ appendCodePointDelta(const uint8_t *cpStart, const uint8_t *cpLimit, int32_t del --cpLimit; length = 0; do { buffer[length++] = *cpStart++; } while (cpStart < cpLimit); - buffer[length++] = (uint8_t)trail; + buffer[length++] = static_cast<uint8_t>(trail); } else { // Decode the code point, add the delta, re-encode. UChar32 c = codePointFromValidUTF8(cpStart, cpLimit) + delta; @@ -205,16 +205,16 @@ UBool ReorderingBuffer::init(int32_t destCapacity, UErrorCode &errorCode) { } UBool ReorderingBuffer::equals(const char16_t *otherStart, const char16_t *otherLimit) const { - int32_t length=(int32_t)(limit-start); + int32_t length = static_cast<int32_t>(limit - start); return - length==(int32_t)(otherLimit-otherStart) && + length == static_cast<int32_t>(otherLimit - otherStart) && 0==u_memcmp(start, otherStart, length); } UBool ReorderingBuffer::equals(const uint8_t *otherStart, const uint8_t *otherLimit) const { U_ASSERT((otherLimit - otherStart) <= INT32_MAX); // ensured by caller - int32_t length = (int32_t)(limit - start); - int32_t otherLength = (int32_t)(otherLimit - otherStart); + int32_t length = static_cast<int32_t>(limit - start); + int32_t otherLength = static_cast<int32_t>(otherLimit - otherStart); // For equal strings, UTF-8 is at least as long as UTF-16, and at most three times as long. if (otherLength < length || (otherLength / 3) > length) { return false; @@ -284,7 +284,7 @@ UBool ReorderingBuffer::append(const char16_t *s, int32_t length, UBool isNFD, U16_NEXT(s, i, length, c); if(i<length) { if (isNFD) { - leadCC = Normalizer2Impl::getCCFromYesOrMaybe(impl.getRawNorm16(c)); + leadCC = Normalizer2Impl::getCCFromYesOrMaybeYes(impl.getRawNorm16(c)); } else { leadCC = impl.getCC(impl.getNorm16(c)); } @@ -304,7 +304,7 @@ UBool ReorderingBuffer::appendZeroCC(UChar32 c, UErrorCode &errorCode) { } remainingCapacity-=cpLength; if(cpLength==1) { - *limit++=(char16_t)c; + *limit++ = static_cast<char16_t>(c); } else { limit[0]=U16_LEAD(c); limit[1]=U16_TRAIL(c); @@ -319,7 +319,7 @@ UBool ReorderingBuffer::appendZeroCC(const char16_t *s, const char16_t *sLimit, if(s==sLimit) { return true; } - int32_t length=(int32_t)(sLimit-s); + int32_t length = static_cast<int32_t>(sLimit - s); if(remainingCapacity<length && !resize(length, errorCode)) { return false; } @@ -350,8 +350,8 @@ void ReorderingBuffer::removeSuffix(int32_t suffixLength) { } UBool ReorderingBuffer::resize(int32_t appendLength, UErrorCode &errorCode) { - int32_t reorderStartIndex=(int32_t)(reorderStart-start); - int32_t length=(int32_t)(limit-start); + int32_t reorderStartIndex = static_cast<int32_t>(reorderStart - start); + int32_t length = static_cast<int32_t>(limit - start); str.releaseBuffer(length); int32_t newCapacity=length+appendLength; int32_t doubleCapacity=2*str.getCapacity(); @@ -392,7 +392,7 @@ uint8_t ReorderingBuffer::previousCC() { --codePointStart; c=U16_GET_SUPPLEMENTARY(c2, c); } - return impl.getCCFromYesOrMaybeCP(c); + return impl.getCCFromYesOrMaybeYesCP(c); } // Inserts c somewhere before the last character. @@ -440,15 +440,14 @@ Normalizer2Impl::init(const int32_t *inIndexes, const UCPTrie *inTrie, minNoNoCompNoMaybeCC = static_cast<uint16_t>(inIndexes[IX_MIN_NO_NO_COMP_NO_MAYBE_CC]); minNoNoEmpty = static_cast<uint16_t>(inIndexes[IX_MIN_NO_NO_EMPTY]); limitNoNo = static_cast<uint16_t>(inIndexes[IX_LIMIT_NO_NO]); + minMaybeNo = static_cast<uint16_t>(inIndexes[IX_MIN_MAYBE_NO]); + minMaybeNoCombinesFwd = static_cast<uint16_t>(inIndexes[IX_MIN_MAYBE_NO_COMBINES_FWD]); minMaybeYes = static_cast<uint16_t>(inIndexes[IX_MIN_MAYBE_YES]); - U_ASSERT((minMaybeYes & 7) == 0); // 8-aligned for noNoDelta bit fields - centerNoNoDelta = (minMaybeYes >> DELTA_SHIFT) - MAX_DELTA - 1; + U_ASSERT((minMaybeNo & 7) == 0); // 8-aligned for noNoDelta bit fields + centerNoNoDelta = (minMaybeNo >> DELTA_SHIFT) - MAX_DELTA - 1; normTrie=inTrie; - - maybeYesCompositions=inExtraData; - extraData=maybeYesCompositions+((MIN_NORMAL_MAYBE_YES-minMaybeYes)>>OFFSET_SHIFT); - + extraData=inExtraData; smallFCD=inSmallFCD; } @@ -486,7 +485,7 @@ Normalizer2Impl::addPropertyStarts(const USetAdder *sa, UErrorCode & /*errorCode while ((end = ucptrie_getRange(normTrie, start, UCPMAP_RANGE_FIXED_LEAD_SURROGATES, INERT, nullptr, nullptr, &value)) >= 0) { sa->add(sa->set, start); - if (start != end && isAlgorithmicNoNo((uint16_t)value) && + if (start != end && isAlgorithmicNoNo(static_cast<uint16_t>(value)) && (value & Normalizer2Impl::DELTA_TCCC_MASK) > Normalizer2Impl::DELTA_TCCC_1) { // Range of code points with same-norm16-value algorithmic decompositions. // They might have different non-zero FCD16 values. @@ -570,7 +569,7 @@ Normalizer2Impl::decompose(const char16_t *src, const char16_t *limit, int32_t destLengthEstimate, UErrorCode &errorCode) const { if(destLengthEstimate<0 && limit!=nullptr) { - destLengthEstimate=(int32_t)(limit-src); + destLengthEstimate = static_cast<int32_t>(limit - src); } dest.remove(); ReorderingBuffer buffer(*this, dest); @@ -650,7 +649,7 @@ Normalizer2Impl::decompose(const char16_t *src, const char16_t *limit, } } else { if(isDecompYes(norm16)) { - uint8_t cc=getCCFromYesOrMaybe(norm16); + uint8_t cc=getCCFromYesOrMaybeYes(norm16); if(prevCC<=cc || cc==0) { prevCC=cc; if(cc<=1) { @@ -702,12 +701,13 @@ UBool Normalizer2Impl::decompose(UChar32 c, uint16_t norm16, UErrorCode &errorCode) const { // get the decomposition and the lead and trail cc's if (norm16 >= limitNoNo) { - if (isMaybeOrNonZeroCC(norm16)) { - return buffer.append(c, getCCFromYesOrMaybe(norm16), errorCode); + if (isMaybeYesOrNonZeroCC(norm16)) { + return buffer.append(c, getCCFromYesOrMaybeYes(norm16), errorCode); + } else if (norm16 < minMaybeNo) { + // Maps to an isCompYesAndZeroCC. + c=mapAlgorithmic(c, norm16); + norm16=getRawNorm16(c); } - // Maps to an isCompYesAndZeroCC. - c=mapAlgorithmic(c, norm16); - norm16=getRawNorm16(c); } if (norm16 < minYesNo) { // c does not decompose @@ -718,17 +718,17 @@ UBool Normalizer2Impl::decompose(UChar32 c, uint16_t norm16, return buffer.appendZeroCC(jamos, jamos+Hangul::decompose(c, jamos), errorCode); } // c decomposes, get everything from the variable-length extra data - const uint16_t *mapping=getMapping(norm16); + const uint16_t *mapping=getData(norm16); uint16_t firstUnit=*mapping; int32_t length=firstUnit&MAPPING_LENGTH_MASK; uint8_t leadCC, trailCC; - trailCC=(uint8_t)(firstUnit>>8); + trailCC = static_cast<uint8_t>(firstUnit >> 8); if(firstUnit&MAPPING_HAS_CCC_LCCC_WORD) { - leadCC=(uint8_t)(*(mapping-1)>>8); + leadCC = static_cast<uint8_t>(*(mapping - 1) >> 8); } else { leadCC=0; } - return buffer.append((const char16_t *)mapping+1, length, true, leadCC, trailCC, errorCode); + return buffer.append(reinterpret_cast<const char16_t*>(mapping) + 1, length, true, leadCC, trailCC, errorCode); } // Dual functionality: @@ -787,9 +787,9 @@ Normalizer2Impl::decomposeUTF8(uint32_t options, } // Medium-fast path: Quick check. - if (isMaybeOrNonZeroCC(norm16)) { + if (isMaybeYesOrNonZeroCC(norm16)) { // Does not decompose. - uint8_t cc = getCCFromYesOrMaybe(norm16); + uint8_t cc = getCCFromYesOrMaybeYes(norm16); if (prevCC <= cc || cc == 0) { prevCC = cc; if (cc <= 1) { @@ -836,7 +836,7 @@ Normalizer2Impl::decomposeUTF8(uint32_t options, } // We already know there was a change if the original character decomposed; // otherwise compare. - if (isMaybeOrNonZeroCC(norm16) && buffer.equals(prevBoundary, src)) { + if (isMaybeYesOrNonZeroCC(norm16) && buffer.equals(prevBoundary, src)) { if (!ByteSinkUtil::appendUnchanged(prevBoundary, src, *sink, options, edits, errorCode)) { break; @@ -867,9 +867,9 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, // Get the decomposition and the lead and trail cc's. UChar32 c = U_SENTINEL; if (norm16 >= limitNoNo) { - if (isMaybeOrNonZeroCC(norm16)) { + if (isMaybeYesOrNonZeroCC(norm16)) { // No comp boundaries around this character. - uint8_t cc = getCCFromYesOrMaybe(norm16); + uint8_t cc = getCCFromYesOrMaybeYes(norm16); if (cc == 0 && stopAt == STOP_AT_DECOMP_BOUNDARY) { return prevSrc; } @@ -881,14 +881,15 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, return src; } continue; + } else if (norm16 < minMaybeNo) { + // Maps to an isCompYesAndZeroCC. + if (stopAt != STOP_AT_LIMIT) { + return prevSrc; + } + c = codePointFromValidUTF8(prevSrc, src); + c = mapAlgorithmic(c, norm16); + norm16 = getRawNorm16(c); } - // Maps to an isCompYesAndZeroCC. - if (stopAt != STOP_AT_LIMIT) { - return prevSrc; - } - c = codePointFromValidUTF8(prevSrc, src); - c = mapAlgorithmic(c, norm16); - norm16 = getRawNorm16(c); } else if (stopAt != STOP_AT_LIMIT && norm16 < minNoNoCompNoMaybeCC) { return prevSrc; } @@ -918,20 +919,20 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, } } else { // The character decomposes, get everything from the variable-length extra data. - const uint16_t *mapping = getMapping(norm16); + const uint16_t *mapping = getData(norm16); uint16_t firstUnit = *mapping; int32_t length = firstUnit & MAPPING_LENGTH_MASK; - uint8_t trailCC = (uint8_t)(firstUnit >> 8); + uint8_t trailCC = static_cast<uint8_t>(firstUnit >> 8); uint8_t leadCC; if (firstUnit & MAPPING_HAS_CCC_LCCC_WORD) { - leadCC = (uint8_t)(*(mapping-1) >> 8); + leadCC = static_cast<uint8_t>(*(mapping - 1) >> 8); } else { leadCC = 0; } if (leadCC == 0 && stopAt == STOP_AT_DECOMP_BOUNDARY) { return prevSrc; } - if (!buffer.append((const char16_t *)mapping+1, length, true, leadCC, trailCC, errorCode)) { + if (!buffer.append(reinterpret_cast<const char16_t*>(mapping) + 1, length, true, leadCC, trailCC, errorCode)) { return nullptr; } } @@ -946,7 +947,7 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, const char16_t * Normalizer2Impl::getDecomposition(UChar32 c, char16_t buffer[4], int32_t &length) const { uint16_t norm16; - if(c<minDecompNoCP || isMaybeOrNonZeroCC(norm16=getNorm16(c))) { + if(c<minDecompNoCP || isMaybeYesOrNonZeroCC(norm16=getNorm16(c))) { // c does not decompose return nullptr; } @@ -968,9 +969,9 @@ Normalizer2Impl::getDecomposition(UChar32 c, char16_t buffer[4], int32_t &length return buffer; } // c decomposes, get everything from the variable-length extra data - const uint16_t *mapping=getMapping(norm16); + const uint16_t *mapping=getData(norm16); length=*mapping&MAPPING_LENGTH_MASK; - return (const char16_t *)mapping+1; + return reinterpret_cast<const char16_t*>(mapping) + 1; } // The capacity of the buffer must be 30=MAPPING_LENGTH_MASK-1 @@ -995,7 +996,7 @@ Normalizer2Impl::getRawDecomposition(UChar32 c, char16_t buffer[30], int32_t &le return buffer; } // c decomposes, get everything from the variable-length extra data - const uint16_t *mapping=getMapping(norm16); + const uint16_t *mapping=getData(norm16); uint16_t firstUnit=*mapping; int32_t mLength=firstUnit&MAPPING_LENGTH_MASK; // length of normal mapping if(firstUnit&MAPPING_HAS_RAW_MAPPING) { @@ -1005,17 +1006,17 @@ Normalizer2Impl::getRawDecomposition(UChar32 c, char16_t buffer[30], int32_t &le uint16_t rm0=*rawMapping; if(rm0<=MAPPING_LENGTH_MASK) { length=rm0; - return (const char16_t *)rawMapping-rm0; + return reinterpret_cast<const char16_t*>(rawMapping) - rm0; } else { // Copy the normal mapping and replace its first two code units with rm0. - buffer[0]=(char16_t)rm0; - u_memcpy(buffer+1, (const char16_t *)mapping+1+2, mLength-2); + buffer[0] = static_cast<char16_t>(rm0); + u_memcpy(buffer + 1, reinterpret_cast<const char16_t*>(mapping) + 1 + 2, mLength - 2); length=mLength-1; return buffer; } } else { length=mLength; - return (const char16_t *)mapping+1; + return reinterpret_cast<const char16_t*>(mapping) + 1; } } @@ -1052,7 +1053,7 @@ void Normalizer2Impl::decomposeAndAppend(const char16_t *src, const char16_t *li limit=u_strchr(p, 0); } - if (buffer.append(src, (int32_t)(p - src), false, firstCC, prevCC, errorCode)) { + if (buffer.append(src, static_cast<int32_t>(p - src), false, firstCC, prevCC, errorCode)) { buffer.appendZeroCC(p, limit, errorCode); } } @@ -1070,7 +1071,7 @@ UBool Normalizer2Impl::norm16HasDecompBoundaryBefore(uint16_t norm16) const { return norm16 <= MIN_NORMAL_MAYBE_YES || norm16 == JAMO_VT; } // c decomposes, get everything from the variable-length extra data - const uint16_t *mapping=getMapping(norm16); + const uint16_t *mapping=getDataForYesOrNo(norm16); uint16_t firstUnit=*mapping; // true if leadCC==0 (hasFCDBoundaryBefore()) return (firstUnit&MAPPING_HAS_CCC_LCCC_WORD)==0 || (*(mapping-1)&0xff00)==0; @@ -1091,14 +1092,15 @@ UBool Normalizer2Impl::norm16HasDecompBoundaryAfter(uint16_t norm16) const { return true; } if (norm16 >= limitNoNo) { - if (isMaybeOrNonZeroCC(norm16)) { + if (isMaybeYesOrNonZeroCC(norm16)) { return norm16 <= MIN_NORMAL_MAYBE_YES || norm16 == JAMO_VT; + } else if (norm16 < minMaybeNo) { + // Maps to an isCompYesAndZeroCC. + return (norm16 & DELTA_TCCC_MASK) <= DELTA_TCCC_1; } - // Maps to an isCompYesAndZeroCC. - return (norm16 & DELTA_TCCC_MASK) <= DELTA_TCCC_1; } // c decomposes, get everything from the variable-length extra data - const uint16_t *mapping=getMapping(norm16); + const uint16_t *mapping=getData(norm16); uint16_t firstUnit=*mapping; // decomp after-boundary: same as hasFCDBoundaryAfter(), // fcd16<=1 || trailCC==0 @@ -1140,13 +1142,13 @@ int32_t Normalizer2Impl::combine(const uint16_t *list, UChar32 trail) { if(trail<COMP_1_TRAIL_LIMIT) { // trail character is 0..33FF // result entry may have 2 or 3 units - key1=(uint16_t)(trail<<1); + key1 = static_cast<uint16_t>(trail << 1); while(key1>(firstUnit=*list)) { list+=2+(firstUnit&COMP_1_TRIPLE); } if(key1==(firstUnit&COMP_1_TRAIL_MASK)) { if(firstUnit&COMP_1_TRIPLE) { - return ((int32_t)list[1]<<16)|list[2]; + return (static_cast<int32_t>(list[1]) << 16) | list[2]; } else { return list[1]; } @@ -1154,10 +1156,10 @@ int32_t Normalizer2Impl::combine(const uint16_t *list, UChar32 trail) { } else { // trail character is 3400..10FFFF // result entry has 3 units - key1=(uint16_t)(COMP_1_TRAIL_LIMIT+ + key1 = static_cast<uint16_t>(COMP_1_TRAIL_LIMIT + (((trail>>COMP_1_TRAIL_SHIFT))& ~COMP_1_TRIPLE)); - uint16_t key2=(uint16_t)(trail<<COMP_2_TRAIL_SHIFT); + uint16_t key2 = static_cast<uint16_t>(trail << COMP_2_TRAIL_SHIFT); uint16_t secondUnit; for(;;) { if(key1>(firstUnit=*list)) { @@ -1170,7 +1172,7 @@ int32_t Normalizer2Impl::combine(const uint16_t *list, UChar32 trail) { list+=3; } } else if(key2==(secondUnit&COMP_2_TRAIL_MASK)) { - return ((int32_t)(secondUnit&~COMP_2_TRAIL_MASK)<<16)|list[2]; + return (static_cast<int32_t>(secondUnit & ~COMP_2_TRAIL_MASK) << 16) | list[2]; } else { break; } @@ -1195,7 +1197,7 @@ void Normalizer2Impl::addComposites(const uint16_t *list, UnicodeSet &set) const compositeAndFwd=list[1]; list+=2; } else { - compositeAndFwd=(((int32_t)list[1]&~COMP_2_TRAIL_MASK)<<16)|list[2]; + compositeAndFwd = ((static_cast<int32_t>(list[1]) & ~COMP_2_TRAIL_MASK) << 16) | list[2]; list+=3; } UChar32 composite=compositeAndFwd>>1; @@ -1240,7 +1242,7 @@ void Normalizer2Impl::recompose(ReorderingBuffer &buffer, int32_t recomposeStart for(;;) { UCPTRIE_FAST_U16_NEXT(normTrie, UCPTRIE_16, p, limit, c, norm16); - cc=getCCFromYesOrMaybe(norm16); + cc=getCCFromYesOrMaybeYes(norm16); if( // this character combines backward and isMaybe(norm16) && // we have seen a starter that combines forward and @@ -1252,15 +1254,15 @@ void Normalizer2Impl::recompose(ReorderingBuffer &buffer, int32_t recomposeStart // c is a Jamo V/T, see if we can compose it with the previous character. if(c<Hangul::JAMO_T_BASE) { // c is a Jamo Vowel, compose with previous Jamo L and following Jamo T. - char16_t prev=(char16_t)(*starter-Hangul::JAMO_L_BASE); + char16_t prev = static_cast<char16_t>(*starter - Hangul::JAMO_L_BASE); if(prev<Hangul::JAMO_L_COUNT) { pRemove=p-1; - char16_t syllable=(char16_t) - (Hangul::HANGUL_BASE+ + char16_t syllable = static_cast<char16_t>( + Hangul::HANGUL_BASE + (prev*Hangul::JAMO_V_COUNT+(c-Hangul::JAMO_V_BASE))* Hangul::JAMO_T_COUNT); char16_t t; - if(p!=limit && (t=(char16_t)(*p-Hangul::JAMO_T_BASE))<Hangul::JAMO_T_COUNT) { + if (p != limit && (t = static_cast<char16_t>(*p - Hangul::JAMO_T_BASE)) < Hangul::JAMO_T_COUNT) { ++p; syllable+=t; // The next character was a Jamo T. } @@ -1298,7 +1300,7 @@ void Normalizer2Impl::recompose(ReorderingBuffer &buffer, int32_t recomposeStart starter[0]=U16_LEAD(composite); starter[1]=U16_TRAIL(composite); } else { - *starter=(char16_t)composite; + *starter = static_cast<char16_t>(composite); // The composite is shorter than the starter, // move the intermediate characters forward one. starterIsSupplementary=false; @@ -1323,7 +1325,7 @@ void Normalizer2Impl::recompose(ReorderingBuffer &buffer, int32_t recomposeStart *--starter=U16_LEAD(composite); // undo the temporary increment } else { // both are on the BMP - *starter=(char16_t)composite; + *starter = static_cast<char16_t>(composite); } /* remove the combining mark by moving the following text over it */ @@ -1414,17 +1416,22 @@ Normalizer2Impl::composePair(UChar32 a, UChar32 b) const { } } else { // 'a' has a compositions list in extraData - list=getMapping(norm16); + list=getDataForYesOrNo(norm16); if(norm16>minYesNo) { // composite 'a' has both mapping & compositions list list+= // mapping pointer 1+ // +1 to skip the first unit with the mapping length (*list&MAPPING_LENGTH_MASK); // + mapping length } } - } else if(norm16<minMaybeYes || MIN_NORMAL_MAYBE_YES<=norm16) { + } else if(norm16<minMaybeNoCombinesFwd || MIN_NORMAL_MAYBE_YES<=norm16) { return U_SENTINEL; } else { - list=getCompositionsListForMaybe(norm16); + list=getDataForMaybe(norm16); + if(norm16<minMaybeYes) { // composite 'a' has both mapping & compositions list + list+= // mapping pointer + 1+ // +1 to skip the first unit with the mapping length + (*list&MAPPING_LENGTH_MASK); // + mapping length + } } if(b<0 || 0x10ffff<b) { // combine(list, b) requires a valid code point b return U_SENTINEL; @@ -1502,12 +1509,12 @@ Normalizer2Impl::compose(const char16_t *src, const char16_t *limit, } // isCompYesAndZeroCC(norm16) is false, that is, norm16>=minNoNo. // The current character is either a "noNo" (has a mapping) - // or a "maybeYes" (combines backward) + // or a "maybeYes" / "maybeNo" (combines backward) // or a "yesYes" with ccc!=0. // It is not a Hangul syllable or Jamo L because those have "yes" properties. // Medium-fast path: Handle cases that do not require full decomposition and recomposition. - if (!isMaybeOrNonZeroCC(norm16)) { // minNoNo <= norm16 < minMaybeYes + if (norm16 < minMaybeNo) { // minNoNo <= norm16 < minMaybeNo if (!doCompose) { return false; } @@ -1534,7 +1541,7 @@ Normalizer2Impl::compose(const char16_t *src, const char16_t *limit, if (prevBoundary != prevSrc && !buffer.appendZeroCC(prevBoundary, prevSrc, errorCode)) { break; } - const char16_t *mapping = reinterpret_cast<const char16_t *>(getMapping(norm16)); + const char16_t *mapping = reinterpret_cast<const char16_t *>(getDataForYesOrNo(norm16)); int32_t length = *mapping++ & MAPPING_LENGTH_MASK; if(!buffer.appendZeroCC(mapping, mapping + length, errorCode)) { break; @@ -1562,14 +1569,14 @@ Normalizer2Impl::compose(const char16_t *src, const char16_t *limit, if(c<Hangul::JAMO_T_BASE) { // The current character is a Jamo Vowel, // compose with previous Jamo L and following Jamo T. - char16_t l = (char16_t)(prev-Hangul::JAMO_L_BASE); + char16_t l = static_cast<char16_t>(prev - Hangul::JAMO_L_BASE); if(l<Hangul::JAMO_L_COUNT) { if (!doCompose) { return false; } int32_t t; if (src != limit && - 0 < (t = ((int32_t)*src - Hangul::JAMO_T_BASE)) && + 0 < (t = (static_cast<int32_t>(*src) - Hangul::JAMO_T_BASE)) && t < Hangul::JAMO_T_COUNT) { // The next character is a Jamo T. ++src; @@ -1587,7 +1594,7 @@ Normalizer2Impl::compose(const char16_t *src, const char16_t *limit, if (prevBoundary != prevSrc && !buffer.appendZeroCC(prevBoundary, prevSrc, errorCode)) { break; } - if(!buffer.appendBMP((char16_t)syllable, 0, errorCode)) { + if (!buffer.appendBMP(static_cast<char16_t>(syllable), 0, errorCode)) { break; } prevBoundary = src; @@ -1612,7 +1619,7 @@ Normalizer2Impl::compose(const char16_t *src, const char16_t *limit, if (prevBoundary != prevSrc && !buffer.appendZeroCC(prevBoundary, prevSrc, errorCode)) { break; } - if(!buffer.appendBMP((char16_t)syllable, 0, errorCode)) { + if (!buffer.appendBMP(static_cast<char16_t>(syllable), 0, errorCode)) { break; } prevBoundary = src; @@ -1763,7 +1770,7 @@ Normalizer2Impl::composeQuickCheck(const char16_t *src, const char16_t *limit, } // isCompYesAndZeroCC(norm16) is false, that is, norm16>=minNoNo. // The current character is either a "noNo" (has a mapping) - // or a "maybeYes" (combines backward) + // or a "maybeYes" / "maybeNo" (combines backward) // or a "yesYes" with ccc!=0. // It is not a Hangul syllable or Jamo L because those have "yes" properties. @@ -1784,8 +1791,9 @@ Normalizer2Impl::composeQuickCheck(const char16_t *src, const char16_t *limit, } } - if(isMaybeOrNonZeroCC(norm16)) { - uint8_t cc=getCCFromYesOrMaybe(norm16); + if (norm16 >= minMaybeNo) { + uint16_t fcd16 = getFCD16FromMaybeOrNonZeroCC(norm16); + uint8_t cc = fcd16 >> 8; if (onlyContiguous /* FCC */ && cc != 0 && getTrailCCFromCompYesAndZeroCC(prevNorm16) > cc) { // The [prevBoundary..prevSrc[ character @@ -1806,11 +1814,12 @@ Normalizer2Impl::composeQuickCheck(const char16_t *src, const char16_t *limit, if (src == limit) { return src; } - uint8_t prevCC = cc; + uint8_t prevCC = fcd16; nextSrc = src; UCPTRIE_FAST_U16_NEXT(normTrie, UCPTRIE_16, nextSrc, limit, c, norm16); - if (isMaybeOrNonZeroCC(norm16)) { - cc = getCCFromYesOrMaybe(norm16); + if (norm16 >= minMaybeNo) { + fcd16 = getFCD16FromMaybeOrNonZeroCC(norm16); + cc = fcd16 >> 8; if (!(prevCC <= cc || cc == 0)) { break; } @@ -1845,11 +1854,11 @@ void Normalizer2Impl::composeAndAppend(const char16_t *src, const char16_t *limi if(src!=firstStarterInSrc) { const char16_t *lastStarterInDest=findPreviousCompBoundary(buffer.getStart(), buffer.getLimit(), onlyContiguous); - int32_t destSuffixLength=(int32_t)(buffer.getLimit()-lastStarterInDest); + int32_t destSuffixLength = static_cast<int32_t>(buffer.getLimit() - lastStarterInDest); UnicodeString middle(lastStarterInDest, destSuffixLength); buffer.removeSuffix(destSuffixLength); safeMiddle=middle; - middle.append(src, (int32_t)(firstStarterInSrc-src)); + middle.append(src, static_cast<int32_t>(firstStarterInSrc - src)); const char16_t *middleStart=middle.getBuffer(); compose(middleStart, middleStart+middle.length(), onlyContiguous, true, buffer, errorCode); @@ -1903,12 +1912,12 @@ Normalizer2Impl::composeUTF8(uint32_t options, UBool onlyContiguous, } // isCompYesAndZeroCC(norm16) is false, that is, norm16>=minNoNo. // The current character is either a "noNo" (has a mapping) - // or a "maybeYes" (combines backward) + // or a "maybeYes" / "maybeNo" (combines backward) // or a "yesYes" with ccc!=0. // It is not a Hangul syllable or Jamo L because those have "yes" properties. // Medium-fast path: Handle cases that do not require full decomposition and recomposition. - if (!isMaybeOrNonZeroCC(norm16)) { // minNoNo <= norm16 < minMaybeYes + if (norm16 < minMaybeNo) { // minNoNo <= norm16 < minMaybeNo if (sink == nullptr) { return false; } @@ -1937,9 +1946,9 @@ Normalizer2Impl::composeUTF8(uint32_t options, UBool onlyContiguous, *sink, options, edits, errorCode)) { break; } - const uint16_t *mapping = getMapping(norm16); + const uint16_t *mapping = getDataForYesOrNo(norm16); int32_t length = *mapping++ & MAPPING_LENGTH_MASK; - if (!ByteSinkUtil::appendChange(prevSrc, src, (const char16_t *)mapping, length, + if (!ByteSinkUtil::appendChange(prevSrc, src, reinterpret_cast<const char16_t*>(mapping), length, *sink, edits, errorCode)) { break; } @@ -1958,7 +1967,7 @@ Normalizer2Impl::composeUTF8(uint32_t options, UBool onlyContiguous, break; } if (edits != nullptr) { - edits->addReplace((int32_t)(src - prevSrc), 0); + edits->addReplace(static_cast<int32_t>(src - prevSrc), 0); } prevBoundary = src; continue; @@ -1976,7 +1985,7 @@ Normalizer2Impl::composeUTF8(uint32_t options, UBool onlyContiguous, // The current character is a Jamo Vowel, // compose with previous Jamo L and following Jamo T. UChar32 l = prev - Hangul::JAMO_L_BASE; - if ((uint32_t)l < Hangul::JAMO_L_COUNT) { + if (static_cast<uint32_t>(l) < Hangul::JAMO_L_COUNT) { if (sink == nullptr) { return false; } @@ -2204,20 +2213,20 @@ uint8_t Normalizer2Impl::getPreviousTrailCC(const char16_t *start, const char16_ if (start == p) { return 0; } - int32_t i = (int32_t)(p - start); + int32_t i = static_cast<int32_t>(p - start); UChar32 c; U16_PREV(start, 0, i, c); - return (uint8_t)getFCD16(c); + return static_cast<uint8_t>(getFCD16(c)); } uint8_t Normalizer2Impl::getPreviousTrailCC(const uint8_t *start, const uint8_t *p) const { if (start == p) { return 0; } - int32_t i = (int32_t)(p - start); + int32_t i = static_cast<int32_t>(p - start); UChar32 c; U8_PREV(start, 0, i, c); - return (uint8_t)getFCD16(c); + return static_cast<uint8_t>(getFCD16(c)); } // Note: normalizer2impl.cpp r30982 (2011-nov-27) @@ -2245,7 +2254,7 @@ uint16_t Normalizer2Impl::getFCD16FromNormData(UChar32 c) const { return norm16|(norm16<<8); } else if(norm16>=minMaybeYes) { return 0; - } else { // isDecompNoAlgorithmic(norm16) + } else if(norm16<minMaybeNo) { // isDecompNoAlgorithmic(norm16) uint16_t deltaTrailCC = norm16 & DELTA_TCCC_MASK; if (deltaTrailCC <= DELTA_TCCC_1) { return deltaTrailCC >> OFFSET_SHIFT; @@ -2260,7 +2269,7 @@ uint16_t Normalizer2Impl::getFCD16FromNormData(UChar32 c) const { return 0; } // c decomposes, get everything from the variable-length extra data - const uint16_t *mapping=getMapping(norm16); + const uint16_t *mapping=getData(norm16); uint16_t firstUnit=*mapping; norm16=firstUnit>>8; // tccc if(firstUnit&MAPPING_HAS_CCC_LCCC_WORD) { @@ -2272,6 +2281,23 @@ uint16_t Normalizer2Impl::getFCD16FromNormData(UChar32 c) const { #pragma optimize( "", on ) #endif +uint16_t Normalizer2Impl::getFCD16FromMaybeOrNonZeroCC(uint16_t norm16) const { + U_ASSERT(norm16 >= minMaybeNo); + if (norm16 >= MIN_NORMAL_MAYBE_YES) { + // combining mark + norm16 = getCCFromNormalYesOrMaybe(norm16); + return norm16 | (norm16<<8); + } else if (norm16 >= minMaybeYes) { + return 0; + } + // c decomposes, get everything from the variable-length extra data + const uint16_t *mapping = getDataForMaybe(norm16); + uint16_t firstUnit = *mapping; + // maybeNo has lccc = 0 + U_ASSERT((firstUnit & MAPPING_HAS_CCC_LCCC_WORD) == 0 || (*(mapping - 1) & 0xff00) == 0); + return firstUnit >> 8; // tccc +} + // Dual functionality: // buffer!=nullptr: normalize // buffer==nullptr: isNormalized/quickCheck/spanQuickCheckYes @@ -2395,7 +2421,7 @@ Normalizer2Impl::makeFCD(const char16_t *src, const char16_t *limit, * already but is now going to be decomposed. * prevSrc is set to after what was copied/appended. */ - buffer->removeSuffix((int32_t)(prevSrc-prevBoundary)); + buffer->removeSuffix(static_cast<int32_t>(prevSrc - prevBoundary)); /* * Find the part of the source that needs to be decomposed, * up to the next safe boundary. @@ -2426,11 +2452,11 @@ void Normalizer2Impl::makeFCDAndAppend(const char16_t *src, const char16_t *limi if(src!=firstBoundaryInSrc) { const char16_t *lastBoundaryInDest=findPreviousFCDBoundary(buffer.getStart(), buffer.getLimit()); - int32_t destSuffixLength=(int32_t)(buffer.getLimit()-lastBoundaryInDest); + int32_t destSuffixLength = static_cast<int32_t>(buffer.getLimit() - lastBoundaryInDest); UnicodeString middle(lastBoundaryInDest, destSuffixLength); buffer.removeSuffix(destSuffixLength); safeMiddle=middle; - middle.append(src, (int32_t)(firstBoundaryInSrc-src)); + middle.append(src, static_cast<int32_t>(firstBoundaryInSrc - src)); const char16_t *middleStart=middle.getBuffer(); makeFCD(middleStart, middleStart+middle.length(), &buffer, errorCode); if(U_FAILURE(errorCode)) { @@ -2507,8 +2533,8 @@ void CanonIterData::addToStartSet(UChar32 origin, UChar32 decompLead, UErrorCode if(U_FAILURE(errorCode)) { return; } - UChar32 firstOrigin=(UChar32)(canonValue&CANON_VALUE_MASK); - canonValue=(canonValue&~CANON_VALUE_MASK)|CANON_HAS_SET|(uint32_t)canonStartSets.size(); + UChar32 firstOrigin = static_cast<UChar32>(canonValue & CANON_VALUE_MASK); + canonValue = (canonValue & ~CANON_VALUE_MASK) | CANON_HAS_SET | static_cast<uint32_t>(canonStartSets.size()); umutablecptrie_set(mutableTrie, decompLead, canonValue, &errorCode); canonStartSets.adoptElement(lpSet.orphan(), errorCode); if (U_FAILURE(errorCode)) { @@ -2518,7 +2544,7 @@ void CanonIterData::addToStartSet(UChar32 origin, UChar32 decompLead, UErrorCode set->add(firstOrigin); } } else { - set=(UnicodeSet *)canonStartSets[(int32_t)(canonValue&CANON_VALUE_MASK)]; + set = static_cast<UnicodeSet*>(canonStartSets[static_cast<int32_t>(canonValue & CANON_VALUE_MASK)]); } set->add(origin); } @@ -2575,9 +2601,11 @@ void InitCanonIterData::doInit(Normalizer2Impl *impl, UErrorCode &errorCode) { void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, const uint16_t norm16, CanonIterData &newData, UErrorCode &errorCode) const { - if(isInert(norm16) || (minYesNo<=norm16 && norm16<minNoNo)) { + if(isInert(norm16) || + (minYesNo<=norm16 && norm16<minNoNo) || + (minMaybeNo<=norm16 && norm16<minMaybeYes)) { // Inert, or 2-way mapping (including Hangul syllable). - // We do not write a canonStartSet for any yesNo character. + // We do not write a canonStartSet for any yesNo/maybeNo character. // Composites from 2-way mappings are added at runtime from the // starter's compositions list, and the other characters in // 2-way mappings get CANON_NOT_SEGMENT_STARTER set because they are @@ -2587,7 +2615,7 @@ void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, co for(UChar32 c=start; c<=end; ++c) { uint32_t oldValue = umutablecptrie_get(newData.mutableTrie, c); uint32_t newValue=oldValue; - if(isMaybeOrNonZeroCC(norm16)) { + if(isMaybeYesOrNonZeroCC(norm16)) { // not a segment starter if it occurs in a decomposition or has cc!=0 newValue|=CANON_NOT_SEGMENT_STARTER; if(norm16<MIN_NORMAL_MAYBE_YES) { @@ -2609,7 +2637,7 @@ void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, co } if (norm16_2 > minYesNo) { // c decomposes, get everything from the variable-length extra data - const uint16_t *mapping=getMapping(norm16_2); + const uint16_t *mapping=getDataForYesOrNo(norm16_2); uint16_t firstUnit=*mapping; int32_t length=firstUnit&MAPPING_LENGTH_MASK; if((firstUnit&MAPPING_HAS_CCC_LCCC_WORD)!=0) { @@ -2657,11 +2685,11 @@ UBool Normalizer2Impl::ensureCanonIterData(UErrorCode &errorCode) const { } int32_t Normalizer2Impl::getCanonValue(UChar32 c) const { - return (int32_t)ucptrie_get(fCanonIterData->trie, c); + return static_cast<int32_t>(ucptrie_get(fCanonIterData->trie, c)); } const UnicodeSet &Normalizer2Impl::getCanonStartSet(int32_t n) const { - return *(const UnicodeSet *)fCanonIterData->canonStartSets[n]; + return *static_cast<const UnicodeSet*>(fCanonIterData->canonStartSets[n]); } UBool Normalizer2Impl::isCanonSegmentStarter(UChar32 c) const { @@ -2684,7 +2712,7 @@ UBool Normalizer2Impl::getCanonStartSet(UChar32 c, UnicodeSet &set) const { uint16_t norm16=getRawNorm16(c); if(norm16==JAMO_L) { UChar32 syllable= - (UChar32)(Hangul::HANGUL_BASE+(c-Hangul::JAMO_L_BASE)*Hangul::JAMO_VT_COUNT); + static_cast<UChar32>(Hangul::HANGUL_BASE + (c - Hangul::JAMO_L_BASE) * Hangul::JAMO_VT_COUNT); set.add(syllable, syllable+Hangul::JAMO_VT_COUNT-1); } else { addComposites(getCompositionsList(norm16), set); @@ -2728,7 +2756,7 @@ unorm2_swap(const UDataSwapper *ds, pInfo->dataFormat[1]==0x72 && pInfo->dataFormat[2]==0x6d && pInfo->dataFormat[3]==0x32 && - (1<=formatVersion0 && formatVersion0<=4) + (1<=formatVersion0 && formatVersion0<=5) )) { udata_printError(ds, "unorm2_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as Normalizer2 data\n", pInfo->dataFormat[0], pInfo->dataFormat[1], @@ -2747,8 +2775,10 @@ unorm2_swap(const UDataSwapper *ds, minIndexesLength=Normalizer2Impl::IX_MIN_MAYBE_YES+1; } else if(formatVersion0==2) { minIndexesLength=Normalizer2Impl::IX_MIN_YES_NO_MAPPINGS_ONLY+1; - } else { + } else if(formatVersion0<=4) { minIndexesLength=Normalizer2Impl::IX_MIN_LCCC_CP+1; + } else { + minIndexesLength=Normalizer2Impl::IX_MIN_MAYBE_NO_COMBINES_FWD+1; } if(length>=0) { diff --git a/thirdparty/icu4c/common/normalizer2impl.h b/thirdparty/icu4c/common/normalizer2impl.h index b74c2a1125..5999190bae 100644 --- a/thirdparty/icu4c/common/normalizer2impl.h +++ b/thirdparty/icu4c/common/normalizer2impl.h @@ -81,10 +81,10 @@ public: return 0<=c && c<HANGUL_COUNT && c%JAMO_T_COUNT==0; } static inline UBool isJamoL(UChar32 c) { - return (uint32_t)(c-JAMO_L_BASE)<JAMO_L_COUNT; + return static_cast<uint32_t>(c - JAMO_L_BASE) < JAMO_L_COUNT; } static inline UBool isJamoV(UChar32 c) { - return (uint32_t)(c-JAMO_V_BASE)<JAMO_V_COUNT; + return static_cast<uint32_t>(c - JAMO_V_BASE) < JAMO_V_COUNT; } static inline UBool isJamoT(UChar32 c) { int32_t t=c-JAMO_T_BASE; @@ -103,12 +103,12 @@ public: c-=HANGUL_BASE; UChar32 c2=c%JAMO_T_COUNT; c/=JAMO_T_COUNT; - buffer[0]=(char16_t)(JAMO_L_BASE+c/JAMO_V_COUNT); - buffer[1]=(char16_t)(JAMO_V_BASE+c%JAMO_V_COUNT); + buffer[0] = static_cast<char16_t>(JAMO_L_BASE + c / JAMO_V_COUNT); + buffer[1] = static_cast<char16_t>(JAMO_V_BASE + c % JAMO_V_COUNT); if(c2==0) { return 2; } else { - buffer[2]=(char16_t)(JAMO_T_BASE+c2); + buffer[2] = static_cast<char16_t>(JAMO_T_BASE + c2); return 3; } } @@ -123,11 +123,11 @@ public: UChar32 c2=c%JAMO_T_COUNT; if(c2==0) { c/=JAMO_T_COUNT; - buffer[0]=(char16_t)(JAMO_L_BASE+c/JAMO_V_COUNT); - buffer[1]=(char16_t)(JAMO_V_BASE+c%JAMO_V_COUNT); + buffer[0] = static_cast<char16_t>(JAMO_L_BASE + c / JAMO_V_COUNT); + buffer[1] = static_cast<char16_t>(JAMO_V_BASE + c % JAMO_V_COUNT); } else { - buffer[0]=(char16_t)(orig-c2); // LV syllable - buffer[1]=(char16_t)(JAMO_T_BASE+c2); + buffer[0] = static_cast<char16_t>(orig - c2); // LV syllable + buffer[1] = static_cast<char16_t>(JAMO_T_BASE + c2); } } private: @@ -147,13 +147,13 @@ public: ReorderingBuffer(const Normalizer2Impl &ni, UnicodeString &dest, UErrorCode &errorCode); ~ReorderingBuffer() { if (start != nullptr) { - str.releaseBuffer((int32_t)(limit-start)); + str.releaseBuffer(static_cast<int32_t>(limit - start)); } } UBool init(int32_t destCapacity, UErrorCode &errorCode); UBool isEmpty() const { return start==limit; } - int32_t length() const { return (int32_t)(limit-start); } + int32_t length() const { return static_cast<int32_t>(limit - start); } char16_t *getStart() { return start; } char16_t *getLimit() { return limit; } uint8_t getLastCC() const { return lastCC; } @@ -163,7 +163,7 @@ public: UBool append(UChar32 c, uint8_t cc, UErrorCode &errorCode) { return (c<=0xffff) ? - appendBMP((char16_t)c, cc, errorCode) : + appendBMP(static_cast<char16_t>(c), cc, errorCode) : appendSupplementary(c, cc, errorCode); } UBool append(const char16_t *s, int32_t length, UBool isNFD, @@ -190,12 +190,12 @@ public: void remove(); void removeSuffix(int32_t suffixLength); void setReorderingLimit(char16_t *newLimit) { - remainingCapacity+=(int32_t)(limit-newLimit); + remainingCapacity += static_cast<int32_t>(limit - newLimit); reorderStart=limit=newLimit; lastCC=0; } void copyReorderableSuffixTo(UnicodeString &s) const { - s.setTo(ConstChar16Ptr(reorderStart), (int32_t)(limit-reorderStart)); + s.setTo(ConstChar16Ptr(reorderStart), static_cast<int32_t>(limit - reorderStart)); } private: /* @@ -215,7 +215,7 @@ private: void insert(UChar32 c, uint8_t cc); static void writeCodePoint(char16_t *p, UChar32 c) { if(c<=0xffff) { - *p=(char16_t)c; + *p = static_cast<char16_t>(c); } else { p[0]=U16_LEAD(c); p[1]=U16_TRAIL(c); @@ -241,7 +241,7 @@ private: * Low-level implementation of the Unicode Normalization Algorithm. * For the data structure and details see the documentation at the end of * this normalizer2impl.h and in the design doc at - * https://icu.unicode.org/design/normalization/custom + * https://unicode-org.github.io/icu/design/normalization/custom.html */ class U_COMMON_API Normalizer2Impl : public UObject { public: @@ -271,14 +271,14 @@ public: UNormalizationCheckResult getCompQuickCheck(uint16_t norm16) const { if(norm16<minNoNo || MIN_YES_YES_WITH_CC<=norm16) { return UNORM_YES; - } else if(minMaybeYes<=norm16) { + } else if(minMaybeNo<=norm16) { return UNORM_MAYBE; } else { return UNORM_NO; } } - UBool isAlgorithmicNoNo(uint16_t norm16) const { return limitNoNo<=norm16 && norm16<minMaybeYes; } - UBool isCompNo(uint16_t norm16) const { return minNoNo<=norm16 && norm16<minMaybeYes; } + UBool isAlgorithmicNoNo(uint16_t norm16) const { return limitNoNo<=norm16 && norm16<minMaybeNo; } + UBool isCompNo(uint16_t norm16) const { return minNoNo<=norm16 && norm16<minMaybeNo; } UBool isDecompYes(uint16_t norm16) const { return norm16<minYesNo || minMaybeYes<=norm16; } uint8_t getCC(uint16_t norm16) const { @@ -291,14 +291,14 @@ public: return getCCFromNoNo(norm16); } static uint8_t getCCFromNormalYesOrMaybe(uint16_t norm16) { - return (uint8_t)(norm16 >> OFFSET_SHIFT); + return static_cast<uint8_t>(norm16 >> OFFSET_SHIFT); } - static uint8_t getCCFromYesOrMaybe(uint16_t norm16) { + static uint8_t getCCFromYesOrMaybeYes(uint16_t norm16) { return norm16>=MIN_NORMAL_MAYBE_YES ? getCCFromNormalYesOrMaybe(norm16) : 0; } - uint8_t getCCFromYesOrMaybeCP(UChar32 c) const { + uint8_t getCCFromYesOrMaybeYesCP(UChar32 c) const { if (c < minCompNoMaybeCP) { return 0; } - return getCCFromYesOrMaybe(getNorm16(c)); + return getCCFromYesOrMaybeYes(getNorm16(c)); } /** @@ -364,11 +364,13 @@ public: // 0<=lead<=0xffff uint8_t bits=smallFCD[lead>>8]; if(bits==0) { return false; } - return (UBool)((bits>>((lead>>5)&7))&1); + return (bits >> ((lead >> 5) & 7)) & 1; } /** Returns the FCD value from the regular normalization data. */ uint16_t getFCD16FromNormData(UChar32 c) const; + uint16_t getFCD16FromMaybeOrNonZeroCC(uint16_t norm16) const; + /** * Gets the decomposition for one code point. * @param c code point @@ -450,7 +452,13 @@ public: IX_MIN_LCCC_CP, IX_RESERVED19, - IX_COUNT + + /** Two-way mappings; each starts with a character that combines backward. */ + IX_MIN_MAYBE_NO, // 20 + /** Two-way mappings & compositions. */ + IX_MIN_MAYBE_NO_COMBINES_FWD, + + IX_COUNT // 22 }; enum { @@ -541,7 +549,8 @@ public: uint16_t norm16=getNorm16(c); return isCompYesAndZeroCC(norm16) && (norm16 & HAS_COMP_BOUNDARY_AFTER) != 0 && - (!onlyContiguous || isInert(norm16) || *getMapping(norm16) <= 0x1ff); + (!onlyContiguous || isInert(norm16) || *getDataForYesOrNo(norm16) <= 0x1ff); + // The last check fetches the mapping's first unit and checks tccc<=1. } UBool hasFCDBoundaryBefore(UChar32 c) const { return hasDecompBoundaryBefore(c); } @@ -551,8 +560,8 @@ private: friend class InitCanonIterData; friend class LcccContext; - UBool isMaybe(uint16_t norm16) const { return minMaybeYes<=norm16 && norm16<=JAMO_VT; } - UBool isMaybeOrNonZeroCC(uint16_t norm16) const { return norm16>=minMaybeYes; } + UBool isMaybe(uint16_t norm16) const { return minMaybeNo<=norm16 && norm16<=JAMO_VT; } + UBool isMaybeYesOrNonZeroCC(uint16_t norm16) const { return norm16>=minMaybeYes; } static UBool isInert(uint16_t norm16) { return norm16==INERT; } static UBool isJamoL(uint16_t norm16) { return norm16==JAMO_L; } static UBool isJamoVT(uint16_t norm16) { return norm16==JAMO_VT; } @@ -566,7 +575,7 @@ private: // return norm16>=MIN_YES_YES_WITH_CC || norm16<minNoNo; // } // UBool isCompYesOrMaybe(uint16_t norm16) const { - // return norm16<minNoNo || minMaybeYes<=norm16; + // return norm16<minNoNo || minMaybeNo<=norm16; // } // UBool hasZeroCCFromDecompYes(uint16_t norm16) const { // return norm16<=MIN_NORMAL_MAYBE_YES || norm16==JAMO_VT; @@ -579,12 +588,12 @@ private: /** * A little faster and simpler than isDecompYesAndZeroCC() but does not include * the MaybeYes which combine-forward and have ccc=0. - * (Standard Unicode 10 normalization does not have such characters.) */ UBool isMostDecompYesAndZeroCC(uint16_t norm16) const { return norm16<minYesNo || norm16==MIN_NORMAL_MAYBE_YES || norm16==JAMO_VT; } - UBool isDecompNoAlgorithmic(uint16_t norm16) const { return norm16>=limitNoNo; } + /** Since formatVersion 5: same as isAlgorithmicNoNo() */ + UBool isDecompNoAlgorithmic(uint16_t norm16) const { return limitNoNo<=norm16 && norm16<minMaybeNo; } // For use with isCompYes(). // Perhaps the compiler can combine the two tests for MIN_YES_YES_WITH_CC. @@ -592,9 +601,9 @@ private: // return norm16>=MIN_YES_YES_WITH_CC ? getCCFromNormalYesOrMaybe(norm16) : 0; // } uint8_t getCCFromNoNo(uint16_t norm16) const { - const uint16_t *mapping=getMapping(norm16); + const uint16_t *mapping=getDataForYesOrNo(norm16); if(*mapping&MAPPING_HAS_CCC_LCCC_WORD) { - return (uint8_t)*(mapping-1); + return static_cast<uint8_t>(*(mapping - 1)); } else { return 0; } @@ -605,7 +614,7 @@ private: return 0; // yesYes and Hangul LV have ccc=tccc=0 } else { // For Hangul LVT we harmlessly fetch a firstUnit with tccc=0 here. - return (uint8_t)(*getMapping(norm16)>>8); // tccc from yesNo + return static_cast<uint8_t>(*getDataForYesOrNo(norm16) >> 8); // tccc from yesNo } } uint8_t getPreviousTrailCC(const char16_t *start, const char16_t *p) const; @@ -619,28 +628,33 @@ private: return (norm16>>DELTA_SHIFT)-centerNoNoDelta; } - // Requires minYesNo<norm16<limitNoNo. - const uint16_t *getMapping(uint16_t norm16) const { return extraData+(norm16>>OFFSET_SHIFT); } + const uint16_t *getDataForYesOrNo(uint16_t norm16) const { + return extraData+(norm16>>OFFSET_SHIFT); + } + const uint16_t *getDataForMaybe(uint16_t norm16) const { + return extraData+((norm16-minMaybeNo+limitNoNo)>>OFFSET_SHIFT); + } + const uint16_t *getData(uint16_t norm16) const { + if(norm16>=minMaybeNo) { + norm16=norm16-minMaybeNo+limitNoNo; + } + return extraData+(norm16>>OFFSET_SHIFT); + } const uint16_t *getCompositionsListForDecompYes(uint16_t norm16) const { if(norm16<JAMO_L || MIN_NORMAL_MAYBE_YES<=norm16) { return nullptr; - } else if(norm16<minMaybeYes) { - return getMapping(norm16); // for yesYes; if Jamo L: harmless empty list } else { - return maybeYesCompositions+norm16-minMaybeYes; + // if yesYes: if Jamo L: harmless empty list + return getData(norm16); } } const uint16_t *getCompositionsListForComposite(uint16_t norm16) const { // A composite has both mapping & compositions list. - const uint16_t *list=getMapping(norm16); + const uint16_t *list=getData(norm16); return list+ // mapping pointer 1+ // +1 to skip the first unit with the mapping length (*list&MAPPING_LENGTH_MASK); // + mapping length } - const uint16_t *getCompositionsListForMaybe(uint16_t norm16) const { - // minMaybeYes<=norm16<MIN_NORMAL_MAYBE_YES - return maybeYesCompositions+((norm16-minMaybeYes)>>OFFSET_SHIFT); - } /** * @param c code point must have compositions * @return compositions list pointer @@ -692,11 +706,13 @@ private: /** For FCC: Given norm16 HAS_COMP_BOUNDARY_AFTER, does it have tccc<=1? */ UBool isTrailCC01ForCompBoundaryAfter(uint16_t norm16) const { return isInert(norm16) || (isDecompNoAlgorithmic(norm16) ? - (norm16 & DELTA_TCCC_MASK) <= DELTA_TCCC_1 : *getMapping(norm16) <= 0x1ff); + (norm16 & DELTA_TCCC_MASK) <= DELTA_TCCC_1 : *getDataForYesOrNo(norm16) <= 0x1ff); } - const char16_t *findPreviousCompBoundary(const char16_t *start, const char16_t *p, UBool onlyContiguous) const; - const char16_t *findNextCompBoundary(const char16_t *p, const char16_t *limit, UBool onlyContiguous) const; + const char16_t *findPreviousCompBoundary(const char16_t *start, const char16_t *p, + UBool onlyContiguous) const; + const char16_t *findNextCompBoundary(const char16_t *p, const char16_t *limit, + UBool onlyContiguous) const; const char16_t *findPreviousFCDBoundary(const char16_t *start, const char16_t *p) const; const char16_t *findNextFCDBoundary(const char16_t *p, const char16_t *limit) const; @@ -723,11 +739,12 @@ private: uint16_t minNoNoEmpty; uint16_t limitNoNo; uint16_t centerNoNoDelta; + uint16_t minMaybeNo; + uint16_t minMaybeNoCombinesFwd; uint16_t minMaybeYes; const UCPTrie *normTrie; - const uint16_t *maybeYesCompositions; - const uint16_t *extraData; // mappings and/or compositions for yesYes, yesNo & noNo characters + const uint16_t *extraData; // mappings and/or compositions const uint8_t *smallFCD; // [0x100] one bit per 32 BMP code points, set if any FCD!=0 UInitOnce fCanonIterDataInitOnce {}; @@ -785,7 +802,7 @@ unorm_getFCD16(UChar32 c); /** * Format of Normalizer2 .nrm data files. - * Format version 4.0. + * Format version 5.0. * * Normalizer2 .nrm data files provide data for the Unicode Normalization algorithms. * ICU ships with data files for standard Unicode Normalization Forms @@ -807,7 +824,7 @@ unorm_getFCD16(UChar32 c); * Constants are defined as enum values of the Normalizer2Impl class. * * Many details of the data structures are described in the design doc - * which is at https://icu.unicode.org/design/normalization/custom + * which is at https://unicode-org.github.io/icu/design/normalization/custom.html * * int32_t indexes[indexesLength]; -- indexesLength=indexes[IX_NORM_TRIE_OFFSET]/4; * @@ -829,7 +846,9 @@ unorm_getFCD16(UChar32 c); * * The next eight indexes are thresholds of 16-bit trie values for ranges of * values indicating multiple normalization properties. - * They are listed here in threshold order, not in the order they are stored in the indexes. + * Format version 5 adds the two minMaybeNo* threshold indexes. + * The thresholds are listed here in threshold order, + * not in the order they are stored in the indexes. * minYesNo=indexes[IX_MIN_YES_NO]; * minYesNoMappingsOnly=indexes[IX_MIN_YES_NO_MAPPINGS_ONLY]; * minNoNo=indexes[IX_MIN_NO_NO]; @@ -837,6 +856,8 @@ unorm_getFCD16(UChar32 c); * minNoNoCompNoMaybeCC=indexes[IX_MIN_NO_NO_COMP_NO_MAYBE_CC]; * minNoNoEmpty=indexes[IX_MIN_NO_NO_EMPTY]; * limitNoNo=indexes[IX_LIMIT_NO_NO]; + * minMaybeNo=indexes[IX_MIN_MAYBE_NO]; + * minMaybeNoCombinesFwd=indexes[IX_MIN_MAYBE_NO_COMBINES_FWD]; * minMaybeYes=indexes[IX_MIN_MAYBE_YES]; * See the normTrie description below and the design doc for details. * @@ -845,13 +866,14 @@ unorm_getFCD16(UChar32 c); * The trie holds the main normalization data. Each code point is mapped to a 16-bit value. * Rather than using independent bits in the value (which would require more than 16 bits), * information is extracted primarily via range checks. - * Except, format version 3 uses bit 0 for hasCompBoundaryAfter(). + * Except, format version 3+ uses bit 0 for hasCompBoundaryAfter(). * For example, a 16-bit value norm16 in the range minYesNo<=norm16<minNoNo * means that the character has NF*C_QC=Yes and NF*D_QC=No properties, * which means it has a two-way (round-trip) decomposition mapping. - * Values in the range 2<=norm16<limitNoNo are also directly indexes into the extraData + * Values in the ranges 2<=norm16<limitNoNo and minMaybeNo<=norm16<minMaybeYes + * are also directly indexes into the extraData * pointing to mappings, compositions lists, or both. - * Value norm16==INERT (0 in versions 1 & 2, 1 in version 3) + * Value norm16==INERT (0 in versions 1 & 2, 1 in version 3+) * means that the character is normalization-inert, that is, * it does not have a mapping, does not participate in composition, has a zero * canonical combining class, and forms a boundary where text before it and after it @@ -870,33 +892,38 @@ unorm_getFCD16(UChar32 c); * When the lead surrogate unit's value exceeds the quick check minimum during processing, * the properties for the full supplementary code point need to be looked up. * - * uint16_t maybeYesCompositions[MIN_NORMAL_MAYBE_YES-minMaybeYes]; * uint16_t extraData[]; * - * There is only one byte offset for the end of these two arrays. - * The split between them is given by the constant and variable mentioned above. - * In version 3, the difference must be shifted right by OFFSET_SHIFT. - * - * The maybeYesCompositions array contains compositions lists for characters that - * combine both forward (as starters in composition pairs) - * and backward (as trailing characters in composition pairs). - * Such characters do not occur in Unicode 5.2 but are allowed by - * the Unicode Normalization algorithms. - * If there are no such characters, then minMaybeYes==MIN_NORMAL_MAYBE_YES - * and the maybeYesCompositions array is empty. - * If there are such characters, then minMaybeYes is subtracted from their norm16 values - * to get the index into this array. - * - * The extraData array contains compositions lists for "YesYes" characters, - * followed by mappings and optional compositions lists for "YesNo" characters, - * followed by only mappings for "NoNo" characters. - * (Referring to pairs of NFC/NFD quick check values.) - * The norm16 values of those characters are directly indexes into the extraData array. - * In version 3, the norm16 values must be shifted right by OFFSET_SHIFT + * The extraData array contains many per-character data sections. + * Each section contains mappings and/or composition lists. + * The norm16 value of each character that has such data is directly an index to + * a section of the extraData array. + * + * In version 3+, the norm16 values must be shifted right by OFFSET_SHIFT * for accessing extraData. * * The data structures for compositions lists and mappings are described in the design doc. * + * In version 4 and below, the composition lists for MaybeYes characters were stored before + * the data for other characters. + * This sub-array had a length of MIN_NORMAL_MAYBE_YES-minMaybeYes. + * In version 3 & 4, the difference must be shifted right by OFFSET_SHIFT. + * + * In version 5, the data for MaybeNo and MaybeYes characters is stored after + * the data for other characters. + * + * If there are no MaybeNo and no MaybeYes characters, + * then minMaybeYes==minMaybeNo==MIN_NORMAL_MAYBE_YES. + * If there are such characters, then minMaybeNo is subtracted from their norm16 values + * to get the index into the extraData. + * In version 4 and below, the data index for Yes* and No* characters needs to be + * offset by the length of the MaybeYes data. + * In version 5, the data index for Maybe* characters needs to be offset by limitNoNo. + * + * Version 5 is the first to support MaybeNo characters, and + * adds the minMaybeNo and minMaybeNoCombinesFwd thresholds and + * the corresponding sections of the extraData. + * * uint8_t smallFCD[0x100]; -- new in format version 2 * * This is a bit set to help speed up FCD value lookups in the absence of a full @@ -936,7 +963,7 @@ unorm_getFCD16(UChar32 c); * to make room for two bits (three values) indicating whether the tccc is 0, 1, or greater. * See DELTA_TCCC_MASK etc. * This helps with fetching tccc/FCD values and FCC hasCompBoundaryAfter(). - * minMaybeYes is 8-aligned so that the DELTA_TCCC_MASK bits can be tested directly. + * minMaybeNo is 8-aligned so that the DELTA_TCCC_MASK bits can be tested directly. * * - Algorithmic mappings are only used for mapping to "comp yes and ccc=0" characters, * and ASCII characters are mapped algorithmically only to other ASCII characters. @@ -982,6 +1009,23 @@ unorm_getFCD16(UChar32 c); * gennorm2 now has to reject mappings for surrogate code points. * UTS #46 maps unpaired surrogates to U+FFFD in code rather than via its * custom normalization data file. + * + * Changes from format version 4 to format version 5 (ICU 76) ------------------ + * + * Unicode 16 adds the first MaybeYes characters which combine both backward and forward, + * taking this formerly theoretical data structure into reality. + * + * Unicode 16 also adds the first characters that have two-way mappings whose first characters + * combine backward. In order for normalization and the quick check to work properly, + * these composite characters also must be marked as NFC_QC=Maybe, + * corresponding to "combines back", although the composites themselves do not combine backward. + * Format version 5 adds two new ranges between "algorithmic NoNo" and MaybeYes, + * with thresholds minMaybeNo and minMaybeNoCombinesFwd, + * and indexes[IX_MIN_MAYBE_NO] and indexes[IX_MIN_MAYBE_NO_COMBINES_FWD], + * and corresponding mappings and composition lists in the extraData. + * + * Format version 5 moves the data for Maybe* characters from the start of the extraData array + * to its end. */ #endif /* !UCONFIG_NO_NORMALIZATION */ diff --git a/thirdparty/icu4c/common/patternprops.cpp b/thirdparty/icu4c/common/patternprops.cpp index 9922683cda..782d3366f9 100644 --- a/thirdparty/icu4c/common/patternprops.cpp +++ b/thirdparty/icu4c/common/patternprops.cpp @@ -120,12 +120,12 @@ PatternProps::isSyntax(UChar32 c) { if(c<0) { return false; } else if(c<=0xff) { - return (UBool)(latin1[c]>>1)&1; + return (latin1[c] >> 1) & 1; } else if(c<0x2010) { return false; } else if(c<=0x3030) { uint32_t bits=syntax2000[index2000[(c-0x2000)>>5]]; - return (UBool)((bits>>(c&0x1f))&1); + return (bits >> (c & 0x1f)) & 1; } else if(0xfd3e<=c && c<=0xfe46) { return c<=0xfd3f || 0xfe45<=c; } else { @@ -138,12 +138,12 @@ PatternProps::isSyntaxOrWhiteSpace(UChar32 c) { if(c<0) { return false; } else if(c<=0xff) { - return (UBool)(latin1[c]&1); + return latin1[c] & 1; } else if(c<0x200e) { return false; } else if(c<=0x3030) { uint32_t bits=syntaxOrWhiteSpace2000[index2000[(c-0x2000)>>5]]; - return (UBool)((bits>>(c&0x1f))&1); + return (bits >> (c & 0x1f)) & 1; } else if(0xfd3e<=c && c<=0xfe46) { return c<=0xfd3f || 0xfe45<=c; } else { @@ -156,7 +156,7 @@ PatternProps::isWhiteSpace(UChar32 c) { if(c<0) { return false; } else if(c<=0xff) { - return (UBool)(latin1[c]>>2)&1; + return (latin1[c] >> 2) & 1; } else if(0x200e<=c && c<=0x2029) { return c<=0x200f || 0x2028<=c; } else { diff --git a/thirdparty/icu4c/common/propname.cpp b/thirdparty/icu4c/common/propname.cpp index 45062bfbd9..640578c5ee 100644 --- a/thirdparty/icu4c/common/propname.cpp +++ b/thirdparty/icu4c/common/propname.cpp @@ -43,7 +43,7 @@ getASCIIPropertyNameChar(const char *name) { ) {} if(c!=0) { - return (i<<8)|(uint8_t)uprv_asciitolower((char)c); + return (i << 8) | static_cast<uint8_t>(uprv_asciitolower(c)); } else { return i<<8; } @@ -66,7 +66,7 @@ getEBCDICPropertyNameChar(const char *name) { ) {} if(c!=0) { - return (i<<8)|(uint8_t)uprv_ebcdictolower((char)c); + return (i << 8) | static_cast<uint8_t>(uprv_ebcdictolower(c)); } else { return i<<8; } @@ -231,7 +231,7 @@ UBool PropNameData::containsName(BytesTrie &trie, const char *name) { if(!USTRINGTRIE_HAS_NEXT(result)) { return false; } - result=trie.next((uint8_t)c); + result = trie.next(static_cast<uint8_t>(c)); } return USTRINGTRIE_HAS_VALUE(result); } diff --git a/thirdparty/icu4c/common/propname_data.h b/thirdparty/icu4c/common/propname_data.h index 579547e416..99233a0bd6 100644 --- a/thirdparty/icu4c/common/propname_data.h +++ b/thirdparty/icu4c/common/propname_data.h @@ -11,105 +11,107 @@ U_NAMESPACE_BEGIN -const int32_t PropNameData::indexes[8]={0x20,0x16fc,0x5471,0xb130,0xb130,0xb130,0x31,0}; +const int32_t PropNameData::indexes[8]={0x20,0x1778,0x5653,0xb539,0xb539,0xb539,0x31,0}; -const int32_t PropNameData::valueMaps[1463]={ -6,0,0x4b,0,0xfb,0x368,0xfb,0x37e,0xfb,0x393,0xfb,0x3a9,0xfb,0x3b4,0xfb,0x3d5, -0xfb,0x3e5,0xfb,0x3f4,0xfb,0x402,0xfb,0x426,0xfb,0x43d,0xfb,0x455,0xfb,0x46c,0xfb,0x47b, -0xfb,0x48a,0xfb,0x49b,0xfb,0x4a9,0xfb,0x4bb,0xfb,0x4d5,0xfb,0x4f0,0xfb,0x505,0xfb,0x522, -0xfb,0x533,0xfb,0x53e,0xfb,0x55d,0xfb,0x573,0xfb,0x584,0xfb,0x594,0xfb,0x5af,0xfb,0x5c8, -0xfb,0x5d9,0xfb,0x5f3,0xfb,0x606,0xfb,0x616,0xfb,0x630,0xfb,0x649,0xfb,0x660,0xfb,0x674, -0xfb,0x68a,0xfb,0x69e,0xfb,0x6b4,0xfb,0x6ce,0xfb,0x6e6,0xfb,0x702,0xfb,0x70a,0xfb,0x712, -0xfb,0x71a,0xfb,0x722,0xfb,0x72b,0xfb,0x738,0xfb,0x74b,0xfb,0x768,0xfb,0x785,0xfb,0x7a2, -0xfb,0x7c0,0xfb,0x7de,0xfb,0x802,0xfb,0x80f,0xfb,0x829,0xfb,0x83e,0xfb,0x859,0xfb,0x870, -0xfb,0x887,0xfb,0x8a9,0xfb,0x8c8,0xfb,0x8e1,0xfb,0x90e,0xfb,0x947,0xfb,0x978,0xfb,0x9a7, -0xfb,0x9d6,0xfb,0x9eb,0xfb,0xa04,0xfb,0xa2f,0xfb,0x1000,0x101a,0xa60,0x177,0xc80,0x192,0x331c, -0x101,0x333b,0x2df,0x3479,0x2f5,0x34d3,0x2ff,0x3730,0x321,0x405b,0x38d,0x40cb,0x397,0x43b0,0x3cb,0x43ee, -0x3d3,0x4f3e,0x4a0,0x4fbc,0x4aa,0x4fe1,0x4b0,0x4ffb,0x4b6,0x501c,0x4bd,0x5036,0x101,0x505b,0x101,0x5081, -0x4c4,0x512b,0x4da,0x51a4,0x4ed,0x5256,0x508,0x528d,0x50f,0x546d,0x523,0x58ed,0x54b,0x594c,0x553,0x2000, -0x2001,0x5999,0x559,0x3000,0x3001,0x5a25,0,0x4000,0x400e,0x5a37,0,0x5a40,0,0x5a5a,0,0x5a6b, -0,0x5a7c,0,0x5a92,0,0x5a9b,0,0x5ab8,0,0x5ad6,0,0x5af4,0,0x5b12,0,0x5b28, -0,0x5b3c,0,0x5b52,0,0x7000,0x7002,0x5b6b,0,0x5b82,0x5a7,0x896,0x12,0,1,0x12, -0x20,0x8b4,0x4a,0,1,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,0x10, -0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20, -0x21,0x22,0x23,0x24,0x54,0x5b,0x67,0x6b,0x76,0x7a,0x81,0x82,0x84,0x85,0xc8,0xca, -0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xe9,0xea,0xf0,0x2e,0x40,0x4c, -0x5e,0x68,0x79,0x84,0x91,0x9e,0xab,0xb8,0xc5,0xd2,0xdf,0xec,0xf9,0x106,0x113,0x120, -0x12d,0x13a,0x147,0x154,0x161,0x16e,0x17b,0x188,0x195,0x1a2,0x1af,0x1bc,0x1c9,0x1d6,0x1e3,0x1f0, -0x1fd,0x20c,0x21b,0x22a,0x239,0x248,0x257,0x266,0x275,0x28f,0x2a3,0x2b7,0x2d2,0x2e1,0x2ea,0x2fa, -0x302,0x30b,0x31a,0x323,0x333,0x344,0x355,0xa55,1,0,0x17,0xa6f,0xa80,0xa91,0xaa5,0xabc, -0xad4,0xae6,0xafb,0xb12,0xb27,0xb37,0xb49,0xb66,0xb82,0xb94,0xbb1,0xbcd,0xbe9,0xbfe,0xc13,0xc2d, -0xc48,0xc63,0xbf7,1,0,0x149,0xc8b,0xc98,0xcab,0xcd3,0xcf1,0xd0f,0xd27,0xd52,0xd7c,0xd94, -0xda7,0xdba,0xdc9,0xdd8,0xde7,0xdf6,0xe0d,0xe1e,0xe31,0xe44,0xe51,0xe5e,0xe6d,0xe7e,0xe93,0xea4, -0xeaf,0xeb8,0xec9,0xeda,0xeed,0xeff,0xf12,0xf25,0xf64,0xf71,0xf7e,0xf8b,0xfa0,0xfd0,0xfea,0x100b, -0x1036,0x1059,0x10b7,0x10de,0x10f9,0x1108,0x112f,0x1157,0x117a,0x119d,0x11c7,0x11e0,0x11ff,0x1222,0x1246,0x1259, -0x1273,0x129d,0x12b5,0x12dd,0x1306,0x1319,0x132c,0x133f,0x1366,0x1375,0x1395,0x13c3,0x13e1,0x140f,0x142b,0x1446, -0x145f,0x1478,0x1499,0x14c9,0x14e8,0x150a,0x153e,0x156b,0x15b0,0x15d1,0x15fb,0x161c,0x1645,0x1658,0x168b,0x16a2, -0x16b1,0x16c2,0x16ed,0x1704,0x1735,0x1763,0x17a6,0x17b1,0x17ea,0x17fb,0x180c,0x1819,0x182c,0x1866,0x188a,0x18ae, -0x18e8,0x1920,0x194b,0x1963,0x198f,0x19bb,0x19c8,0x19d7,0x19f4,0x1a16,0x1a44,0x1a64,0x1a8b,0x1ab2,0x1ad1,0x1ae4, -0x1af5,0x1b06,0x1b2b,0x1b50,0x1b77,0x1bab,0x1bd8,0x1bf6,0x1c09,0x1c22,0x1c5b,0x1c6a,0x1c8a,0x1cac,0x1cce,0x1ce5, -0x1cfc,0x1d29,0x1d42,0x1d5b,0x1d8c,0x1db6,0x1dd1,0x1de4,0x1e03,0x1e0c,0x1e1f,0x1e3d,0x1e5b,0x1e6e,0x1e85,0x1e9a, -0x1ecf,0x1ef3,0x1f08,0x1f17,0x1f2a,0x1f4e,0x1f57,0x1f7b,0x1f92,0x1fa5,0x1fb4,0x1fbf,0x1fe0,0x1ff8,0x2007,0x2016, -0x2025,0x203c,0x2051,0x2066,0x209f,0x20b2,0x20ce,0x20d9,0x20e6,0x2114,0x2138,0x215b,0x216e,0x2190,0x21a3,0x21be, -0x21e1,0x2204,0x2229,0x223a,0x2269,0x2296,0x22ad,0x22c8,0x22d7,0x2302,0x233a,0x2374,0x23a2,0x23b3,0x23c0,0x23e4, -0x23f3,0x240f,0x2429,0x2446,0x247e,0x2493,0x24c0,0x24df,0x250d,0x252d,0x2561,0x2570,0x259a,0x25bd,0x25e8,0x25f3, -0x2604,0x261f,0x2643,0x2650,0x2665,0x268c,0x26b7,0x26ee,0x2701,0x2712,0x2742,0x2753,0x2762,0x2777,0x2795,0x27a8, -0x27bb,0x27d2,0x27ef,0x27fa,0x2803,0x2825,0x283a,0x285f,0x2876,0x289f,0x28ba,0x28cf,0x28e8,0x2909,0x293e,0x294f, -0x2980,0x29a4,0x29b5,0x29ce,0x29d9,0x2a06,0x2a28,0x2a56,0x2a89,0x2a98,0x2aa9,0x2ac6,0x2b08,0x2b2f,0x2b3c,0x2b51, -0x2b75,0x2b9b,0x2bd4,0x2be5,0x2c09,0x2c14,0x2c21,0x2c30,0x2c55,0x2c83,0x2c9f,0x2cbc,0x2cc9,0x2cda,0x2cf8,0x2d1b, -0x2d38,0x2d45,0x2d65,0x2d82,0x2da3,0x2dcc,0x2ddd,0x2dfc,0x2e15,0x2e2e,0x2e3f,0x2e88,0x2e99,0x2eb2,0x2ee1,0x2f0e, -0x2f33,0x2f75,0x2f91,0x2fa0,0x2fb7,0x2fe5,0x2ffe,0x3027,0x3041,0x307c,0x309a,0x30a9,0x30c9,0x30e4,0x3108,0x3124, -0x3142,0x3160,0x3177,0x3186,0x3191,0x31ce,0x31e1,0x320b,0x322b,0x3259,0x327d,0x32a5,0x32ca,0x32d5,0x32ee,0x2001, -1,0,0x12,0x3352,0x3362,0x3375,0x3385,0x3395,0x33a4,0x33b4,0x33c6,0x33d9,0x33eb,0x33fb,0x340b,0x341a, -0x3429,0x3439,0x3446,0x3455,0x3469,0x20bf,1,0,6,0x348e,0x3499,0x34a6,0x34b3,0x34c0,0x34cb,0x2103, -1,0,0x1e,0x34e8,0x34f7,0x350c,0x3521,0x3536,0x354a,0x355b,0x356f,0x3582,0x3593,0x35ac,0x35be,0x35cf, -0x35e3,0x35f6,0x360e,0x3620,0x362b,0x363b,0x3649,0x365e,0x3673,0x3689,0x36a3,0x36b9,0x36c9,0x36dd,0x36f1,0x3702, -0x371a,0x232e,1,0,0x68,0x3742,0x3765,0x376e,0x377b,0x3786,0x378f,0x379a,0x37a3,0x37bc,0x37c1,0x37ca, -0x37e7,0x37f0,0x37fd,0x3806,0x382a,0x3831,0x383a,0x384d,0x3858,0x3861,0x386c,0x3885,0x388e,0x389d,0x38a8,0x38b1, -0x38bc,0x38c5,0x38cc,0x38d5,0x38e0,0x38e9,0x3902,0x390b,0x3918,0x3923,0x3934,0x393f,0x3954,0x396b,0x3974,0x397d, -0x3996,0x39a1,0x39aa,0x39b3,0x39ca,0x39e7,0x39f2,0x3a03,0x3a0e,0x3a15,0x3a22,0x3a2f,0x3a5c,0x3a71,0x3a7a,0x3a95, -0x3ab8,0x3ad9,0x3afa,0x3b1f,0x3b46,0x3b67,0x3b8a,0x3bab,0x3bd2,0x3bf3,0x3c18,0x3c37,0x3c56,0x3c75,0x3c92,0x3cb3, -0x3cd4,0x3cf7,0x3d1c,0x3d3b,0x3d5a,0x3d7b,0x3da2,0x3dc7,0x3de6,0x3e07,0x3e2a,0x3e45,0x3e5e,0x3e79,0x3e92,0x3eaf, -0x3eca,0x3ee7,0x3f06,0x3f23,0x3f40,0x3f5f,0x3f7c,0x3f97,0x3fb4,0x3fd1,0x4004,0x402b,0x403e,0x2691,1,0, -6,0x406c,0x407b,0x408b,0x409b,0x40ab,0x40bc,0x26ef,1,0,0x30,0x40da,0x40e6,0x40f4,0x4103,0x4112, -0x4122,0x4133,0x4147,0x415c,0x4172,0x4185,0x4199,0x41a9,0x41b2,0x41bd,0x41cd,0x41e9,0x41fb,0x4209,0x4218,0x4224, -0x4239,0x424d,0x4260,0x426e,0x4282,0x4290,0x429a,0x42ac,0x42b8,0x42c6,0x42d6,0x42dd,0x42e4,0x42eb,0x42f2,0x42f9, -0x430f,0x4330,0x870,0x4342,0x434d,0x435c,0x4365,0x4370,0x4383,0x4394,0x43a5,0x297f,1,0,4,0x43c1, -0x43cc,0x43d8,0x43e2,0x29a5,1,0,0xc9,0x43f9,0x4406,0x441b,0x4428,0x4437,0x4445,0x4454,0x4463,0x4475, -0x4484,0x4492,0x44a3,0x44b2,0x44c1,0x44ce,0x44da,0x44e9,0x44f8,0x4502,0x450f,0x451c,0x452b,0x4539,0x4548,0x4554, -0x455e,0x456a,0x457a,0x458a,0x4598,0x45a4,0x45b5,0x45c1,0x45cd,0x45db,0x45e8,0x45f4,0x4601,0xea4,0x460e,0x461c, -0x4636,0x463f,0x464d,0x465b,0x4667,0x4676,0x4684,0x4692,0x469e,0x46ad,0x46bb,0x46c9,0x46d6,0x46e5,0x4700,0x470f, -0x4720,0x4731,0x4744,0x4756,0x4765,0x4777,0x4786,0x4792,0x479d,0x1fb4,0x47aa,0x47b5,0x47c0,0x47cb,0x47d6,0x47f1, -0x47fc,0x4807,0x4812,0x4825,0x4839,0x4844,0x4853,0x4862,0x486d,0x4878,0x4885,0x4894,0x48a2,0x48ad,0x48c8,0x48d2, -0x48e3,0x48f4,0x4903,0x4914,0x491f,0x492a,0x4935,0x4940,0x494b,0x4956,0x4961,0x496b,0x4976,0x4986,0x4991,0x499f, -0x49ac,0x49b7,0x49c6,0x49d3,0x49e0,0x49ef,0x49fc,0x4a0d,0x4a1f,0x4a2f,0x4a3a,0x4a4d,0x4a64,0x4a72,0x4a7f,0x4a8a, -0x4a97,0x4aa8,0x4ac4,0x4ada,0x4ae5,0x4b02,0x4b12,0x4b21,0x4b2c,0x4b37,0x20ce,0x4b43,0x4b4e,0x4b66,0x4b76,0x4b85, -0x4b93,0x4ba1,0x4bac,0x4bb7,0x4bcb,0x4be2,0x4bfa,0x4c0a,0x4c1a,0x4c2a,0x4c3c,0x4c47,0x4c52,0x4c5c,0x4c68,0x4c76, -0x4c89,0x4c95,0x4ca2,0x4cad,0x4cc9,0x4cd6,0x4ce4,0x4cfd,0x29ce,0x4d0c,0x27ef,0x4d19,0x4d27,0x4d39,0x4d47,0x4d53, -0x4d63,0x2c09,0x4d71,0x4d7d,0x4d88,0x4d93,0x4d9e,0x4db2,0x4dc0,0x4dd7,0x4de3,0x4df7,0x4e05,0x4e17,0x4e2d,0x4e3b, -0x4e4d,0x4e5b,0x4e78,0x4e8a,0x4e97,0x4ea8,0x4eba,0x4ed4,0x4ee1,0x4ef4,0x4f05,0x3186,0x4f12,0x32ca,0x4f21,0x4f33, -0x3403,1,0,6,0x4f58,0x4f6b,0x4f7b,0x4f89,0x4f9a,0x4faa,0x345f,0x12,0,1,0x4fd4,0x4fda, -0x346c,0x12,0,1,0x4fd4,0x4fda,0x3479,1,0,3,0x4fd4,0x4fda,0x5013,0x348f,1,0, -3,0x4fd4,0x4fda,0x5013,0x34a5,1,0,0x12,0x509d,0x50a7,0x50b3,0x50ba,0x50c5,0x50ca,0x50d1,0x50d8, -0x50e1,0x50e6,0x50eb,0x50fb,0x870,0x4342,0x5107,0x434d,0x5117,0x435c,0x354e,1,0,0xf,0x509d,0x513e, -0x5148,0x5152,0x515d,0x4218,0x5167,0x5173,0x517b,0x5182,0x518c,0x50b3,0x50ba,0x50ca,0x5196,0x35d5,1,0, -0x17,0x509d,0x51b3,0x5152,0x51bf,0x51cc,0x51da,0x4218,0x51e5,0x50b3,0x51f6,0x50ca,0x5205,0x5213,0x870,0x4330, -0x521f,0x5230,0x4342,0x5107,0x434d,0x5117,0x435c,0x5241,0x36f2,1,0,3,0x5274,0x527c,0x5284,0x370b, -1,0,0x10,0x52ad,0x52b4,0x52c3,0x52e4,0x5307,0x5312,0x5331,0x5348,0x5355,0x535e,0x537d,0x53b0,0x53cb, -0x53fa,0x5417,0x543c,0x37a4,1,0,0x24,0x548b,0x5498,0x54ab,0x54b8,0x54e5,0x550a,0x551f,0x553e,0x555f, -0x558c,0x55c5,0x55e8,0x560b,0x5638,0x566d,0x5694,0x56bd,0x56f4,0x5723,0x5744,0x5769,0x5778,0x579b,0x57b2,0x57bf, -0x57ce,0x57eb,0x5804,0x5827,0x584c,0x5865,0x587a,0x5889,0x589a,0x58a7,0x58c8,0x3974,1,0,4,0x5906, -0x5911,0x5929,0x5941,0x39b0,0x12,0,1,0x5971,0x5988,0x39c7,0x36,1,2,4,8,0xe, -0x10,0x20,0x3e,0x40,0x80,0x100,0x1c0,0x200,0x400,0x800,0xe00,0x1000,0x2000,0x4000,0x7000,0x8000, -0x10000,0x20000,0x40000,0x78001,0x80000,0x100000,0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,0xf000000,0x10000000,0x20000000, -0x30f80000,0x34e8,0x34f7,0x350c,0x3521,0x59c7,0x3536,0x354a,0x59bd,0x355b,0x356f,0x3582,0x59d8,0x3593,0x35ac,0x35be, -0x59ef,0x35cf,0x35e3,0x35f6,0x5a18,0x360e,0x3620,0x362b,0x363b,0x59b4,0x3649,0x365e,0x3673,0x3689,0x36a3,0x36b9, -0x36c9,0x36dd,0x36f1,0x5a0e,0x3702,0x371a,0x59f9,0x3cde,1,0,0xc,0x5ba3,0x5bc0,0x5bd7,0x5bfc,0x5c0f, -0x5c20,0x5c35,0x5c48,0x5c5d,0x5c78,0x5c91,0x5ca6 +const int32_t PropNameData::valueMaps[1494]={ +6,0,0x4c,0,0xff,0x368,0xff,0x37e,0xff,0x393,0xff,0x3a9,0xff,0x3b4,0xff,0x3d5, +0xff,0x3e5,0xff,0x3f4,0xff,0x402,0xff,0x426,0xff,0x43d,0xff,0x455,0xff,0x46c,0xff,0x47b, +0xff,0x48a,0xff,0x49b,0xff,0x4a9,0xff,0x4bb,0xff,0x4d5,0xff,0x4f0,0xff,0x505,0xff,0x522, +0xff,0x533,0xff,0x53e,0xff,0x55d,0xff,0x573,0xff,0x584,0xff,0x594,0xff,0x5af,0xff,0x5c8, +0xff,0x5d9,0xff,0x5f3,0xff,0x606,0xff,0x616,0xff,0x630,0xff,0x649,0xff,0x660,0xff,0x674, +0xff,0x68a,0xff,0x69e,0xff,0x6b4,0xff,0x6ce,0xff,0x6e6,0xff,0x702,0xff,0x70a,0xff,0x712, +0xff,0x71a,0xff,0x722,0xff,0x72b,0xff,0x738,0xff,0x74b,0xff,0x768,0xff,0x785,0xff,0x7a2, +0xff,0x7c0,0xff,0x7de,0xff,0x802,0xff,0x80f,0xff,0x829,0xff,0x83e,0xff,0x859,0xff,0x870, +0xff,0x887,0xff,0x8a9,0xff,0x8c8,0xff,0x8e1,0xff,0x90e,0xff,0x947,0xff,0x978,0xff,0x9a7, +0xff,0x9d6,0xff,0x9eb,0xff,0xa04,0xff,0xa2f,0xff,0xa60,0xff,0x1000,0x101b,0xa7d,0x17b,0xc9d, +0x196,0x346c,0x105,0x348b,0x2ed,0x35c9,0x303,0x3623,0x30d,0x3880,0x32f,0x41d7,0x39c,0x4247,0x3a6,0x452c, +0x3da,0x456a,0x3e2,0x5126,0x4b6,0x51a4,0x4c0,0x51c9,0x4c6,0x51e3,0x4cc,0x5204,0x4d3,0x521e,0x105,0x5243, +0x105,0x5269,0x4da,0x5313,0x4f0,0x538c,0x503,0x543e,0x51e,0x5475,0x525,0x5655,0x539,0x5afa,0x562,0x5b59, +0x56a,0x5b9e,0x570,0x2000,0x2001,0x5bc8,0x578,0x3000,0x3001,0x5c54,0,0x4000,0x400e,0x5c66,0,0x5c6f, +0,0x5c89,0,0x5c9a,0,0x5cab,0,0x5cc1,0,0x5cca,0,0x5ce7,0,0x5d05,0,0x5d23, +0,0x5d41,0,0x5d57,0,0x5d6b,0,0x5d81,0,0x7000,0x7002,0x5d9a,0,0x5db1,0x5c6,0x8de, +0x12,0,1,0x12,0x20,0x8fc,0x4a,0,1,6,7,8,9,0xa,0xb,0xc, +0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, +0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x54,0x5b,0x67,0x6b,0x76,0x7a,0x81,0x82, +0x84,0x85,0xc8,0xca,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xe9,0xea, +0xf0,0x2e,0x40,0x4c,0x5e,0x68,0x79,0x84,0x91,0x9e,0xab,0xb8,0xc5,0xd2,0xdf,0xec, +0xf9,0x106,0x113,0x120,0x12d,0x13a,0x147,0x154,0x161,0x16e,0x17b,0x188,0x195,0x1a2,0x1af,0x1bc, +0x1c9,0x1d6,0x1e3,0x1f0,0x1fd,0x20c,0x21b,0x22a,0x239,0x248,0x257,0x266,0x275,0x28f,0x2a3,0x2b7, +0x2d2,0x2e1,0x2ea,0x2fa,0x302,0x30b,0x31a,0x323,0x333,0x344,0x355,0xa9d,1,0,0x17,0xa8c, +0xa9d,0xaae,0xac2,0xad9,0xaf1,0xb03,0xb18,0xb2f,0xb44,0xb54,0xb66,0xb83,0xb9f,0xbb1,0xbce,0xbea, +0xc06,0xc1b,0xc30,0xc4a,0xc65,0xc80,0xc3f,1,0,0x153,0xca8,0xcb5,0xcc8,0xcf0,0xd0e,0xd2c, +0xd44,0xd6f,0xd99,0xdb1,0xdc4,0xdd7,0xde6,0xdf5,0xe04,0xe13,0xe2a,0xe3b,0xe4e,0xe61,0xe6e,0xe7b, +0xe8a,0xe9b,0xeb0,0xec1,0xecc,0xed5,0xee6,0xef7,0xf0a,0xf1c,0xf2f,0xf42,0xf81,0xf8e,0xf9b,0xfa8, +0xfbd,0xfed,0x1007,0x1028,0x1053,0x1076,0x10d4,0x10fb,0x1116,0x1125,0x114c,0x1174,0x1197,0x11ba,0x11e4,0x11fd, +0x121c,0x123f,0x1263,0x1276,0x1290,0x12ba,0x12d2,0x12fa,0x1323,0x1336,0x1349,0x135c,0x1383,0x1392,0x13b2,0x13e0, +0x13fe,0x142c,0x1448,0x1463,0x147c,0x1495,0x14b6,0x14e6,0x1505,0x1527,0x155b,0x1588,0x15cd,0x15ee,0x1618,0x1639, +0x1662,0x1675,0x16a8,0x16bf,0x16ce,0x16df,0x170a,0x1721,0x1752,0x1780,0x17c3,0x17ce,0x1807,0x1818,0x1829,0x1836, +0x1849,0x1883,0x18a7,0x18cb,0x1905,0x193d,0x1968,0x1980,0x19ac,0x19d8,0x19e5,0x19f4,0x1a11,0x1a33,0x1a61,0x1a81, +0x1aa8,0x1acf,0x1aee,0x1b01,0x1b12,0x1b23,0x1b48,0x1b6d,0x1b94,0x1bc8,0x1bf5,0x1c13,0x1c26,0x1c3f,0x1c78,0x1c87, +0x1ca7,0x1cc9,0x1ceb,0x1d02,0x1d19,0x1d46,0x1d5f,0x1d78,0x1da9,0x1dd3,0x1dee,0x1e01,0x1e20,0x1e29,0x1e3c,0x1e5a, +0x1e78,0x1e8b,0x1ea2,0x1eb7,0x1eec,0x1f10,0x1f25,0x1f34,0x1f47,0x1f6b,0x1f74,0x1f98,0x1faf,0x1fc2,0x1fd1,0x1fdc, +0x1ffd,0x2015,0x2024,0x2033,0x2042,0x2059,0x206e,0x2083,0x20bc,0x20cf,0x20eb,0x20f6,0x2103,0x2131,0x2155,0x2178, +0x218b,0x21ad,0x21c0,0x21db,0x21fe,0x2221,0x2246,0x2257,0x2286,0x22b3,0x22ca,0x22e5,0x22f4,0x231f,0x2357,0x2391, +0x23bf,0x23d0,0x23dd,0x2401,0x2410,0x242c,0x2446,0x2463,0x249b,0x24b0,0x24dd,0x24fc,0x252a,0x254a,0x257e,0x258d, +0x25b7,0x25da,0x2605,0x2610,0x2621,0x263c,0x2660,0x266d,0x2682,0x26a9,0x26d4,0x270b,0x271e,0x272f,0x275f,0x2770, +0x277f,0x2794,0x27b2,0x27c5,0x27d8,0x27ef,0x280c,0x2817,0x2820,0x2842,0x2857,0x287c,0x2893,0x28bc,0x28d7,0x28ec, +0x2905,0x2926,0x295b,0x296c,0x299d,0x29c1,0x29d2,0x29eb,0x29f6,0x2a23,0x2a45,0x2a73,0x2aa6,0x2ab5,0x2ac6,0x2ae3, +0x2b25,0x2b4c,0x2b59,0x2b6e,0x2b92,0x2bb8,0x2bf1,0x2c02,0x2c26,0x2c31,0x2c3e,0x2c4d,0x2c72,0x2ca0,0x2cbc,0x2cd9, +0x2ce6,0x2cf7,0x2d15,0x2d38,0x2d55,0x2d62,0x2d82,0x2d9f,0x2dc0,0x2de9,0x2dfa,0x2e19,0x2e32,0x2e4b,0x2e5c,0x2ea5, +0x2eb6,0x2ecf,0x2efe,0x2f2b,0x2f50,0x2f92,0x2fae,0x2fbd,0x2fd4,0x3002,0x301b,0x3044,0x305e,0x3099,0x30b7,0x30c6, +0x30e6,0x3101,0x3125,0x3141,0x315f,0x317d,0x3194,0x31a3,0x31ae,0x31eb,0x31fe,0x3228,0x3248,0x3276,0x329a,0x32c2, +0x32e7,0x32f2,0x330b,0x3339,0x3375,0x3382,0x339d,0x33b2,0x33d4,0x33e5,0x33f6,0x3440,0x344f,0x20b6,1,0, +0x12,0x34a2,0x34b2,0x34c5,0x34d5,0x34e5,0x34f4,0x3504,0x3516,0x3529,0x353b,0x354b,0x355b,0x356a,0x3579,0x3589, +0x3596,0x35a5,0x35b9,0x2174,1,0,6,0x35de,0x35e9,0x35f6,0x3603,0x3610,0x361b,0x21b8,1,0, +0x1e,0x3638,0x3647,0x365c,0x3671,0x3686,0x369a,0x36ab,0x36bf,0x36d2,0x36e3,0x36fc,0x370e,0x371f,0x3733,0x3746, +0x375e,0x3770,0x377b,0x378b,0x3799,0x37ae,0x37c3,0x37d9,0x37f3,0x3809,0x3819,0x382d,0x3841,0x3852,0x386a,0x23e3, +1,0,0x69,0x3892,0x38b5,0x38be,0x38cb,0x38d6,0x38df,0x38ea,0x38f3,0x390c,0x3911,0x391a,0x3937,0x3940, +0x394d,0x3956,0x398b,0x3992,0x399b,0x39ae,0x39b9,0x39c2,0x39cd,0x39e6,0x39ef,0x39fe,0x3a09,0x3a12,0x3a1d,0x3a26, +0x3a2d,0x3a36,0x3a41,0x3a4a,0x3a63,0x3a6c,0x3a79,0x3a84,0x3a95,0x3aa0,0x3ab5,0x3acc,0x3ad5,0x3ade,0x3af7,0x3b02, +0x3b0b,0x3b14,0x3b2b,0x3b48,0x3b53,0x3b64,0x3b6f,0x3b76,0x3b83,0x3b90,0x3bbd,0x3bd2,0x3bdb,0x3bf6,0x3c19,0x3c3a, +0x3c5b,0x3c80,0x3ca7,0x3cc8,0x3ceb,0x3d0c,0x3d33,0x3d54,0x3d79,0x3d98,0x3db7,0x3dd6,0x3df3,0x3e14,0x3e35,0x3e58, +0x3e7d,0x3e9c,0x3ebb,0x3edc,0x3f03,0x3f28,0x3f47,0x3f68,0x3f8b,0x3fa6,0x3fbf,0x3fda,0x3ff3,0x4010,0x402b,0x4048, +0x4067,0x4084,0x40a1,0x40c0,0x40dd,0x40f8,0x4115,0x4132,0x4165,0x418c,0x419f,0x41bc,0x2753,1,0,6, +0x41e8,0x41f7,0x4207,0x4217,0x4227,0x4238,0x27b1,1,0,0x30,0x4256,0x4262,0x4270,0x427f,0x428e,0x429e, +0x42af,0x42c3,0x42d8,0x42ee,0x4301,0x4315,0x4325,0x432e,0x4339,0x4349,0x4365,0x4377,0x4385,0x4394,0x43a0,0x43b5, +0x43c9,0x43dc,0x43ea,0x43fe,0x440c,0x4416,0x4428,0x4434,0x4442,0x4452,0x4459,0x4460,0x4467,0x446e,0x4475,0x448b, +0x44ac,0x870,0x44be,0x44c9,0x44d8,0x44e1,0x44ec,0x44ff,0x4510,0x4521,0x2a41,1,0,4,0x453d,0x4548, +0x4554,0x455e,0x2a67,1,0,0xd0,0x4575,0x4582,0x4597,0x45a4,0x45b3,0x45c1,0x45d0,0x45df,0x45f1,0x4600, +0x460e,0x461f,0x462e,0x463d,0x464a,0x4656,0x4665,0x4674,0x467e,0x468b,0x4698,0x46a7,0x46b5,0x46c4,0x46d0,0x46da, +0x46e6,0x46f6,0x4706,0x4714,0x4720,0x4731,0x473d,0x4749,0x4757,0x4764,0x4770,0x477d,0xec1,0x478a,0x4798,0x47b2, +0x47bb,0x47c9,0x47d7,0x47e3,0x47f2,0x4800,0x480e,0x481a,0x4829,0x4837,0x4845,0x4852,0x4861,0x487c,0x488b,0x489c, +0x48ad,0x48c0,0x48d2,0x48e1,0x48f3,0x4902,0x490e,0x4919,0x1fd1,0x4926,0x4931,0x493c,0x4947,0x4952,0x496d,0x4978, +0x4983,0x498e,0x49a1,0x49b5,0x49c0,0x49cf,0x49de,0x49e9,0x49f4,0x4a01,0x4a10,0x4a1e,0x4a29,0x4a44,0x4a4e,0x4a5f, +0x4a70,0x4a7f,0x4a90,0x4a9b,0x4aa6,0x4ab1,0x4abc,0x4ac7,0x4ad2,0x4add,0x4ae7,0x4af2,0x4b02,0x4b0d,0x4b1b,0x4b28, +0x4b33,0x4b42,0x4b4f,0x4b5c,0x4b6b,0x4b78,0x4b89,0x4b9b,0x4bab,0x4bb6,0x4bc9,0x4be0,0x4bee,0x4bfb,0x4c06,0x4c13, +0x4c24,0x4c40,0x4c56,0x4c61,0x4c7e,0x4c8e,0x4c9d,0x4ca8,0x4cb3,0x20eb,0x4cbf,0x4cca,0x4ce2,0x4cf2,0x4d01,0x4d0f, +0x4d1d,0x4d28,0x4d33,0x4d47,0x4d5e,0x4d76,0x4d86,0x4d96,0x4da6,0x4db8,0x4dc3,0x4dce,0x4dd8,0x4de4,0x4df2,0x4e05, +0x4e11,0x4e1e,0x4e29,0x4e45,0x4e52,0x4e60,0x4e79,0x29eb,0x4e88,0x280c,0x4e95,0x4ea3,0x4eb5,0x4ec3,0x4ecf,0x4edf, +0x2c26,0x4eed,0x4ef9,0x4f04,0x4f0f,0x4f1a,0x4f2e,0x4f3c,0x4f53,0x4f5f,0x4f73,0x4f81,0x4f93,0x4fa9,0x4fb7,0x4fc9, +0x4fd7,0x4ff4,0x5006,0x5013,0x5024,0x5036,0x5050,0x505d,0x5070,0x5081,0x31a3,0x508e,0x32e7,0x509d,0x50af,0x50ba, +0x50c6,0x50d9,0x50e9,0x50f7,0x5105,0x5112,0x3531,1,0,6,0x5140,0x5153,0x5163,0x5171,0x5182,0x5192, +0x358d,0x12,0,1,0x51bc,0x51c2,0x359a,0x12,0,1,0x51bc,0x51c2,0x35a7,1,0,3, +0x51bc,0x51c2,0x51fb,0x35bd,1,0,3,0x51bc,0x51c2,0x51fb,0x35d3,1,0,0x12,0x5285,0x528f, +0x529b,0x52a2,0x52ad,0x52b2,0x52b9,0x52c0,0x52c9,0x52ce,0x52d3,0x52e3,0x870,0x44be,0x52ef,0x44c9,0x52ff,0x44d8, +0x367c,1,0,0xf,0x5285,0x5326,0x5330,0x533a,0x5345,0x4394,0x534f,0x535b,0x5363,0x536a,0x5374,0x529b, +0x52a2,0x52b2,0x537e,0x3703,1,0,0x17,0x5285,0x539b,0x533a,0x53a7,0x53b4,0x53c2,0x4394,0x53cd,0x529b, +0x53de,0x52b2,0x53ed,0x53fb,0x870,0x44ac,0x5407,0x5418,0x44be,0x52ef,0x44c9,0x52ff,0x44d8,0x5429,0x3820,1, +0,3,0x545c,0x5464,0x546c,0x3839,1,0,0x10,0x5495,0x549c,0x54ab,0x54cc,0x54ef,0x54fa,0x5519, +0x5530,0x553d,0x5546,0x5565,0x5598,0x55b3,0x55e2,0x55ff,0x5624,0x38d2,1,0,0x25,0x5673,0x5680,0x5693, +0x56a0,0x56cd,0x56f2,0x5707,0x5726,0x5747,0x5774,0x57ad,0x57d0,0x57f3,0x5820,0x5855,0x587c,0x58a5,0x58dc,0x590b, +0x592c,0x5951,0x5960,0x5983,0x599a,0x59a7,0x59b6,0x59d3,0x59ec,0x5a0f,0x5a34,0x5a4d,0x5a62,0x5a71,0x5a82,0x5a8f, +0x5ab0,0x5ad5,0x3ab5,1,0,4,0x5b13,0x5b1e,0x5b36,0x5b4e,0x3af1,0x12,0,1,0x5b76,0x5b8d, +0x3b08,1,0,4,0x453d,0x56f2,0x53de,0x5bb9,0x3b2d,0x36,1,2,4,8,0xe,0x10, +0x20,0x3e,0x40,0x80,0x100,0x1c0,0x200,0x400,0x800,0xe00,0x1000,0x2000,0x4000,0x7000,0x8000,0x10000, +0x20000,0x40000,0x78001,0x80000,0x100000,0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,0xf000000,0x10000000,0x20000000,0x30f80000, +0x3638,0x3647,0x365c,0x3671,0x5bf6,0x3686,0x369a,0x5bec,0x36ab,0x36bf,0x36d2,0x5c07,0x36e3,0x36fc,0x370e,0x5c1e, +0x371f,0x3733,0x3746,0x5c47,0x375e,0x3770,0x377b,0x378b,0x5be3,0x3799,0x37ae,0x37c3,0x37d9,0x37f3,0x3809,0x3819, +0x382d,0x3841,0x5c3d,0x3852,0x386a,0x5c28,0x3e44,1,0,0xc,0x5dca,0x5de7,0x5dfe,0x5e23,0x5e36,0x5e47, +0x5e5c,0x5e6f,0x5e84,0x5e9f,0x5eb8,0x5ecd }; -const uint8_t PropNameData::bytesTries[15733]={ -0,0x15,0x6d,0xc3,0xc7,0x73,0xc2,0x12,0x76,0x7a,0x76,0x6a,0x77,0xa2,0x52,0x78, +const uint8_t PropNameData::bytesTries[16091]={ +0,0x15,0x6d,0xc3,0xe7,0x73,0xc2,0x12,0x76,0x7a,0x76,0x6a,0x77,0xa2,0x52,0x78, 1,0x64,0x50,0x69,0x10,0x64,1,0x63,0x30,0x73,0x62,0x13,0x74,0x61,0x72,0x74, 0x63,0x60,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x61,0x13,0x69,0x67,0x69,0x74, 0x81,3,0x61,0x2e,0x65,0x4c,0x6f,0xc3,0x18,0x73,0x69,0x1e,0x72,0x69,0x61,0x74, @@ -142,15 +144,17 @@ const uint8_t PropNameData::bytesTries[15733]={ 0x6e,0x69,0x6e,0x67,0x63,0x6c,0x61,0x73,0x73,0xc3,0x11,0xd8,0x40,0xa,0x11,0x63, 0x63,0xc3,0x11,0x11,0x72,0x6d,0x58,0x1e,0x69,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63, 0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,0x1d,0x74,0x6c,0x65,0x63,0x61,0x73,0x65, -0x6d,0x61,0x70,0x70,0x69,0x6e,0x67,0xd9,0x40,0xa,0x6d,0xa2,0x76,0x6e,0xa2,0x78, -0x70,0xa4,0x3e,0x71,0xa4,0x90,0x72,3,0x61,0x2c,0x65,0x36,0x67,0x54,0x69,0x9d, +0x6d,0x61,0x70,0x70,0x69,0x6e,0x67,0xd9,0x40,0xa,0x6d,0xa2,0x76,0x6e,0xa2,0x98, +0x70,0xa4,0x5e,0x71,0xa4,0xb0,0x72,3,0x61,0x2c,0x65,0x36,0x67,0x54,0x69,0x9d, 0x14,0x64,0x69,0x63,0x61,0x6c,0x55,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e, 0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x9d,0x15,0x69,0x65,0x6d,0x6f,0x6a,0x69,0xa2, 0x47,3,0x66,0x44,0x6d,0x5c,0x74,0x7c,0x7a,0x19,0x77,0x6a,0x73,0x65,0x71,0x75, 0x65,0x6e,0x63,0x65,0xa3,0x46,0x1a,0x6c,0x61,0x67,0x73,0x65,0x71,0x75,0x65,0x6e, 0x63,0x65,0xa3,0x44,0x1e,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x73,0x65,0x71,0x75, 0x65,0x6e,0x63,0x65,0xa3,0x43,0x19,0x61,0x67,0x73,0x65,0x71,0x75,0x65,0x6e,0x63, -0x65,0xa3,0x45,0x12,0x61,0x74,0x68,0x4f,6,0x6f,0x39,0x6f,0x32,0x74,0xc3,9, +0x65,0xa3,0x45,2,0x61,0x54,0x63,0x58,0x6f,0x12,0x64,0x69,0x66,0x1f,0x69,0x65, +0x72,0x63,0x6f,0x6d,0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa3,0x4b, +0x11,0x74,0x68,0x4f,0x10,0x6d,0xa3,0x4b,6,0x6f,0x39,0x6f,0x32,0x74,0xc3,9, 0x75,0x54,0x76,0xd9,0x30,0,0x12,0x6e,0x63,0x68,0x1f,0x61,0x72,0x61,0x63,0x74, 0x65,0x72,0x63,0x6f,0x64,0x65,0x70,0x6f,0x69,0x6e,0x74,0x51,0x14,0x6d,0x65,0x72, 0x69,0x63,1,0x74,0x32,0x76,0x13,0x61,0x6c,0x75,0x65,0xd9,0x30,0,0x12,0x79, @@ -169,158 +173,162 @@ const uint8_t PropNameData::bytesTries[15733]={ 0x30,0x77,0x10,0x73,0x77,0x11,0x79,0x6e,0x75,0x12,0x65,0x72,0x6e,1,0x73,0x38, 0x77,0x18,0x68,0x69,0x74,0x65,0x73,0x70,0x61,0x63,0x65,0x77,0x14,0x79,0x6e,0x74, 0x61,0x78,0x75,0x10,0x6d,0x9f,1,0x6d,0x3c,0x75,0x1a,0x6f,0x74,0x61,0x74,0x69, -0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x53,0x12,0x61,0x72,0x6b,0x53,0x66,0xc2,0x4a,0x69, -0xc1,0x8e,0x69,0xa2,0x6f,0x6a,0xa4,0x5b,0x6c,4,0x62,0xc3,8,0x63,0x8c,0x65, +0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x53,0x12,0x61,0x72,0x6b,0x53,0x66,0xc2,0x72,0x69, +0xc1,0xb6,0x69,0xa2,0x6f,0x6a,0xa4,0x83,0x6c,4,0x62,0xc3,8,0x63,0x8c,0x65, 0x98,0x69,0xa2,0x56,0x6f,2,0x65,0x4b,0x67,0x4c,0x77,0x11,0x65,0x72,0x4c,0x13, 0x63,0x61,0x73,0x65,0x4c,0x16,0x6d,0x61,0x70,0x70,0x69,0x6e,0x67,0xd9,0x40,4, 0x11,0x69,0x63,0x1f,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72,0x65,0x78,0x63,0x65,0x70, 0x74,0x69,0x6f,0x6e,0x4b,0xd8,0x40,4,0x11,0x63,0x63,0xc3,0x10,0x18,0x61,0x64, 0x63,0x61,0x6e,0x6f,0x6e,0x69,0x63,0x1f,0x61,0x6c,0x63,0x6f,0x6d,0x62,0x69,0x6e, 0x69,0x6e,0x67,0x63,0x6c,0x61,0x73,0x73,0xc3,0x10,0x16,0x6e,0x65,0x62,0x72,0x65, -0x61,0x6b,0xc3,8,2,0x64,0x4a,0x6e,0xa2,0xad,0x73,1,0x63,0xd9,0x40,3, -0x6f,0x16,0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0xd9,0x40,3,2,0x63,0xa2,0x44, -0x65,0xa2,0x6c,0x73,0x40,2,0x62,0x48,0x74,0x64,0x75,0xa2,0x48,0x1b,0x6e,0x61, -0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0xa3,0x48,0x44,0x1c,0x69,0x6e, -0x61,0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x45,0x46,1,0x61,0x40, -0x72,0x1c,0x69,0x6e,0x61,0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x47, -0x11,0x72,0x74,0x41,0x3e,0x10,0x6f,1,0x6d,0x30,0x6e,0x14,0x74,0x69,0x6e,0x75, -0x65,0x3f,0x16,0x70,0x61,0x74,0x6d,0x61,0x74,0x68,1,0x63,0x30,0x73,0x13,0x74, -0x61,0x72,0x74,0xa3,0x49,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0xa3,0x4a,1, -0x6e,0x36,0x6f,0x42,0x16,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x43,0x15,0x74,0x69, -0x66,0x69,0x65,0x72,1,0x73,0x30,0x74,0x12,0x79,0x70,0x65,0xd9,0x70,1,0x14, -0x74,0x61,0x74,0x75,0x73,0xc3,0x19,2,0x64,0x2e,0x70,0x86,0x73,0x10,0x63,0xc3, -0x17,0x11,0x69,0x63,1,0x70,0x46,0x73,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63, -0x63,0x61,0x74,0x65,0x67,0x6f,0x72,0x79,0xc3,0x17,0x10,0x6f,0x1f,0x73,0x69,0x74, -0x69,0x6f,0x6e,0x61,0x6c,0x63,0x61,0x74,0x65,0x67,0x6f,0x72,0x79,0xc3,0x16,0x10, -0x63,0xc3,0x16,2,0x67,0xc3,6,0x6f,0x26,0x74,0xc3,7,0x11,0x69,0x6e,1, -0x63,0x4a,0x69,0x11,0x6e,0x67,1,0x67,0x2e,0x74,0x12,0x79,0x70,0x65,0xc3,7, -0x13,0x72,0x6f,0x75,0x70,0xc3,6,0x48,0x15,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x49, -0x66,0x86,0x67,0xa2,0x4a,0x68,3,0x61,0x36,0x65,0x58,0x73,0x68,0x79,0x13,0x70, -0x68,0x65,0x6e,0x3d,0x1f,0x6e,0x67,0x75,0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c, -0x65,0x74,0x79,0x70,0x65,0xc3,0xb,0x10,0x78,0x3a,0x14,0x64,0x69,0x67,0x69,0x74, -0x3b,0x10,0x74,0xc3,0xb,0x16,0x75,0x6c,0x6c,0x63,0x6f,0x6d,0x70,0x1f,0x6f,0x73, -0x69,0x74,0x69,0x6f,0x6e,0x65,0x78,0x63,0x6c,0x75,0x73,0x69,0x6f,0x6e,0x33,2, -0x63,0xa2,0x44,0x65,0xa2,0x4b,0x72,3,0x61,0x34,0x62,0x84,0x65,0x8a,0x6c,0x12, -0x69,0x6e,0x6b,0x39,0x11,0x70,0x68,0x7c,0x12,0x65,0x6d,0x65,3,0x62,0x5e,0x63, -0x30,0x65,0x48,0x6c,0x12,0x69,0x6e,0x6b,0x39,0x1a,0x6c,0x75,0x73,0x74,0x65,0x72, -0x62,0x72,0x65,0x61,0x6b,0xc3,0x12,0x14,0x78,0x74,0x65,0x6e,0x64,0x37,0x12,0x61, -0x73,0x65,0x35,0x11,0x78,0x74,0x37,0xc2,5,1,0x62,0xc3,0x12,0x6d,0xd9,0x20, -0,0x1c,0x6e,0x65,0x72,0x61,0x6c,0x63,0x61,0x74,0x65,0x67,0x6f,0x72,0x79,0xc2, -5,0x13,0x6d,0x61,0x73,0x6b,0xd9,0x20,0,0x61,0xa2,0xa2,0x62,0xa2,0xd0,0x63, -0xa4,0x4f,0x64,0xa6,0x1c,0x65,5,0x6d,0x75,0x6d,0x6e,0x70,0xa2,0x6b,0x78,0x10, -0x74,0x30,1,0x65,0x2c,0x70,0x12,0x69,0x63,0x74,0xa1,0x12,0x6e,0x64,0x65,1, -0x64,0x24,0x72,0x31,0x1b,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x69, -0x63,0xa1,0x10,0x6f,1,0x64,0x97,0x6a,0x10,0x69,0x92,3,0x63,0x44,0x6b,0x54, -0x6d,0x70,0x70,0x1a,0x72,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x95, -0x17,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x9b,0x1c,0x65,0x79,0x63,0x61,0x70, -0x73,0x65,0x71,0x75,0x65,0x6e,0x63,0x65,0xa3,0x42,0x16,0x6f,0x64,0x69,0x66,0x69, -0x65,0x72,0x96,0x13,0x62,0x61,0x73,0x65,0x99,0x12,0x72,0x65,0x73,0x95,0x61,0x30, -0x62,0x4e,0x63,0x12,0x6f,0x6d,0x70,0x9b,0xc2,4,0x1b,0x73,0x74,0x61,0x73,0x69, -0x61,0x6e,0x77,0x69,0x64,0x74,0x68,0xc3,4,0x12,0x61,0x73,0x65,0x99,3,0x67, -0x44,0x68,0x4a,0x6c,0x4e,0x73,0x1a,0x63,0x69,0x69,0x68,0x65,0x78,0x64,0x69,0x67, -0x69,0x74,0x23,0x10,0x65,0xd9,0x40,0,0x11,0x65,0x78,0x23,1,0x6e,0x38,0x70, -0x11,0x68,0x61,0x20,0x14,0x62,0x65,0x74,0x69,0x63,0x21,0x11,0x75,0x6d,0x79,5, -0x6c,0x22,0x6c,0x36,0x6d,0x52,0x70,1,0x62,0xd9,0x40,0xd,0x74,0xc3,0x15,2, -0x61,0x32,0x6b,0xc3,1,0x6f,0x11,0x63,0x6b,0xc3,1,0x11,0x6e,0x6b,0x7b,0x10, -0x67,0xd9,0x40,1,0x61,0xa2,0x4f,0x63,0xc3,0,0x69,0x11,0x64,0x69,2,0x63, -0x54,0x6d,0x74,0x70,0x1b,0x61,0x69,0x72,0x65,0x64,0x62,0x72,0x61,0x63,0x6b,0x65, -0x74,0xd8,0x40,0xd,0x13,0x74,0x79,0x70,0x65,0xc3,0x15,0x24,1,0x6c,0x30,0x6f, -0x14,0x6e,0x74,0x72,0x6f,0x6c,0x25,0x12,0x61,0x73,0x73,0xc3,0,0x26,0x14,0x69, -0x72,0x72,0x6f,0x72,1,0x65,0x38,0x69,0x16,0x6e,0x67,0x67,0x6c,0x79,0x70,0x68, -0xd9,0x40,1,0x10,0x64,0x27,0x17,0x73,0x69,0x63,0x65,0x6d,0x6f,0x6a,0x69,0xa3, -0x41,6,0x68,0x7c,0x68,0x54,0x69,0x85,0x6f,0xa2,0x6f,0x77,4,0x63,0x30,0x6b, -0x36,0x6c,0x87,0x74,0x8b,0x75,0x89,1,0x66,0x8d,0x6d,0x8f,0x11,0x63,0x66,0x91, -0x18,0x61,0x6e,0x67,0x65,0x73,0x77,0x68,0x65,0x6e,4,0x63,0x44,0x6c,0x6c,0x6e, -0x7e,0x74,0x98,0x75,0x18,0x70,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x64,0x89,0x12, -0x61,0x73,0x65,1,0x66,0x30,0x6d,0x14,0x61,0x70,0x70,0x65,0x64,0x8f,0x14,0x6f, -0x6c,0x64,0x65,0x64,0x8d,0x18,0x6f,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x64,0x87, -0x1c,0x66,0x6b,0x63,0x63,0x61,0x73,0x65,0x66,0x6f,0x6c,0x64,0x65,0x64,0x91,0x18, -0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x64,0x8b,0x13,0x6d,0x70,0x65,0x78,0x33, -0x61,0x2e,0x63,0xa2,0x48,0x66,0xd9,0x40,2,1,0x6e,0x72,0x73,0x10,0x65,3, -0x64,0x83,0x66,0x3a,0x69,0x4a,0x73,0x17,0x65,0x6e,0x73,0x69,0x74,0x69,0x76,0x65, -0x65,0x15,0x6f,0x6c,0x64,0x69,0x6e,0x67,0xd9,0x40,2,0x17,0x67,0x6e,0x6f,0x72, -0x61,0x62,0x6c,0x65,0x85,0x13,0x6f,0x6e,0x69,0x63,0x1f,0x61,0x6c,0x63,0x6f,0x6d, -0x62,0x69,0x6e,0x69,0x6e,0x67,0x63,0x6c,0x61,0x73,0x73,0xc3,2,0x10,0x63,0xc3, -2,3,0x61,0x30,0x65,0x34,0x69,0xa2,0x41,0x74,0xc3,3,0x11,0x73,0x68,0x29, -2,0x63,0x3a,0x66,0x58,0x70,0x2c,0x16,0x72,0x65,0x63,0x61,0x74,0x65,0x64,0x2d, -0x1d,0x6f,0x6d,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x74,0x79,0x70,0x65,0xc3, -3,0x15,0x61,0x75,0x6c,0x74,0x69,0x67,0x1f,0x6e,0x6f,0x72,0x61,0x62,0x6c,0x65, -0x63,0x6f,0x64,0x65,0x70,0x6f,0x69,0x6e,0x74,0x2b,0x2a,0x10,0x61,0x2e,0x15,0x63, -0x72,0x69,0x74,0x69,0x63,0x2f,3,0x66,0x34,0x6e,0x3e,0x74,0x42,0x79,0x22,0x11, -0x65,0x73,0x23,0x20,0x13,0x61,0x6c,0x73,0x65,0x21,0x20,0x10,0x6f,0x21,0x22,0x12, -0x72,0x75,0x65,0x23,0xb,0x6b,0x5b,0x6f,0x23,0x6f,0x3c,0x72,0x4c,0x76,1,0x69, -0x24,0x72,0x33,0x13,0x72,0x61,0x6d,0x61,0x33,0x10,0x76,0x22,0x14,0x65,0x72,0x6c, -0x61,0x79,0x23,0xa2,0xe2,0x13,0x69,0x67,0x68,0x74,0xa3,0xe2,0x6b,0x58,0x6c,0x74, -0x6e,3,0x6b,0x2f,0x6f,0x30,0x72,0x21,0x75,0x12,0x6b,0x74,0x61,0x2f,0x19,0x74, -0x72,0x65,0x6f,0x72,0x64,0x65,0x72,0x65,0x64,0x21,1,0x61,0x24,0x76,0x31,0x18, -0x6e,0x61,0x76,0x6f,0x69,0x63,0x69,0x6e,0x67,0x31,0xa2,0xe0,0x12,0x65,0x66,0x74, -0xa3,0xe0,0x64,0x45,0x64,0x4e,0x68,0x88,0x69,1,0x6f,0x26,0x73,0xa3,0xf0,0x1a, -0x74,0x61,0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0xa3,0xf0,2,0x61,0xa3, -0xea,0x62,0xa3,0xe9,0x6f,0x13,0x75,0x62,0x6c,0x65,1,0x61,0x30,0x62,0x13,0x65, -0x6c,0x6f,0x77,0xa3,0xe9,0x13,0x62,0x6f,0x76,0x65,0xa3,0xea,0x12,0x61,0x6e,0x72, -0x2c,0x15,0x65,0x61,0x64,0x69,0x6e,0x67,0x2d,0x61,0xa2,0x7b,0x62,0xa2,0xd4,0x63, -0x11,0x63,0x63,4,0x31,0x3c,0x32,0xa2,0x42,0x33,0xa2,0x56,0x38,0xa2,0x64,0x39, -0x10,0x31,0xa3,0x5b,9,0x35,0xa,0x35,0x3f,0x36,0x41,0x37,0x43,0x38,0x45,0x39, -0x47,0x30,0x30,0x31,0x3c,0x32,0x42,0x33,0x4e,0x34,0x3d,0x34,1,0x33,0xa3,0x67, -0x37,0xa3,0x6b,0x36,0x10,0x38,0xa3,0x76,0x38,1,0x32,0xa3,0x7a,0x39,0xa3,0x81, -0x3a,2,0x30,0xa3,0x82,0x32,0xa3,0x84,0x33,0xa3,0x85,9,0x35,0xa,0x35,0x53, -0x36,0x55,0x37,0x57,0x38,0x59,0x39,0x5b,0x30,0x49,0x31,0x4b,0x32,0x4d,0x33,0x4f, -0x34,0x51,6,0x33,8,0x33,0x63,0x34,0x65,0x35,0x67,0x36,0x69,0x30,0x5d,0x31, -0x5f,0x32,0x61,0x10,0x34,0xa3,0x54,0xa2,0xe6,3,0x62,0xa0,0x6c,0xa3,0xe4,0x72, -0xa3,0xe8,0x74,2,0x61,0x74,0x62,0x7c,0x74,0x14,0x61,0x63,0x68,0x65,0x64,1, -0x61,0x3e,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa2,0xca,0x13,0x6c,0x65,0x66,0x74,0xa3, -0xc8,0x13,0x62,0x6f,0x76,0x65,0xa2,0xd6,0x14,0x72,0x69,0x67,0x68,0x74,0xa3,0xd8, -0xa2,0xd6,0x10,0x72,0xa3,0xd8,0xa2,0xca,0x10,0x6c,0xa3,0xc8,0x12,0x6f,0x76,0x65, -0xa2,0xe6,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xe8,0x12,0x65,0x66, -0x74,0xa3,0xe4,0xa2,0xdc,2,0x65,0x2c,0x6c,0xa3,0xda,0x72,0xa3,0xde,0x12,0x6c, -0x6f,0x77,0xa2,0xdc,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xde,0x12, -0x65,0x66,0x74,0xa3,0xda,0xb,0x6e,0xc0,0xca,0x72,0x5f,0x72,0x46,0x73,0xa2,0x48, -0x77,1,0x68,0x24,0x73,0x33,0x17,0x69,0x74,0x65,0x73,0x70,0x61,0x63,0x65,0x33, -0x22,1,0x69,0x30,0x6c,2,0x65,0x3d,0x69,0x4b,0x6f,0x3f,0x18,0x67,0x68,0x74, -0x74,0x6f,0x6c,0x65,0x66,0x74,0x22,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65, -0x72,0x72,0x69,0x64,0x65,0x3f,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x3d, -0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4b,0x30,0x1e,0x65,0x67,0x6d,0x65,0x6e,0x74, -0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x31,0x6e,0xa2,0x41,0x6f,0xa2,0x53, -0x70,2,0x61,0x66,0x64,0x86,0x6f,0x1b,0x70,0x64,0x69,0x72,0x65,0x63,0x74,0x69, -0x6f,0x6e,0x61,0x6c,1,0x66,0x32,0x69,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4d, -0x14,0x6f,0x72,0x6d,0x61,0x74,0x41,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73, -0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2f,1,0x66,0x41,0x69,0x4d,1,0x6f, -0x28,0x73,0x10,0x6d,0x43,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61, -0x72,0x6b,0x43,1,0x6e,0x35,0x74,0x19,0x68,0x65,0x72,0x6e,0x65,0x75,0x74,0x72, -0x61,0x6c,0x35,0x65,0x88,0x65,0x98,0x66,0xa2,0x6a,0x6c,0x20,1,0x65,0x30,0x72, -2,0x65,0x37,0x69,0x49,0x6f,0x39,0x18,0x66,0x74,0x74,0x6f,0x72,0x69,0x67,0x68, -0x74,0x20,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65, -0x39,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x37,0x15,0x73,0x6f,0x6c,0x61, -0x74,0x65,0x49,3,0x6e,0x25,0x73,0x27,0x74,0x29,0x75,0x15,0x72,0x6f,0x70,0x65, -0x61,0x6e,2,0x6e,0x3c,0x73,0x46,0x74,0x18,0x65,0x72,0x6d,0x69,0x6e,0x61,0x74, -0x6f,0x72,0x29,0x14,0x75,0x6d,0x62,0x65,0x72,0x25,0x17,0x65,0x70,0x61,0x72,0x61, -0x74,0x6f,0x72,0x27,1,0x69,0x28,0x73,0x10,0x69,0x47,0x1f,0x72,0x73,0x74,0x73, -0x74,0x72,0x6f,0x6e,0x67,0x69,0x73,0x6f,0x6c,0x61,0x74,0x65,0x47,0x61,0x4e,0x62, -0x84,0x63,1,0x6f,0x24,0x73,0x2d,0x1c,0x6d,0x6d,0x6f,0x6e,0x73,0x65,0x70,0x61, -0x72,0x61,0x74,0x6f,0x72,0x2d,2,0x6c,0x3b,0x6e,0x2b,0x72,0x13,0x61,0x62,0x69, -0x63,1,0x6c,0x30,0x6e,0x14,0x75,0x6d,0x62,0x65,0x72,0x2b,0x14,0x65,0x74,0x74, -0x65,0x72,0x3b,0x2e,1,0x6e,0x45,0x6f,0x1c,0x75,0x6e,0x64,0x61,0x72,0x79,0x6e, -0x65,0x75,0x74,0x72,0x61,0x6c,0x45,0,0x16,0x6d,0xc9,0x20,0x74,0xc2,0x30,0x77, -0x89,0x77,0x86,0x79,0xa2,0x46,0x7a,1,0x61,0x58,0x6e,0x1a,0x61,0x6d,0x65,0x6e, -0x6e,0x79,0x6d,0x75,0x73,0x69,0x63,0xa4,0x40,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61, -0x74,0x69,0x6f,0x6e,0xa5,0x40,0x1c,0x6e,0x61,0x62,0x61,0x7a,0x61,0x72,0x73,0x71, -0x75,0x61,0x72,0x65,0xa5,0x18,0x10,0x61,1,0x6e,0x36,0x72,0x16,0x61,0x6e,0x67, -0x63,0x69,0x74,0x69,0xa3,0xfc,0x12,0x63,0x68,0x6f,0xa5,0x2c,1,0x65,0x88,0x69, -2,0x6a,0x3c,0x72,0x68,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3, -0x48,0x12,0x69,0x6e,0x67,0xa2,0x74,0x1e,0x68,0x65,0x78,0x61,0x67,0x72,0x61,0x6d, -0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x74,0x16,0x61,0x64,0x69,0x63,0x61,0x6c, -0x73,0xa3,0x49,0x13,0x7a,0x69,0x64,0x69,0xa5,0x34,0x74,0xa2,0x65,0x75,0xa4,0x4f, -0x76,3,0x61,0x3c,0x65,0x80,0x69,0xa2,0x50,0x73,0xa2,0x6c,0x12,0x73,0x75,0x70, -0xa3,0x7d,1,0x69,0xa3,0x9f,0x72,0x1e,0x69,0x61,0x74,0x69,0x6f,0x6e,0x73,0x65, -0x6c,0x65,0x63,0x74,0x6f,0x72,0x73,0xa2,0x6c,0x19,0x73,0x75,0x70,0x70,0x6c,0x65, -0x6d,0x65,0x6e,0x74,0xa3,0x7d,1,0x64,0x3c,0x72,0x19,0x74,0x69,0x63,0x61,0x6c, -0x66,0x6f,0x72,0x6d,0x73,0xa3,0x91,0x14,0x69,0x63,0x65,0x78,0x74,0xa2,0xaf,0x16, -0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xaf,0x15,0x74,0x68,0x6b,0x75,0x71,0x69, -0xa5,0x3f,5,0x69,0x3f,0x69,0x5a,0x6f,0x8c,0x72,0x1c,0x61,0x6e,0x73,0x70,0x6f, +0x61,0x6b,0xc3,8,2,0x64,0x4a,0x6e,0xa2,0xbd,0x73,1,0x63,0xd9,0x40,3, +0x6f,0x16,0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0xd9,0x40,3,3,0x63,0x3a,0x65, +0x8c,0x73,0xa2,0x5b,0x74,0x12,0x79,0x70,0x65,0xd9,0x70,1,0x3e,0x10,0x6f,1, +0x6d,0x30,0x6e,0x14,0x74,0x69,0x6e,0x75,0x65,0x3f,0x16,0x70,0x61,0x74,0x6d,0x61, +0x74,0x68,1,0x63,0x30,0x73,0x13,0x74,0x61,0x72,0x74,0xa3,0x49,0x16,0x6f,0x6e, +0x74,0x69,0x6e,0x75,0x65,0xa3,0x4a,1,0x6e,0x36,0x6f,0x42,0x16,0x67,0x72,0x61, +0x70,0x68,0x69,0x63,0x43,0x15,0x74,0x69,0x66,0x69,0x65,0x72,1,0x73,0x30,0x74, +0x12,0x79,0x70,0x65,0xd9,0x70,1,0x14,0x74,0x61,0x74,0x75,0x73,0xc3,0x19,0x40, +2,0x62,0x48,0x74,0x64,0x75,0xa2,0x48,0x1b,0x6e,0x61,0x72,0x79,0x6f,0x70,0x65, +0x72,0x61,0x74,0x6f,0x72,0xa3,0x48,0x44,0x1c,0x69,0x6e,0x61,0x72,0x79,0x6f,0x70, +0x65,0x72,0x61,0x74,0x6f,0x72,0x45,0x46,1,0x61,0x40,0x72,0x1c,0x69,0x6e,0x61, +0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x47,1,0x72,0x2c,0x74,0x11, +0x75,0x73,0xc3,0x19,0x10,0x74,0x41,3,0x63,0x34,0x64,0x38,0x70,0xa2,0x48,0x73, +0x10,0x63,0xc3,0x17,0x10,0x62,0xc3,0x1a,0x11,0x69,0x63,2,0x63,0x4a,0x70,0x64, +0x73,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x63,0x61,0x74,0x65,0x67,0x6f,0x72, +0x79,0xc3,0x17,0x1b,0x6f,0x6e,0x6a,0x75,0x6e,0x63,0x74,0x62,0x72,0x65,0x61,0x6b, +0xc3,0x1a,0x10,0x6f,0x1f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x63,0x61,0x74, +0x65,0x67,0x6f,0x72,0x79,0xc3,0x16,0x10,0x63,0xc3,0x16,2,0x67,0xc3,6,0x6f, +0x26,0x74,0xc3,7,0x11,0x69,0x6e,1,0x63,0x4a,0x69,0x11,0x6e,0x67,1,0x67, +0x2e,0x74,0x12,0x79,0x70,0x65,0xc3,7,0x13,0x72,0x6f,0x75,0x70,0xc3,6,0x48, +0x15,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x49,0x66,0x86,0x67,0xa2,0x4a,0x68,3,0x61, +0x36,0x65,0x58,0x73,0x68,0x79,0x13,0x70,0x68,0x65,0x6e,0x3d,0x1f,0x6e,0x67,0x75, +0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x74,0x79,0x70,0x65,0xc3,0xb,0x10, +0x78,0x3a,0x14,0x64,0x69,0x67,0x69,0x74,0x3b,0x10,0x74,0xc3,0xb,0x16,0x75,0x6c, +0x6c,0x63,0x6f,0x6d,0x70,0x1f,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x65,0x78,0x63, +0x6c,0x75,0x73,0x69,0x6f,0x6e,0x33,2,0x63,0xa2,0x44,0x65,0xa2,0x4b,0x72,3, +0x61,0x34,0x62,0x84,0x65,0x8a,0x6c,0x12,0x69,0x6e,0x6b,0x39,0x11,0x70,0x68,0x7c, +0x12,0x65,0x6d,0x65,3,0x62,0x5e,0x63,0x30,0x65,0x48,0x6c,0x12,0x69,0x6e,0x6b, +0x39,0x1a,0x6c,0x75,0x73,0x74,0x65,0x72,0x62,0x72,0x65,0x61,0x6b,0xc3,0x12,0x14, +0x78,0x74,0x65,0x6e,0x64,0x37,0x12,0x61,0x73,0x65,0x35,0x11,0x78,0x74,0x37,0xc2, +5,1,0x62,0xc3,0x12,0x6d,0xd9,0x20,0,0x1c,0x6e,0x65,0x72,0x61,0x6c,0x63, +0x61,0x74,0x65,0x67,0x6f,0x72,0x79,0xc2,5,0x13,0x6d,0x61,0x73,0x6b,0xd9,0x20, +0,0x61,0xa2,0xa2,0x62,0xa2,0xd0,0x63,0xa4,0x4f,0x64,0xa6,0x1c,0x65,5,0x6d, +0x75,0x6d,0x6e,0x70,0xa2,0x6b,0x78,0x10,0x74,0x30,1,0x65,0x2c,0x70,0x12,0x69, +0x63,0x74,0xa1,0x12,0x6e,0x64,0x65,1,0x64,0x24,0x72,0x31,0x1b,0x70,0x69,0x63, +0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0xa1,0x10,0x6f,1,0x64,0x97,0x6a, +0x10,0x69,0x92,3,0x63,0x44,0x6b,0x54,0x6d,0x70,0x70,0x1a,0x72,0x65,0x73,0x65, +0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x95,0x17,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e, +0x74,0x9b,0x1c,0x65,0x79,0x63,0x61,0x70,0x73,0x65,0x71,0x75,0x65,0x6e,0x63,0x65, +0xa3,0x42,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x96,0x13,0x62,0x61,0x73,0x65, +0x99,0x12,0x72,0x65,0x73,0x95,0x61,0x30,0x62,0x4e,0x63,0x12,0x6f,0x6d,0x70,0x9b, +0xc2,4,0x1b,0x73,0x74,0x61,0x73,0x69,0x61,0x6e,0x77,0x69,0x64,0x74,0x68,0xc3, +4,0x12,0x61,0x73,0x65,0x99,3,0x67,0x44,0x68,0x4a,0x6c,0x4e,0x73,0x1a,0x63, +0x69,0x69,0x68,0x65,0x78,0x64,0x69,0x67,0x69,0x74,0x23,0x10,0x65,0xd9,0x40,0, +0x11,0x65,0x78,0x23,1,0x6e,0x38,0x70,0x11,0x68,0x61,0x20,0x14,0x62,0x65,0x74, +0x69,0x63,0x21,0x11,0x75,0x6d,0x79,5,0x6c,0x22,0x6c,0x36,0x6d,0x52,0x70,1, +0x62,0xd9,0x40,0xd,0x74,0xc3,0x15,2,0x61,0x32,0x6b,0xc3,1,0x6f,0x11,0x63, +0x6b,0xc3,1,0x11,0x6e,0x6b,0x7b,0x10,0x67,0xd9,0x40,1,0x61,0xa2,0x4f,0x63, +0xc3,0,0x69,0x11,0x64,0x69,2,0x63,0x54,0x6d,0x74,0x70,0x1b,0x61,0x69,0x72, +0x65,0x64,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0xd8,0x40,0xd,0x13,0x74,0x79,0x70, +0x65,0xc3,0x15,0x24,1,0x6c,0x30,0x6f,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x25,0x12, +0x61,0x73,0x73,0xc3,0,0x26,0x14,0x69,0x72,0x72,0x6f,0x72,1,0x65,0x38,0x69, +0x16,0x6e,0x67,0x67,0x6c,0x79,0x70,0x68,0xd9,0x40,1,0x10,0x64,0x27,0x17,0x73, +0x69,0x63,0x65,0x6d,0x6f,0x6a,0x69,0xa3,0x41,6,0x68,0x7c,0x68,0x54,0x69,0x85, +0x6f,0xa2,0x6f,0x77,4,0x63,0x30,0x6b,0x36,0x6c,0x87,0x74,0x8b,0x75,0x89,1, +0x66,0x8d,0x6d,0x8f,0x11,0x63,0x66,0x91,0x18,0x61,0x6e,0x67,0x65,0x73,0x77,0x68, +0x65,0x6e,4,0x63,0x44,0x6c,0x6c,0x6e,0x7e,0x74,0x98,0x75,0x18,0x70,0x70,0x65, +0x72,0x63,0x61,0x73,0x65,0x64,0x89,0x12,0x61,0x73,0x65,1,0x66,0x30,0x6d,0x14, +0x61,0x70,0x70,0x65,0x64,0x8f,0x14,0x6f,0x6c,0x64,0x65,0x64,0x8d,0x18,0x6f,0x77, +0x65,0x72,0x63,0x61,0x73,0x65,0x64,0x87,0x1c,0x66,0x6b,0x63,0x63,0x61,0x73,0x65, +0x66,0x6f,0x6c,0x64,0x65,0x64,0x91,0x18,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65, +0x64,0x8b,0x13,0x6d,0x70,0x65,0x78,0x33,0x61,0x2e,0x63,0xa2,0x48,0x66,0xd9,0x40, +2,1,0x6e,0x72,0x73,0x10,0x65,3,0x64,0x83,0x66,0x3a,0x69,0x4a,0x73,0x17, +0x65,0x6e,0x73,0x69,0x74,0x69,0x76,0x65,0x65,0x15,0x6f,0x6c,0x64,0x69,0x6e,0x67, +0xd9,0x40,2,0x17,0x67,0x6e,0x6f,0x72,0x61,0x62,0x6c,0x65,0x85,0x13,0x6f,0x6e, +0x69,0x63,0x1f,0x61,0x6c,0x63,0x6f,0x6d,0x62,0x69,0x6e,0x69,0x6e,0x67,0x63,0x6c, +0x61,0x73,0x73,0xc3,2,0x10,0x63,0xc3,2,3,0x61,0x30,0x65,0x34,0x69,0xa2, +0x41,0x74,0xc3,3,0x11,0x73,0x68,0x29,2,0x63,0x3a,0x66,0x58,0x70,0x2c,0x16, +0x72,0x65,0x63,0x61,0x74,0x65,0x64,0x2d,0x1d,0x6f,0x6d,0x70,0x6f,0x73,0x69,0x74, +0x69,0x6f,0x6e,0x74,0x79,0x70,0x65,0xc3,3,0x15,0x61,0x75,0x6c,0x74,0x69,0x67, +0x1f,0x6e,0x6f,0x72,0x61,0x62,0x6c,0x65,0x63,0x6f,0x64,0x65,0x70,0x6f,0x69,0x6e, +0x74,0x2b,0x2a,0x10,0x61,0x2e,0x15,0x63,0x72,0x69,0x74,0x69,0x63,0x2f,3,0x66, +0x34,0x6e,0x3e,0x74,0x42,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x13,0x61,0x6c,0x73, +0x65,0x21,0x20,0x10,0x6f,0x21,0x22,0x12,0x72,0x75,0x65,0x23,0xb,0x6b,0x5b,0x6f, +0x23,0x6f,0x3c,0x72,0x4c,0x76,1,0x69,0x24,0x72,0x33,0x13,0x72,0x61,0x6d,0x61, +0x33,0x10,0x76,0x22,0x14,0x65,0x72,0x6c,0x61,0x79,0x23,0xa2,0xe2,0x13,0x69,0x67, +0x68,0x74,0xa3,0xe2,0x6b,0x58,0x6c,0x74,0x6e,3,0x6b,0x2f,0x6f,0x30,0x72,0x21, +0x75,0x12,0x6b,0x74,0x61,0x2f,0x19,0x74,0x72,0x65,0x6f,0x72,0x64,0x65,0x72,0x65, +0x64,0x21,1,0x61,0x24,0x76,0x31,0x18,0x6e,0x61,0x76,0x6f,0x69,0x63,0x69,0x6e, +0x67,0x31,0xa2,0xe0,0x12,0x65,0x66,0x74,0xa3,0xe0,0x64,0x45,0x64,0x4e,0x68,0x88, +0x69,1,0x6f,0x26,0x73,0xa3,0xf0,0x1a,0x74,0x61,0x73,0x75,0x62,0x73,0x63,0x72, +0x69,0x70,0x74,0xa3,0xf0,2,0x61,0xa3,0xea,0x62,0xa3,0xe9,0x6f,0x13,0x75,0x62, +0x6c,0x65,1,0x61,0x30,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa3,0xe9,0x13,0x62,0x6f, +0x76,0x65,0xa3,0xea,0x12,0x61,0x6e,0x72,0x2c,0x15,0x65,0x61,0x64,0x69,0x6e,0x67, +0x2d,0x61,0xa2,0x7b,0x62,0xa2,0xd4,0x63,0x11,0x63,0x63,4,0x31,0x3c,0x32,0xa2, +0x42,0x33,0xa2,0x56,0x38,0xa2,0x64,0x39,0x10,0x31,0xa3,0x5b,9,0x35,0xa,0x35, +0x3f,0x36,0x41,0x37,0x43,0x38,0x45,0x39,0x47,0x30,0x30,0x31,0x3c,0x32,0x42,0x33, +0x4e,0x34,0x3d,0x34,1,0x33,0xa3,0x67,0x37,0xa3,0x6b,0x36,0x10,0x38,0xa3,0x76, +0x38,1,0x32,0xa3,0x7a,0x39,0xa3,0x81,0x3a,2,0x30,0xa3,0x82,0x32,0xa3,0x84, +0x33,0xa3,0x85,9,0x35,0xa,0x35,0x53,0x36,0x55,0x37,0x57,0x38,0x59,0x39,0x5b, +0x30,0x49,0x31,0x4b,0x32,0x4d,0x33,0x4f,0x34,0x51,6,0x33,8,0x33,0x63,0x34, +0x65,0x35,0x67,0x36,0x69,0x30,0x5d,0x31,0x5f,0x32,0x61,0x10,0x34,0xa3,0x54,0xa2, +0xe6,3,0x62,0xa0,0x6c,0xa3,0xe4,0x72,0xa3,0xe8,0x74,2,0x61,0x74,0x62,0x7c, +0x74,0x14,0x61,0x63,0x68,0x65,0x64,1,0x61,0x3e,0x62,0x13,0x65,0x6c,0x6f,0x77, +0xa2,0xca,0x13,0x6c,0x65,0x66,0x74,0xa3,0xc8,0x13,0x62,0x6f,0x76,0x65,0xa2,0xd6, +0x14,0x72,0x69,0x67,0x68,0x74,0xa3,0xd8,0xa2,0xd6,0x10,0x72,0xa3,0xd8,0xa2,0xca, +0x10,0x6c,0xa3,0xc8,0x12,0x6f,0x76,0x65,0xa2,0xe6,1,0x6c,0x30,0x72,0x13,0x69, +0x67,0x68,0x74,0xa3,0xe8,0x12,0x65,0x66,0x74,0xa3,0xe4,0xa2,0xdc,2,0x65,0x2c, +0x6c,0xa3,0xda,0x72,0xa3,0xde,0x12,0x6c,0x6f,0x77,0xa2,0xdc,1,0x6c,0x30,0x72, +0x13,0x69,0x67,0x68,0x74,0xa3,0xde,0x12,0x65,0x66,0x74,0xa3,0xda,0xb,0x6e,0xc0, +0xca,0x72,0x5f,0x72,0x46,0x73,0xa2,0x48,0x77,1,0x68,0x24,0x73,0x33,0x17,0x69, +0x74,0x65,0x73,0x70,0x61,0x63,0x65,0x33,0x22,1,0x69,0x30,0x6c,2,0x65,0x3d, +0x69,0x4b,0x6f,0x3f,0x18,0x67,0x68,0x74,0x74,0x6f,0x6c,0x65,0x66,0x74,0x22,2, +0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65,0x3f,0x17,0x6d, +0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x3d,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4b, +0x30,0x1e,0x65,0x67,0x6d,0x65,0x6e,0x74,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f, +0x72,0x31,0x6e,0xa2,0x41,0x6f,0xa2,0x53,0x70,2,0x61,0x66,0x64,0x86,0x6f,0x1b, +0x70,0x64,0x69,0x72,0x65,0x63,0x74,0x69,0x6f,0x6e,0x61,0x6c,1,0x66,0x32,0x69, +0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4d,0x14,0x6f,0x72,0x6d,0x61,0x74,0x41,0x1f, +0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, +0x2f,1,0x66,0x41,0x69,0x4d,1,0x6f,0x28,0x73,0x10,0x6d,0x43,0x1b,0x6e,0x73, +0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x43,1,0x6e,0x35,0x74,0x19, +0x68,0x65,0x72,0x6e,0x65,0x75,0x74,0x72,0x61,0x6c,0x35,0x65,0x88,0x65,0x98,0x66, +0xa2,0x6a,0x6c,0x20,1,0x65,0x30,0x72,2,0x65,0x37,0x69,0x49,0x6f,0x39,0x18, +0x66,0x74,0x74,0x6f,0x72,0x69,0x67,0x68,0x74,0x20,2,0x65,0x38,0x69,0x48,0x6f, +0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65,0x39,0x17,0x6d,0x62,0x65,0x64,0x64,0x69, +0x6e,0x67,0x37,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x49,3,0x6e,0x25,0x73,0x27, +0x74,0x29,0x75,0x15,0x72,0x6f,0x70,0x65,0x61,0x6e,2,0x6e,0x3c,0x73,0x46,0x74, +0x18,0x65,0x72,0x6d,0x69,0x6e,0x61,0x74,0x6f,0x72,0x29,0x14,0x75,0x6d,0x62,0x65, +0x72,0x25,0x17,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x27,1,0x69,0x28,0x73, +0x10,0x69,0x47,0x1f,0x72,0x73,0x74,0x73,0x74,0x72,0x6f,0x6e,0x67,0x69,0x73,0x6f, +0x6c,0x61,0x74,0x65,0x47,0x61,0x4e,0x62,0x84,0x63,1,0x6f,0x24,0x73,0x2d,0x1c, +0x6d,0x6d,0x6f,0x6e,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2d,2,0x6c, +0x3b,0x6e,0x2b,0x72,0x13,0x61,0x62,0x69,0x63,1,0x6c,0x30,0x6e,0x14,0x75,0x6d, +0x62,0x65,0x72,0x2b,0x14,0x65,0x74,0x74,0x65,0x72,0x3b,0x2e,1,0x6e,0x45,0x6f, +0x1c,0x75,0x6e,0x64,0x61,0x72,0x79,0x6e,0x65,0x75,0x74,0x72,0x61,0x6c,0x45,0, +0x16,0x6d,0xc9,0x5e,0x74,0xc2,0x48,0x77,0x89,0x77,0x86,0x79,0xa2,0x46,0x7a,1, +0x61,0x58,0x6e,0x1a,0x61,0x6d,0x65,0x6e,0x6e,0x79,0x6d,0x75,0x73,0x69,0x63,0xa4, +0x40,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa5,0x40,0x1c,0x6e, +0x61,0x62,0x61,0x7a,0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa5,0x18,0x10,0x61, +1,0x6e,0x36,0x72,0x16,0x61,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0xfc,0x12,0x63, +0x68,0x6f,0xa5,0x2c,1,0x65,0x88,0x69,2,0x6a,0x3c,0x72,0x68,0x73,0x17,0x79, +0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3,0x48,0x12,0x69,0x6e,0x67,0xa2,0x74,0x1e, +0x68,0x65,0x78,0x61,0x67,0x72,0x61,0x6d,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3, +0x74,0x16,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0xa3,0x49,0x13,0x7a,0x69,0x64,0x69, +0xa5,0x34,0x74,0xa2,0x65,0x75,0xa4,0x67,0x76,3,0x61,0x3c,0x65,0x80,0x69,0xa2, +0x50,0x73,0xa2,0x6c,0x12,0x73,0x75,0x70,0xa3,0x7d,1,0x69,0xa3,0x9f,0x72,0x1e, +0x69,0x61,0x74,0x69,0x6f,0x6e,0x73,0x65,0x6c,0x65,0x63,0x74,0x6f,0x72,0x73,0xa2, +0x6c,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x7d,1,0x64, +0x3c,0x72,0x19,0x74,0x69,0x63,0x61,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x91,0x14, +0x69,0x63,0x65,0x78,0x74,0xa2,0xaf,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3, +0xaf,0x15,0x74,0x68,0x6b,0x75,0x71,0x69,0xa5,0x3f,6,0x69,0x57,0x69,0x44,0x6f, +0x76,0x72,0x8e,0x75,0x19,0x6c,0x75,0x74,0x69,0x67,0x61,0x6c,0x61,0x72,0x69,0xa5, +0x52,2,0x62,0x34,0x66,0x3c,0x72,0x13,0x68,0x75,0x74,0x61,0xa3,0xfb,0x13,0x65, +0x74,0x61,0x6e,0x57,0x14,0x69,0x6e,0x61,0x67,0x68,0xa3,0x90,1,0x64,0x2a,0x74, +0x10,0x6f,0xa5,0x3d,0x12,0x68,0x72,0x69,0xa5,0x51,0x1c,0x61,0x6e,0x73,0x70,0x6f, 0x72,0x74,0x61,0x6e,0x64,0x6d,0x61,0x70,0xa2,0xcf,0x16,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0xa3,0xcf,2,0x62,0x34,0x66,0x3c,0x72,0x13,0x68,0x75,0x74,0x61,0xa3, -0xfb,0x13,0x65,0x74,0x61,0x6e,0x57,0x14,0x69,0x6e,0x61,0x67,0x68,0xa3,0x90,0x11, -0x74,0x6f,0xa5,0x3d,0x61,0x3e,0x65,0xa2,0xa0,0x68,0x10,0x61,1,0x61,0x24,0x69, +0x6c,0x73,0xa3,0xcf,0x61,0x3e,0x65,0xa2,0xa0,0x68,0x10,0x61,1,0x61,0x24,0x69, 0x53,0x11,0x6e,0x61,0x3d,4,0x67,0x8e,0x69,0xa2,0x49,0x6b,0xa2,0x72,0x6d,0xa2, 0x74,0x6e,0x10,0x67,1,0x73,0x68,0x75,0x10,0x74,0xa4,0x10,1,0x63,0x40,0x73, 0x11,0x75,0x70,0xa4,0x33,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x33,0x18, @@ -336,518 +344,528 @@ const uint8_t PropNameData::bytesTries[15733]={ 0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x62,0x17,0x65,0x78,0x74,0x65,0x6e,0x64, 0x65,0x64,0xa2,0xad,0x10,0x61,0xa5,0x3e,0x11,0x61,0x73,0x62,0x12,0x65,0x78,0x74, 0xa2,0xad,0x10,0x61,0xa5,0x3e,0x15,0x61,0x72,0x69,0x74,0x69,0x63,0xa3,0x78,0x70, -0xc3,0x4b,0x70,0xa6,0x61,0x72,0xa8,0x1d,0x73,7,0x6f,0xc1,0xbe,0x6f,0xa2,0x69, -0x70,0xa2,0x85,0x75,0xa2,0xa4,0x79,2,0x6c,0x50,0x6d,0x62,0x72,0x12,0x69,0x61, +0xc3,0x64,0x70,0xa6,0x7a,0x72,0xa8,0x36,0x73,7,0x6f,0xc1,0xd7,0x6f,0xa2,0x79, +0x70,0xa2,0x95,0x75,0xa2,0xb4,0x79,2,0x6c,0x50,0x6d,0x62,0x72,0x12,0x69,0x61, 0x63,0x3a,0x12,0x73,0x75,0x70,0xa4,0x17,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, 0xa5,0x17,0x17,0x6f,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0xa3,0x8f,0x13,0x62,0x6f, -0x6c,0x73,1,0x61,0x4c,0x66,0x10,0x6f,0x1f,0x72,0x6c,0x65,0x67,0x61,0x63,0x79, -0x63,0x6f,0x6d,0x70,0x75,0x74,0x69,0x6e,0x67,0xa5,0x32,0x1f,0x6e,0x64,0x70,0x69, +0x6c,0x73,1,0x61,0x6c,0x66,0x10,0x6f,0x1f,0x72,0x6c,0x65,0x67,0x61,0x63,0x79, +0x63,0x6f,0x6d,0x70,0x75,0x74,0x69,0x6e,0x67,0xa4,0x32,0x12,0x73,0x75,0x70,0xa4, +0x50,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x50,0x1f,0x6e,0x64,0x70,0x69, 0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x78,0x74,1,0x61,0xa5,0x2a, 0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa5,0x2a,2,0x67,0x34,0x72,0x3e,0x79,0x13, 0x6f,0x6d,0x62,0x6f,0xa5,0x16,0x13,0x64,0x69,0x61,0x6e,0xa5,0x23,0x17,0x61,0x73, 0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0xda,1,0x61,0x32,0x65,0x14,0x63,0x69,0x61, 0x6c,0x73,0xa3,0x56,0x12,0x63,0x69,0x6e,0x1f,0x67,0x6d,0x6f,0x64,0x69,0x66,0x69, -0x65,0x72,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,2,0x6e,0x48,0x70,0x76,0x74, +0x65,0x72,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,2,0x6e,0x48,0x70,0x88,0x74, 0x1d,0x74,0x6f,0x6e,0x73,0x69,0x67,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa5, -6,0x15,0x64,0x61,0x6e,0x65,0x73,0x65,0xa2,0x9b,0x12,0x73,0x75,0x70,0xa2,0xdb, -0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xdb,4,0x61,0xa2,0xa8,0x65,0x5c, -0x6d,0x9e,0x70,0xa2,0x4b,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e, -0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x10,0x72, -1,0x61,0x4e,0x73,0x12,0x63,0x72,0x69,0x1f,0x70,0x74,0x73,0x61,0x6e,0x64,0x73, -0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0x73,0x73,0x14,0x6e,0x64,0x73,0x75,0x62, -0x73,0x1b,0x61,0x74,0x68,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a, -1,0x6c,0x40,0x75,1,0x61,0x6e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0xa3,0x8e,0x15,0x65,0x6d,0x65,0x6e,0x74,0x61,1,0x6c,0x50,0x72,0x1e,0x79, -0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x61,0x72,0x65,0x61,1,0x61, -0xa3,0x6d,0x62,0xa3,0x6e,3,0x61,0x5c,0x6d,0x78,0x70,0xa2,0x41,0x73,0x13,0x79, -0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72, -0x61,0x70,0x68,0x73,0xa5,5,0x14,0x72,0x72,0x6f,0x77,0x73,2,0x61,0xa3,0x67, -0x62,0xa3,0x68,0x63,0xa3,0xfa,0x13,0x61,0x74,0x68,0x65,0x1f,0x6d,0x61,0x74,0x69, -0x63,0x61,0x6c,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,0x19,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x61,0x88,0x68,0xa2,0x48, -0x69,0xa2,0x71,0x6d,0x12,0x61,0x6c,0x6c,1,0x66,0x46,0x6b,0x15,0x61,0x6e,0x61, -0x65,0x78,0x74,0xa4,0x29,0x15,0x65,0x6e,0x73,0x69,0x6f,0x6e,0xa5,0x29,0x12,0x6f, -0x72,0x6d,1,0x73,0xa3,0x54,0x76,0x16,0x61,0x72,0x69,0x61,0x6e,0x74,0x73,0xa3, -0x54,1,0x6d,0x36,0x75,0x16,0x72,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0xa1,0x15, -0x61,0x72,0x69,0x74,0x61,0x6e,0xa3,0xac,1,0x61,0x52,0x6f,0x13,0x72,0x74,0x68, -0x61,0x1f,0x6e,0x64,0x66,0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f, -0x6c,0x73,0xa3,0xf7,1,0x72,0x2e,0x76,0x12,0x69,0x61,0x6e,0xa3,0x79,0x12,0x61, -0x64,0x61,0xa3,0xd9,1,0x64,0x50,0x6e,0x13,0x68,0x61,0x6c,0x61,0x50,0x1d,0x61, -0x72,0x63,0x68,0x61,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xf9,0x13, -0x64,0x68,0x61,0x6d,0xa3,0xf8,5,0x72,0x35,0x72,0x44,0x73,0x64,0x75,1,0x61, -0xa3,0x4e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x69,0x76, -0x61,0x74,0x65,0x75,0x73,0x65,0xa2,0x4e,0x13,0x61,0x72,0x65,0x61,0xa3,0x4e,0x1b, -0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0xf6,0x61,0x40, -0x68,0x82,0x6c,0x19,0x61,0x79,0x69,0x6e,0x67,0x63,0x61,0x72,0x64,0x73,0xa3,0xcc, -2,0x68,0x38,0x6c,0x4a,0x75,0x15,0x63,0x69,0x6e,0x68,0x61,0x75,0xa3,0xf5,0x17, -0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xf3,0x15,0x6d,0x79,0x72,0x65,0x6e, -0x65,0xa3,0xf4,1,0x61,0x8e,0x6f,1,0x65,0x74,0x6e,0x16,0x65,0x74,0x69,0x63, -0x65,0x78,0x74,0xa2,0x72,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0x8d,0x15,0x6e, -0x73,0x69,0x6f,0x6e,0x73,0xa2,0x72,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa3,0x8d,0x15,0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x97,1,0x67,0x3e, -0x69,0x13,0x73,0x74,0x6f,0x73,0xa2,0xa6,0x13,0x64,0x69,0x73,0x63,0xa3,0xa6,0x12, -0x73,0x70,0x61,0xa3,0x96,1,0x65,0x5c,0x75,1,0x6d,0x2a,0x6e,0x11,0x69,0x63, -0x67,0x10,0x69,0xa2,0xc0,0x1d,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0x79,0x6d, -0x62,0x6f,0x6c,0x73,0xa3,0xc0,0x13,0x6a,0x61,0x6e,0x67,0xa3,0xa3,0x6d,0xa2,0xf0, -0x6e,0xa8,0x23,0x6f,6,0x70,0x63,0x70,0x56,0x72,0x8a,0x73,0xa2,0x4c,0x74,0x10, -0x74,0x1f,0x6f,0x6d,0x61,0x6e,0x73,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65, -0x72,0x73,0xa5,0x28,0x18,0x74,0x69,0x63,0x61,0x6c,0x63,0x68,0x61,0x72,0x1f,0x61, -0x63,0x74,0x65,0x72,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x74,0x69,0x6f,0x6e,0x85, -1,0x69,0x46,0x6e,0x1e,0x61,0x6d,0x65,0x6e,0x74,0x61,0x6c,0x64,0x69,0x6e,0x67, -0x62,0x61,0x74,0x73,0xa3,0xf2,0x11,0x79,0x61,0x47,1,0x61,0x30,0x6d,0x13,0x61, -0x6e,0x79,0x61,0xa3,0x7a,0x11,0x67,0x65,0xa5,0xf,0x63,0xa2,0x7b,0x67,0xa2,0x7b, -0x6c,1,0x63,0xa2,0x6c,0x64,6,0x70,0x42,0x70,0x3a,0x73,0x5a,0x74,0x88,0x75, -0x14,0x79,0x67,0x68,0x75,0x72,0xa5,0x3b,0x11,0x65,0x72,1,0x6d,0x2e,0x73,0x12, -0x69,0x61,0x6e,0xa3,0x8c,0x11,0x69,0x63,0xa3,0xf1,0x10,0x6f,1,0x67,0x3a,0x75, -0x18,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xbb,0x13,0x64,0x69,0x61, -0x6e,0xa5,0x22,0x14,0x75,0x72,0x6b,0x69,0x63,0xa3,0xbf,0x68,0x42,0x69,0x54,0x6e, -0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xf0,0x17,0x75, -0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa5,4,0x14,0x74,0x61,0x6c,0x69,0x63,0xa3, -0x58,0x13,0x68,0x69,0x6b,0x69,0xa3,0x9d,0x10,0x72,0x85,0x12,0x68,0x61,0x6d,0x65, -6,0x6f,0x86,0x6f,0x6c,0x72,0xa2,0x61,0x75,0xa2,0x62,0x79,0x14,0x61,0x6e,0x6d, -0x61,0x72,0x58,0x12,0x65,0x78,0x74,2,0x61,0xa3,0xb6,0x62,0xa3,0xee,0x65,0x13, -0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb6,0x62,0xa3,0xee,1,0x64,0x52,0x6e,0x15, -0x67,0x6f,0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73,0x75,0x70,0xa4,0xd,0x16,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0xa5,0xd,0x10,0x69,0xa2,0xec,0x13,0x66,0x69,0x65,0x72, -1,0x6c,0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0xa3, -0x8a,0x15,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,0x10,0x6f,0xa3,0xed,1,0x6c,0x44, -0x73,0x11,0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0xa3,0x5c,0x13,0x74,0x61,0x6e,0x69,0xa5,3,0x61,0xa2,0x9b,0x65,0xa4,0x4c,0x69, -1,0x61,0xa2,0x8f,0x73,0x10,0x63,5,0x70,0x18,0x70,0xa2,0x71,0x73,0x36,0x74, -0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x15,0x79,0x6d,0x62,0x6f,0x6c, -0x73,0x8f,0x61,0xa2,0x66,0x65,0x46,0x6d,0x19,0x61,0x74,0x68,0x73,0x79,0x6d,0x62, -0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x17,0x6c,0x6c,0x61,0x6e,0x65, -0x6f,0x75,0x73,2,0x6d,0x3a,0x73,0x6c,0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63, -0x61,0x6c,0x81,0x11,0x61,0x74,0x1f,0x68,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c, -0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x15,0x79, -0x6d,0x62,0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e,0x64,1,0x61,0x3c,0x70,0x19,0x69, -0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa3,0xcd,0x14,0x72,0x72,0x6f,0x77, -0x73,0xa3,0x73,0x10,0x6f,0xa3,0xd8,7,0x72,0x6f,0x72,0x44,0x73,0x4e,0x74,0x62, -0x79,0x19,0x61,0x6e,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0xa5,0x20,0x13,0x63, -0x68,0x65,0x6e,0xa5,0xc,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa5, -0x14,0x10,0x68,2,0x61,0x3a,0x65,0x4a,0x6f,0x17,0x70,0x65,0x72,0x61,0x74,0x6f, -0x72,0x73,0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0xa3,0x5d,0x16,0x6d,0x61, -0x74,0x69,0x63,0x61,0x6c,1,0x61,0x36,0x6f,0x17,0x70,0x65,0x72,0x61,0x74,0x6f, -0x72,0x73,0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63, -0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d,0x68,0x50,0x6b,0x7e,0x6c,0x88,0x6e, -1,0x64,0x34,0x69,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3,0xea,0x12,0x61,0x69, -0x63,0xa3,0xc6,1,0x61,0x3e,0x6a,0x12,0x6f,0x6e,0x67,0xa2,0xaa,0x14,0x74,0x69, -0x6c,0x65,0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xe9,0x13,0x61,0x73,0x61, -0x72,0xa5,0x1f,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x4f,3,0x64,0x6c,0x65,0x7e, -0x6e,0xa2,0x47,0x72,0x14,0x6f,0x69,0x74,0x69,0x63,1,0x63,0x3c,0x68,0x19,0x69, -0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xd7,0x15,0x75,0x72,0x73,0x69, -0x76,0x65,0xa3,0xd6,0x17,0x65,0x66,0x61,0x69,0x64,0x72,0x69,0x6e,0xa5,0x21,0x17, -0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa2,0xb8,0x12,0x65,0x78,0x74,0xa2,0xd5, -0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xd5,0x18,0x64,0x65,0x6b,0x69,0x6b, -0x61,0x6b,0x75,0x69,0xa3,0xeb,6,0x6b,0x3b,0x6b,0x56,0x6f,0x5a,0x75,0x64,0x79, -0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63,0x68,0x75,0x65,0x68, -0x6d,0x6f,0x6e,0x67,0xa5,0x27,0x10,0x6f,0xa3,0x92,0x14,0x62,0x6c,0x6f,0x63,0x6b, -0x21,1,0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5,0x15,0x17,0x62,0x65,0x72,0x66,0x6f, -0x72,0x6d,0x73,0x7b,0x61,0x44,0x62,0x21,0x65,0x10,0x77,1,0x61,0xa5,0xe,0x74, -0x14,0x61,0x69,0x6c,0x75,0x65,0xa3,0x8b,2,0x62,0x3c,0x67,0x4a,0x6e,0x17,0x64, -0x69,0x6e,0x61,0x67,0x61,0x72,0x69,0xa5,0x26,0x15,0x61,0x74,0x61,0x65,0x61,0x6e, -0xa3,0xef,0x16,0x6d,0x75,0x6e,0x64,0x61,0x72,0x69,0xa5,0x47,0x67,0xc4,0x5d,0x6a, -0xc1,0xe4,0x6a,0xa2,0xdf,0x6b,0xa2,0xf8,0x6c,4,0x61,0x54,0x65,0xa2,0x6b,0x69, -0xa2,0x82,0x6f,0xa2,0xc1,0x79,1,0x63,0x2e,0x64,0x12,0x69,0x61,0x6e,0xa3,0xa9, -0x12,0x69,0x61,0x6e,0xa3,0xa7,1,0x6f,0x55,0x74,0x11,0x69,0x6e,1,0x31,0x96, -0x65,0x11,0x78,0x74,6,0x64,0x21,0x64,0xa3,0x95,0x65,0x2c,0x66,0xa5,0x39,0x67, -0xa5,0x3a,0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,6,0x64,0xc,0x64,0xa3,0x95,0x65, -0xa3,0xe7,0x66,0xa5,0x39,0x67,0xa5,0x3a,0x61,0x2a,0x62,0x29,0x63,0xa3,0x94,0x26, -0x18,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6d,0x24,0x12,0x73,0x75,0x70, -0x24,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x25,1,0x70,0x42,0x74,0x1d,0x74, -0x65,0x72,0x6c,0x69,0x6b,0x65,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x79,0x12,0x63, -0x68,0x61,0xa3,0x9c,2,0x6d,0x4e,0x6e,0x54,0x73,0x10,0x75,0xa2,0xb0,0x12,0x73, -0x75,0x70,0xa4,0x31,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x31,0x11,0x62, -0x75,0xa3,0x6f,0x12,0x65,0x61,0x72,1,0x61,0xa3,0xe8,0x62,1,0x69,0x38,0x73, -0x17,0x79,0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3,0x75,0x17,0x64,0x65,0x6f,0x67, -0x72,0x61,0x6d,0x73,0xa3,0x76,0x1a,0x77,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74, -0x65,0x73,0xa3,0x4d,0x10,0x61,1,0x6d,0x32,0x76,0x14,0x61,0x6e,0x65,0x73,0x65, -0xa3,0xb5,0x10,0x6f,0x5c,0x12,0x65,0x78,0x74,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9, -1,0x61,0xa2,0x43,0x68,4,0x61,0x40,0x69,0x50,0x6d,0x6e,0x6f,0x86,0x75,0x15, +6,1,0x64,0x2e,0x75,0x12,0x77,0x61,0x72,0xa5,0x4f,0x14,0x61,0x6e,0x65,0x73, +0x65,0xa2,0x9b,0x12,0x73,0x75,0x70,0xa2,0xdb,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e, +0x74,0xa3,0xdb,4,0x61,0xa2,0xa8,0x65,0x5c,0x6d,0x9e,0x70,0xa2,0x4b,0x73,0x13, +0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67, +0x72,0x61,0x70,0x68,0x73,0xa5,5,0x10,0x72,1,0x61,0x4e,0x73,0x12,0x63,0x72, +0x69,0x1f,0x70,0x74,0x73,0x61,0x6e,0x64,0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70, +0x74,0x73,0x73,0x14,0x6e,0x64,0x73,0x75,0x62,0x73,0x1b,0x61,0x74,0x68,0x6f,0x70, +0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,1,0x6c,0x40,0x75,1,0x61,0x6e, +0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x15,0x65,0x6d,0x65, +0x6e,0x74,0x61,1,0x6c,0x50,0x72,0x1e,0x79,0x70,0x72,0x69,0x76,0x61,0x74,0x65, +0x75,0x73,0x65,0x61,0x72,0x65,0x61,1,0x61,0xa3,0x6d,0x62,0xa3,0x6e,3,0x61, +0x5c,0x6d,0x78,0x70,0xa2,0x41,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61, +0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x14, +0x72,0x72,0x6f,0x77,0x73,2,0x61,0xa3,0x67,0x62,0xa3,0x68,0x63,0xa3,0xfa,0x13, +0x61,0x74,0x68,0x65,0x1f,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x6f,0x70,0x65,0x72, +0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, +0x6f,0x6e,0xa3,0x8e,0x61,0x88,0x68,0xa2,0x48,0x69,0xa2,0x71,0x6d,0x12,0x61,0x6c, +0x6c,1,0x66,0x46,0x6b,0x15,0x61,0x6e,0x61,0x65,0x78,0x74,0xa4,0x29,0x15,0x65, +0x6e,0x73,0x69,0x6f,0x6e,0xa5,0x29,0x12,0x6f,0x72,0x6d,1,0x73,0xa3,0x54,0x76, +0x16,0x61,0x72,0x69,0x61,0x6e,0x74,0x73,0xa3,0x54,1,0x6d,0x36,0x75,0x16,0x72, +0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0xa1,0x15,0x61,0x72,0x69,0x74,0x61,0x6e,0xa3, +0xac,1,0x61,0x52,0x6f,0x13,0x72,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x6f,0x72, +0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa3,0xf7,1,0x72,0x2e, +0x76,0x12,0x69,0x61,0x6e,0xa3,0x79,0x12,0x61,0x64,0x61,0xa3,0xd9,1,0x64,0x50, +0x6e,0x13,0x68,0x61,0x6c,0x61,0x50,0x1d,0x61,0x72,0x63,0x68,0x61,0x69,0x63,0x6e, +0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xf9,0x13,0x64,0x68,0x61,0x6d,0xa3,0xf8,5, +0x72,0x35,0x72,0x44,0x73,0x64,0x75,1,0x61,0xa3,0x4e,0x6e,0x17,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xa2, +0x4e,0x13,0x61,0x72,0x65,0x61,0xa3,0x4e,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61, +0x68,0x6c,0x61,0x76,0x69,0xa3,0xf6,0x61,0x40,0x68,0x82,0x6c,0x19,0x61,0x79,0x69, +0x6e,0x67,0x63,0x61,0x72,0x64,0x73,0xa3,0xcc,2,0x68,0x38,0x6c,0x4a,0x75,0x15, +0x63,0x69,0x6e,0x68,0x61,0x75,0xa3,0xf5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e, +0x67,0xa3,0xf3,0x15,0x6d,0x79,0x72,0x65,0x6e,0x65,0xa3,0xf4,1,0x61,0x8e,0x6f, +1,0x65,0x74,0x6e,0x16,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0xa2,0x72,1,0x65, +0x2c,0x73,0x11,0x75,0x70,0xa3,0x8d,0x15,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa2,0x72, +0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x8d,0x15,0x6e,0x69, +0x63,0x69,0x61,0x6e,0xa3,0x97,1,0x67,0x3e,0x69,0x13,0x73,0x74,0x6f,0x73,0xa2, +0xa6,0x13,0x64,0x69,0x73,0x63,0xa3,0xa6,0x12,0x73,0x70,0x61,0xa3,0x96,1,0x65, +0x5c,0x75,1,0x6d,0x2a,0x6e,0x11,0x69,0x63,0x67,0x10,0x69,0xa2,0xc0,0x1d,0x6e, +0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xc0,0x13, +0x6a,0x61,0x6e,0x67,0xa3,0xa3,0x6d,0xa2,0xf7,0x6e,0xa8,0x30,0x6f,6,0x70,0x63, +0x70,0x56,0x72,0x8a,0x73,0xa2,0x4c,0x74,0x10,0x74,0x1f,0x6f,0x6d,0x61,0x6e,0x73, +0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa5,0x28,0x18,0x74,0x69, +0x63,0x61,0x6c,0x63,0x68,0x61,0x72,0x1f,0x61,0x63,0x74,0x65,0x72,0x72,0x65,0x63, +0x6f,0x67,0x6e,0x69,0x74,0x69,0x6f,0x6e,0x85,1,0x69,0x46,0x6e,0x1e,0x61,0x6d, +0x65,0x6e,0x74,0x61,0x6c,0x64,0x69,0x6e,0x67,0x62,0x61,0x74,0x73,0xa3,0xf2,0x11, +0x79,0x61,0x47,1,0x61,0x30,0x6d,0x13,0x61,0x6e,0x79,0x61,0xa3,0x7a,0x11,0x67, +0x65,0xa5,0xf,0x63,0xa2,0x82,0x67,0xa2,0x82,0x6c,2,0x63,0x32,0x64,0x3c,0x6f, +0x12,0x6e,0x61,0x6c,0xa5,0x4e,0x13,0x68,0x69,0x6b,0x69,0xa3,0x9d,6,0x70,0x42, +0x70,0x3a,0x73,0x5a,0x74,0x88,0x75,0x14,0x79,0x67,0x68,0x75,0x72,0xa5,0x3b,0x11, +0x65,0x72,1,0x6d,0x2e,0x73,0x12,0x69,0x61,0x6e,0xa3,0x8c,0x11,0x69,0x63,0xa3, +0xf1,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61, +0x6e,0xa3,0xbb,0x13,0x64,0x69,0x61,0x6e,0xa5,0x22,0x14,0x75,0x72,0x6b,0x69,0x63, +0xa3,0xbf,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62, +0x69,0x61,0x6e,0xa3,0xf0,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa5,4, +0x14,0x74,0x61,0x6c,0x69,0x63,0xa3,0x58,0x10,0x72,0x85,0x12,0x68,0x61,0x6d,0x65, +6,0x6f,0x8c,0x6f,0x78,0x72,0xa2,0x67,0x75,0xa2,0x68,0x79,0x14,0x61,0x6e,0x6d, +0x61,0x72,0x58,0x12,0x65,0x78,0x74,3,0x61,0xa3,0xb6,0x62,0xa3,0xee,0x63,0xa5, +0x4d,0x65,0x13,0x6e,0x64,0x65,0x64,2,0x61,0xa3,0xb6,0x62,0xa3,0xee,0x63,0xa5, +0x4d,1,0x64,0x52,0x6e,0x15,0x67,0x6f,0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73,0x75, +0x70,0xa4,0xd,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xd,0x10,0x69,0xa2, +0xec,0x13,0x66,0x69,0x65,0x72,1,0x6c,0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c,0x65, +0x74,0x74,0x65,0x72,0x73,0xa3,0x8a,0x15,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,0x10, +0x6f,0xa3,0xed,1,0x6c,0x44,0x73,0x11,0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5c,0x13,0x74,0x61,0x6e,0x69,0xa5,3,0x61, +0xa2,0x9b,0x65,0xa4,0x4c,0x69,1,0x61,0xa2,0x8f,0x73,0x10,0x63,5,0x70,0x18, +0x70,0xa2,0x71,0x73,0x36,0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81, +0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8f,0x61,0xa2,0x66,0x65,0x46,0x6d,0x19,0x61, +0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69, +0x17,0x6c,0x6c,0x61,0x6e,0x65,0x6f,0x75,0x73,2,0x6d,0x3a,0x73,0x6c,0x74,0x17, +0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x11,0x61,0x74,0x1f,0x68,0x65,0x6d, +0x61,0x74,0x69,0x63,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3, +0x66,0x62,0xa3,0x69,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e,0x64, +1,0x61,0x3c,0x70,0x19,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa3, +0xcd,0x14,0x72,0x72,0x6f,0x77,0x73,0xa3,0x73,0x10,0x6f,0xa3,0xd8,7,0x72,0x6f, +0x72,0x44,0x73,0x4e,0x74,0x62,0x79,0x19,0x61,0x6e,0x6e,0x75,0x6d,0x65,0x72,0x61, +0x6c,0x73,0xa5,0x20,0x13,0x63,0x68,0x65,0x6e,0xa5,0xc,0x18,0x61,0x72,0x61,0x6d, +0x67,0x6f,0x6e,0x64,0x69,0xa5,0x14,0x10,0x68,2,0x61,0x3a,0x65,0x4a,0x6f,0x17, +0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75, +0x6d,0xa3,0x5d,0x16,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,1,0x61,0x36,0x6f,0x17, +0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61,0x6e, +0x75,0x6d,0x65,0x72,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d,0x68, +0x50,0x6b,0x7e,0x6c,0x88,0x6e,1,0x64,0x34,0x69,0x15,0x63,0x68,0x61,0x65,0x61, +0x6e,0xa3,0xea,0x12,0x61,0x69,0x63,0xa3,0xc6,1,0x61,0x3e,0x6a,0x12,0x6f,0x6e, +0x67,0xa2,0xaa,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e,0x69, +0xa3,0xe9,0x13,0x61,0x73,0x61,0x72,0xa5,0x1f,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d, +0x4f,3,0x64,0x6c,0x65,0x7e,0x6e,0xa2,0x47,0x72,0x14,0x6f,0x69,0x74,0x69,0x63, +1,0x63,0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3, +0xd7,0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0xd6,0x17,0x65,0x66,0x61,0x69,0x64, +0x72,0x69,0x6e,0xa5,0x21,0x17,0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa2,0xb8, +0x12,0x65,0x78,0x74,0xa2,0xd5,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xd5, +0x18,0x64,0x65,0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0xeb,6,0x6b,0x3b,0x6b, +0x56,0x6f,0x5a,0x75,0x64,0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75, +0x61,0x63,0x68,0x75,0x65,0x68,0x6d,0x6f,0x6e,0x67,0xa5,0x27,0x10,0x6f,0xa3,0x92, +0x14,0x62,0x6c,0x6f,0x63,0x6b,0x21,1,0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5,0x15, +0x17,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0x7b,0x61,0x44,0x62,0x21,0x65,0x10, +0x77,1,0x61,0xa5,0xe,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0xa3,0x8b,2,0x62, +0x3c,0x67,0x4a,0x6e,0x17,0x64,0x69,0x6e,0x61,0x67,0x61,0x72,0x69,0xa5,0x26,0x15, +0x61,0x74,0x61,0x65,0x61,0x6e,0xa3,0xef,0x16,0x6d,0x75,0x6e,0x64,0x61,0x72,0x69, +0xa5,0x47,0x67,0xc4,0x7b,0x6a,0xc1,0xef,0x6a,0xa2,0xdf,0x6b,0xa2,0xf8,0x6c,4, +0x61,0x54,0x65,0xa2,0x6b,0x69,0xa2,0x82,0x6f,0xa2,0xc1,0x79,1,0x63,0x2e,0x64, +0x12,0x69,0x61,0x6e,0xa3,0xa9,0x12,0x69,0x61,0x6e,0xa3,0xa7,1,0x6f,0x55,0x74, +0x11,0x69,0x6e,1,0x31,0x96,0x65,0x11,0x78,0x74,6,0x64,0x21,0x64,0xa3,0x95, +0x65,0x2c,0x66,0xa5,0x39,0x67,0xa5,0x3a,0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,6, +0x64,0xc,0x64,0xa3,0x95,0x65,0xa3,0xe7,0x66,0xa5,0x39,0x67,0xa5,0x3a,0x61,0x2a, +0x62,0x29,0x63,0xa3,0x94,0x26,0x18,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c, +0x6d,0x24,0x12,0x73,0x75,0x70,0x24,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x25, +1,0x70,0x42,0x74,0x1d,0x74,0x65,0x72,0x6c,0x69,0x6b,0x65,0x73,0x79,0x6d,0x62, +0x6f,0x6c,0x73,0x79,0x12,0x63,0x68,0x61,0xa3,0x9c,2,0x6d,0x4e,0x6e,0x54,0x73, +0x10,0x75,0xa2,0xb0,0x12,0x73,0x75,0x70,0xa4,0x31,0x16,0x70,0x6c,0x65,0x6d,0x65, +0x6e,0x74,0xa5,0x31,0x11,0x62,0x75,0xa3,0x6f,0x12,0x65,0x61,0x72,1,0x61,0xa3, +0xe8,0x62,1,0x69,0x38,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3, +0x75,0x17,0x64,0x65,0x6f,0x67,0x72,0x61,0x6d,0x73,0xa3,0x76,0x1a,0x77,0x73,0x75, +0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4d,0x10,0x61,1,0x6d,0x32,0x76, +0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0xb5,0x10,0x6f,0x5c,0x12,0x65,0x78,0x74,1, +0x61,0xa3,0xb4,0x62,0xa3,0xb9,2,0x61,0x3a,0x68,0xa2,0xa9,0x69,0x15,0x72,0x61, +0x74,0x72,0x61,0x69,0xa5,0x4c,5,0x74,0x35,0x74,0x34,0x77,0x7a,0x79,0x13,0x61, +0x68,0x6c,0x69,0xa3,0xa2,0x14,0x61,0x6b,0x61,0x6e,0x61,0x9e,1,0x65,0x4c,0x70, +0x10,0x68,0x1f,0x6f,0x6e,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0x65,0x6e,0x73,0x69, +0x6f,0x6e,0x73,0xa3,0x6b,0x11,0x78,0x74,0xa3,0x6b,0x10,0x69,0xa5,0x46,0x69,0xa2, +0x4e,0x6b,0xa2,0x51,0x6e,3,0x61,0x34,0x62,0x84,0x67,0x8a,0x6e,0x12,0x61,0x64, +0x61,0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0xcb,0x16,0x70,0x6c,0x65,0x6d, +0x65,0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,2,0x61,0xa5,0x13,0x62,0xa5,0x38,0x65, +0x13,0x6e,0x64,0x65,0x64,1,0x61,0xa5,0x13,0x62,0xa5,0x38,0x11,0x75,0x6e,0xa3, +0x42,0x11,0x78,0x69,0x96,0x17,0x72,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x97,0x12, +0x74,0x68,0x69,0xa3,0xc1,0x1c,0x74,0x6f,0x76,0x69,0x6b,0x6e,0x75,0x6d,0x65,0x72, +0x61,0x6c,0x73,0xa5,0x45,4,0x61,0x40,0x69,0x50,0x6d,0x6e,0x6f,0x86,0x75,0x15, 0x64,0x61,0x77,0x61,0x64,0x69,0xa3,0xe6,0x16,0x72,0x6f,0x73,0x68,0x74,0x68,0x69, 0xa3,0x89,0x1d,0x74,0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70, 0x74,0xa5,0x30,0x11,0x65,0x72,0x68,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3, -0x71,0x12,0x6a,0x6b,0x69,0xa3,0xe5,5,0x74,0x35,0x74,0x34,0x77,0x7a,0x79,0x13, -0x61,0x68,0x6c,0x69,0xa3,0xa2,0x14,0x61,0x6b,0x61,0x6e,0x61,0x9e,1,0x65,0x4c, -0x70,0x10,0x68,0x1f,0x6f,0x6e,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0x65,0x6e,0x73, -0x69,0x6f,0x6e,0x73,0xa3,0x6b,0x11,0x78,0x74,0xa3,0x6b,0x10,0x69,0xa5,0x46,0x69, -0xa2,0x4e,0x6b,0xa2,0x51,0x6e,3,0x61,0x34,0x62,0x84,0x67,0x8a,0x6e,0x12,0x61, -0x64,0x61,0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0xcb,0x16,0x70,0x6c,0x65, -0x6d,0x65,0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,2,0x61,0xa5,0x13,0x62,0xa5,0x38, -0x65,0x13,0x6e,0x64,0x65,0x64,1,0x61,0xa5,0x13,0x62,0xa5,0x38,0x11,0x75,0x6e, -0xa3,0x42,0x11,0x78,0x69,0x96,0x17,0x72,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x97, -0x12,0x74,0x68,0x69,0xa3,0xc1,0x1c,0x74,0x6f,0x76,0x69,0x6b,0x6e,0x75,0x6d,0x65, -0x72,0x61,0x6c,0x73,0xa5,0x45,0x67,0xa2,0xb5,0x68,0xa4,0x84,0x69,3,0x64,0x4c, -0x6d,0xa2,0x55,0x6e,0xa2,0x62,0x70,0x13,0x61,0x65,0x78,0x74,0x2a,0x16,0x65,0x6e, -0x73,0x69,0x6f,0x6e,0x73,0x2b,1,0x63,0x99,0x65,0x17,0x6f,0x67,0x72,0x61,0x70, -0x68,0x69,0x63,1,0x64,0x56,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa4,0xb, -0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa5, -0xb,0x13,0x65,0x73,0x63,0x72,0x1f,0x69,0x70,0x74,0x69,0x6f,0x6e,0x63,0x68,0x61, -0x72,0x61,0x63,0x74,0x65,0x72,0x73,0x99,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61, -0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0xba,1,0x64,0x62,0x73,0x1b,0x63,0x72,0x69, -0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68, -0x69,0x61,0x6e,0xa3,0xbd,0x13,0x6c,0x61,0x76,0x69,0xa3,0xbe,0x11,0x69,0x63,1, -0x6e,0x3e,0x73,0x1a,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa5, -0x1e,0x19,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2,4,0x65, -0x74,0x6c,0xa2,0x82,0x6f,0xa2,0x9a,0x72,0xa2,0x9e,0x75,2,0x6a,0x34,0x6e,0x3e, -0x72,0x14,0x6d,0x75,0x6b,0x68,0x69,0x43,0x14,0x61,0x72,0x61,0x74,0x69,0x45,0x18, -0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa5,0x1c,1,0x6e,0xa2,0x46,0x6f, -1,0x6d,0x6e,0x72,0x13,0x67,0x69,0x61,0x6e,0x5a,1,0x65,0x40,0x73,0x11,0x75, -0x70,0xa2,0x87,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x87,0x11,0x78,0x74, -0xa4,0x1b,0x14,0x65,0x6e,0x64,0x65,0x64,0xa5,0x1b,0x1a,0x65,0x74,0x72,0x69,0x63, -0x73,0x68,0x61,0x70,0x65,0x73,0x8c,0x12,0x65,0x78,0x74,0xa2,0xe3,0x14,0x65,0x6e, -0x64,0x65,0x64,0xa3,0xe3,0x1e,0x65,0x72,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75, -0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x61,0x67,0x6f,0x6c,0x69,0x74,0x69,0x63,0xa2, -0x88,0x12,0x73,0x75,0x70,0xa4,0xa,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5, -0xa,0x13,0x74,0x68,0x69,0x63,0xa3,0x59,1,0x61,0x5c,0x65,0x11,0x65,0x6b,0x30, -1,0x61,0x38,0x65,0x11,0x78,0x74,0x6e,0x14,0x65,0x6e,0x64,0x65,0x64,0x6f,0x17, -0x6e,0x64,0x63,0x6f,0x70,0x74,0x69,0x63,0x31,0x13,0x6e,0x74,0x68,0x61,0xa3,0xe4, -2,0x61,0xa2,0x48,0x65,0xa2,0xdf,0x69,1,0x67,0x30,0x72,0x14,0x61,0x67,0x61, -0x6e,0x61,0x9d,0x10,0x68,1,0x70,0x3a,0x73,0x18,0x75,0x72,0x72,0x6f,0x67,0x61, -0x74,0x65,0x73,0xa3,0x4b,1,0x72,0x3c,0x75,0x19,0x73,0x75,0x72,0x72,0x6f,0x67, -0x61,0x74,0x65,0x73,0xa3,0x4c,0x11,0x69,0x76,0x1f,0x61,0x74,0x65,0x75,0x73,0x65, -0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,2,0x6c,0x32,0x6e, -0x9a,0x74,0x12,0x72,0x61,0x6e,0xa5,2,0x10,0x66,2,0x61,0x58,0x6d,0x70,0x77, -0x14,0x69,0x64,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x75,0x6c,0x6c,0x77,0x69,0x64, -0x74,0x68,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x1a,0x6e,0x64,0x66,0x75,0x6c,0x6c, -0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x13,0x61,0x72,0x6b,0x73,0xa3,0x52,2,0x67, -0x34,0x69,0xa2,0x45,0x75,0x12,0x6e,0x6f,0x6f,0xa3,0x63,0x11,0x75,0x6c,0xa2,0x4a, -2,0x63,0x3c,0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3, -0x4a,0x1f,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x6a,0x61, -0x6d,0x6f,0xa3,0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17,0x65,0x78,0x74,0x65,0x6e,0x64, -0x65,0x64,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x19,0x66,0x69,0x72,0x6f,0x68,0x69, -0x6e,0x67,0x79,0x61,0xa5,0x1d,0x13,0x62,0x72,0x65,0x77,0x37,0x61,0xa4,0xc,0x62, -0xa6,0x59,0x63,0xa8,0x2e,0x64,0xac,0xe9,0x65,5,0x6d,0xa9,0x6d,0x94,0x6e,0xa2, -0x41,0x74,0x15,0x68,0x69,0x6f,0x70,0x69,0x63,0x5e,1,0x65,0x40,0x73,0x11,0x75, -0x70,0xa2,0x86,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x86,0x11,0x78,0x74, -0xa2,0x85,2,0x61,0xa3,0xc8,0x62,0xa5,0x37,0x65,0x13,0x6e,0x64,0x65,0x64,0xa2, -0x85,1,0x61,0xa3,0xc8,0x62,0xa5,0x37,0x16,0x6f,0x74,0x69,0x63,0x6f,0x6e,0x73, -0xa3,0xce,0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2,0x61,0x5a,0x63,0x9e,0x69,0x1c, -0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x75,0x70,0xa2,0xc4,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75, -0x6d,0x86,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0xc3,0x13,0x72,0x69,0x63,0x73, -0x86,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc3,0x11,0x6a,0x6b, -0xa2,0x44,0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x61,0x6e,0x64,0x6d,0x6f,0x6e, -0x74,0x68,0x73,0xa3,0x44,0x61,0x4a,0x67,0x76,0x6c,1,0x62,0x30,0x79,0x13,0x6d, -0x61,0x69,0x63,0xa5,0x25,0x13,0x61,0x73,0x61,0x6e,0xa3,0xe2,0x13,0x72,0x6c,0x79, -0x64,0x1f,0x79,0x6e,0x61,0x73,0x74,0x69,0x63,0x63,0x75,0x6e,0x65,0x69,0x66,0x6f, -0x72,0x6d,0xa5,1,0x1f,0x79,0x70,0x74,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f, -0x67,0x6c,0x79,0x70,0x68,1,0x66,0x26,0x73,0xa3,0xc2,0x1c,0x6f,0x72,0x6d,0x61, -0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa5,0x24,7,0x6e,0xc0,0xf2,0x6e, -0x3e,0x72,0xa2,0x5d,0x73,0xa2,0xe5,0x76,0x14,0x65,0x73,0x74,0x61,0x6e,0xa3,0xbc, -1,0x61,0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1,0x67,0x34,0x73,0x15,0x79,0x6d, -0x62,0x6f,0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65,0x6b,1,0x6d,0x34,0x6e,0x15, -0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75,0x73,0x69,0x63,0xa2,0x7e,0x19, -0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x7e,0x10,0x74,0x1f,0x6f, -0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3, -0xfe,2,0x61,0x32,0x6d,0xa2,0x7e,0x72,0x12,0x6f,0x77,0x73,0x7d,0x12,0x62,0x69, -0x63,0x38,3,0x65,0x4a,0x6d,0x80,0x70,0xa2,0x50,0x73,0x11,0x75,0x70,0xa2,0x80, -0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80,0x11,0x78,0x74,3,0x61,0xa3, -0xd2,0x62,0xa5,0x35,0x63,0xa5,0x41,0x65,0x13,0x6e,0x64,0x65,0x64,2,0x61,0xa3, -0xd2,0x62,0xa5,0x35,0x63,0xa5,0x41,0x12,0x61,0x74,0x68,0xa2,0xd3,0x18,0x65,0x6d, -0x61,0x74,0x69,0x63,0x61,0x6c,0x61,0x1f,0x6c,0x70,0x68,0x61,0x62,0x65,0x74,0x69, -0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd3,1,0x66,0x42,0x72,0x1e,0x65, -0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73,1,0x61, -0xa3,0x51,0x62,0xa3,0x55,0x14,0x65,0x6e,0x69,0x61,0x6e,0x35,0x12,0x63,0x69,0x69, -0x23,0x64,0x9e,0x65,0xa2,0x42,0x68,0xa2,0x4d,0x6c,1,0x63,0x62,0x70,0x17,0x68, -0x61,0x62,0x65,0x74,0x69,0x63,0x70,1,0x66,0xa3,0x50,0x72,0x1e,0x65,0x73,0x65, -0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x50,0x16,0x68, -0x65,0x6d,0x69,0x63,0x61,0x6c,0xa2,0xd0,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0xa3,0xd0,0x12,0x6c,0x61,0x6d,0xa5,7,0x1a,0x67,0x65,0x61,0x6e,0x6e,0x75,0x6d, -0x62,0x65,0x72,0x73,0xa3,0x77,0x11,0x6f,0x6d,0xa3,0xfd,7,0x6f,0x71,0x6f,0x64, -0x72,0xa2,0x41,0x75,0xa2,0x58,0x79,0x1b,0x7a,0x61,0x6e,0x74,0x69,0x6e,0x65,0x6d, -0x75,0x73,0x69,0x63,0xa2,0x5b,0x18,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0xa3,0x5b,1,0x70,0x34,0x78,0x16,0x64,0x72,0x61,0x77,0x69,0x6e,0x67,0x89,0x14, -0x6f,0x6d,0x6f,0x66,0x6f,0xa0,0x12,0x65,0x78,0x74,0xa2,0x43,0x14,0x65,0x6e,0x64, -0x65,0x64,0xa3,0x43,0x10,0x61,1,0x68,0x40,0x69,0x12,0x6c,0x6c,0x65,0x92,0x17, -0x70,0x61,0x74,0x74,0x65,0x72,0x6e,0x73,0x93,0x11,0x6d,0x69,0xa3,0xc9,1,0x67, -0x2c,0x68,0x11,0x69,0x64,0xa3,0x64,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x81,0x61, -0x48,0x65,0xa2,0x4e,0x68,0xa2,0x52,0x6c,0x1a,0x6f,0x63,0x6b,0x65,0x6c,0x65,0x6d, -0x65,0x6e,0x74,0x73,0x8b,3,0x6c,0x34,0x6d,0x40,0x73,0x66,0x74,0x11,0x61,0x6b, -0xa3,0xc7,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x93,0x11,0x75,0x6d,0xa2,0xb1,0x12, -0x73,0x75,0x70,0xa2,0xca,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xca,1, -0x69,0x30,0x73,0x13,0x61,0x76,0x61,0x68,0xa3,0xdd,0x15,0x63,0x6c,0x61,0x74,0x69, -0x6e,0x23,0x14,0x6e,0x67,0x61,0x6c,0x69,0x41,0x16,0x61,0x69,0x6b,0x73,0x75,0x6b, -0x69,0xa5,8,5,0x6f,0xc1,0x60,0x6f,0xa2,0x69,0x75,0xa4,0x24,0x79,1,0x70, -0xa2,0x44,0x72,0x14,0x69,0x6c,0x6c,0x69,0x63,0x32,1,0x65,0x4c,0x73,0x11,0x75, -0x70,0xa2,0x61,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa2,0x61,0x12,0x61,0x72, -0x79,0xa3,0x61,0x11,0x78,0x74,4,0x61,0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5,9, -0x64,0xa5,0x43,0x65,0x13,0x6e,0x64,0x65,0x64,3,0x61,0xa3,0x9e,0x62,0xa3,0xa0, -0x63,0xa5,9,0x64,0xa5,0x43,0x10,0x72,1,0x69,0x34,0x6f,0x15,0x6d,0x69,0x6e, -0x6f,0x61,0x6e,0xa5,0x36,0x1a,0x6f,0x74,0x73,0x79,0x6c,0x6c,0x61,0x62,0x61,0x72, -0x79,0xa3,0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2,0xa0,0x75,0x17,0x6e,0x74, -0x69,0x6e,0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c, -0x73,0xa3,0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15,0x61,0x74,0x6a,0x61,0x6d, -0x6f,0xa3,0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64,0x46,0x68,0x9e,0x6d,0x1d, -0x61,0x72,0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,0x1e, -0x69,0x61,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d,0x61,0x72,0x6b,0x73,0x2e, -2,0x65,0x40,0x66,0xa6,0x52,0x73,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e, -0x74,0xa3,0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe0,0x17,0x61,0x6c, -0x66,0x6d,0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e,0x1f,0x69,0x6e,0x64,0x69, -0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2,0x1b,0x74, -0x72,0x6f,0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73,0x83,0x12,0x74,0x69,0x63, -0xa2,0x84,0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3, -0xdf,1,0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2,0x98,0x16,0x6e,0x75,0x6d, -0x62,0x65,0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75, -0x61,0x74,0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xea,0x68,0xa4,0x14,0x6a,0x10,0x6b, -0xa2,0x47,4,0x63,0x92,0x65,0xa2,0x83,0x72,0xa2,0xa1,0x73,0xa2,0xb3,0x75,0x1f, -0x6e,0x69,0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73, -0xa2,0x47,0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e,8,0x65,0x71,0x65, -0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e,0x68,0xa5,0x42,0x69,0xa5,0x48,0x14,0x6f, -0x6d,0x70,0x61,0x74,0xa2,0x45,1,0x66,0x96,0x69,1,0x62,0x44,0x64,0x17,0x65, -0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x12,0x73,0x75,0x70,0xa3,0x5f,0x14, -0x69,0x6c,0x69,0x74,0x79,0xa2,0x45,1,0x66,0x54,0x69,0x18,0x64,0x65,0x6f,0x67, -0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa3,0x5f,0x13,0x6f,0x72,0x6d,0x73,0xa3,0x53,0x11,0x78,0x74,8,0x65, -0xf,0x65,0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e,0x68,0xa5,0x42,0x69,0xa5,0x48, -0x61,0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3,0xc5,0x64,0xa3,0xd1,0x19,0x61,0x64,0x69, -0x63,0x61,0x6c,0x73,0x73,0x75,0x70,0x94,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0x95,1,0x74,0x50,0x79,0x14,0x6d,0x62,0x6f,0x6c,0x73,0x9a,0x1d,0x61,0x6e,0x64, -0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x9b,0x14,0x72,0x6f,0x6b, -0x65,0x73,0xa3,0x82,2,0x6e,0x48,0x72,0x64,0x75,0x1d,0x63,0x61,0x73,0x69,0x61, -0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0xde,0x1d,0x61,0x64,0x69,0x61, -0x6e,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x63,0x12,0x69,0x61,0x6e,0xa3, -0xa8,2,0x61,0x3a,0x65,0x4c,0x6f,0x16,0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa5, -0x2d,1,0x6b,0x26,0x6d,0xa3,0xa4,0x11,0x6d,0x61,0xa3,0xd4,1,0x72,0x38,0x73, -0x17,0x73,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa5,0x19,0x13,0x6f,0x6b,0x65,0x65, -0x60,0x12,0x73,0x75,0x70,0xa2,0xff,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, -0xff,3,0x65,0x3e,0x69,0x8e,0x6f,0xa2,0x71,0x75,0x15,0x70,0x6c,0x6f,0x79,0x61, -0x6e,0xa3,0xe1,1,0x73,0x60,0x76,0x16,0x61,0x6e,0x61,0x67,0x61,0x72,0x69,0x3e, -0x12,0x65,0x78,0x74,0xa2,0xb3,1,0x61,0xa5,0x44,0x65,0x13,0x6e,0x64,0x65,0x64, -0xa2,0xb3,0x10,0x61,0xa5,0x44,0x13,0x65,0x72,0x65,0x74,0xa3,0x5a,2,0x61,0x3a, -0x6e,0x82,0x76,0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75,0xa5,0x2f,0x18,0x63,0x72, -0x69,0x74,0x69,0x63,0x61,0x6c,0x73,0x2e,2,0x65,0x30,0x66,0x36,0x73,0x11,0x75, -0x70,0xa3,0x83,0x11,0x78,0x74,0xa3,0xe0,0x18,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0x77,0x14,0x67,0x62,0x61,0x74,0x73,0x91,1,0x67,0x3e,0x6d,0x12,0x69, -0x6e,0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xab,0x11,0x72,0x61,0xa5, -0x1a,8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48,0x73,0x7a,0x76,0xa2,0x4b,0x77,0x12,0x69, -0x64,0x65,0x43,0x11,0x65,0x64,0x32,0x12,0x69,0x61,0x6c,0x33,2,0x61,0x40,0x62, -0x37,0x6f,1,0x62,0x28,0x6e,0x10,0x65,0x21,0x13,0x72,0x65,0x61,0x6b,0x37,0x10, -0x72,0x34,0x12,0x72,0x6f,0x77,0x35,2,0x6d,0x38,0x71,0x46,0x75,1,0x62,0x3d, -0x70,0x3e,0x11,0x65,0x72,0x3f,1,0x61,0x24,0x6c,0x39,0x11,0x6c,0x6c,0x39,1, -0x72,0x3b,0x75,0x12,0x61,0x72,0x65,0x3b,0x12,0x65,0x72,0x74,0x40,0x13,0x69,0x63, -0x61,0x6c,0x41,0x63,0x58,0x65,0x92,0x66,0x96,0x69,1,0x6e,0x36,0x73,0x10,0x6f, -0x30,0x14,0x6c,0x61,0x74,0x65,0x64,0x31,0x11,0x69,0x74,0x2e,0x12,0x69,0x61,0x6c, -0x2f,2,0x61,0x36,0x69,0x48,0x6f,0x10,0x6d,0x24,0x12,0x70,0x61,0x74,0x25,0x10, -0x6e,0x22,0x15,0x6f,0x6e,0x69,0x63,0x61,0x6c,0x23,0x13,0x72,0x63,0x6c,0x65,0x27, -0x11,0x6e,0x63,0x27,2,0x69,0x3a,0x6f,0x44,0x72,0x10,0x61,0x2c,0x14,0x63,0x74, -0x69,0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11,0x61,0x6c,0x29,0x11,0x6e,0x74,0x2b,4, -0x61,0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70,0x77,0x2a,0x12,0x69,0x64,0x65,0x2b,0x22, -0x17,0x6d,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x26,0x17,0x75,0x6c,0x6c,0x77, -0x69,0x64,0x74,0x68,0x27,0x24,0x17,0x61,0x6c,0x66,0x77,0x69,0x64,0x74,0x68,0x25, -0x20,1,0x61,0x30,0x65,0x14,0x75,0x74,0x72,0x61,0x6c,0x21,0x28,0x13,0x72,0x72, -0x6f,0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73,0x6d,0x73,0x3a,0x74,0x98,0x75,0xa2,0x49, -0x7a,2,0x6c,0x3b,0x70,0x3d,0x73,0x39,5,0x6f,0x28,0x6f,0x57,0x70,0x34,0x75, -0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x45,0x11,0x61,0x63,1,0x65,0x32,0x69, -0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31,0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74, -0x6f,0x72,0x39,0x63,0x53,0x6b,0x55,0x6d,0x51,0x1d,0x69,0x74,0x6c,0x65,0x63,0x61, -0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x27,1,0x6e,0x40,0x70,0x1c,0x70,0x65, -0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x17,0x61,0x73,0x73, -0x69,0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a,0x6f,0xa2,0x47,0x70,8,0x66,0x14,0x66, -0x5b,0x69,0x59,0x6f,0x4f,0x72,0x24,0x73,0x49,0x17,0x69,0x76,0x61,0x74,0x65,0x75, -0x73,0x65,0x43,0x61,0x2c,0x63,0x4d,0x64,0x47,0x65,0x4b,0x1f,0x72,0x61,0x67,0x72, -0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x3d,2,0x64,0x33, -0x6c,0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72, -0x6b,0x2d,1,0x70,0x7c,0x74,0x12,0x68,0x65,0x72,3,0x6c,0x38,0x6e,0x42,0x70, -0x4c,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x57,0x14,0x65,0x74,0x74,0x65,0x72,0x2b, -0x14,0x75,0x6d,0x62,0x65,0x72,0x37,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, -0x6f,0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0x49,0x66,0x9e,0x66,0x88,0x69,0xa2,0x4b,0x6c,0xa2,0x5c,0x6d,4,0x61,0x60, -0x63,0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c, -0x30,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x55,0x14,0x65,0x74,0x74,0x65,0x72,0x29, -0x17,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x51,1,0x69,0x2e,0x6f,0x13,0x72, -0x6d,0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63, -0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,6,0x6d,0x18,0x6d,0x29,0x6f,0x28,0x74, -0x27,0x75,0x23,0x2a,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74, -0x65,0x72,0x25,0x65,0x28,0x69,0x3c,0x6c,0x25,0x19,0x74,0x74,0x65,0x72,0x6e,0x75, -0x6d,0x62,0x65,0x72,0x35,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f, -0x72,0x3b,0x63,0x44,0x64,0xa2,0x60,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e, -0x67,0x6d,0x61,0x72,0x6b,0x2f,6,0x6e,0x39,0x6e,0x46,0x6f,0x4e,0x73,0x45,0x75, -0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x53,0x20,0x12, -0x74,0x72,0x6c,0x3f,0x42,0x10,0x6e,1,0x6e,0x2c,0x74,0x12,0x72,0x6f,0x6c,0x3f, -0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d,0x6f,0x73,0x65,0x70,0x75,0x6e,0x63,0x74, -0x75,0x61,0x74,0x69,0x6f,0x6e,0x4b,2,0x61,0x30,0x65,0x4a,0x69,0x12,0x67,0x69, -0x74,0x33,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, -0x47,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65,0x72,0x33,0,0x13, -0x6e,0xc1,0xf,0x74,0x76,0x74,0x4c,0x76,0x9a,0x77,0xa2,0x48,0x79,0xa2,0x49,0x7a, -1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e,0x8b,0x11,0x69,0x6e,0x85,2,0x61,0x36, -0x65,0x3c,0x68,0x14,0x69,0x6e,0x79,0x65,0x68,0xa3,0x66,1,0x68,0x71,0x77,0x73, -1,0x68,0x28,0x74,0x10,0x68,0x77,0x16,0x6d,0x61,0x72,0x62,0x75,0x74,0x61,0x74, -0x13,0x67,0x6f,0x61,0x6c,0x3d,0x1a,0x65,0x72,0x74,0x69,0x63,0x61,0x6c,0x74,0x61, -0x69,0x6c,0xa3,0x67,0x11,0x61,0x77,0x79,1,0x65,0x32,0x75,0x11,0x64,0x68,0x80, -0x11,0x68,0x65,0x83,0x10,0x68,0x7a,1,0x62,0x34,0x77,0x16,0x69,0x74,0x68,0x74, -0x61,0x69,0x6c,0x7f,0x14,0x61,0x72,0x72,0x65,0x65,0x7d,0x6e,0xa2,0x4c,0x70,0xa2, -0x69,0x71,0xa2,0x69,0x72,0xa2,0x6f,0x73,5,0x74,0x22,0x74,0x38,0x77,0x4c,0x79, -0x16,0x72,0x69,0x61,0x63,0x77,0x61,0x77,0x6f,0x18,0x72,0x61,0x69,0x67,0x68,0x74, -0x77,0x61,0x77,0xa3,0x55,0x15,0x61,0x73,0x68,0x6b,0x61,0x66,0x6d,0x61,0x2e,0x65, -0x38,0x68,0x11,0x69,0x6e,0x6b,0x10,0x64,0x62,0x11,0x68,0x65,0x65,1,0x65,0x2e, -0x6d,0x13,0x6b,0x61,0x74,0x68,0x69,0x10,0x6e,0x67,2,0x6f,0x2c,0x75,0x50,0x79, -0x10,0x61,0x91,1,0x6a,0x28,0x6f,0x10,0x6e,0x55,0x1a,0x6f,0x69,0x6e,0x69,0x6e, -0x67,0x67,0x72,0x6f,0x75,0x70,0x21,0x10,0x6e,0x57,0x10,0x65,0x59,0x10,0x61,1, -0x66,0x5b,0x70,0x10,0x68,0x5d,1,0x65,0x38,0x6f,0x18,0x68,0x69,0x6e,0x67,0x79, -0x61,0x79,0x65,0x68,0x93,1,0x68,0x5f,0x76,0x16,0x65,0x72,0x73,0x65,0x64,0x70, -0x65,0x61,0x67,0xc1,0xc7,0x67,0xa4,0x52,0x68,0xa4,0x59,0x6b,0xa4,0x99,0x6c,0xa4, -0xb2,0x6d,2,0x61,0x2e,0x65,0xa4,0x3e,0x69,0x10,0x6d,0x53,1,0x6c,0xa2,0xe7, -0x6e,0x16,0x69,0x63,0x68,0x61,0x65,0x61,0x6e,0,0x12,0x6e,0x76,0x73,0x51,0x73, -0x3e,0x74,0x5c,0x77,0xa0,0x79,0xa2,0x42,0x7a,0x13,0x61,0x79,0x69,0x6e,0xa3,0x54, -0x10,0x61,1,0x64,0x2e,0x6d,0x12,0x65,0x6b,0x68,0xa3,0x4c,0x11,0x68,0x65,0xa3, -0x4b,3,0x61,0x38,0x65,0x3c,0x68,0x4a,0x77,0x13,0x65,0x6e,0x74,0x79,0xa3,0x51, -0x10,0x77,0xa3,0x4d,1,0x6e,0xa3,0x4e,0x74,0x10,0x68,0xa3,0x4f,0x14,0x61,0x6d, -0x65,0x64,0x68,0xa3,0x50,0x11,0x61,0x77,0xa3,0x52,0x12,0x6f,0x64,0x68,0xa3,0x53, -0x6e,0x3a,0x6f,0x40,0x70,0x46,0x71,0x4a,0x72,0x12,0x65,0x73,0x68,0xa3,0x4a,0x11, -0x75,0x6e,0xa3,0x46,0x11,0x6e,0x65,0xa3,0x47,0x10,0x65,0xa3,0x48,0x12,0x6f,0x70, -0x68,0xa3,0x49,0x67,0x33,0x67,0x38,0x68,0x40,0x6b,0x5e,0x6c,0x66,0x6d,0x11,0x65, -0x6d,0xa3,0x45,0x13,0x69,0x6d,0x65,0x6c,0xa1,1,0x65,0x32,0x75,0x14,0x6e,0x64, -0x72,0x65,0x64,0xa3,0x42,0x11,0x74,0x68,0xa3,0x41,0x12,0x61,0x70,0x68,0xa3,0x43, -0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x44,0x61,0x34,0x62,0x4a,0x64,0x50,0x66,0x12, -0x69,0x76,0x65,0x9f,1,0x6c,0x2a,0x79,0x11,0x69,0x6e,0x97,0x12,0x65,0x70,0x68, -0x95,0x12,0x65,0x74,0x68,0x99,1,0x61,0x30,0x68,0x14,0x61,0x6d,0x65,0x64,0x68, -0x9d,0x13,0x6c,0x65,0x74,0x68,0x9b,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,6,0x6e, -0x2c,0x6e,0x34,0x72,0x5e,0x73,0x62,0x74,0x11,0x74,0x61,0xa3,0x63,2,0x67,0x2e, -0x6e,0x32,0x79,0x10,0x61,0xa3,0x60,0x10,0x61,0xa3,0x5d,1,0x61,0xa3,0x5e,0x6e, -0x10,0x61,0xa3,0x5f,0x10,0x61,0xa3,0x61,0x11,0x73,0x61,0xa3,0x62,0x62,0x3c,0x6a, -0x42,0x6c,0x10,0x6c,1,0x61,0xa3,0x5b,0x6c,0x10,0x61,0xa3,0x5c,0x11,0x68,0x61, -0xa3,0x59,0x10,0x61,0xa3,0x5a,0x11,0x65,0x6d,0x51,0x10,0x61,1,0x66,0x37,0x6d, -0x11,0x61,0x6c,0x39,1,0x61,0x40,0x65,0x3e,1,0x68,0x28,0x74,0x10,0x68,0x45, -0x40,0x13,0x67,0x6f,0x61,0x6c,0x43,2,0x68,0x3b,0x6d,0x5c,0x6e,0x1a,0x69,0x66, -0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,1,0x6b,0x2a,0x70,0x10,0x61,0xa3, -0x65,0x15,0x69,0x6e,0x6e,0x61,0x79,0x61,0xa3,0x64,0x1a,0x7a,0x61,0x6f,0x6e,0x68, -0x65,0x68,0x67,0x6f,0x61,0x6c,0x3d,2,0x61,0x3a,0x68,0x44,0x6e,0x17,0x6f,0x74, -0x74,0x65,0x64,0x68,0x65,0x68,0x4b,1,0x66,0x47,0x70,0x10,0x68,0x49,0x12,0x61, -0x70,0x68,0x89,0x11,0x61,0x6d,0x4c,0x12,0x61,0x64,0x68,0x4f,0x61,0x6e,0x62,0xa2, -0x54,0x64,0xa2,0x70,0x65,0x31,0x66,2,0x61,0x3e,0x65,0x4a,0x69,0x19,0x6e,0x61, -0x6c,0x73,0x65,0x6d,0x6b,0x61,0x74,0x68,0x35,0x15,0x72,0x73,0x69,0x79,0x65,0x68, -0x8f,0x86,0x10,0x68,0x33,2,0x66,0x3c,0x69,0x70,0x6c,1,0x61,0x28,0x65,0x10, -0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72,0x69,0x63,0x61,0x6e,2,0x66,0x30,0x6e, -0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11,0x65,0x68,0xa3,0x56,0x12,0x6f,0x6f,0x6e, -0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a,0x75,0x10,0x72,0x1f,0x75,0x73,0x68,0x61, -0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61,0x72,0x72,0x65,0x65,0x8d,1,0x68,0x29, -0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c,0x16,0x61,0x74,0x68,0x72,0x69,0x73,0x68, -0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e,0x74,0x56,0x75,0x21,0x18,0x6f,0x6e,0x6a, -0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28,0x1a,0x69,0x67,0x68,0x74,0x6a,0x6f,0x69, -0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72,0x61,0x6e,0x73,0x70,0x61,0x72,0x65,0x6e, -0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56,0x6c,0x26,0x19,0x65,0x66,0x74,0x6a,0x6f, -0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19,0x75,0x61,0x6c,0x6a,0x6f,0x69,0x6e,0x69, -0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63,0x61,0x75,0x73,0x69,0x6e,0x67,0x23,0, -0x14,0x6e,0xc0,0xe5,0x73,0x5e,0x77,0x23,0x77,0x40,0x78,0x58,0x7a,0x10,0x77,0x58, -1,0x6a,0x75,0x73,0x13,0x70,0x61,0x63,0x65,0x59,1,0x6a,0x5d,0x6f,0x17,0x72, -0x64,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x5d,0x10,0x78,0x21,0x73,0x4a,0x75,0x7a,0x76, -1,0x66,0x7d,0x69,0x7e,0x13,0x72,0x61,0x6d,0x61,0x7e,0x14,0x66,0x69,0x6e,0x61, -0x6c,0x7d,4,0x61,0x51,0x67,0x53,0x70,0x28,0x75,0x30,0x79,0x57,0x54,0x12,0x61, -0x63,0x65,0x55,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x53,0x15,0x6e,0x6b,0x6e, -0x6f,0x77,0x6e,0x21,0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50,0x71,0xa2,0x6e,0x72, -1,0x65,0x24,0x69,0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69, -0x63,0x61,0x74,0x6f,0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f,0x46,0x73,0x45,0x75, -0x46,0x14,0x6d,0x65,0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c,0x69,0x6e,0x65,0x5b, -0x17,0x6e,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70,0x48,0x1c,0x65,0x6e, -0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,1,0x6f,0x3e,0x72, -0x4c,0x1a,0x65,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4d,0x4a,0x1b, -0x73,0x74,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4b,0x10,0x75,0x4e, -0x16,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68,0x50,0x69,0x86,0x6a, -0xa2,0x61,0x6c,0xa2,0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74,0x6f,0x72,0x79,0x62, -0x72,0x65,0x61,0x6b,0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34,0x6c,0x6d,0x79,0x3a, -0x13,0x70,0x68,0x65,0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65, -0x72,0x6d,2,0x64,0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65,0x6f,0x67,0x72,0x61, -0x70,0x68,0x69,0x63,0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65,0x70,1,0x61,0x22, -0x65,0x14,0x72,0x61,0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72, -0x69,0x63,0x41,2,0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66,0x43,0x69,0x15,0x6e, -0x65,0x66,0x65,0x65,0x64,0x43,0x61,0x42,0x62,0xa2,0x49,0x63,0xa2,0x76,0x65,0xa2, -0xfc,0x67,0x10,0x6c,0x38,0x11,0x75,0x65,0x39,5,0x6d,0xf,0x6d,0x28,0x70,0x79, -0x73,0x7b,0x16,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x69,0x23,0x6b,0x38,0x6c, -0x24,0x17,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x25,0x76,0x13,0x73,0x61,0x72, -0x61,0x76,1,0x70,0x2e,0x73,0x13,0x74,0x61,0x72,0x74,0x7b,0x15,0x72,0x65,0x62, -0x61,0x73,0x65,0x79,4,0x32,0x27,0x61,0x29,0x62,0x2b,0x6b,0x2d,0x72,0x12,0x65, -0x61,0x6b,2,0x61,0x36,0x62,0x3e,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x57, -0x13,0x66,0x74,0x65,0x72,0x29,1,0x65,0x2a,0x6f,0x11,0x74,0x68,0x27,0x13,0x66, -0x6f,0x72,0x65,0x2b,7,0x6d,0x51,0x6d,0x33,0x6f,0x28,0x70,0x69,0x72,0x35,1, -0x6d,0x76,0x6e,1,0x64,0x3c,0x74,0x1a,0x69,0x6e,0x67,0x65,0x6e,0x74,0x62,0x72, -0x65,0x61,0x6b,0x2f,0x15,0x69,0x74,0x69,0x6f,0x6e,0x61,0x1f,0x6c,0x6a,0x61,0x70, -0x61,0x6e,0x65,0x73,0x65,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x6b,1,0x62,0x3a, -0x70,0x19,0x6c,0x65,0x78,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x51,0x18,0x69,0x6e, -0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x33,0x61,0x6a,0x62,0x2f,0x6a,0x6b,0x6c,0x30, -0x13,0x6f,0x73,0x65,0x70,1,0x61,0x38,0x75,0x18,0x6e,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0x31,0x18,0x72,0x65,0x6e,0x74,0x68,0x65,0x73,0x69,0x73,0x69,0x1b, -0x72,0x72,0x69,0x61,0x67,0x65,0x72,0x65,0x74,0x75,0x72,0x6e,0x35,2,0x62,0x3e, -0x6d,0x46,0x78,0x36,0x18,0x63,0x6c,0x61,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x37,0x70, -0x12,0x61,0x73,0x65,0x71,0x72,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x73,1, -0x64,0x42,0x6e,1,0x6f,0x32,0x75,0x26,0x14,0x6d,0x65,0x72,0x69,0x63,0x27,0x11, -0x6e,0x65,0x21,1,0x65,0x2e,0x69,0x24,0x12,0x67,0x69,0x74,0x25,0x22,0x14,0x63, -0x69,0x6d,0x61,0x6c,0x23,0,0x18,0x6e,0xc4,0x6f,0x74,0xc1,0x91,0x77,0x96,0x77, -0xa2,0x4c,0x78,0xa2,0x70,0x79,0xa2,0x7a,0x7a,6,0x73,0x1e,0x73,0x34,0x78,0x42, -0x79,0x48,0x7a,0x11,0x7a,0x7a,0xa3,0x67,0x10,0x79,1,0x65,0xa3,0xae,0x6d,0xa3, -0x81,0x11,0x78,0x78,0xa3,0x66,0x11,0x79,0x79,0x21,0x61,0x30,0x69,0x58,0x6d,0x11, -0x74,0x68,0xa3,0x80,0x10,0x6e,1,0x61,0x26,0x62,0xa3,0xb1,0x1a,0x62,0x61,0x7a, -0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa3,0xb1,0x11,0x6e,0x68,0x23,2,0x61, -0x30,0x63,0x5a,0x6f,0x11,0x6c,0x65,0xa3,0x9b,1,0x6e,0x3c,0x72,0x10,0x61,0xa2, -0x92,0x15,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0x92,0x12,0x63,0x68,0x6f,0xa3,0xbc, -0x11,0x68,0x6f,0xa3,0xbc,1,0x70,0x2c,0x73,0x11,0x75,0x78,0xa3,0x65,0x11,0x65, -0x6f,0x9b,1,0x65,0x2c,0x69,0x72,0x11,0x69,0x69,0x73,0x11,0x7a,0x69,0xa2,0xc0, -0x11,0x64,0x69,0xa3,0xc0,0x74,0x66,0x75,0xa2,0xde,0x76,1,0x61,0x48,0x69,1, -0x73,0x38,0x74,0x10,0x68,0xa2,0xc5,0x13,0x6b,0x75,0x71,0x69,0xa3,0xc5,0x10,0x70, -0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,7,0x68,0x3e,0x68,0x34,0x69, -0x48,0x6e,0x86,0x6f,0x11,0x74,0x6f,0xa3,0xc4,0x10,0x61,1,0x61,0x24,0x69,0x6d, -0x6a,0x11,0x6e,0x61,0x6b,2,0x62,0x3a,0x66,0x4a,0x72,0x10,0x68,0xa2,0x9e,0x12, -0x75,0x74,0x61,0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12,0x74,0x61,0x6e,0x6f,0x14, -0x69,0x6e,0x61,0x67,0x68,0x99,0x11,0x73,0x61,0xa3,0xc3,0x61,0x36,0x65,0xa2,0x65, -0x66,0xa2,0x71,0x67,0x11,0x6c,0x67,0x75,6,0x6c,0x28,0x6c,0x32,0x6d,0x38,0x6e, -0x44,0x76,0x10,0x74,0xa3,0x7f,1,0x65,0x89,0x75,0x97,1,0x69,0x24,0x6c,0x67, -0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a,1,0x73,0x2a,0x75,0x10,0x74,0xa3,0x9a,0x10, -0x61,0xa3,0xc3,0x67,0x36,0x69,0x52,0x6b,0x10,0x72,0xa2,0x99,0x10,0x69,0xa3,0x99, -1,0x61,0x30,0x62,0x7a,0x13,0x61,0x6e,0x77,0x61,0x7b,0x12,0x6c,0x6f,0x67,0x75, -2,0x6c,0x32,0x74,0x34,0x76,0x12,0x69,0x65,0x74,0xa3,0x7f,0x10,0x65,0x89,0x12, -0x68,0x61,0x6d,0xa3,0x6a,1,0x6c,0x2a,0x6e,0x10,0x67,0xa3,0x62,0x10,0x75,0x68, -0x11,0x67,0x75,0x69,0x11,0x6e,0x67,0x99,1,0x67,0x32,0x6e,0x14,0x6b,0x6e,0x6f, -0x77,0x6e,0xa3,0x67,0x11,0x61,0x72,0x8a,0x13,0x69,0x74,0x69,0x63,0x8b,0x71,0xc1, -0x13,0x71,0xa2,0xde,0x72,0xa2,0xe3,0x73,6,0x69,0x8a,0x69,0x72,0x6f,0xa2,0x4c, -0x75,0xa2,0x75,0x79,1,0x6c,0x46,0x72,4,0x63,0x65,0x65,0xa3,0x5f,0x69,0x2c, -0x6a,0xa3,0x60,0x6e,0xa3,0x61,0x11,0x61,0x63,0x65,0x10,0x6f,0x94,0x16,0x74,0x69, -0x6e,0x61,0x67,0x72,0x69,0x95,2,0x64,0x3c,0x67,0x4c,0x6e,1,0x64,0xa3,0x91, -0x68,0x62,0x12,0x61,0x6c,0x61,0x63,0x10,0x64,0xa2,0xa6,0x12,0x68,0x61,0x6d,0xa3, -0xa6,0x17,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa3,0x70,2,0x67,0x3a,0x72, -0x52,0x79,0x10,0x6f,0xa2,0xb0,0x12,0x6d,0x62,0x6f,0xa3,0xb0,1,0x64,0x26,0x6f, -0xa3,0xb8,0xa2,0xb7,0x12,0x69,0x61,0x6e,0xa3,0xb7,0x10,0x61,0xa2,0x98,0x16,0x73, -0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0x98,0x11,0x6e,0x64,0xa2,0x71,0x14,0x61,0x6e, -0x65,0x73,0x65,0xa3,0x71,0x61,0x5c,0x67,0xa2,0x43,0x68,1,0x61,0x2a,0x72,0x10, -0x64,0xa3,0x97,2,0x72,0x28,0x76,0x30,0x77,0x87,0x12,0x61,0x64,0x61,0xa3,0x97, -0x12,0x69,0x61,0x6e,0x87,2,0x6d,0x40,0x72,0x58,0x75,0x10,0x72,0xa2,0x6f,0x15, -0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0x6f,1,0x61,0x26,0x72,0xa3,0x7e,0x14,0x72, -0x69,0x74,0x61,0x6e,0xa3,0x7e,1,0x61,0xa3,0x5e,0x62,0xa3,0x85,0x11,0x6e,0x77, -0xa3,0x70,0x11,0x61,0x61,1,0x63,0x2f,0x69,0x23,3,0x65,0x3e,0x6a,0x48,0x6f, -0x4e,0x75,0x10,0x6e,1,0x69,0x24,0x72,0x61,0x10,0x63,0x61,0x13,0x6a,0x61,0x6e, -0x67,0xa3,0x6e,0x11,0x6e,0x67,0xa3,0x6e,1,0x68,0x2a,0x72,0x10,0x6f,0xa3,0x5d, -0x10,0x67,0xa3,0xb6,0x6e,0xa2,0x83,0x6f,0xa4,1,0x70,5,0x6c,0x1e,0x6c,0x44, -0x72,0x4a,0x73,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69, -0xa3,0x7b,0x11,0x72,0x64,0xa3,0x5c,0x11,0x74,0x69,0xa3,0x7d,0x61,0x7c,0x65,0xa2, -0x54,0x68,3,0x61,0x3e,0x6c,0x4e,0x6e,0x5e,0x6f,0x16,0x65,0x6e,0x69,0x63,0x69, -0x61,0x6e,0xa3,0x5b,0x10,0x67,0xa2,0x5a,0x12,0x73,0x70,0x61,0xa3,0x5a,2,0x69, -0xa3,0x7a,0x70,0xa3,0x7b,0x76,0xa3,0x7c,0x10,0x78,0xa3,0x5b,2,0x68,0x3e,0x6c, -0x50,0x75,0x10,0x63,0xa2,0xa5,0x14,0x69,0x6e,0x68,0x61,0x75,0xa3,0xa5,0x17,0x61, -0x77,0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0x4b,0x10,0x6d,0xa2,0x90,0x14,0x79,0x72, -0x65,0x6e,0x65,0xa3,0x90,0x11,0x72,0x6d,0xa3,0x59,6,0x6b,0x36,0x6b,0x56,0x73, -0x6e,0x75,0x74,0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63, -0x68,0x75,0x65,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xba,1,0x67,0x2e,0x6f,0xa2,0x57, -0x10,0x6f,0xa3,0x57,0x10,0x62,0xa3,0x84,0x11,0x68,0x75,0xa3,0x96,0x12,0x73,0x68, -0x75,0xa3,0x96,0x61,0x42,0x62,0x9e,0x65,0x10,0x77,1,0x61,0xa3,0xaa,0x74,0x14, -0x61,0x69,0x6c,0x75,0x65,0x97,3,0x62,0x32,0x67,0x40,0x6e,0x56,0x72,0x10,0x62, -0xa3,0x8e,0x15,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3,0x8f,0x10,0x6d,0xa2,0xc7,0x15, -0x75,0x6e,0x64,0x61,0x72,0x69,0xa3,0xc7,0x10,0x64,0xa2,0xbb,0x16,0x69,0x6e,0x61, -0x67,0x61,0x72,0x69,0xa3,0xbb,0x11,0x61,0x74,0xa3,0x8f,4,0x67,0x3c,0x6c,0x4e, -0x72,0xa2,0x8e,0x73,0xa2,0x9c,0x75,0x11,0x67,0x72,0xa3,0xc2,1,0x61,0x2a,0x68, -0x11,0x61,0x6d,0x5b,0x10,0x6d,0x5b,1,0x63,0xa2,0x6a,0x64,6,0x70,0x41,0x70, -0x3a,0x73,0x58,0x74,0x86,0x75,0x14,0x79,0x67,0x68,0x75,0x72,0xa3,0xc2,0x11,0x65, -0x72,1,0x6d,0x2c,0x73,0x12,0x69,0x61,0x6e,0x9b,0x11,0x69,0x63,0xa3,0x59,0x10, -0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3, -0x85,0x13,0x64,0x69,0x61,0x6e,0xa3,0xb8,0x14,0x75,0x72,0x6b,0x69,0x63,0xa3,0x58, -0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61, -0x6e,0xa3,0x8e,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa3,0x4c,0x14,0x74, -0x61,0x6c,0x69,0x63,0x5d,1,0x68,0x26,0x6b,0xa3,0x6d,0x12,0x69,0x6b,0x69,0xa3, -0x6d,2,0x69,0x2c,0x6b,0x30,0x79,0x10,0x61,0x5f,0x11,0x79,0x61,0x5f,0x10,0x68, -0xa3,0x58,2,0x61,0x36,0x67,0x3c,0x6d,0x10,0x61,0x84,0x12,0x6e,0x79,0x61,0x85, -0x11,0x67,0x65,0xa3,0xab,0x10,0x65,0xa3,0xab,0x68,0xc3,0x15,0x6b,0xc2,0x2c,0x6b, -0xa4,0x17,0x6c,0xa4,0xba,0x6d,8,0x6f,0x46,0x6f,0x48,0x72,0x74,0x74,0x80,0x75, +0x71,0x12,0x6a,0x6b,0x69,0xa3,0xe5,0x67,0xa2,0xb5,0x68,0xa4,0x97,0x69,3,0x64, +0x4c,0x6d,0xa2,0x55,0x6e,0xa2,0x62,0x70,0x13,0x61,0x65,0x78,0x74,0x2a,0x16,0x65, +0x6e,0x73,0x69,0x6f,0x6e,0x73,0x2b,1,0x63,0x99,0x65,0x17,0x6f,0x67,0x72,0x61, +0x70,0x68,0x69,0x63,1,0x64,0x56,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa4, +0xb,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, +0xa5,0xb,0x13,0x65,0x73,0x63,0x72,0x1f,0x69,0x70,0x74,0x69,0x6f,0x6e,0x63,0x68, +0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x73,0x99,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c, +0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0xba,1,0x64,0x62,0x73,0x1b,0x63,0x72, +0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74, +0x68,0x69,0x61,0x6e,0xa3,0xbd,0x13,0x6c,0x61,0x76,0x69,0xa3,0xbe,0x11,0x69,0x63, +1,0x6e,0x3e,0x73,0x1a,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73, +0xa5,0x1e,0x19,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2,5, +0x6f,0x61,0x6f,0x80,0x72,0x8a,0x75,2,0x6a,0x4e,0x6e,0x58,0x72,1,0x6d,0x36, +0x75,0x16,0x6e,0x67,0x6b,0x68,0x65,0x6d,0x61,0xa5,0x4b,0x13,0x75,0x6b,0x68,0x69, +0x43,0x14,0x61,0x72,0x61,0x74,0x69,0x45,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e, +0x64,0x69,0xa5,0x1c,0x13,0x74,0x68,0x69,0x63,0xa3,0x59,1,0x61,0x5c,0x65,0x11, +0x65,0x6b,0x30,1,0x61,0x38,0x65,0x11,0x78,0x74,0x6e,0x14,0x65,0x6e,0x64,0x65, +0x64,0x6f,0x17,0x6e,0x64,0x63,0x6f,0x70,0x74,0x69,0x63,0x31,0x13,0x6e,0x74,0x68, +0x61,0xa3,0xe4,0x61,0x5c,0x65,0x64,0x6c,0x17,0x61,0x67,0x6f,0x6c,0x69,0x74,0x69, +0x63,0xa2,0x88,0x12,0x73,0x75,0x70,0xa4,0xa,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e, +0x74,0xa5,0xa,0x12,0x72,0x61,0x79,0xa5,0x4a,1,0x6e,0xa2,0x46,0x6f,1,0x6d, +0x6e,0x72,0x13,0x67,0x69,0x61,0x6e,0x5a,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2, +0x87,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x87,0x11,0x78,0x74,0xa4,0x1b, +0x14,0x65,0x6e,0x64,0x65,0x64,0xa5,0x1b,0x1a,0x65,0x74,0x72,0x69,0x63,0x73,0x68, +0x61,0x70,0x65,0x73,0x8c,0x12,0x65,0x78,0x74,0xa2,0xe3,0x14,0x65,0x6e,0x64,0x65, +0x64,0xa3,0xe3,0x1e,0x65,0x72,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, +0x69,0x6f,0x6e,0x71,2,0x61,0xa2,0x48,0x65,0xa2,0xdf,0x69,1,0x67,0x30,0x72, +0x14,0x61,0x67,0x61,0x6e,0x61,0x9d,0x10,0x68,1,0x70,0x3a,0x73,0x18,0x75,0x72, +0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4b,1,0x72,0x3c,0x75,0x19,0x73,0x75, +0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,0x11,0x69,0x76,0x1f,0x61,0x74, +0x65,0x75,0x73,0x65,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c, +2,0x6c,0x32,0x6e,0x9a,0x74,0x12,0x72,0x61,0x6e,0xa5,2,0x10,0x66,2,0x61, +0x58,0x6d,0x70,0x77,0x14,0x69,0x64,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x75,0x6c, +0x6c,0x77,0x69,0x64,0x74,0x68,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x1a,0x6e,0x64, +0x66,0x75,0x6c,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x13,0x61,0x72,0x6b,0x73, +0xa3,0x52,2,0x67,0x34,0x69,0xa2,0x45,0x75,0x12,0x6e,0x6f,0x6f,0xa3,0x63,0x11, +0x75,0x6c,0xa2,0x4a,2,0x63,0x3c,0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62, +0x6c,0x65,0x73,0xa3,0x4a,0x1f,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c,0x69, +0x74,0x79,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17,0x65,0x78, +0x74,0x65,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x19,0x66,0x69, +0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa5,0x1d,0x13,0x62,0x72,0x65,0x77,0x37, +0x61,0xa4,0x1d,0x62,0xa6,0x6a,0x63,0xa8,0x3f,0x64,0xac,0xfa,0x65,5,0x6d,0xa9, +0x6d,0x94,0x6e,0xa2,0x41,0x74,0x15,0x68,0x69,0x6f,0x70,0x69,0x63,0x5e,1,0x65, +0x40,0x73,0x11,0x75,0x70,0xa2,0x86,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, +0x86,0x11,0x78,0x74,0xa2,0x85,2,0x61,0xa3,0xc8,0x62,0xa5,0x37,0x65,0x13,0x6e, +0x64,0x65,0x64,0xa2,0x85,1,0x61,0xa3,0xc8,0x62,0xa5,0x37,0x16,0x6f,0x74,0x69, +0x63,0x6f,0x6e,0x73,0xa3,0xce,0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2,0x61,0x5a, +0x63,0x9e,0x69,0x1c,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x75, +0x70,0xa2,0xc4,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16,0x6c,0x70, +0x68,0x61,0x6e,0x75,0x6d,0x86,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0xc3,0x13, +0x72,0x69,0x63,0x73,0x86,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, +0xc3,0x11,0x6a,0x6b,0xa2,0x44,0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x61,0x6e, +0x64,0x6d,0x6f,0x6e,0x74,0x68,0x73,0xa3,0x44,0x61,0x4a,0x67,0x76,0x6c,1,0x62, +0x30,0x79,0x13,0x6d,0x61,0x69,0x63,0xa5,0x25,0x13,0x61,0x73,0x61,0x6e,0xa3,0xe2, +0x13,0x72,0x6c,0x79,0x64,0x1f,0x79,0x6e,0x61,0x73,0x74,0x69,0x63,0x63,0x75,0x6e, +0x65,0x69,0x66,0x6f,0x72,0x6d,0xa5,1,0x1f,0x79,0x70,0x74,0x69,0x61,0x6e,0x68, +0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,1,0x66,0x48,0x73,0xa2,0xc2,0x12, +0x65,0x78,0x74,1,0x61,0xa5,0x49,0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa5,0x49, +0x1c,0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa5,0x24, +7,0x6e,0xc0,0xf2,0x6e,0x3e,0x72,0xa2,0x5d,0x73,0xa2,0xe5,0x76,0x14,0x65,0x73, +0x74,0x61,0x6e,0xa3,0xbc,1,0x61,0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1,0x67, +0x34,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65,0x6b, +1,0x6d,0x34,0x6e,0x15,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75,0x73, +0x69,0x63,0xa2,0x7e,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa3, +0x7e,0x10,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c, +0x79,0x70,0x68,0x73,0xa3,0xfe,2,0x61,0x32,0x6d,0xa2,0x7e,0x72,0x12,0x6f,0x77, +0x73,0x7d,0x12,0x62,0x69,0x63,0x38,3,0x65,0x4a,0x6d,0x80,0x70,0xa2,0x50,0x73, +0x11,0x75,0x70,0xa2,0x80,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80,0x11, +0x78,0x74,3,0x61,0xa3,0xd2,0x62,0xa5,0x35,0x63,0xa5,0x41,0x65,0x13,0x6e,0x64, +0x65,0x64,2,0x61,0xa3,0xd2,0x62,0xa5,0x35,0x63,0xa5,0x41,0x12,0x61,0x74,0x68, +0xa2,0xd3,0x18,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x61,0x1f,0x6c,0x70,0x68, +0x61,0x62,0x65,0x74,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd3,1, +0x66,0x42,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f, +0x72,0x6d,0x73,1,0x61,0xa3,0x51,0x62,0xa3,0x55,0x14,0x65,0x6e,0x69,0x61,0x6e, +0x35,0x12,0x63,0x69,0x69,0x23,0x64,0x9e,0x65,0xa2,0x42,0x68,0xa2,0x4d,0x6c,1, +0x63,0x62,0x70,0x17,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x70,1,0x66,0xa3,0x50, +0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d, +0x73,0xa3,0x50,0x16,0x68,0x65,0x6d,0x69,0x63,0x61,0x6c,0xa2,0xd0,0x16,0x73,0x79, +0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd0,0x12,0x6c,0x61,0x6d,0xa5,7,0x1a,0x67,0x65, +0x61,0x6e,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x77,0x11,0x6f,0x6d,0xa3,0xfd, +7,0x6f,0x71,0x6f,0x64,0x72,0xa2,0x41,0x75,0xa2,0x58,0x79,0x1b,0x7a,0x61,0x6e, +0x74,0x69,0x6e,0x65,0x6d,0x75,0x73,0x69,0x63,0xa2,0x5b,0x18,0x61,0x6c,0x73,0x79, +0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5b,1,0x70,0x34,0x78,0x16,0x64,0x72,0x61,0x77, +0x69,0x6e,0x67,0x89,0x14,0x6f,0x6d,0x6f,0x66,0x6f,0xa0,0x12,0x65,0x78,0x74,0xa2, +0x43,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0x43,0x10,0x61,1,0x68,0x40,0x69,0x12, +0x6c,0x6c,0x65,0x92,0x17,0x70,0x61,0x74,0x74,0x65,0x72,0x6e,0x73,0x93,0x11,0x6d, +0x69,0xa3,0xc9,1,0x67,0x2c,0x68,0x11,0x69,0x64,0xa3,0x64,0x14,0x69,0x6e,0x65, +0x73,0x65,0xa3,0x81,0x61,0x48,0x65,0xa2,0x4e,0x68,0xa2,0x52,0x6c,0x1a,0x6f,0x63, +0x6b,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x8b,3,0x6c,0x34,0x6d,0x40,0x73, +0x66,0x74,0x11,0x61,0x6b,0xa3,0xc7,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x93,0x11, +0x75,0x6d,0xa2,0xb1,0x12,0x73,0x75,0x70,0xa2,0xca,0x16,0x70,0x6c,0x65,0x6d,0x65, +0x6e,0x74,0xa3,0xca,1,0x69,0x30,0x73,0x13,0x61,0x76,0x61,0x68,0xa3,0xdd,0x15, +0x63,0x6c,0x61,0x74,0x69,0x6e,0x23,0x14,0x6e,0x67,0x61,0x6c,0x69,0x41,0x16,0x61, +0x69,0x6b,0x73,0x75,0x6b,0x69,0xa5,8,5,0x6f,0xc1,0x60,0x6f,0xa2,0x69,0x75, +0xa4,0x24,0x79,1,0x70,0xa2,0x44,0x72,0x14,0x69,0x6c,0x6c,0x69,0x63,0x32,1, +0x65,0x4c,0x73,0x11,0x75,0x70,0xa2,0x61,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, +0xa2,0x61,0x12,0x61,0x72,0x79,0xa3,0x61,0x11,0x78,0x74,4,0x61,0xa3,0x9e,0x62, +0xa3,0xa0,0x63,0xa5,9,0x64,0xa5,0x43,0x65,0x13,0x6e,0x64,0x65,0x64,3,0x61, +0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5,9,0x64,0xa5,0x43,0x10,0x72,1,0x69,0x34, +0x6f,0x15,0x6d,0x69,0x6e,0x6f,0x61,0x6e,0xa5,0x36,0x1a,0x6f,0x74,0x73,0x79,0x6c, +0x6c,0x61,0x62,0x61,0x72,0x79,0xa3,0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2, +0xa0,0x75,0x17,0x6e,0x74,0x69,0x6e,0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75, +0x6d,0x65,0x72,0x61,0x6c,0x73,0xa3,0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15, +0x61,0x74,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64, +0x46,0x68,0x9e,0x6d,0x1d,0x61,0x72,0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62, +0x6f,0x6c,0x73,0x77,0x1e,0x69,0x61,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d, +0x61,0x72,0x6b,0x73,0x2e,2,0x65,0x40,0x66,0xa6,0x52,0x73,0x18,0x75,0x70,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64, +0xa3,0xe0,0x17,0x61,0x6c,0x66,0x6d,0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e, +0x1f,0x69,0x6e,0x64,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d, +0x73,0xa3,0xb2,0x1b,0x74,0x72,0x6f,0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73, +0x83,0x12,0x74,0x69,0x63,0xa2,0x84,0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d, +0x62,0x65,0x72,0x73,0xa3,0xdf,1,0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79, +0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2, +0x98,0x16,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70, +0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xea,0x68, +0xa4,0x14,0x6a,0x10,0x6b,0xa2,0x47,4,0x63,0x92,0x65,0xa2,0x83,0x72,0xa2,0xa1, +0x73,0xa2,0xb3,0x75,0x1f,0x6e,0x69,0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67, +0x72,0x61,0x70,0x68,0x73,0xa2,0x47,0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f, +0x6e,8,0x65,0x71,0x65,0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e,0x68,0xa5,0x42, +0x69,0xa5,0x48,0x14,0x6f,0x6d,0x70,0x61,0x74,0xa2,0x45,1,0x66,0x96,0x69,1, +0x62,0x44,0x64,0x17,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x12,0x73, +0x75,0x70,0xa3,0x5f,0x14,0x69,0x6c,0x69,0x74,0x79,0xa2,0x45,1,0x66,0x54,0x69, +0x18,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x19,0x73,0x75,0x70, +0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x5f,0x13,0x6f,0x72,0x6d,0x73,0xa3,0x53, +0x11,0x78,0x74,8,0x65,0xf,0x65,0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e,0x68, +0xa5,0x42,0x69,0xa5,0x48,0x61,0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3,0xc5,0x64,0xa3, +0xd1,0x19,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x73,0x75,0x70,0x94,0x16,0x70,0x6c, +0x65,0x6d,0x65,0x6e,0x74,0x95,1,0x74,0x50,0x79,0x14,0x6d,0x62,0x6f,0x6c,0x73, +0x9a,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, +0x9b,0x14,0x72,0x6f,0x6b,0x65,0x73,0xa3,0x82,2,0x6e,0x48,0x72,0x64,0x75,0x1d, +0x63,0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0xde, +0x1d,0x61,0x64,0x69,0x61,0x6e,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x63, +0x12,0x69,0x61,0x6e,0xa3,0xa8,2,0x61,0x3a,0x65,0x4c,0x6f,0x16,0x72,0x61,0x73, +0x6d,0x69,0x61,0x6e,0xa5,0x2d,1,0x6b,0x26,0x6d,0xa3,0xa4,0x11,0x6d,0x61,0xa3, +0xd4,1,0x72,0x38,0x73,0x17,0x73,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa5,0x19, +0x13,0x6f,0x6b,0x65,0x65,0x60,0x12,0x73,0x75,0x70,0xa2,0xff,0x16,0x70,0x6c,0x65, +0x6d,0x65,0x6e,0x74,0xa3,0xff,3,0x65,0x3e,0x69,0x8e,0x6f,0xa2,0x71,0x75,0x15, +0x70,0x6c,0x6f,0x79,0x61,0x6e,0xa3,0xe1,1,0x73,0x60,0x76,0x16,0x61,0x6e,0x61, +0x67,0x61,0x72,0x69,0x3e,0x12,0x65,0x78,0x74,0xa2,0xb3,1,0x61,0xa5,0x44,0x65, +0x13,0x6e,0x64,0x65,0x64,0xa2,0xb3,0x10,0x61,0xa5,0x44,0x13,0x65,0x72,0x65,0x74, +0xa3,0x5a,2,0x61,0x3a,0x6e,0x82,0x76,0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75, +0xa5,0x2f,0x18,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x73,0x2e,2,0x65,0x30, +0x66,0x36,0x73,0x11,0x75,0x70,0xa3,0x83,0x11,0x78,0x74,0xa3,0xe0,0x18,0x6f,0x72, +0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,0x14,0x67,0x62,0x61,0x74,0x73,0x91,1, +0x67,0x3e,0x6d,0x12,0x69,0x6e,0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3, +0xab,0x11,0x72,0x61,0xa5,0x1a,8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48,0x73,0x7a,0x76, +0xa2,0x4b,0x77,0x12,0x69,0x64,0x65,0x43,0x11,0x65,0x64,0x32,0x12,0x69,0x61,0x6c, +0x33,2,0x61,0x40,0x62,0x37,0x6f,1,0x62,0x28,0x6e,0x10,0x65,0x21,0x13,0x72, +0x65,0x61,0x6b,0x37,0x10,0x72,0x34,0x12,0x72,0x6f,0x77,0x35,2,0x6d,0x38,0x71, +0x46,0x75,1,0x62,0x3d,0x70,0x3e,0x11,0x65,0x72,0x3f,1,0x61,0x24,0x6c,0x39, +0x11,0x6c,0x6c,0x39,1,0x72,0x3b,0x75,0x12,0x61,0x72,0x65,0x3b,0x12,0x65,0x72, +0x74,0x40,0x13,0x69,0x63,0x61,0x6c,0x41,0x63,0x58,0x65,0x92,0x66,0x96,0x69,1, +0x6e,0x36,0x73,0x10,0x6f,0x30,0x14,0x6c,0x61,0x74,0x65,0x64,0x31,0x11,0x69,0x74, +0x2e,0x12,0x69,0x61,0x6c,0x2f,2,0x61,0x36,0x69,0x48,0x6f,0x10,0x6d,0x24,0x12, +0x70,0x61,0x74,0x25,0x10,0x6e,0x22,0x15,0x6f,0x6e,0x69,0x63,0x61,0x6c,0x23,0x13, +0x72,0x63,0x6c,0x65,0x27,0x11,0x6e,0x63,0x27,2,0x69,0x3a,0x6f,0x44,0x72,0x10, +0x61,0x2c,0x14,0x63,0x74,0x69,0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11,0x61,0x6c,0x29, +0x11,0x6e,0x74,0x2b,4,0x61,0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70,0x77,0x2a,0x12, +0x69,0x64,0x65,0x2b,0x22,0x17,0x6d,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x26, +0x17,0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x27,0x24,0x17,0x61,0x6c,0x66,0x77, +0x69,0x64,0x74,0x68,0x25,0x20,1,0x61,0x30,0x65,0x14,0x75,0x74,0x72,0x61,0x6c, +0x21,0x28,0x13,0x72,0x72,0x6f,0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73,0x6d,0x73,0x3a, +0x74,0x98,0x75,0xa2,0x49,0x7a,2,0x6c,0x3b,0x70,0x3d,0x73,0x39,5,0x6f,0x28, +0x6f,0x57,0x70,0x34,0x75,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x45,0x11,0x61, +0x63,1,0x65,0x32,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31,0x18,0x73,0x65, +0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x39,0x63,0x53,0x6b,0x55,0x6d,0x51,0x1d,0x69, +0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x27,1,0x6e, +0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72, +0x23,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a,0x6f,0xa2,0x47, +0x70,8,0x66,0x14,0x66,0x5b,0x69,0x59,0x6f,0x4f,0x72,0x24,0x73,0x49,0x17,0x69, +0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x43,0x61,0x2c,0x63,0x4d,0x64,0x47,0x65,0x4b, +0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f, +0x72,0x3d,2,0x64,0x33,0x6c,0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69, +0x6e,0x67,0x6d,0x61,0x72,0x6b,0x2d,1,0x70,0x7c,0x74,0x12,0x68,0x65,0x72,3, +0x6c,0x38,0x6e,0x42,0x70,0x4c,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x57,0x14,0x65, +0x74,0x74,0x65,0x72,0x2b,0x14,0x75,0x6d,0x62,0x65,0x72,0x37,0x19,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74, +0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,0x66,0x9e,0x66,0x88,0x69,0xa2,0x4b,0x6c,0xa2, +0x5c,0x6d,4,0x61,0x60,0x63,0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15,0x64,0x69,0x66, +0x69,0x65,0x72,1,0x6c,0x30,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x55,0x14,0x65, +0x74,0x74,0x65,0x72,0x29,0x17,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x51,1, +0x69,0x2e,0x6f,0x13,0x72,0x6d,0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e, +0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61, +0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,6,0x6d,0x18, +0x6d,0x29,0x6f,0x28,0x74,0x27,0x75,0x23,0x2a,0x1c,0x77,0x65,0x72,0x63,0x61,0x73, +0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x25,0x65,0x28,0x69,0x3c,0x6c,0x25,0x19,0x74, +0x74,0x65,0x72,0x6e,0x75,0x6d,0x62,0x65,0x72,0x35,0x1a,0x6e,0x65,0x73,0x65,0x70, +0x61,0x72,0x61,0x74,0x6f,0x72,0x3b,0x63,0x44,0x64,0xa2,0x60,0x65,0x1b,0x6e,0x63, +0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x2f,6,0x6e,0x39,0x6e,0x46, +0x6f,0x4e,0x73,0x45,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62, +0x6f,0x6c,0x53,0x20,0x12,0x74,0x72,0x6c,0x3f,0x42,0x10,0x6e,1,0x6e,0x2c,0x74, +0x12,0x72,0x6f,0x6c,0x3f,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74, +0x75,0x61,0x74,0x69,0x6f,0x6e,0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d,0x6f,0x73,0x65, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4b,2,0x61,0x30,0x65, +0x4a,0x69,0x12,0x67,0x69,0x74,0x33,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x47,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62, +0x65,0x72,0x33,0,0x13,0x6e,0xc1,0xf,0x74,0x76,0x74,0x4c,0x76,0x9a,0x77,0xa2, +0x48,0x79,0xa2,0x49,0x7a,1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e,0x8b,0x11,0x69, +0x6e,0x85,2,0x61,0x36,0x65,0x3c,0x68,0x14,0x69,0x6e,0x79,0x65,0x68,0xa3,0x66, +1,0x68,0x71,0x77,0x73,1,0x68,0x28,0x74,0x10,0x68,0x77,0x16,0x6d,0x61,0x72, +0x62,0x75,0x74,0x61,0x74,0x13,0x67,0x6f,0x61,0x6c,0x3d,0x1a,0x65,0x72,0x74,0x69, +0x63,0x61,0x6c,0x74,0x61,0x69,0x6c,0xa3,0x67,0x11,0x61,0x77,0x79,1,0x65,0x32, +0x75,0x11,0x64,0x68,0x80,0x11,0x68,0x65,0x83,0x10,0x68,0x7a,1,0x62,0x34,0x77, +0x16,0x69,0x74,0x68,0x74,0x61,0x69,0x6c,0x7f,0x14,0x61,0x72,0x72,0x65,0x65,0x7d, +0x6e,0xa2,0x4c,0x70,0xa2,0x69,0x71,0xa2,0x69,0x72,0xa2,0x6f,0x73,5,0x74,0x22, +0x74,0x38,0x77,0x4c,0x79,0x16,0x72,0x69,0x61,0x63,0x77,0x61,0x77,0x6f,0x18,0x72, +0x61,0x69,0x67,0x68,0x74,0x77,0x61,0x77,0xa3,0x55,0x15,0x61,0x73,0x68,0x6b,0x61, +0x66,0x6d,0x61,0x2e,0x65,0x38,0x68,0x11,0x69,0x6e,0x6b,0x10,0x64,0x62,0x11,0x68, +0x65,0x65,1,0x65,0x2e,0x6d,0x13,0x6b,0x61,0x74,0x68,0x69,0x10,0x6e,0x67,2, +0x6f,0x2c,0x75,0x50,0x79,0x10,0x61,0x91,1,0x6a,0x28,0x6f,0x10,0x6e,0x55,0x1a, +0x6f,0x69,0x6e,0x69,0x6e,0x67,0x67,0x72,0x6f,0x75,0x70,0x21,0x10,0x6e,0x57,0x10, +0x65,0x59,0x10,0x61,1,0x66,0x5b,0x70,0x10,0x68,0x5d,1,0x65,0x38,0x6f,0x18, +0x68,0x69,0x6e,0x67,0x79,0x61,0x79,0x65,0x68,0x93,1,0x68,0x5f,0x76,0x16,0x65, +0x72,0x73,0x65,0x64,0x70,0x65,0x61,0x67,0xc1,0xd4,0x67,0xa4,0x52,0x68,0xa4,0x59, +0x6b,0xa4,0x99,0x6c,0xa4,0xbf,0x6d,2,0x61,0x2e,0x65,0xa4,0x3e,0x69,0x10,0x6d, +0x53,1,0x6c,0xa2,0xe7,0x6e,0x16,0x69,0x63,0x68,0x61,0x65,0x61,0x6e,0,0x12, +0x6e,0x76,0x73,0x51,0x73,0x3e,0x74,0x5c,0x77,0xa0,0x79,0xa2,0x42,0x7a,0x13,0x61, +0x79,0x69,0x6e,0xa3,0x54,0x10,0x61,1,0x64,0x2e,0x6d,0x12,0x65,0x6b,0x68,0xa3, +0x4c,0x11,0x68,0x65,0xa3,0x4b,3,0x61,0x38,0x65,0x3c,0x68,0x4a,0x77,0x13,0x65, +0x6e,0x74,0x79,0xa3,0x51,0x10,0x77,0xa3,0x4d,1,0x6e,0xa3,0x4e,0x74,0x10,0x68, +0xa3,0x4f,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x50,0x11,0x61,0x77,0xa3,0x52,0x12, +0x6f,0x64,0x68,0xa3,0x53,0x6e,0x3a,0x6f,0x40,0x70,0x46,0x71,0x4a,0x72,0x12,0x65, +0x73,0x68,0xa3,0x4a,0x11,0x75,0x6e,0xa3,0x46,0x11,0x6e,0x65,0xa3,0x47,0x10,0x65, +0xa3,0x48,0x12,0x6f,0x70,0x68,0xa3,0x49,0x67,0x33,0x67,0x38,0x68,0x40,0x6b,0x5e, +0x6c,0x66,0x6d,0x11,0x65,0x6d,0xa3,0x45,0x13,0x69,0x6d,0x65,0x6c,0xa1,1,0x65, +0x32,0x75,0x14,0x6e,0x64,0x72,0x65,0x64,0xa3,0x42,0x11,0x74,0x68,0xa3,0x41,0x12, +0x61,0x70,0x68,0xa3,0x43,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x44,0x61,0x34,0x62, +0x4a,0x64,0x50,0x66,0x12,0x69,0x76,0x65,0x9f,1,0x6c,0x2a,0x79,0x11,0x69,0x6e, +0x97,0x12,0x65,0x70,0x68,0x95,0x12,0x65,0x74,0x68,0x99,1,0x61,0x30,0x68,0x14, +0x61,0x6d,0x65,0x64,0x68,0x9d,0x13,0x6c,0x65,0x74,0x68,0x9b,0x15,0x61,0x79,0x61, +0x6c,0x61,0x6d,6,0x6e,0x2c,0x6e,0x34,0x72,0x5e,0x73,0x62,0x74,0x11,0x74,0x61, +0xa3,0x63,2,0x67,0x2e,0x6e,0x32,0x79,0x10,0x61,0xa3,0x60,0x10,0x61,0xa3,0x5d, +1,0x61,0xa3,0x5e,0x6e,0x10,0x61,0xa3,0x5f,0x10,0x61,0xa3,0x61,0x11,0x73,0x61, +0xa3,0x62,0x62,0x3c,0x6a,0x42,0x6c,0x10,0x6c,1,0x61,0xa3,0x5b,0x6c,0x10,0x61, +0xa3,0x5c,0x11,0x68,0x61,0xa3,0x59,0x10,0x61,0xa3,0x5a,0x11,0x65,0x6d,0x51,0x10, +0x61,1,0x66,0x37,0x6d,0x11,0x61,0x6c,0x39,1,0x61,0x40,0x65,0x3e,1,0x68, +0x28,0x74,0x10,0x68,0x45,0x40,0x13,0x67,0x6f,0x61,0x6c,0x43,2,0x68,0x3b,0x6d, +0x5c,0x6e,0x1a,0x69,0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,1,0x6b, +0x2a,0x70,0x10,0x61,0xa3,0x65,0x15,0x69,0x6e,0x6e,0x61,0x79,0x61,0xa3,0x64,0x1a, +0x7a,0x61,0x6f,0x6e,0x68,0x65,0x68,0x67,0x6f,0x61,0x6c,0x3d,2,0x61,0x3a,0x68, +0x5e,0x6e,0x17,0x6f,0x74,0x74,0x65,0x64,0x68,0x65,0x68,0x4b,2,0x66,0x47,0x70, +0x38,0x73,0x17,0x68,0x6d,0x69,0x72,0x69,0x79,0x65,0x68,0xa3,0x68,0x10,0x68,0x49, +0x12,0x61,0x70,0x68,0x89,0x11,0x61,0x6d,0x4c,0x12,0x61,0x64,0x68,0x4f,0x61,0x6e, +0x62,0xa2,0x54,0x64,0xa2,0x70,0x65,0x31,0x66,2,0x61,0x3e,0x65,0x4a,0x69,0x19, +0x6e,0x61,0x6c,0x73,0x65,0x6d,0x6b,0x61,0x74,0x68,0x35,0x15,0x72,0x73,0x69,0x79, +0x65,0x68,0x8f,0x86,0x10,0x68,0x33,2,0x66,0x3c,0x69,0x70,0x6c,1,0x61,0x28, +0x65,0x10,0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72,0x69,0x63,0x61,0x6e,2,0x66, +0x30,0x6e,0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11,0x65,0x68,0xa3,0x56,0x12,0x6f, +0x6f,0x6e,0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a,0x75,0x10,0x72,0x1f,0x75,0x73, +0x68,0x61,0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61,0x72,0x72,0x65,0x65,0x8d,1, +0x68,0x29,0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c,0x16,0x61,0x74,0x68,0x72,0x69, +0x73,0x68,0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e,0x74,0x56,0x75,0x21,0x18,0x6f, +0x6e,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28,0x1a,0x69,0x67,0x68,0x74,0x6a, +0x6f,0x69,0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72,0x61,0x6e,0x73,0x70,0x61,0x72, +0x65,0x6e,0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56,0x6c,0x26,0x19,0x65,0x66,0x74, +0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19,0x75,0x61,0x6c,0x6a,0x6f,0x69, +0x6e,0x69,0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63,0x61,0x75,0x73,0x69,0x6e,0x67, +0x23,0,0x14,0x6e,0xc0,0xe5,0x73,0x5e,0x77,0x23,0x77,0x40,0x78,0x58,0x7a,0x10, +0x77,0x58,1,0x6a,0x75,0x73,0x13,0x70,0x61,0x63,0x65,0x59,1,0x6a,0x5d,0x6f, +0x17,0x72,0x64,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x5d,0x10,0x78,0x21,0x73,0x4a,0x75, +0x7a,0x76,1,0x66,0x7d,0x69,0x7e,0x13,0x72,0x61,0x6d,0x61,0x7e,0x14,0x66,0x69, +0x6e,0x61,0x6c,0x7d,4,0x61,0x51,0x67,0x53,0x70,0x28,0x75,0x30,0x79,0x57,0x54, +0x12,0x61,0x63,0x65,0x55,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x53,0x15,0x6e, +0x6b,0x6e,0x6f,0x77,0x6e,0x21,0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50,0x71,0xa2, +0x6e,0x72,1,0x65,0x24,0x69,0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e, +0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f,0x46,0x73, +0x45,0x75,0x46,0x14,0x6d,0x65,0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c,0x69,0x6e, +0x65,0x5b,0x17,0x6e,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70,0x48,0x1c, +0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,1,0x6f, +0x3e,0x72,0x4c,0x1a,0x65,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4d, +0x4a,0x1b,0x73,0x74,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4b,0x10, +0x75,0x4e,0x16,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68,0x50,0x69, +0x86,0x6a,0xa2,0x61,0x6c,0xa2,0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74,0x6f,0x72, +0x79,0x62,0x72,0x65,0x61,0x6b,0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34,0x6c,0x6d, +0x79,0x3a,0x13,0x70,0x68,0x65,0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74, +0x74,0x65,0x72,0x6d,2,0x64,0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65,0x6f,0x67, +0x72,0x61,0x70,0x68,0x69,0x63,0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65,0x70,1, +0x61,0x22,0x65,0x14,0x72,0x61,0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e,0x75,0x6d, +0x65,0x72,0x69,0x63,0x41,2,0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66,0x43,0x69, +0x15,0x6e,0x65,0x66,0x65,0x65,0x64,0x43,0x61,0x42,0x62,0xa2,0x49,0x63,0xa2,0x76, +0x65,0xa2,0xfc,0x67,0x10,0x6c,0x38,0x11,0x75,0x65,0x39,5,0x6d,0xf,0x6d,0x28, +0x70,0x79,0x73,0x7b,0x16,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x69,0x23,0x6b, +0x38,0x6c,0x24,0x17,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x25,0x76,0x13,0x73, +0x61,0x72,0x61,0x76,1,0x70,0x2e,0x73,0x13,0x74,0x61,0x72,0x74,0x7b,0x15,0x72, +0x65,0x62,0x61,0x73,0x65,0x79,4,0x32,0x27,0x61,0x29,0x62,0x2b,0x6b,0x2d,0x72, +0x12,0x65,0x61,0x6b,2,0x61,0x36,0x62,0x3e,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c, +0x73,0x57,0x13,0x66,0x74,0x65,0x72,0x29,1,0x65,0x2a,0x6f,0x11,0x74,0x68,0x27, +0x13,0x66,0x6f,0x72,0x65,0x2b,7,0x6d,0x51,0x6d,0x33,0x6f,0x28,0x70,0x69,0x72, +0x35,1,0x6d,0x76,0x6e,1,0x64,0x3c,0x74,0x1a,0x69,0x6e,0x67,0x65,0x6e,0x74, +0x62,0x72,0x65,0x61,0x6b,0x2f,0x15,0x69,0x74,0x69,0x6f,0x6e,0x61,0x1f,0x6c,0x6a, +0x61,0x70,0x61,0x6e,0x65,0x73,0x65,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x6b,1, +0x62,0x3a,0x70,0x19,0x6c,0x65,0x78,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x51,0x18, +0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x33,0x61,0x6a,0x62,0x2f,0x6a,0x6b, +0x6c,0x30,0x13,0x6f,0x73,0x65,0x70,1,0x61,0x38,0x75,0x18,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x31,0x18,0x72,0x65,0x6e,0x74,0x68,0x65,0x73,0x69,0x73, +0x69,0x1b,0x72,0x72,0x69,0x61,0x67,0x65,0x72,0x65,0x74,0x75,0x72,0x6e,0x35,2, +0x62,0x3e,0x6d,0x46,0x78,0x36,0x18,0x63,0x6c,0x61,0x6d,0x61,0x74,0x69,0x6f,0x6e, +0x37,0x70,0x12,0x61,0x73,0x65,0x71,0x72,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72, +0x73,1,0x64,0x42,0x6e,1,0x6f,0x32,0x75,0x26,0x14,0x6d,0x65,0x72,0x69,0x63, +0x27,0x11,0x6e,0x65,0x21,1,0x65,0x2e,0x69,0x24,0x12,0x67,0x69,0x74,0x25,0x22, +0x14,0x63,0x69,0x6d,0x61,0x6c,0x23,0,0x18,0x6e,0xc4,0xad,0x74,0xc1,0xb7,0x77, +0x96,0x77,0xa2,0x4c,0x78,0xa2,0x70,0x79,0xa2,0x7a,0x7a,6,0x73,0x1e,0x73,0x34, +0x78,0x42,0x79,0x48,0x7a,0x11,0x7a,0x7a,0xa3,0x67,0x10,0x79,1,0x65,0xa3,0xae, +0x6d,0xa3,0x81,0x11,0x78,0x78,0xa3,0x66,0x11,0x79,0x79,0x21,0x61,0x30,0x69,0x58, +0x6d,0x11,0x74,0x68,0xa3,0x80,0x10,0x6e,1,0x61,0x26,0x62,0xa3,0xb1,0x1a,0x62, +0x61,0x7a,0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa3,0xb1,0x11,0x6e,0x68,0x23, +2,0x61,0x30,0x63,0x5a,0x6f,0x11,0x6c,0x65,0xa3,0x9b,1,0x6e,0x3c,0x72,0x10, +0x61,0xa2,0x92,0x15,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0x92,0x12,0x63,0x68,0x6f, +0xa3,0xbc,0x11,0x68,0x6f,0xa3,0xbc,1,0x70,0x2c,0x73,0x11,0x75,0x78,0xa3,0x65, +0x11,0x65,0x6f,0x9b,1,0x65,0x2c,0x69,0x72,0x11,0x69,0x69,0x73,0x11,0x7a,0x69, +0xa2,0xc0,0x11,0x64,0x69,0xa3,0xc0,0x74,0x66,0x75,0xa4,4,0x76,1,0x61,0x48, +0x69,1,0x73,0x38,0x74,0x10,0x68,0xa2,0xc5,0x13,0x6b,0x75,0x71,0x69,0xa3,0xc5, +0x10,0x70,0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,8,0x68,0x64,0x68, +0x5a,0x69,0x6e,0x6e,0xa2,0x45,0x6f,0xa2,0x47,0x75,1,0x6c,0x2a,0x74,0x10,0x67, +0xa3,0xcf,0x18,0x75,0x74,0x69,0x67,0x61,0x6c,0x61,0x72,0x69,0xa3,0xcf,0x10,0x61, +1,0x61,0x24,0x69,0x6d,0x6a,0x11,0x6e,0x61,0x6b,2,0x62,0x3a,0x66,0x4a,0x72, +0x10,0x68,0xa2,0x9e,0x12,0x75,0x74,0x61,0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12, +0x74,0x61,0x6e,0x6f,0x14,0x69,0x6e,0x61,0x67,0x68,0x99,0x11,0x73,0x61,0xa3,0xc3, +1,0x64,0x2a,0x74,0x10,0x6f,0xa3,0xc4,1,0x68,0x26,0x72,0xa3,0xce,0x11,0x72, +0x69,0xa3,0xce,0x61,0x36,0x65,0xa2,0x65,0x66,0xa2,0x71,0x67,0x11,0x6c,0x67,0x75, +6,0x6c,0x28,0x6c,0x32,0x6d,0x38,0x6e,0x44,0x76,0x10,0x74,0xa3,0x7f,1,0x65, +0x89,0x75,0x97,1,0x69,0x24,0x6c,0x67,0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a,1, +0x73,0x2a,0x75,0x10,0x74,0xa3,0x9a,0x10,0x61,0xa3,0xc3,0x67,0x36,0x69,0x52,0x6b, +0x10,0x72,0xa2,0x99,0x10,0x69,0xa3,0x99,1,0x61,0x30,0x62,0x7a,0x13,0x61,0x6e, +0x77,0x61,0x7b,0x12,0x6c,0x6f,0x67,0x75,2,0x6c,0x32,0x74,0x34,0x76,0x12,0x69, +0x65,0x74,0xa3,0x7f,0x10,0x65,0x89,0x12,0x68,0x61,0x6d,0xa3,0x6a,1,0x6c,0x2a, +0x6e,0x10,0x67,0xa3,0x62,0x10,0x75,0x68,0x11,0x67,0x75,0x69,0x11,0x6e,0x67,0x99, +1,0x67,0x32,0x6e,0x14,0x6b,0x6e,0x6f,0x77,0x6e,0xa3,0x67,0x11,0x61,0x72,0x8a, +0x13,0x69,0x74,0x69,0x63,0x8b,0x71,0xc1,0x1e,0x71,0xa2,0xe9,0x72,0xa2,0xee,0x73, +6,0x69,0x95,0x69,0x72,0x6f,0xa2,0x4c,0x75,0xa2,0x75,0x79,1,0x6c,0x46,0x72, +4,0x63,0x65,0x65,0xa3,0x5f,0x69,0x2c,0x6a,0xa3,0x60,0x6e,0xa3,0x61,0x11,0x61, +0x63,0x65,0x10,0x6f,0x94,0x16,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0x95,2,0x64, +0x3c,0x67,0x4c,0x6e,1,0x64,0xa3,0x91,0x68,0x62,0x12,0x61,0x6c,0x61,0x63,0x10, +0x64,0xa2,0xa6,0x12,0x68,0x61,0x6d,0xa3,0xa6,0x17,0x6e,0x77,0x72,0x69,0x74,0x69, +0x6e,0x67,0xa3,0x70,2,0x67,0x3a,0x72,0x52,0x79,0x10,0x6f,0xa2,0xb0,0x12,0x6d, +0x62,0x6f,0xa3,0xb0,1,0x64,0x26,0x6f,0xa3,0xb8,0xa2,0xb7,0x12,0x69,0x61,0x6e, +0xa3,0xb7,0x10,0x61,0xa2,0x98,0x16,0x73,0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0x98, +0x10,0x6e,1,0x64,0x32,0x75,0xa2,0xcd,0x12,0x77,0x61,0x72,0xa3,0xcd,0xa2,0x71, +0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0x71,0x61,0x5c,0x67,0xa2,0x43,0x68,1,0x61, +0x2a,0x72,0x10,0x64,0xa3,0x97,2,0x72,0x28,0x76,0x30,0x77,0x87,0x12,0x61,0x64, +0x61,0xa3,0x97,0x12,0x69,0x61,0x6e,0x87,2,0x6d,0x40,0x72,0x58,0x75,0x10,0x72, +0xa2,0x6f,0x15,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0x6f,1,0x61,0x26,0x72,0xa3, +0x7e,0x14,0x72,0x69,0x74,0x61,0x6e,0xa3,0x7e,1,0x61,0xa3,0x5e,0x62,0xa3,0x85, +0x11,0x6e,0x77,0xa3,0x70,0x11,0x61,0x61,1,0x63,0x2f,0x69,0x23,3,0x65,0x3e, +0x6a,0x48,0x6f,0x4e,0x75,0x10,0x6e,1,0x69,0x24,0x72,0x61,0x10,0x63,0x61,0x13, +0x6a,0x61,0x6e,0x67,0xa3,0x6e,0x11,0x6e,0x67,0xa3,0x6e,1,0x68,0x2a,0x72,0x10, +0x6f,0xa3,0x5d,0x10,0x67,0xa3,0xb6,0x6e,0xa2,0x83,0x6f,0xa4,1,0x70,5,0x6c, +0x1e,0x6c,0x44,0x72,0x4a,0x73,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68,0x6c, +0x61,0x76,0x69,0xa3,0x7b,0x11,0x72,0x64,0xa3,0x5c,0x11,0x74,0x69,0xa3,0x7d,0x61, +0x7c,0x65,0xa2,0x54,0x68,3,0x61,0x3e,0x6c,0x4e,0x6e,0x5e,0x6f,0x16,0x65,0x6e, +0x69,0x63,0x69,0x61,0x6e,0xa3,0x5b,0x10,0x67,0xa2,0x5a,0x12,0x73,0x70,0x61,0xa3, +0x5a,2,0x69,0xa3,0x7a,0x70,0xa3,0x7b,0x76,0xa3,0x7c,0x10,0x78,0xa3,0x5b,2, +0x68,0x3e,0x6c,0x50,0x75,0x10,0x63,0xa2,0xa5,0x14,0x69,0x6e,0x68,0x61,0x75,0xa3, +0xa5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0x4b,0x10,0x6d,0xa2,0x90, +0x14,0x79,0x72,0x65,0x6e,0x65,0xa3,0x90,0x11,0x72,0x6d,0xa3,0x59,6,0x6b,0x36, +0x6b,0x56,0x73,0x6e,0x75,0x74,0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70, +0x75,0x61,0x63,0x68,0x75,0x65,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xba,1,0x67,0x2e, +0x6f,0xa2,0x57,0x10,0x6f,0xa3,0x57,0x10,0x62,0xa3,0x84,0x11,0x68,0x75,0xa3,0x96, +0x12,0x73,0x68,0x75,0xa3,0x96,0x61,0x42,0x62,0x9e,0x65,0x10,0x77,1,0x61,0xa3, +0xaa,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0x97,3,0x62,0x32,0x67,0x40,0x6e,0x56, +0x72,0x10,0x62,0xa3,0x8e,0x15,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3,0x8f,0x10,0x6d, +0xa2,0xc7,0x15,0x75,0x6e,0x64,0x61,0x72,0x69,0xa3,0xc7,0x10,0x64,0xa2,0xbb,0x16, +0x69,0x6e,0x61,0x67,0x61,0x72,0x69,0xa3,0xbb,0x11,0x61,0x74,0xa3,0x8f,5,0x72, +0x32,0x72,0x30,0x73,0x4e,0x75,0x11,0x67,0x72,0xa3,0xc2,2,0x69,0x2c,0x6b,0x30, +0x79,0x10,0x61,0x5f,0x11,0x79,0x61,0x5f,0x10,0x68,0xa3,0x58,2,0x61,0x36,0x67, +0x3c,0x6d,0x10,0x61,0x84,0x12,0x6e,0x79,0x61,0x85,0x11,0x67,0x65,0xa3,0xab,0x10, +0x65,0xa3,0xab,0x67,0x30,0x6c,0x42,0x6e,0x11,0x61,0x6f,0xa3,0xcc,1,0x61,0x2a, +0x68,0x11,0x61,0x6d,0x5b,0x10,0x6d,0x5b,2,0x63,0x32,0x64,0x46,0x6f,0x12,0x6e, +0x61,0x6c,0xa3,0xcc,1,0x68,0x26,0x6b,0xa3,0x6d,0x12,0x69,0x6b,0x69,0xa3,0x6d, +6,0x70,0x41,0x70,0x3a,0x73,0x58,0x74,0x86,0x75,0x14,0x79,0x67,0x68,0x75,0x72, +0xa3,0xc2,0x11,0x65,0x72,1,0x6d,0x2c,0x73,0x12,0x69,0x61,0x6e,0x9b,0x11,0x69, +0x63,0xa3,0x59,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62, +0x69,0x61,0x6e,0xa3,0x85,0x13,0x64,0x69,0x61,0x6e,0xa3,0xb8,0x14,0x75,0x72,0x6b, +0x69,0x63,0xa3,0x58,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72, +0x61,0x62,0x69,0x61,0x6e,0xa3,0x8e,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e, +0xa3,0x4c,0x14,0x74,0x61,0x6c,0x69,0x63,0x5d,0x68,0xc3,0x28,0x6b,0xc2,0x3f,0x6b, +0xa4,0x17,0x6c,0xa4,0xcd,0x6d,8,0x6f,0x46,0x6f,0x48,0x72,0x74,0x74,0x80,0x75, 0x86,0x79,1,0x61,0x28,0x6d,0x10,0x72,0x59,0x13,0x6e,0x6d,0x61,0x72,0x59,2, 0x64,0x2e,0x6e,0x32,0x6f,0x10,0x6e,0xa3,0x72,0x10,0x69,0xa3,0xa3,0x10,0x67,0x56, 0x14,0x6f,0x6c,0x69,0x61,0x6e,0x57,0x10,0x6f,0xa2,0x95,0x10,0x6f,0xa3,0x95,0x11, @@ -864,238 +882,244 @@ const uint8_t PropNameData::bytesTries[15733]={ 0x56,0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0x8d,1,0x65,0x26,0x66,0xa3,0xb5, 0x16,0x66,0x61,0x69,0x64,0x72,0x69,0x6e,0xa3,0xb5,0x17,0x74,0x65,0x69,0x6d,0x61, 0x79,0x65,0x6b,0xa3,0x73,0x10,0x64,0xa2,0x8c,0x17,0x65,0x6b,0x69,0x6b,0x61,0x6b, -0x75,0x69,0xa3,0x8c,0x11,0x61,0x6f,0xa3,0x5c,6,0x6e,0x1a,0x6e,0x34,0x6f,0x38, -0x70,0x3e,0x74,0x11,0x68,0x69,0xa3,0x78,0x11,0x64,0x61,0x4b,0x11,0x72,0x65,0xa3, -0x77,0x11,0x65,0x6c,0xa3,0x8a,0x61,0x32,0x68,0xa2,0x44,0x69,0x11,0x74,0x73,0xa3, -0xbf,5,0x74,0x23,0x74,0x34,0x77,0x56,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3,0x4f, -0x14,0x61,0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72,0x68,0x69,0x72,0x61,0x67,0x61, -0x6e,0x61,0x8d,0x10,0x69,0xa3,0xc6,0x69,0x38,0x6c,0x40,0x6e,1,0x61,0x4d,0x6e, -0x12,0x61,0x64,0x61,0x4b,0x12,0x74,0x68,0x69,0xa3,0x78,0x10,0x69,0xa3,0x4f,4, -0x61,0x40,0x69,0x52,0x6d,0x70,0x6f,0x7c,0x75,0x15,0x64,0x61,0x77,0x61,0x64,0x69, -0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73,0x68,0x74,0x68,0x69,0x93,0x1d,0x74,0x61, -0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70,0x74,0xa3,0xbf,1,0x65, -0x24,0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2,0x9d,0x11,0x6b,0x69,0xa3,0x9d,4, -0x61,0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d,0x79,1,0x63,0x34,0x64,0x10,0x69, -0xa2,0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69,0xa2,0x6b,0x11,0x61,0x6e,0xa3,0x6b, -2,0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3,0x50,0x67,0xa3,0x51,0x69,0x24,0x6e, -0x53,0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50,0x10,0x6f,0x51,0x11,0x70,0x63,0xa2, -0x52,0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e,0x6e,0x36,0x73,0x10,0x75,0xa3,0x83, -0x10,0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3,0x53,0x62,0x83,0x65,0x11,0x61,0x72, -1,0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61,0xa3,0x8b,0x68,0x6e,0x69,0xa2,0x95, -0x6a,2,0x61,0x30,0x70,0x52,0x75,0x11,0x72,0x63,0xa3,0x94,1,0x6d,0x38,0x76, -0x10,0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65,0xa3,0x4e,0x10,0x6f,0xa3,0xad,0x11, -0x61,0x6e,0xa3,0x69,6,0x6c,0x1e,0x6c,0x34,0x6d,0x3a,0x72,0x48,0x75,0x11,0x6e, -0x67,0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x10,0x6e,1,0x67,0xa3,0x4b,0x70,0xa3, -0xba,0x11,0x6b,0x74,0x8d,0x61,0x3c,0x65,0xa2,0x43,0x69,0x11,0x72,0x61,0x48,0x13, -0x67,0x61,0x6e,0x61,0x49,1,0x6e,0x34,0x74,0x10,0x72,0xa2,0xa2,0x11,0x61,0x6e, -0xa3,0xa2,0x42,6,0x6f,0xe,0x6f,0x77,0x73,0xa3,0x49,0x74,0xa3,0x4a,0x75,0x12, -0x6e,0x6f,0x6f,0x77,0x62,0xa3,0xac,0x67,0x3e,0x69,0x42,0x19,0x66,0x69,0x72,0x6f, -0x68,0x69,0x6e,0x67,0x79,0x61,0xa3,0xb6,0x44,0x11,0x75,0x6c,0x45,0x11,0x62,0x72, -0x46,0x11,0x65,0x77,0x47,2,0x6d,0x2e,0x6e,0x4a,0x74,0x11,0x61,0x6c,0x5d,0x1c, -0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0x74,2, -0x64,0x66,0x68,0x6a,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c, -0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0x7d,0x13,0x6c, -0x61,0x76,0x69,0xa3,0x7a,0x10,0x73,0xa3,0x4d,0x15,0x65,0x72,0x69,0x74,0x65,0x64, -0x23,0x64,0xc1,0xd,0x64,0xa2,0x7a,0x65,0xa2,0xc1,0x67,4,0x65,0x82,0x6c,0x9a, -0x6f,0xa2,0x46,0x72,0xa2,0x55,0x75,2,0x6a,0x3c,0x6e,0x4e,0x72,1,0x6d,0x24, -0x75,0x41,0x13,0x75,0x6b,0x68,0x69,0x41,1,0x61,0x24,0x72,0x3f,0x13,0x72,0x61, -0x74,0x69,0x3f,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xb3,0x10, -0x6f,1,0x6b,0xa3,0x48,0x72,0x38,0x13,0x67,0x69,0x61,0x6e,0x39,0x11,0x61,0x67, -0x90,0x15,0x6f,0x6c,0x69,0x74,0x69,0x63,0x91,1,0x6e,0x30,0x74,0x10,0x68,0x3a, -0x11,0x69,0x63,0x3b,1,0x67,0xa3,0xb3,0x6d,0xa3,0xaf,1,0x61,0x32,0x65,1, -0x65,0x24,0x6b,0x3d,0x10,0x6b,0x3d,0x10,0x6e,0xa2,0x89,0x12,0x74,0x68,0x61,0xa3, -0x89,4,0x65,0x46,0x69,0x6c,0x6f,0x8c,0x73,0x9a,0x75,0x11,0x70,0x6c,0xa2,0x87, -0x13,0x6f,0x79,0x61,0x6e,0xa3,0x87,1,0x73,0x38,0x76,0x10,0x61,0x34,0x15,0x6e, -0x61,0x67,0x61,0x72,0x69,0x35,0x13,0x65,0x72,0x65,0x74,0x33,1,0x61,0x36,0x76, -0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75,0xa3,0xbe,0x10,0x6b,0xa3,0xbe,0x11,0x67, -0x72,0xa2,0xb2,0x10,0x61,0xa3,0xb2,0x11,0x72,0x74,0x33,2,0x67,0x3a,0x6c,0x72, -0x74,0x11,0x68,0x69,0x36,0x13,0x6f,0x70,0x69,0x63,0x37,0x10,0x79,2,0x64,0xa3, -0x45,0x68,0xa3,0x46,0x70,0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e,0x68,0x69,0x65,0x72, -0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x47,1,0x62,0x36,0x79,0x10,0x6d,0xa2, -0xb9,0x12,0x61,0x69,0x63,0xa3,0xb9,0x10,0x61,0xa2,0x88,0x12,0x73,0x61,0x6e,0xa3, -0x88,0x61,0xa2,0xc9,0x62,0xa4,0x32,0x63,6,0x6f,0x52,0x6f,0x76,0x70,0x92,0x75, -0xa2,0x41,0x79,1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31,0x73,0xa3,0x44,0x13, -0x6c,0x6c,0x69,0x63,0x31,0x10,0x72,1,0x69,0x34,0x6f,0x15,0x6d,0x69,0x6e,0x6f, -0x61,0x6e,0xa3,0xc1,0x11,0x6f,0x74,0x7f,1,0x6d,0x30,0x70,0x10,0x74,0x2e,0x11, -0x69,0x63,0x2f,0x12,0x6d,0x6f,0x6e,0x21,1,0x6d,0x28,0x72,0x10,0x74,0x7f,0x10, -0x6e,0xa3,0xc1,0x16,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa3,0x65,0x61,0x32,0x68, -0xa2,0x41,0x69,0x11,0x72,0x74,0xa3,0x43,3,0x6b,0x4c,0x6e,0x50,0x72,0x76,0x75, -0x1d,0x63,0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3, -0x9f,0x10,0x6d,0xa3,0x76,1,0x61,0x24,0x73,0x71,0x1d,0x64,0x69,0x61,0x6e,0x61, -0x62,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x71,0x10,0x69,0xa2,0x68,0x11,0x61, -0x6e,0xa3,0x68,3,0x61,0x32,0x65,0x44,0x6f,0x52,0x72,0x10,0x73,0xa3,0xbd,1, -0x6b,0x26,0x6d,0xa3,0x42,0x11,0x6d,0x61,0xa3,0x76,0x10,0x72,0x2c,0x13,0x6f,0x6b, -0x65,0x65,0x2d,0x16,0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa3,0xbd,6,0x68,0x4e, -0x68,0x48,0x6e,0x4e,0x72,0x76,0x76,1,0x65,0x2a,0x73,0x10,0x74,0xa3,0x75,0x13, -0x73,0x74,0x61,0x6e,0xa3,0x75,0x11,0x6f,0x6d,0xa3,0xa1,0x11,0x61,0x74,0x1f,0x6f, -0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3, -0x9c,1,0x61,0x3e,0x6d,2,0x65,0x2a,0x69,0xa3,0x74,0x6e,0x27,0x13,0x6e,0x69, -0x61,0x6e,0x27,1,0x62,0x26,0x6e,0xa3,0xc8,0x24,0x11,0x69,0x63,0x25,0x64,0x30, -0x66,0x44,0x67,0x11,0x68,0x62,0xa3,0x9f,0x10,0x6c,1,0x61,0x26,0x6d,0xa3,0xa7, -0x10,0x6d,0xa3,0xa7,0x11,0x61,0x6b,0xa3,0x93,6,0x6c,0x3c,0x6c,0x52,0x6f,0x56, -0x72,0x66,0x75,1,0x67,0x30,0x68,1,0x64,0x79,0x69,0x10,0x64,0x79,0x10,0x69, -0x8e,0x13,0x6e,0x65,0x73,0x65,0x8f,0x11,0x69,0x73,0xa1,0x11,0x70,0x6f,0x2a,0x13, -0x6d,0x6f,0x66,0x6f,0x2b,0x10,0x61,1,0x68,0x2e,0x69,0x7c,0x12,0x6c,0x6c,0x65, -0x7d,0xa2,0x41,0x11,0x6d,0x69,0xa3,0x41,0x61,0x48,0x65,0x9c,0x68,1,0x61,0x2a, -0x6b,0x10,0x73,0xa3,0xa8,0x15,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa3,0xa8,3,0x6c, -0x3a,0x6d,0x48,0x73,0x54,0x74,1,0x61,0x24,0x6b,0x9f,0x10,0x6b,0x9f,0x10,0x69, -0x9c,0x13,0x6e,0x65,0x73,0x65,0x9d,0x10,0x75,0xa2,0x82,0x10,0x6d,0xa3,0x82,0x10, -0x73,0xa2,0x86,0x13,0x61,0x76,0x61,0x68,0xa3,0x86,0x11,0x6e,0x67,0x28,0x12,0x61, -0x6c,0x69,0x29,3,0x6c,0x42,0x6e,0x90,0x74,0xa2,0x46,0x76,0x24,0x17,0x6f,0x77, -0x65,0x6c,0x6a,0x61,0x6d,0x6f,0x25,0x22,1,0x65,0x54,0x76,0x28,1,0x73,0x38, -0x74,0x2a,0x17,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x2b,0x16,0x79,0x6c,0x6c, -0x61,0x62,0x6c,0x65,0x29,0x18,0x61,0x64,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x23, -1,0x61,0x21,0x6f,0x1a,0x74,0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x62,0x6c,0x65, -0x21,0x26,0x1a,0x72,0x61,0x69,0x6c,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x27,1, -0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,1,0x6e,0x2c,0x79, -0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22, -0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,2, -0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65, -0x25,0x20,0x10,0x6f,0x21,0xb,0x72,0x39,0x76,0xc,0x76,0x33,0x78,0x2a,0x7a,0x11, -0x77,0x6a,0x43,0x10,0x78,0x21,0x72,0x28,0x73,0x50,0x74,0x31,1,0x65,0x24,0x69, -0x39,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f, -0x72,0x39,1,0x6d,0x35,0x70,0x18,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b, -0x35,0x6c,0x1f,0x6c,0x3c,0x6f,0x4a,0x70,1,0x70,0x37,0x72,0x14,0x65,0x70,0x65, -0x6e,0x64,0x37,0x28,1,0x66,0x2b,0x76,0x2c,0x10,0x74,0x2f,0x13,0x74,0x68,0x65, -0x72,0x21,0x63,0x4c,0x65,0x64,0x67,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66, -0x74,0x65,0x72,0x7a,0x77,0x6a,0x41,0x10,0x7a,0x41,2,0x6e,0x23,0x6f,0x24,0x72, -0x25,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x23,2,0x62,0x34,0x6d,0x4e,0x78,0x26,0x13, -0x74,0x65,0x6e,0x64,0x27,0x3a,1,0x61,0x24,0x67,0x3d,0x11,0x73,0x65,0x3a,0x12, -0x67,0x61,0x7a,0x3d,0x3e,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x3f,9,0x6e, -0x4a,0x6e,0x34,0x6f,0x44,0x73,0x60,0x75,0x94,0x78,0x10,0x78,0x21,0x10,0x75,0x2a, -0x14,0x6d,0x65,0x72,0x69,0x63,0x2b,1,0x6c,0x2c,0x74,0x12,0x68,0x65,0x72,0x21, -0x14,0x65,0x74,0x74,0x65,0x72,0x2d,3,0x63,0x36,0x65,0x46,0x70,0x31,0x74,0x32, -0x12,0x65,0x72,0x6d,0x33,0x3c,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3d,0x2e, -0x10,0x70,0x2f,0x10,0x70,0x34,0x12,0x70,0x65,0x72,0x35,0x61,0x46,0x63,0x52,0x65, -0x64,0x66,0x72,0x6c,2,0x65,0x2d,0x66,0x3b,0x6f,0x28,0x12,0x77,0x65,0x72,0x29, -0x10,0x74,0x22,0x12,0x65,0x72,0x6d,0x23,1,0x6c,0x24,0x72,0x37,0x24,0x12,0x6f, -0x73,0x65,0x25,0x10,0x78,0x38,0x13,0x74,0x65,0x6e,0x64,0x39,0x10,0x6f,0x26,0x13, -0x72,0x6d,0x61,0x74,0x27,0,0x10,0x6c,0x88,0x72,0x40,0x72,0x36,0x73,0x5e,0x77, -0x7a,0x78,0x8a,0x7a,0x11,0x77,0x6a,0x4b,1,0x65,0x24,0x69,0x3b,0x1e,0x67,0x69, -0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x3b,1,0x69, -0x24,0x71,0x3f,0x18,0x6e,0x67,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x3f,0x17,0x73, -0x65,0x67,0x73,0x70,0x61,0x63,0x65,0x4d,0x10,0x78,0x21,0x6c,0x36,0x6d,0x3c,0x6e, -0x76,0x6f,0x13,0x74,0x68,0x65,0x72,0x21,1,0x65,0x23,0x66,0x35,3,0x62,0x37, -0x69,0x28,0x6c,0x29,0x6e,0x2b,0x10,0x64,1,0x6c,0x34,0x6e,0x11,0x75,0x6d,0x2a, -0x12,0x6c,0x65,0x74,0x37,0x14,0x65,0x74,0x74,0x65,0x72,0x29,2,0x65,0x36,0x6c, -0x39,0x75,0x2c,0x14,0x6d,0x65,0x72,0x69,0x63,0x2d,0x14,0x77,0x6c,0x69,0x6e,0x65, -0x39,0x66,0x3f,0x66,0x40,0x67,0x4e,0x68,0x70,0x6b,0x10,0x61,0x26,0x15,0x74,0x61, -0x6b,0x61,0x6e,0x61,0x27,0x10,0x6f,0x24,0x13,0x72,0x6d,0x61,0x74,0x25,1,0x61, -0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x49,0x10,0x7a, -0x49,1,0x65,0x24,0x6c,0x3d,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65, -0x72,0x3d,0x61,0x86,0x63,0x92,0x64,0x94,0x65,2,0x62,0x44,0x6d,0x5e,0x78,0x2e, -0x13,0x74,0x65,0x6e,0x64,0x32,0x15,0x6e,0x75,0x6d,0x6c,0x65,0x74,0x2f,0x42,1, -0x61,0x24,0x67,0x45,0x11,0x73,0x65,0x42,0x12,0x67,0x61,0x7a,0x45,0x46,0x16,0x6f, -0x64,0x69,0x66,0x69,0x65,0x72,0x47,0x15,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x10, -0x72,0x31,1,0x6f,0x24,0x71,0x41,0x18,0x75,0x62,0x6c,0x65,0x71,0x75,0x6f,0x74, -0x65,0x41,2,0x63,0x32,0x6e,0x3c,0x6f,0x22,0x12,0x70,0x65,0x6e,0x23,0x24,0x13, -0x6c,0x6f,0x73,0x65,0x25,0x20,0x12,0x6f,0x6e,0x65,0x21,6,0x6f,0x65,0x6f,0x4a, -0x72,0x5c,0x74,0x64,0x76,0x1d,0x69,0x73,0x75,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72, -0x6c,0x65,0x66,0x74,0x3d,0x18,0x76,0x65,0x72,0x73,0x74,0x72,0x75,0x63,0x6b,0x2d, -0x13,0x69,0x67,0x68,0x74,0x2f,0x11,0x6f,0x70,0x30,0x12,0x61,0x6e,0x64,2,0x62, -0x32,0x6c,0x62,0x72,0x13,0x69,0x67,0x68,0x74,0x3b,0x14,0x6f,0x74,0x74,0x6f,0x6d, -0x32,0x12,0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x35,0x12, -0x65,0x66,0x74,0x3f,0x12,0x65,0x66,0x74,0x36,0x17,0x61,0x6e,0x64,0x72,0x69,0x67, -0x68,0x74,0x39,0x62,0x2c,0x6c,0x5c,0x6e,0x10,0x61,0x21,0x14,0x6f,0x74,0x74,0x6f, -0x6d,0x22,0x12,0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x27, -0x12,0x65,0x66,0x74,0x25,0x12,0x65,0x66,0x74,0x28,0x17,0x61,0x6e,0x64,0x72,0x69, -0x67,0x68,0x74,0x2b,0xd,0x6e,0xaa,0x72,0x70,0x72,0x92,0x73,0xa2,0x46,0x74,0xa2, -0x54,0x76,1,0x69,0x60,0x6f,0x12,0x77,0x65,0x6c,0x62,1,0x64,0x3a,0x69,0x19, -0x6e,0x64,0x65,0x70,0x65,0x6e,0x64,0x65,0x6e,0x74,0x67,0x17,0x65,0x70,0x65,0x6e, -0x64,0x65,0x6e,0x74,0x65,1,0x72,0x2e,0x73,0x13,0x61,0x72,0x67,0x61,0x61,0x12, -0x61,0x6d,0x61,0x5f,0x1d,0x65,0x67,0x69,0x73,0x74,0x65,0x72,0x73,0x68,0x69,0x66, -0x74,0x65,0x72,0x57,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x6d,0x6f,0x64,0x69, -0x66,0x69,0x65,0x72,0x59,0x12,0x6f,0x6e,0x65,1,0x6c,0x2c,0x6d,0x12,0x61,0x72, -0x6b,0x5d,0x14,0x65,0x74,0x74,0x65,0x72,0x5b,0x6e,0x3c,0x6f,0x7c,0x70,0x18,0x75, -0x72,0x65,0x6b,0x69,0x6c,0x6c,0x65,0x72,0x55,1,0x6f,0x4c,0x75,1,0x6b,0x3c, -0x6d,0x12,0x62,0x65,0x72,0x50,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x53,0x11,0x74, -0x61,0x4f,0x16,0x6e,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x4d,0x13,0x74,0x68,0x65,0x72, -0x21,0x67,0x3e,0x67,0x4a,0x69,0x64,0x6a,0x82,0x6d,0x1d,0x6f,0x64,0x69,0x66,0x79, -0x69,0x6e,0x67,0x6c,0x65,0x74,0x74,0x65,0x72,0x4b,0x1c,0x65,0x6d,0x69,0x6e,0x61, -0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x45,0x1e,0x6e,0x76,0x69,0x73,0x69,0x62, -0x6c,0x65,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x47,0x14,0x6f,0x69,0x6e,0x65,0x72, -0x49,0x61,0xa2,0xba,0x62,0xa2,0xc0,0x63,1,0x61,0xa2,0xa2,0x6f,0x16,0x6e,0x73, -0x6f,0x6e,0x61,0x6e,0x74,0x2a,8,0x6b,0x67,0x6b,0x48,0x6d,0x52,0x70,0x5c,0x73, -0xa2,0x42,0x77,0x19,0x69,0x74,0x68,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x43,0x14, -0x69,0x6c,0x6c,0x65,0x72,0x35,0x14,0x65,0x64,0x69,0x61,0x6c,0x37,1,0x6c,0x52, -0x72,0x10,0x65,1,0x63,0x2e,0x66,0x13,0x69,0x78,0x65,0x64,0x3d,0x19,0x65,0x64, -0x69,0x6e,0x67,0x72,0x65,0x70,0x68,0x61,0x3b,0x18,0x61,0x63,0x65,0x68,0x6f,0x6c, -0x64,0x65,0x72,0x39,0x10,0x75,1,0x62,0x3e,0x63,0x1b,0x63,0x65,0x65,0x64,0x69, -0x6e,0x67,0x72,0x65,0x70,0x68,0x61,0x41,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x64,0x3f, -0x64,0x4c,0x66,0x52,0x68,0x5a,0x69,0x1e,0x6e,0x69,0x74,0x69,0x61,0x6c,0x70,0x6f, -0x73,0x74,0x66,0x69,0x78,0x65,0x64,0x33,0x12,0x65,0x61,0x64,0x2d,0x13,0x69,0x6e, -0x61,0x6c,0x2f,0x18,0x65,0x61,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,0x1d,0x6e, -0x74,0x69,0x6c,0x6c,0x61,0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x29,0x16,0x76, -0x61,0x67,0x72,0x61,0x68,0x61,0x23,1,0x69,0x4a,0x72,0x10,0x61,0x1f,0x68,0x6d, -0x69,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27,0x12, -0x6e,0x64,0x75,0x25,2,0x72,0x38,0x74,0x46,0x75,0x26,0x15,0x70,0x72,0x69,0x67, -0x68,0x74,0x27,0x20,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x21,1,0x72,0x24,0x75, -0x25,0x22,0x18,0x61,0x6e,0x73,0x66,0x6f,0x72,0x6d,0x65,0x64,1,0x72,0x32,0x75, -0x15,0x70,0x72,0x69,0x67,0x68,0x74,0x25,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x23, -1,0x61,0x38,0x72,0x18,0x65,0x73,0x74,0x72,0x69,0x63,0x74,0x65,0x64,0x21,0x15, -0x6c,0x6c,0x6f,0x77,0x65,0x64,0x23,0xd,0x6e,0xc1,0x86,0x73,0xa8,0x73,0x4c,0x74, -0xa2,0x76,0x75,0xa2,0x83,0x7a,0xd8,0x70,0,2,0x6c,0xd9,0x20,0,0x70,0xd9, -0x40,0,0x73,0xc3,0,0xfe,0xf,0,0,0,7,0x6f,0x3c,0x6f,0xff,8, -0,0,0,0x70,0x3a,0x75,0x6e,0x79,0x13,0x6d,0x62,0x6f,0x6c,0xff,0xf,0, -0,0,0x11,0x61,0x63,1,0x65,0x34,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b, -0xa5,0,0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xc3,0,0x16,0x72, -0x72,0x6f,0x67,0x61,0x74,0x65,0xe1,0,0,0x63,0xff,2,0,0,0,0x65, -0x38,0x6b,0xff,4,0,0,0,0x6d,0xff,1,0,0,0,0x16,0x70,0x61, -0x72,0x61,0x74,0x6f,0x72,0xd9,0x70,0,0x1d,0x69,0x74,0x6c,0x65,0x63,0x61,0x73, -0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,1,0x6e,0x40,0x70,0x1c,0x70,0x65,0x72, -0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x25,0x17,0x61,0x73,0x73,0x69, -0x67,0x6e,0x65,0x64,0x23,0x6e,0xa2,0x69,0x6f,0xa2,0x89,0x70,0xfe,0x30,0xf8,0, -0,9,0x69,0x33,0x69,0xff,0x10,0,0,0,0x6f,0xfd,0x80,0,0,0x72, -0x54,0x73,0xf9,0,0,0x75,0x12,0x6e,0x63,0x74,0xfe,0x30,0xf8,0,0,0x15, -0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x30,0xf8,0,0,0x17,0x69,0x76,0x61,0x74, -0x65,0x75,0x73,0x65,0xdd,0,0,0x61,0x48,0x63,0xfd,0x40,0,0,0x64,0xe9, -0,0,0x65,0xfd,0x20,0,0,0x66,0xff,0x20,0,0,0,0x1f,0x72,0x61, -0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x40, -0,0xbe,0,3,0x64,0xa7,0,0x6c,0xab,0,0x6f,0x30,0x75,0x13,0x6d,0x62, -0x65,0x72,0xbf,0,0xb2,0,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d, -0x61,0x72,0x6b,0xa1,1,0x70,0x92,0x74,0x12,0x68,0x65,0x72,0xe6,0x80,1,3, -0x6c,0x40,0x6e,0x4a,0x70,0x56,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff,8,0, -0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x61,0x14,0x75,0x6d,0x62,0x65,0x72,0xb3, -0,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x80,0,0, -0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xf9,0, -0,0x66,0xc0,0xc4,0x66,0xa2,0x47,0x69,0xa2,0x64,0x6c,0xa2,0x79,0x6d,0xa4,0xc0, -4,0x61,0x6c,0x63,0xa5,0,0x65,0xa3,0x80,0x6e,0xa1,0x6f,0x15,0x64,0x69,0x66, -0x69,0x65,0x72,1,0x6c,0x38,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff,4,0, -0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x41,1,0x72,0x3c,0x74,0x16,0x68,0x73, -0x79,0x6d,0x62,0x6f,0x6c,0xff,1,0,0,0,0x10,0x6b,0xa5,0xc0,1,0x69, -0x32,0x6f,0x13,0x72,0x6d,0x61,0x74,0xdb,0,0,0x1d,0x6e,0x61,0x6c,0x70,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x20,0,0,0,0x10,0x6e, -0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0xff,0x10,0,0,0,0x9c,7,0x6d,0x18,0x6d,0x41,0x6f,0x28,0x74,0x31, -0x75,0x25,0x60,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65, -0x72,0x29,0x63,0x3d,0x65,0x28,0x69,0x42,0x6c,0x29,0x13,0x74,0x74,0x65,0x72,0x9c, -0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0xab,0,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61, -0x72,0x61,0x74,0x6f,0x72,0xd9,0x20,0,0x63,0x46,0x64,0xa2,0x96,0x65,0x1b,0x6e, -0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa3,0x80,0xe6,0x80,1, -7,0x6e,0x57,0x6e,0x52,0x6f,0x5e,0x73,0xe1,0,0,0x75,0x1b,0x72,0x72,0x65, -0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,2,0,0,0,0x22,0x12, -0x74,0x72,0x6c,0xd9,0x80,0,0xdc,0,0,1,0x6d,0x62,0x6e,1,0x6e,0x30, -0x74,0x12,0x72,0x6f,0x6c,0xd9,0x80,0,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x40,0,0,0x19,0x62,0x69, -0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0xc0,0x61,0x58,0x63,0xd9,0x80,0, -0x66,0xdb,0,0,0x6c,0x1d,0x6f,0x73,0x65,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, -0x74,0x69,0x6f,0x6e,0xfd,0x20,0,0,0x18,0x73,0x65,0x64,0x6c,0x65,0x74,0x74, -0x65,0x72,0x3d,2,0x61,0x32,0x65,0x50,0x69,0x12,0x67,0x69,0x74,0xa7,0,0x1c, -0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xe9,0,0, -0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65,0x72,0xa7,0,8,0x6e, -0x50,0x6e,0x46,0x6f,0x7a,0x72,0x88,0x74,0x9c,0x75,0x19,0x6e,0x63,0x6f,0x6d,0x6d, -0x6f,0x6e,0x75,0x73,0x65,0x31,0x11,0x6f,0x74,2,0x63,0x2e,0x6e,0x3e,0x78,0x11, -0x69,0x64,0x29,0x17,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x21,0x12,0x66,0x6b, -0x63,0x27,0x16,0x62,0x73,0x6f,0x6c,0x65,0x74,0x65,0x2d,0x19,0x65,0x63,0x6f,0x6d, -0x6d,0x65,0x6e,0x64,0x65,0x64,0x37,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c, -0x2f,0x64,0x40,0x65,0x78,0x69,0x88,0x6c,0x18,0x69,0x6d,0x69,0x74,0x65,0x64,0x75, -0x73,0x65,0x33,0x10,0x65,1,0x66,0x34,0x70,0x16,0x72,0x65,0x63,0x61,0x74,0x65, -0x64,0x23,0x1c,0x61,0x75,0x6c,0x74,0x69,0x67,0x6e,0x6f,0x72,0x61,0x62,0x6c,0x65, -0x25,0x17,0x78,0x63,0x6c,0x75,0x73,0x69,0x6f,0x6e,0x2b,0x17,0x6e,0x63,0x6c,0x75, -0x73,0x69,0x6f,0x6e,0x35 +0x75,0x69,0xa3,0x8c,0x11,0x61,0x6f,0xa3,0x5c,7,0x6f,0x1b,0x6f,0x34,0x70,0x3a, +0x72,0x40,0x74,0x11,0x68,0x69,0xa3,0x78,0x11,0x72,0x65,0xa3,0x77,0x11,0x65,0x6c, +0xa3,0x8a,0x11,0x61,0x69,0xa3,0xcb,0x61,0x36,0x68,0xa2,0x46,0x69,0xa2,0x83,0x6e, +0x11,0x64,0x61,0x4b,5,0x74,0x23,0x74,0x34,0x77,0x56,0x79,0x13,0x61,0x68,0x6c, +0x69,0xa3,0x4f,0x14,0x61,0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72,0x68,0x69,0x72, +0x61,0x67,0x61,0x6e,0x61,0x8d,0x10,0x69,0xa3,0xc6,0x69,0x38,0x6c,0x40,0x6e,1, +0x61,0x4d,0x6e,0x12,0x61,0x64,0x61,0x4b,0x12,0x74,0x68,0x69,0xa3,0x78,0x10,0x69, +0xa3,0x4f,4,0x61,0x40,0x69,0x52,0x6d,0x70,0x6f,0x7c,0x75,0x15,0x64,0x61,0x77, +0x61,0x64,0x69,0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73,0x68,0x74,0x68,0x69,0x93, +0x1d,0x74,0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70,0x74,0xa3, +0xbf,1,0x65,0x24,0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2,0x9d,0x11,0x6b,0x69, +0xa3,0x9d,1,0x72,0x2a,0x74,0x10,0x73,0xa3,0xbf,0x14,0x61,0x74,0x72,0x61,0x69, +0xa3,0xcb,4,0x61,0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d,0x79,1,0x63,0x34, +0x64,0x10,0x69,0xa2,0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69,0xa2,0x6b,0x11,0x61, +0x6e,0xa3,0x6b,2,0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3,0x50,0x67,0xa3,0x51, +0x69,0x24,0x6e,0x53,0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50,0x10,0x6f,0x51,0x11, +0x70,0x63,0xa2,0x52,0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e,0x6e,0x36,0x73,0x10, +0x75,0xa3,0x83,0x10,0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3,0x53,0x62,0x83,0x65, +0x11,0x61,0x72,1,0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61,0xa3,0x8b,0x68,0x6e, +0x69,0xa2,0x95,0x6a,2,0x61,0x30,0x70,0x52,0x75,0x11,0x72,0x63,0xa3,0x94,1, +0x6d,0x38,0x76,0x10,0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65,0xa3,0x4e,0x10,0x6f, +0xa3,0xad,0x11,0x61,0x6e,0xa3,0x69,6,0x6c,0x1e,0x6c,0x34,0x6d,0x3a,0x72,0x48, +0x75,0x11,0x6e,0x67,0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x10,0x6e,1,0x67,0xa3, +0x4b,0x70,0xa3,0xba,0x11,0x6b,0x74,0x8d,0x61,0x3c,0x65,0xa2,0x43,0x69,0x11,0x72, +0x61,0x48,0x13,0x67,0x61,0x6e,0x61,0x49,1,0x6e,0x34,0x74,0x10,0x72,0xa2,0xa2, +0x11,0x61,0x6e,0xa3,0xa2,0x42,6,0x6f,0xe,0x6f,0x77,0x73,0xa3,0x49,0x74,0xa3, +0x4a,0x75,0x12,0x6e,0x6f,0x6f,0x77,0x62,0xa3,0xac,0x67,0x3e,0x69,0x42,0x19,0x66, +0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa3,0xb6,0x44,0x11,0x75,0x6c,0x45, +0x11,0x62,0x72,0x46,0x11,0x65,0x77,0x47,2,0x6d,0x2e,0x6e,0x4a,0x74,0x11,0x61, +0x6c,0x5d,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63, +0xa3,0x74,2,0x64,0x66,0x68,0x6a,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f, +0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3, +0x7d,0x13,0x6c,0x61,0x76,0x69,0xa3,0x7a,0x10,0x73,0xa3,0x4d,0x15,0x65,0x72,0x69, +0x74,0x65,0x64,0x23,0x64,0xc1,0x28,0x64,0xa2,0x95,0x65,0xa2,0xdc,0x67,5,0x6f, +0x66,0x6f,0x98,0x72,0xa2,0x4b,0x75,3,0x6a,0x54,0x6b,0x66,0x6e,0x6a,0x72,1, +0x6d,0x38,0x75,0x40,0x16,0x6e,0x67,0x6b,0x68,0x65,0x6d,0x61,0xa3,0xca,0x13,0x75, +0x6b,0x68,0x69,0x41,1,0x61,0x24,0x72,0x3f,0x13,0x72,0x61,0x74,0x69,0x3f,0x10, +0x68,0xa3,0xca,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xb3,1, +0x6e,0x30,0x74,0x10,0x68,0x3a,0x11,0x69,0x63,0x3b,1,0x67,0xa3,0xb3,0x6d,0xa3, +0xaf,1,0x61,0x32,0x65,1,0x65,0x24,0x6b,0x3d,0x10,0x6b,0x3d,0x10,0x6e,0xa2, +0x89,0x12,0x74,0x68,0x61,0xa3,0x89,0x61,0x3e,0x65,0x4c,0x6c,0x11,0x61,0x67,0x90, +0x15,0x6f,0x6c,0x69,0x74,0x69,0x63,0x91,0x11,0x72,0x61,0xa2,0xc9,0x10,0x79,0xa3, +0xc9,0x10,0x6f,1,0x6b,0xa3,0x48,0x72,0x38,0x13,0x67,0x69,0x61,0x6e,0x39,4, +0x65,0x46,0x69,0x6c,0x6f,0x8c,0x73,0x9a,0x75,0x11,0x70,0x6c,0xa2,0x87,0x13,0x6f, +0x79,0x61,0x6e,0xa3,0x87,1,0x73,0x38,0x76,0x10,0x61,0x34,0x15,0x6e,0x61,0x67, +0x61,0x72,0x69,0x35,0x13,0x65,0x72,0x65,0x74,0x33,1,0x61,0x36,0x76,0x16,0x65, +0x73,0x61,0x6b,0x75,0x72,0x75,0xa3,0xbe,0x10,0x6b,0xa3,0xbe,0x11,0x67,0x72,0xa2, +0xb2,0x10,0x61,0xa3,0xb2,0x11,0x72,0x74,0x33,2,0x67,0x3a,0x6c,0x72,0x74,0x11, +0x68,0x69,0x36,0x13,0x6f,0x70,0x69,0x63,0x37,0x10,0x79,2,0x64,0xa3,0x45,0x68, +0xa3,0x46,0x70,0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67, +0x6c,0x79,0x70,0x68,0x73,0xa3,0x47,1,0x62,0x36,0x79,0x10,0x6d,0xa2,0xb9,0x12, +0x61,0x69,0x63,0xa3,0xb9,0x10,0x61,0xa2,0x88,0x12,0x73,0x61,0x6e,0xa3,0x88,0x61, +0xa2,0xc9,0x62,0xa4,0x32,0x63,6,0x6f,0x52,0x6f,0x76,0x70,0x92,0x75,0xa2,0x41, +0x79,1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31,0x73,0xa3,0x44,0x13,0x6c,0x6c, +0x69,0x63,0x31,0x10,0x72,1,0x69,0x34,0x6f,0x15,0x6d,0x69,0x6e,0x6f,0x61,0x6e, +0xa3,0xc1,0x11,0x6f,0x74,0x7f,1,0x6d,0x30,0x70,0x10,0x74,0x2e,0x11,0x69,0x63, +0x2f,0x12,0x6d,0x6f,0x6e,0x21,1,0x6d,0x28,0x72,0x10,0x74,0x7f,0x10,0x6e,0xa3, +0xc1,0x16,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa3,0x65,0x61,0x32,0x68,0xa2,0x41, +0x69,0x11,0x72,0x74,0xa3,0x43,3,0x6b,0x4c,0x6e,0x50,0x72,0x76,0x75,0x1d,0x63, +0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0x9f,0x10, +0x6d,0xa3,0x76,1,0x61,0x24,0x73,0x71,0x1d,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f, +0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x71,0x10,0x69,0xa2,0x68,0x11,0x61,0x6e,0xa3, +0x68,3,0x61,0x32,0x65,0x44,0x6f,0x52,0x72,0x10,0x73,0xa3,0xbd,1,0x6b,0x26, +0x6d,0xa3,0x42,0x11,0x6d,0x61,0xa3,0x76,0x10,0x72,0x2c,0x13,0x6f,0x6b,0x65,0x65, +0x2d,0x16,0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa3,0xbd,6,0x68,0x4e,0x68,0x48, +0x6e,0x4e,0x72,0x76,0x76,1,0x65,0x2a,0x73,0x10,0x74,0xa3,0x75,0x13,0x73,0x74, +0x61,0x6e,0xa3,0x75,0x11,0x6f,0x6d,0xa3,0xa1,0x11,0x61,0x74,0x1f,0x6f,0x6c,0x69, +0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x9c,1, +0x61,0x3e,0x6d,2,0x65,0x2a,0x69,0xa3,0x74,0x6e,0x27,0x13,0x6e,0x69,0x61,0x6e, +0x27,1,0x62,0x26,0x6e,0xa3,0xc8,0x24,0x11,0x69,0x63,0x25,0x64,0x30,0x66,0x44, +0x67,0x11,0x68,0x62,0xa3,0x9f,0x10,0x6c,1,0x61,0x26,0x6d,0xa3,0xa7,0x10,0x6d, +0xa3,0xa7,0x11,0x61,0x6b,0xa3,0x93,6,0x6c,0x3c,0x6c,0x52,0x6f,0x56,0x72,0x66, +0x75,1,0x67,0x30,0x68,1,0x64,0x79,0x69,0x10,0x64,0x79,0x10,0x69,0x8e,0x13, +0x6e,0x65,0x73,0x65,0x8f,0x11,0x69,0x73,0xa1,0x11,0x70,0x6f,0x2a,0x13,0x6d,0x6f, +0x66,0x6f,0x2b,0x10,0x61,1,0x68,0x2e,0x69,0x7c,0x12,0x6c,0x6c,0x65,0x7d,0xa2, +0x41,0x11,0x6d,0x69,0xa3,0x41,0x61,0x48,0x65,0x9c,0x68,1,0x61,0x2a,0x6b,0x10, +0x73,0xa3,0xa8,0x15,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa3,0xa8,3,0x6c,0x3a,0x6d, +0x48,0x73,0x54,0x74,1,0x61,0x24,0x6b,0x9f,0x10,0x6b,0x9f,0x10,0x69,0x9c,0x13, +0x6e,0x65,0x73,0x65,0x9d,0x10,0x75,0xa2,0x82,0x10,0x6d,0xa3,0x82,0x10,0x73,0xa2, +0x86,0x13,0x61,0x76,0x61,0x68,0xa3,0x86,0x11,0x6e,0x67,0x28,0x12,0x61,0x6c,0x69, +0x29,3,0x6c,0x42,0x6e,0x90,0x74,0xa2,0x46,0x76,0x24,0x17,0x6f,0x77,0x65,0x6c, +0x6a,0x61,0x6d,0x6f,0x25,0x22,1,0x65,0x54,0x76,0x28,1,0x73,0x38,0x74,0x2a, +0x17,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x2b,0x16,0x79,0x6c,0x6c,0x61,0x62, +0x6c,0x65,0x29,0x18,0x61,0x64,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x23,1,0x61, +0x21,0x6f,0x1a,0x74,0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x62,0x6c,0x65,0x21,0x26, +0x1a,0x72,0x61,0x69,0x6c,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x27,1,0x6e,0x2c, +0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,1,0x6e,0x2c,0x79,0x22,0x11, +0x65,0x73,0x23,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65, +0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,2,0x6d,0x30, +0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20, +0x10,0x6f,0x21,0xb,0x72,0x39,0x76,0xc,0x76,0x33,0x78,0x2a,0x7a,0x11,0x77,0x6a, +0x43,0x10,0x78,0x21,0x72,0x28,0x73,0x50,0x74,0x31,1,0x65,0x24,0x69,0x39,0x1e, +0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x39, +1,0x6d,0x35,0x70,0x18,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x35,0x6c, +0x1f,0x6c,0x3c,0x6f,0x4a,0x70,1,0x70,0x37,0x72,0x14,0x65,0x70,0x65,0x6e,0x64, +0x37,0x28,1,0x66,0x2b,0x76,0x2c,0x10,0x74,0x2f,0x13,0x74,0x68,0x65,0x72,0x21, +0x63,0x4c,0x65,0x64,0x67,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65, +0x72,0x7a,0x77,0x6a,0x41,0x10,0x7a,0x41,2,0x6e,0x23,0x6f,0x24,0x72,0x25,0x14, +0x6e,0x74,0x72,0x6f,0x6c,0x23,2,0x62,0x34,0x6d,0x4e,0x78,0x26,0x13,0x74,0x65, +0x6e,0x64,0x27,0x3a,1,0x61,0x24,0x67,0x3d,0x11,0x73,0x65,0x3a,0x12,0x67,0x61, +0x7a,0x3d,0x3e,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x3f,9,0x6e,0x4a,0x6e, +0x34,0x6f,0x44,0x73,0x60,0x75,0x94,0x78,0x10,0x78,0x21,0x10,0x75,0x2a,0x14,0x6d, +0x65,0x72,0x69,0x63,0x2b,1,0x6c,0x2c,0x74,0x12,0x68,0x65,0x72,0x21,0x14,0x65, +0x74,0x74,0x65,0x72,0x2d,3,0x63,0x36,0x65,0x46,0x70,0x31,0x74,0x32,0x12,0x65, +0x72,0x6d,0x33,0x3c,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3d,0x2e,0x10,0x70, +0x2f,0x10,0x70,0x34,0x12,0x70,0x65,0x72,0x35,0x61,0x46,0x63,0x52,0x65,0x64,0x66, +0x72,0x6c,2,0x65,0x2d,0x66,0x3b,0x6f,0x28,0x12,0x77,0x65,0x72,0x29,0x10,0x74, +0x22,0x12,0x65,0x72,0x6d,0x23,1,0x6c,0x24,0x72,0x37,0x24,0x12,0x6f,0x73,0x65, +0x25,0x10,0x78,0x38,0x13,0x74,0x65,0x6e,0x64,0x39,0x10,0x6f,0x26,0x13,0x72,0x6d, +0x61,0x74,0x27,0,0x10,0x6c,0x88,0x72,0x40,0x72,0x36,0x73,0x5e,0x77,0x7a,0x78, +0x8a,0x7a,0x11,0x77,0x6a,0x4b,1,0x65,0x24,0x69,0x3b,0x1e,0x67,0x69,0x6f,0x6e, +0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x3b,1,0x69,0x24,0x71, +0x3f,0x18,0x6e,0x67,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x3f,0x17,0x73,0x65,0x67, +0x73,0x70,0x61,0x63,0x65,0x4d,0x10,0x78,0x21,0x6c,0x36,0x6d,0x3c,0x6e,0x76,0x6f, +0x13,0x74,0x68,0x65,0x72,0x21,1,0x65,0x23,0x66,0x35,3,0x62,0x37,0x69,0x28, +0x6c,0x29,0x6e,0x2b,0x10,0x64,1,0x6c,0x34,0x6e,0x11,0x75,0x6d,0x2a,0x12,0x6c, +0x65,0x74,0x37,0x14,0x65,0x74,0x74,0x65,0x72,0x29,2,0x65,0x36,0x6c,0x39,0x75, +0x2c,0x14,0x6d,0x65,0x72,0x69,0x63,0x2d,0x14,0x77,0x6c,0x69,0x6e,0x65,0x39,0x66, +0x3f,0x66,0x40,0x67,0x4e,0x68,0x70,0x6b,0x10,0x61,0x26,0x15,0x74,0x61,0x6b,0x61, +0x6e,0x61,0x27,0x10,0x6f,0x24,0x13,0x72,0x6d,0x61,0x74,0x25,1,0x61,0x3a,0x6c, +0x19,0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x49,0x10,0x7a,0x49,1, +0x65,0x24,0x6c,0x3d,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d, +0x61,0x86,0x63,0x92,0x64,0x94,0x65,2,0x62,0x44,0x6d,0x5e,0x78,0x2e,0x13,0x74, +0x65,0x6e,0x64,0x32,0x15,0x6e,0x75,0x6d,0x6c,0x65,0x74,0x2f,0x42,1,0x61,0x24, +0x67,0x45,0x11,0x73,0x65,0x42,0x12,0x67,0x61,0x7a,0x45,0x46,0x16,0x6f,0x64,0x69, +0x66,0x69,0x65,0x72,0x47,0x15,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x10,0x72,0x31, +1,0x6f,0x24,0x71,0x41,0x18,0x75,0x62,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x41, +2,0x63,0x32,0x6e,0x3c,0x6f,0x22,0x12,0x70,0x65,0x6e,0x23,0x24,0x13,0x6c,0x6f, +0x73,0x65,0x25,0x20,0x12,0x6f,0x6e,0x65,0x21,6,0x6f,0x65,0x6f,0x4a,0x72,0x5c, +0x74,0x64,0x76,0x1d,0x69,0x73,0x75,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72,0x6c,0x65, +0x66,0x74,0x3d,0x18,0x76,0x65,0x72,0x73,0x74,0x72,0x75,0x63,0x6b,0x2d,0x13,0x69, +0x67,0x68,0x74,0x2f,0x11,0x6f,0x70,0x30,0x12,0x61,0x6e,0x64,2,0x62,0x32,0x6c, +0x62,0x72,0x13,0x69,0x67,0x68,0x74,0x3b,0x14,0x6f,0x74,0x74,0x6f,0x6d,0x32,0x12, +0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x35,0x12,0x65,0x66, +0x74,0x3f,0x12,0x65,0x66,0x74,0x36,0x17,0x61,0x6e,0x64,0x72,0x69,0x67,0x68,0x74, +0x39,0x62,0x2c,0x6c,0x5c,0x6e,0x10,0x61,0x21,0x14,0x6f,0x74,0x74,0x6f,0x6d,0x22, +0x12,0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x27,0x12,0x65, +0x66,0x74,0x25,0x12,0x65,0x66,0x74,0x28,0x17,0x61,0x6e,0x64,0x72,0x69,0x67,0x68, +0x74,0x2b,0xd,0x6e,0xbd,0x72,0x83,0x72,0x92,0x73,0xa2,0x59,0x74,0xa2,0x67,0x76, +1,0x69,0x60,0x6f,0x12,0x77,0x65,0x6c,0x62,1,0x64,0x3a,0x69,0x19,0x6e,0x64, +0x65,0x70,0x65,0x6e,0x64,0x65,0x6e,0x74,0x67,0x17,0x65,0x70,0x65,0x6e,0x64,0x65, +0x6e,0x74,0x65,1,0x72,0x2e,0x73,0x13,0x61,0x72,0x67,0x61,0x61,0x12,0x61,0x6d, +0x61,0x5f,0x10,0x65,1,0x67,0x40,0x6f,0x1c,0x72,0x64,0x65,0x72,0x69,0x6e,0x67, +0x6b,0x69,0x6c,0x6c,0x65,0x72,0x69,0x1b,0x69,0x73,0x74,0x65,0x72,0x73,0x68,0x69, +0x66,0x74,0x65,0x72,0x57,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x6d,0x6f,0x64, +0x69,0x66,0x69,0x65,0x72,0x59,0x12,0x6f,0x6e,0x65,1,0x6c,0x2c,0x6d,0x12,0x61, +0x72,0x6b,0x5d,0x14,0x65,0x74,0x74,0x65,0x72,0x5b,0x6e,0x3c,0x6f,0x7c,0x70,0x18, +0x75,0x72,0x65,0x6b,0x69,0x6c,0x6c,0x65,0x72,0x55,1,0x6f,0x4c,0x75,1,0x6b, +0x3c,0x6d,0x12,0x62,0x65,0x72,0x50,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x53,0x11, +0x74,0x61,0x4f,0x16,0x6e,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x4d,0x13,0x74,0x68,0x65, +0x72,0x21,0x67,0x3e,0x67,0x4a,0x69,0x64,0x6a,0x82,0x6d,0x1d,0x6f,0x64,0x69,0x66, +0x79,0x69,0x6e,0x67,0x6c,0x65,0x74,0x74,0x65,0x72,0x4b,0x1c,0x65,0x6d,0x69,0x6e, +0x61,0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x45,0x1e,0x6e,0x76,0x69,0x73,0x69, +0x62,0x6c,0x65,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x47,0x14,0x6f,0x69,0x6e,0x65, +0x72,0x49,0x61,0xa2,0xba,0x62,0xa2,0xc0,0x63,1,0x61,0xa2,0xa2,0x6f,0x16,0x6e, +0x73,0x6f,0x6e,0x61,0x6e,0x74,0x2a,8,0x6b,0x67,0x6b,0x48,0x6d,0x52,0x70,0x5c, +0x73,0xa2,0x42,0x77,0x19,0x69,0x74,0x68,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x43, +0x14,0x69,0x6c,0x6c,0x65,0x72,0x35,0x14,0x65,0x64,0x69,0x61,0x6c,0x37,1,0x6c, +0x52,0x72,0x10,0x65,1,0x63,0x2e,0x66,0x13,0x69,0x78,0x65,0x64,0x3d,0x19,0x65, +0x64,0x69,0x6e,0x67,0x72,0x65,0x70,0x68,0x61,0x3b,0x18,0x61,0x63,0x65,0x68,0x6f, +0x6c,0x64,0x65,0x72,0x39,0x10,0x75,1,0x62,0x3e,0x63,0x1b,0x63,0x65,0x65,0x64, +0x69,0x6e,0x67,0x72,0x65,0x70,0x68,0x61,0x41,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x64, +0x3f,0x64,0x4c,0x66,0x52,0x68,0x5a,0x69,0x1e,0x6e,0x69,0x74,0x69,0x61,0x6c,0x70, +0x6f,0x73,0x74,0x66,0x69,0x78,0x65,0x64,0x33,0x12,0x65,0x61,0x64,0x2d,0x13,0x69, +0x6e,0x61,0x6c,0x2f,0x18,0x65,0x61,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,0x1d, +0x6e,0x74,0x69,0x6c,0x6c,0x61,0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x29,0x16, +0x76,0x61,0x67,0x72,0x61,0x68,0x61,0x23,1,0x69,0x4a,0x72,0x10,0x61,0x1f,0x68, +0x6d,0x69,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27, +0x12,0x6e,0x64,0x75,0x25,2,0x72,0x38,0x74,0x46,0x75,0x26,0x15,0x70,0x72,0x69, +0x67,0x68,0x74,0x27,0x20,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x21,1,0x72,0x24, +0x75,0x25,0x22,0x18,0x61,0x6e,0x73,0x66,0x6f,0x72,0x6d,0x65,0x64,1,0x72,0x32, +0x75,0x15,0x70,0x72,0x69,0x67,0x68,0x74,0x25,0x15,0x6f,0x74,0x61,0x74,0x65,0x64, +0x23,1,0x61,0x38,0x72,0x18,0x65,0x73,0x74,0x72,0x69,0x63,0x74,0x65,0x64,0x21, +0x15,0x6c,0x6c,0x6f,0x77,0x65,0x64,0x23,3,0x63,0x34,0x65,0x44,0x6c,0x4e,0x6e, +0x12,0x6f,0x6e,0x65,0x21,0x17,0x6f,0x6e,0x73,0x6f,0x6e,0x61,0x6e,0x74,0x23,0x14, +0x78,0x74,0x65,0x6e,0x64,0x25,0x14,0x69,0x6e,0x6b,0x65,0x72,0x27,0xd,0x6e,0xc1, +0x86,0x73,0xa8,0x73,0x4c,0x74,0xa2,0x76,0x75,0xa2,0x83,0x7a,0xd8,0x70,0,2, +0x6c,0xd9,0x20,0,0x70,0xd9,0x40,0,0x73,0xc3,0,0xfe,0xf,0,0,0, +7,0x6f,0x3c,0x6f,0xff,8,0,0,0,0x70,0x3a,0x75,0x6e,0x79,0x13,0x6d, +0x62,0x6f,0x6c,0xff,0xf,0,0,0,0x11,0x61,0x63,1,0x65,0x34,0x69,0x15, +0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0,0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74, +0x6f,0x72,0xc3,0,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0xe1,0,0,0x63, +0xff,2,0,0,0,0x65,0x38,0x6b,0xff,4,0,0,0,0x6d,0xff,1, +0,0,0,0x16,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x70,0,0x1d,0x69, +0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,1,0x6e, +0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72, +0x25,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x23,0x6e,0xa2,0x69,0x6f,0xa2, +0x89,0x70,0xfe,0x30,0xf8,0,0,9,0x69,0x33,0x69,0xff,0x10,0,0,0, +0x6f,0xfd,0x80,0,0,0x72,0x54,0x73,0xf9,0,0,0x75,0x12,0x6e,0x63,0x74, +0xfe,0x30,0xf8,0,0,0x15,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x30,0xf8,0, +0,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xdd,0,0,0x61,0x48,0x63, +0xfd,0x40,0,0,0x64,0xe9,0,0,0x65,0xfd,0x20,0,0,0x66,0xff,0x20, +0,0,0,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72, +0x61,0x74,0x6f,0x72,0xd9,0x40,0,0xbe,0,3,0x64,0xa7,0,0x6c,0xab,0, +0x6f,0x30,0x75,0x13,0x6d,0x62,0x65,0x72,0xbf,0,0xb2,0,0x1b,0x6e,0x73,0x70, +0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa1,1,0x70,0x92,0x74,0x12,0x68, +0x65,0x72,0xe6,0x80,1,3,0x6c,0x40,0x6e,0x4a,0x70,0x56,0x73,0x14,0x79,0x6d, +0x62,0x6f,0x6c,0xff,8,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x61,0x14, +0x75,0x6d,0x62,0x65,0x72,0xb3,0,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, +0x6f,0x6e,0xfd,0x80,0,0,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, +0x74,0x69,0x6f,0x6e,0xf9,0,0,0x66,0xc0,0xc4,0x66,0xa2,0x47,0x69,0xa2,0x64, +0x6c,0xa2,0x79,0x6d,0xa4,0xc0,4,0x61,0x6c,0x63,0xa5,0,0x65,0xa3,0x80,0x6e, +0xa1,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x38,0x73,0x14,0x79,0x6d, +0x62,0x6f,0x6c,0xff,4,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x41,1, +0x72,0x3c,0x74,0x16,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,1,0,0,0, +0x10,0x6b,0xa5,0xc0,1,0x69,0x32,0x6f,0x13,0x72,0x6d,0x61,0x74,0xdb,0,0, +0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff, +0x20,0,0,0,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x10,0,0,0,0x9c,7,0x6d,0x18, +0x6d,0x41,0x6f,0x28,0x74,0x31,0x75,0x25,0x60,0x1c,0x77,0x65,0x72,0x63,0x61,0x73, +0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x29,0x63,0x3d,0x65,0x28,0x69,0x42,0x6c,0x29, +0x13,0x74,0x74,0x65,0x72,0x9c,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0xab,0,0x1a, +0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x20,0,0x63,0x46, +0x64,0xa2,0x96,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72, +0x6b,0xa3,0x80,0xe6,0x80,1,7,0x6e,0x57,0x6e,0x52,0x6f,0x5e,0x73,0xe1,0, +0,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff, +2,0,0,0,0x22,0x12,0x74,0x72,0x6c,0xd9,0x80,0,0xdc,0,0,1, +0x6d,0x62,0x6e,1,0x6e,0x30,0x74,0x12,0x72,0x6f,0x6c,0xd9,0x80,0,0x1f,0x65, +0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd, +0x40,0,0,0x19,0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0xc0, +0x61,0x58,0x63,0xd9,0x80,0,0x66,0xdb,0,0,0x6c,0x1d,0x6f,0x73,0x65,0x70, +0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x20,0,0,0x18,0x73, +0x65,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,2,0x61,0x32,0x65,0x50,0x69,0x12, +0x67,0x69,0x74,0xa7,0,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, +0x69,0x6f,0x6e,0xe9,0,0,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62, +0x65,0x72,0xa7,0,8,0x6e,0x50,0x6e,0x46,0x6f,0x7a,0x72,0x88,0x74,0x9c,0x75, +0x19,0x6e,0x63,0x6f,0x6d,0x6d,0x6f,0x6e,0x75,0x73,0x65,0x31,0x11,0x6f,0x74,2, +0x63,0x2e,0x6e,0x3e,0x78,0x11,0x69,0x64,0x29,0x17,0x68,0x61,0x72,0x61,0x63,0x74, +0x65,0x72,0x21,0x12,0x66,0x6b,0x63,0x27,0x16,0x62,0x73,0x6f,0x6c,0x65,0x74,0x65, +0x2d,0x19,0x65,0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x64,0x65,0x64,0x37,0x17,0x65,0x63, +0x68,0x6e,0x69,0x63,0x61,0x6c,0x2f,0x64,0x40,0x65,0x78,0x69,0x88,0x6c,0x18,0x69, +0x6d,0x69,0x74,0x65,0x64,0x75,0x73,0x65,0x33,0x10,0x65,1,0x66,0x34,0x70,0x16, +0x72,0x65,0x63,0x61,0x74,0x65,0x64,0x23,0x1c,0x61,0x75,0x6c,0x74,0x69,0x67,0x6e, +0x6f,0x72,0x61,0x62,0x6c,0x65,0x25,0x17,0x78,0x63,0x6c,0x75,0x73,0x69,0x6f,0x6e, +0x2b,0x17,0x6e,0x63,0x6c,0x75,0x73,0x69,0x6f,0x6e,0x35 }; -const char PropNameData::nameGroups[23743]={ +const char PropNameData::nameGroups[24294]={ 2,'A','l','p','h','a',0,'A','l','p','h','a','b','e','t','i','c',0, 4,'N',0,'N','o',0,'F',0,'F','a','l','s','e',0,4,'Y',0,'Y','e','s',0,'T',0,'T','r','u','e',0, 2,'N','R',0,'N','o','t','_','R','e','o','r','d','e','r','e','d',0, @@ -1203,6 +1227,7 @@ const char PropNameData::nameGroups[23743]={ 2,'I','D','_','C','o','m','p','a','t','_','M','a','t','h','_','S','t','a','r','t',0,'I','D','_','C','o','m','p','a','t','_', 'M','a','t','h','_','S','t','a','r','t',0,2,'I','D','_','C','o','m','p','a','t','_','M','a','t','h','_','C','o','n','t','i', 'n','u','e',0,'I','D','_','C','o','m','p','a','t','_','M','a','t','h','_','C','o','n','t','i','n','u','e',0, +2,'M','C','M',0,'M','o','d','i','f','i','e','r','_','C','o','m','b','i','n','i','n','g','_','M','a','r','k',0, 2,'b','c',0,'B','i','d','i','_','C','l','a','s','s',0,2,'L',0,'L','e','f','t','_','T','o','_','R','i','g','h','t',0, 2,'R',0,'R','i','g','h','t','_','T','o','_','L','e','f','t',0, 2,'E','N',0,'E','u','r','o','p','e','a','n','_','N','u','m','b','e','r',0, @@ -1597,6 +1622,18 @@ const char PropNameData::nameGroups[23743]={ 2,'K','a','w','i',0,'K','a','w','i',0,2,'N','a','g','_','M','u','n','d','a','r','i',0, 'N','a','g','_','M','u','n','d','a','r','i',0,2,'C','J','K','_','E','x','t','_','I',0,'C','J','K','_','U','n','i','f','i', 'e','d','_','I','d','e','o','g','r','a','p','h','s','_','E','x','t','e','n','s','i','o','n','_','I',0, +2,'E','g','y','p','t','i','a','n','_','H','i','e','r','o','g','l','y','p','h','s','_','E','x','t','_','A',0, +'E','g','y','p','t','i','a','n','_','H','i','e','r','o','g','l','y','p','h','s','_','E','x','t','e','n','d','e','d','_','A',0, +2,'G','a','r','a','y',0,'G','a','r','a','y',0,2,'G','u','r','u','n','g','_','K','h','e','m','a',0, +'G','u','r','u','n','g','_','K','h','e','m','a',0,2,'K','i','r','a','t','_','R','a','i',0, +'K','i','r','a','t','_','R','a','i',0,2,'M','y','a','n','m','a','r','_','E','x','t','_','C',0, +'M','y','a','n','m','a','r','_','E','x','t','e','n','d','e','d','_','C',0, +2,'O','l','_','O','n','a','l',0,'O','l','_','O','n','a','l',0, +2,'S','u','n','u','w','a','r',0,'S','u','n','u','w','a','r',0, +2,'S','y','m','b','o','l','s','_','F','o','r','_','L','e','g','a','c','y','_','C','o','m','p','u','t','i','n','g','_','S','u', +'p',0,'S','y','m','b','o','l','s','_','F','o','r','_','L','e','g','a','c','y','_','C','o','m','p','u','t','i','n','g','_','S', +'u','p','p','l','e','m','e','n','t',0,2,'T','o','d','h','r','i',0,'T','o','d','h','r','i',0, +2,'T','u','l','u','_','T','i','g','a','l','a','r','i',0,'T','u','l','u','_','T','i','g','a','l','a','r','i',0, 2,'c','c','c',0,'C','a','n','o','n','i','c','a','l','_','C','o','m','b','i','n','i','n','g','_','C','l','a','s','s',0, 2,'d','t',0,'D','e','c','o','m','p','o','s','i','t','i','o','n','_','T','y','p','e',0, 3,'N','o','n','e',0,'N','o','n','e',0,'n','o','n','e',0, @@ -1655,8 +1692,9 @@ const char PropNameData::nameGroups[23743]={ 2,'E',0,'E',0,2,'F','e','h',0,'F','e','h',0,2,'F','i','n','a','l','_','S','e','m','k','a','t','h',0, 'F','i','n','a','l','_','S','e','m','k','a','t','h',0,2,'G','a','f',0,'G','a','f',0, 2,'G','a','m','a','l',0,'G','a','m','a','l',0,2,'H','a','h',0,'H','a','h',0, -2,'T','e','h','_','M','a','r','b','u','t','a','_','G','o','a','l',0,'H','a','m','z','a','_','O','n','_','H','e','h','_','G', -'o','a','l',0,2,'H','e',0,'H','e',0,2,'H','e','h',0,'H','e','h',0, +3,'T','e','h','_','M','a','r','b','u','t','a','_','G','o','a','l',0,'T','e','h','_','M','a','r','b','u','t','a','_','G','o', +'a','l',0,'H','a','m','z','a','_','O','n','_','H','e','h','_','G','o','a','l',0, +2,'H','e',0,'H','e',0,2,'H','e','h',0,'H','e','h',0, 2,'H','e','h','_','G','o','a','l',0,'H','e','h','_','G','o','a','l',0, 2,'H','e','t','h',0,'H','e','t','h',0,2,'K','a','f',0,'K','a','f',0, 2,'K','a','p','h',0,'K','a','p','h',0,2,'K','n','o','t','t','e','d','_','H','e','h',0, @@ -1734,6 +1772,7 @@ const char PropNameData::nameGroups[23743]={ 2,'H','a','n','i','f','i','_','R','o','h','i','n','g','y','a','_','P','a',0,'H','a','n','i','f','i','_','R','o','h','i','n', 'g','y','a','_','P','a',0,2,'T','h','i','n','_','Y','e','h',0,'T','h','i','n','_','Y','e','h',0, 2,'V','e','r','t','i','c','a','l','_','T','a','i','l',0,'V','e','r','t','i','c','a','l','_','T','a','i','l',0, +2,'K','a','s','h','m','i','r','i','_','Y','e','h',0,'K','a','s','h','m','i','r','i','_','Y','e','h',0, 2,'j','t',0,'J','o','i','n','i','n','g','_','T','y','p','e',0, 2,'U',0,'N','o','n','_','J','o','i','n','i','n','g',0,2,'C',0,'J','o','i','n','_','C','a','u','s','i','n','g',0, 2,'D',0,'D','u','a','l','_','J','o','i','n','i','n','g',0, @@ -1893,8 +1932,13 @@ const char PropNameData::nameGroups[23743]={ 2,'O','u','g','r',0,'O','l','d','_','U','y','g','h','u','r',0, 2,'T','n','s','a',0,'T','a','n','g','s','a',0,2,'V','i','t','h',0,'V','i','t','h','k','u','q','i',0, 2,'N','a','g','m',0,'N','a','g','_','M','u','n','d','a','r','i',0, -2,'A','r','a','n',0,'A','r','a','n',0,2,'h','s','t',0,'H','a','n','g','u','l','_','S','y','l','l','a','b','l','e','_', -'T','y','p','e',0,2,'N','A',0,'N','o','t','_','A','p','p','l','i','c','a','b','l','e',0, +2,'A','r','a','n',0,'A','r','a','n',0,2,'G','a','r','a',0,'G','a','r','a','y',0, +2,'G','u','k','h',0,'G','u','r','u','n','g','_','K','h','e','m','a',0, +2,'K','r','a','i',0,'K','i','r','a','t','_','R','a','i',0, +2,'O','n','a','o',0,'O','l','_','O','n','a','l',0,2,'S','u','n','u',0,'S','u','n','u','w','a','r',0, +2,'T','o','d','r',0,'T','o','d','h','r','i',0,2,'T','u','t','g',0,'T','u','l','u','_','T','i','g','a','l','a','r','i', +0,2,'h','s','t',0,'H','a','n','g','u','l','_','S','y','l','l','a','b','l','e','_','T','y','p','e',0, +2,'N','A',0,'N','o','t','_','A','p','p','l','i','c','a','b','l','e',0, 2,'L',0,'L','e','a','d','i','n','g','_','J','a','m','o',0, 2,'V',0,'V','o','w','e','l','_','J','a','m','o',0,2,'T',0,'T','r','a','i','l','i','n','g','_','J','a','m','o',0, 2,'L','V',0,'L','V','_','S','y','l','l','a','b','l','e',0, @@ -1987,16 +2031,18 @@ const char PropNameData::nameGroups[23743]={ 'V','i','s','a','r','g','a',0,2,'V','o','w','e','l',0,'V','o','w','e','l',0, 2,'V','o','w','e','l','_','D','e','p','e','n','d','e','n','t',0,'V','o','w','e','l','_','D','e','p','e','n','d','e','n','t', 0,2,'V','o','w','e','l','_','I','n','d','e','p','e','n','d','e','n','t',0,'V','o','w','e','l','_','I','n','d','e','p','e', -'n','d','e','n','t',0,2,'v','o',0,'V','e','r','t','i','c','a','l','_','O','r','i','e','n','t','a','t','i','o','n',0, +'n','d','e','n','t',0,2,'R','e','o','r','d','e','r','i','n','g','_','K','i','l','l','e','r',0, +'R','e','o','r','d','e','r','i','n','g','_','K','i','l','l','e','r',0, +2,'v','o',0,'V','e','r','t','i','c','a','l','_','O','r','i','e','n','t','a','t','i','o','n',0, 2,'R',0,'R','o','t','a','t','e','d',0,2,'T','r',0,'T','r','a','n','s','f','o','r','m','e','d','_','R','o','t','a','t', 'e','d',0,2,'T','u',0,'T','r','a','n','s','f','o','r','m','e','d','_','U','p','r','i','g','h','t',0, -2,'U',0,'U','p','r','i','g','h','t',0,2,'I','d','e','n','t','i','f','i','e','r','_','S','t','a','t','u','s',0, -'I','d','e','n','t','i','f','i','e','r','_','S','t','a','t','u','s',0, -2,'R','e','s','t','r','i','c','t','e','d',0,'R','e','s','t','r','i','c','t','e','d',0, +2,'U',0,'U','p','r','i','g','h','t',0,2,'I','D','_','S','t','a','t','u','s',0,'I','d','e','n','t','i','f','i','e','r', +'_','S','t','a','t','u','s',0,2,'R','e','s','t','r','i','c','t','e','d',0,'R','e','s','t','r','i','c','t','e','d',0, 2,'A','l','l','o','w','e','d',0,'A','l','l','o','w','e','d',0, -2,'g','c','m',0,'G','e','n','e','r','a','l','_','C','a','t','e','g','o','r','y','_','M','a','s','k',0, -2,'C',0,'O','t','h','e','r',0,2,'L',0,'L','e','t','t','e','r',0, -2,'L','C',0,'C','a','s','e','d','_','L','e','t','t','e','r',0, +2,'I','n','C','B',0,'I','n','d','i','c','_','C','o','n','j','u','n','c','t','_','B','r','e','a','k',0, +2,'L','i','n','k','e','r',0,'L','i','n','k','e','r',0,2,'g','c','m',0,'G','e','n','e','r','a','l','_','C','a','t','e', +'g','o','r','y','_','M','a','s','k',0,2,'C',0,'O','t','h','e','r',0, +2,'L',0,'L','e','t','t','e','r',0,2,'L','C',0,'C','a','s','e','d','_','L','e','t','t','e','r',0, 3,'M',0,'M','a','r','k',0,'C','o','m','b','i','n','i','n','g','_','M','a','r','k',0, 2,'N',0,'N','u','m','b','e','r',0,3,'P',0,'P','u','n','c','t','u','a','t','i','o','n',0, 'p','u','n','c','t',0,2,'S',0,'S','y','m','b','o','l',0, @@ -2014,8 +2060,8 @@ const char PropNameData::nameGroups[23743]={ 2,'u','c',0,'U','p','p','e','r','c','a','s','e','_','M','a','p','p','i','n','g',0, 2,'b','p','b',0,'B','i','d','i','_','P','a','i','r','e','d','_','B','r','a','c','k','e','t',0, 2,'s','c','x',0,'S','c','r','i','p','t','_','E','x','t','e','n','s','i','o','n','s',0, -2,'I','d','e','n','t','i','f','i','e','r','_','T','y','p','e',0,'I','d','e','n','t','i','f','i','e','r','_','T','y','p','e', -0,2,'N','o','t','_','C','h','a','r','a','c','t','e','r',0,'N','o','t','_','C','h','a','r','a','c','t','e','r',0, +2,'I','D','_','T','y','p','e',0,'I','d','e','n','t','i','f','i','e','r','_','T','y','p','e',0, +2,'N','o','t','_','C','h','a','r','a','c','t','e','r',0,'N','o','t','_','C','h','a','r','a','c','t','e','r',0, 2,'D','e','p','r','e','c','a','t','e','d',0,'D','e','p','r','e','c','a','t','e','d',0, 2,'D','e','f','a','u','l','t','_','I','g','n','o','r','a','b','l','e',0,'D','e','f','a','u','l','t','_','I','g','n','o','r', 'a','b','l','e',0,2,'N','o','t','_','N','F','K','C',0,'N','o','t','_','N','F','K','C',0, diff --git a/thirdparty/icu4c/common/propsvec.cpp b/thirdparty/icu4c/common/propsvec.cpp index 18cc3e8cd8..64997313f9 100644 --- a/thirdparty/icu4c/common/propsvec.cpp +++ b/thirdparty/icu4c/common/propsvec.cpp @@ -102,29 +102,29 @@ _findRow(UPropsVectors *pv, UChar32 rangeStart) { /* check the vicinity of the last-seen row (start searching with an unrolled loop) */ row=pv->v+prevRow*columns; - if(rangeStart>=(UChar32)row[0]) { - if(rangeStart<(UChar32)row[1]) { + if (rangeStart >= static_cast<UChar32>(row[0])) { + if (rangeStart < static_cast<UChar32>(row[1])) { /* same row as last seen */ return row; - } else if(rangeStart<(UChar32)(row+=columns)[1]) { + } else if (rangeStart < static_cast<UChar32>((row += columns)[1])) { /* next row after the last one */ pv->prevRow=prevRow+1; return row; - } else if(rangeStart<(UChar32)(row+=columns)[1]) { + } else if (rangeStart < static_cast<UChar32>((row += columns)[1])) { /* second row after the last one */ pv->prevRow=prevRow+2; return row; - } else if((rangeStart-(UChar32)row[1])<10) { + } else if ((rangeStart - static_cast<UChar32>(row[1])) < 10) { /* we are close, continue looping */ prevRow+=2; do { ++prevRow; row+=columns; - } while(rangeStart>=(UChar32)row[1]); + } while (rangeStart >= static_cast<UChar32>(row[1])); pv->prevRow=prevRow; return row; } - } else if(rangeStart<(UChar32)pv->v[1]) { + } else if (rangeStart < static_cast<UChar32>(pv->v[1])) { /* the very first row */ pv->prevRow=0; return pv->v; @@ -135,9 +135,9 @@ _findRow(UPropsVectors *pv, UChar32 rangeStart) { while(start<limit-1) { i=(start+limit)/2; row=pv->v+i*columns; - if(rangeStart<(UChar32)row[0]) { + if (rangeStart < static_cast<UChar32>(row[0])) { limit=i; - } else if(rangeStart<(UChar32)row[1]) { + } else if (rangeStart < static_cast<UChar32>(row[1])) { pv->prevRow=i; return row; } else { @@ -194,8 +194,8 @@ upvec_setValue(UPropsVectors *pv, * input range (only possible for the first and last rows) * and if their value differs from the input value. */ - splitFirstRow= (UBool)(start!=(UChar32)firstRow[0] && value!=(firstRow[column]&mask)); - splitLastRow= (UBool)(limit!=(UChar32)lastRow[1] && value!=(lastRow[column]&mask)); + splitFirstRow = start != static_cast<UChar32>(firstRow[0]) && value != (firstRow[column] & mask); + splitLastRow = limit != static_cast<UChar32>(lastRow[1]) && value != (lastRow[column] & mask); /* split first/last rows if necessary */ if(splitFirstRow || splitLastRow) { @@ -312,8 +312,8 @@ upvec_getRow(const UPropsVectors *pv, int32_t rowIndex, static int32_t U_CALLCONV upvec_compareRows(const void *context, const void *l, const void *r) { - const uint32_t *left=(const uint32_t *)l, *right=(const uint32_t *)r; - const UPropsVectors *pv=(const UPropsVectors *)context; + const uint32_t* left = static_cast<const uint32_t*>(l), *right = static_cast<const uint32_t*>(r); + const UPropsVectors* pv = static_cast<const UPropsVectors*>(context); int32_t i, count, columns; count=columns=pv->columns; /* includes start/limit columns */ diff --git a/thirdparty/icu4c/common/punycode.cpp b/thirdparty/icu4c/common/punycode.cpp index 7ebdebc188..aa02298c5e 100644 --- a/thirdparty/icu4c/common/punycode.cpp +++ b/thirdparty/icu4c/common/punycode.cpp @@ -97,12 +97,12 @@ digitToBasic(int32_t digit, UBool uppercase) { /* 26..35 map to ASCII 0..9 */ if(digit<26) { if(uppercase) { - return (char)(_CAPITAL_A+digit); + return static_cast<char>(_CAPITAL_A + digit); } else { - return (char)(_SMALL_A+digit); + return static_cast<char>(_SMALL_A + digit); } } else { - return (char)((_ZERO_-26)+digit); + return static_cast<char>((_ZERO_ - 26) + digit); } } @@ -353,10 +353,10 @@ u_strToPunycode(const char16_t *src, int32_t srcLength, } if(destLength<destCapacity) { - dest[destLength]=digitToBasic(q, (UBool)(cpBuffer[j]<0)); + dest[destLength] = digitToBasic(q, cpBuffer[j] < 0); } ++destLength; - bias=adaptBias(delta, handledCPCount+1, (UBool)(handledCPCount==basicLength)); + bias = adaptBias(delta, handledCPCount + 1, handledCPCount == basicLength); delta=0; ++handledCPCount; } @@ -421,7 +421,7 @@ u_strFromPunycode(const char16_t *src, int32_t srcLength, } if(j<destCapacity) { - dest[j]=(char16_t)b; + dest[j] = b; if(caseFlags!=nullptr) { caseFlags[j]=IS_BASIC_UPPERCASE(b); @@ -500,7 +500,7 @@ u_strFromPunycode(const char16_t *src, int32_t srcLength, * where needed instead of in for() loop tail. */ ++destCPCount; - bias=adaptBias(i-oldi, destCPCount, (UBool)(oldi==0)); + bias = adaptBias(i - oldi, destCPCount, oldi == 0); /* * i was supposed to wrap around from (incremented) destCPCount to 0, diff --git a/thirdparty/icu4c/common/putil.cpp b/thirdparty/icu4c/common/putil.cpp index 92c7940827..4cf07797ba 100644 --- a/thirdparty/icu4c/common/putil.cpp +++ b/thirdparty/icu4c/common/putil.cpp @@ -46,11 +46,6 @@ // First, the platform type. Need this for U_PLATFORM. #include "unicode/platform.h" -#if U_PLATFORM == U_PF_MINGW && defined __STRICT_ANSI__ -/* tzset isn't defined in strict ANSI on MinGW. */ -#undef __STRICT_ANSI__ -#endif - /* * Cygwin with GCC requires inclusion of time.h after the above disabling strict asci mode statement. */ @@ -180,8 +175,8 @@ typedef union { int64_t i64; /* This must be defined first in order to allow the initialization to work. This is a C89 feature. */ double d64; } BitPatternConversion; -static const BitPatternConversion gNan = { (int64_t) INT64_C(0x7FF8000000000000) }; -static const BitPatternConversion gInf = { (int64_t) INT64_C(0x7FF0000000000000) }; +static const BitPatternConversion gNan = {static_cast<int64_t>(INT64_C(0x7FF8000000000000))}; +static const BitPatternConversion gInf = {static_cast<int64_t>(INT64_C(0x7FF0000000000000))}; /*--------------------------------------------------------------------------- Platform utilities @@ -230,7 +225,7 @@ u_signBit(double d) { #if U_IS_BIG_ENDIAN hiByte = *(uint8_t *)&d; #else - hiByte = *(((uint8_t *)&d) + sizeof(double) - 1); + hiByte = *(reinterpret_cast<uint8_t*>(&d) + sizeof(double) - 1); #endif return (hiByte & 0x80) != 0; } @@ -347,7 +342,7 @@ uprv_isNaN(double number) BitPatternConversion convertedNumber; convertedNumber.d64 = number; /* Infinity is 0x7FF0000000000000U. Anything greater than that is a NaN */ - return (UBool)((convertedNumber.i64 & U_INT64_MAX) > gInf.i64); + return (convertedNumber.i64 & U_INT64_MAX) > gInf.i64; #elif U_PLATFORM == U_PF_OS390 uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number, @@ -373,7 +368,7 @@ uprv_isInfinite(double number) BitPatternConversion convertedNumber; convertedNumber.d64 = number; /* Infinity is exactly 0x7FF0000000000000U. */ - return (UBool)((convertedNumber.i64 & U_INT64_MAX) == gInf.i64); + return (convertedNumber.i64 & U_INT64_MAX) == gInf.i64; #elif U_PLATFORM == U_PF_OS390 uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number, sizeof(uint32_t)); @@ -394,7 +389,7 @@ U_CAPI UBool U_EXPORT2 uprv_isPositiveInfinity(double number) { #if IEEE_754 || U_PLATFORM == U_PF_OS390 - return (UBool)(number > 0 && uprv_isInfinite(number)); + return number > 0 && uprv_isInfinite(number); #else return uprv_isInfinite(number); #endif @@ -404,7 +399,7 @@ U_CAPI UBool U_EXPORT2 uprv_isNegativeInfinity(double number) { #if IEEE_754 || U_PLATFORM == U_PF_OS390 - return (UBool)(number < 0 && uprv_isInfinite(number)); + return number < 0 && uprv_isInfinite(number); #else uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number, @@ -749,11 +744,11 @@ static UBool isValidOlsonID(const char *id) { The timezone is sometimes set to "CST-7CDT", "CST6CDT5,J129,J131/19:30", "GRNLNDST3GRNLNDDT" or similar, so we cannot use it. The rest of the time it could be an Olson ID. George */ - return (UBool)(id[idx] == 0 + return id[idx] == 0 || uprv_strcmp(id, "PST8PDT") == 0 || uprv_strcmp(id, "MST7MDT") == 0 || uprv_strcmp(id, "CST6CDT") == 0 - || uprv_strcmp(id, "EST5EDT") == 0); + || uprv_strcmp(id, "EST5EDT") == 0; } /* On some Unix-like OS, 'posix' subdirectory in @@ -932,7 +927,7 @@ static UBool compareBinaryFiles(const char* defaultTZFileName, const char* TZFil */ if (tzInfo->defaultTZBuffer == nullptr) { rewind(tzInfo->defaultTZFilePtr); - tzInfo->defaultTZBuffer = (char*)uprv_malloc(sizeof(char) * tzInfo->defaultTZFileSize); + tzInfo->defaultTZBuffer = static_cast<char*>(uprv_malloc(sizeof(char) * tzInfo->defaultTZFileSize)); sizeFileRead = fread(tzInfo->defaultTZBuffer, 1, tzInfo->defaultTZFileSize, tzInfo->defaultTZFilePtr); } rewind(file); diff --git a/thirdparty/icu4c/common/putilimp.h b/thirdparty/icu4c/common/putilimp.h index 5b95a68418..8a8ff50081 100644 --- a/thirdparty/icu4c/common/putilimp.h +++ b/thirdparty/icu4c/common/putilimp.h @@ -90,6 +90,8 @@ typedef size_t uintptr_t; # define U_NL_LANGINFO_CODESET -1 #elif U_PLATFORM == U_PF_OS400 /* not defined */ +#elif U_PLATFORM == U_PF_HAIKU + /* not defined */ #else # define U_NL_LANGINFO_CODESET CODESET #endif @@ -103,6 +105,8 @@ typedef size_t uintptr_t; #endif #elif U_PLATFORM == U_PF_OS400 /* not defined */ +#elif U_PLATFORM == U_PF_HAIKU + /* not defined */ #else # define U_TZSET tzset #endif @@ -141,6 +145,8 @@ typedef size_t uintptr_t; #endif #elif U_PLATFORM == U_PF_OS400 /* not defined */ +#elif U_PLATFORM == U_PF_HAIKU + /* not defined, (well it is but a loop back to icu) */ #else # define U_TZNAME tzname #endif @@ -553,7 +559,7 @@ inline int32_t pinCapacity(T *dest, int32_t capacity) { if (maxInt < destInt) { // Less than 2GB to the end of the address space. // Pin to that to prevent address overflow. - maxInt = (uintptr_t)-1; + maxInt = static_cast<uintptr_t>(-1); } # endif diff --git a/thirdparty/icu4c/common/rbbi.cpp b/thirdparty/icu4c/common/rbbi.cpp index 9c4141022c..069af21537 100644 --- a/thirdparty/icu4c/common/rbbi.cpp +++ b/thirdparty/icu4c/common/rbbi.cpp @@ -110,7 +110,7 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(const uint8_t *compiledRules, status = U_ILLEGAL_ARGUMENT_ERROR; return; } - const RBBIDataHeader *data = (const RBBIDataHeader *)compiledRules; + const RBBIDataHeader* data = reinterpret_cast<const RBBIDataHeader*>(compiledRules); if (data->fLength > ruleLength) { status = U_ILLEGAL_ARGUMENT_ERROR; return; @@ -553,7 +553,7 @@ int32_t RuleBasedBreakIterator::first() { * @return The text's past-the-end offset. */ int32_t RuleBasedBreakIterator::last() { - int32_t endPos = (int32_t)utext_nativeLength(&fText); + int32_t endPos = static_cast<int32_t>(utext_nativeLength(&fText)); UBool endShouldBeBoundary = isBoundary(endPos); // Has side effect of setting iterator position. (void)endShouldBeBoundary; U_ASSERT(endShouldBeBoundary); @@ -625,7 +625,7 @@ int32_t RuleBasedBreakIterator::following(int32_t startPos) { // Move requested offset to a code point start. It might be on a trail surrogate, // or on a trail byte if the input is UTF-8. Or it may be beyond the end of the text. utext_setNativeIndex(&fText, startPos); - startPos = (int32_t)utext_getNativeIndex(&fText); + startPos = static_cast<int32_t>(utext_getNativeIndex(&fText)); UErrorCode status = U_ZERO_ERROR; fBreakCache->following(startPos, status); @@ -881,7 +881,7 @@ int32_t RuleBasedBreakIterator::handleNext() { if (accepting == ACCEPTING_UNCONDITIONAL) { // Match found, common case. if (mode != RBBI_START) { - result = (int32_t)UTEXT_GETNATIVEINDEX(&fText); + result = static_cast<int32_t>(UTEXT_GETNATIVEINDEX(&fText)); } fRuleStatusIndex = row->fTagsIdx; // Remember the break status (tag) values. } else if (accepting > ACCEPTING_UNCONDITIONAL) { @@ -905,7 +905,7 @@ int32_t RuleBasedBreakIterator::handleNext() { U_ASSERT(rule == 0 || rule > ACCEPTING_UNCONDITIONAL); U_ASSERT(rule == 0 || rule < fData->fForwardTable->fLookAheadResultsSize); if (rule > ACCEPTING_UNCONDITIONAL) { - int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(&fText); + int32_t pos = static_cast<int32_t>(UTEXT_GETNATIVEINDEX(&fText)); fLookAheadMatches[rule] = pos; } @@ -937,7 +937,7 @@ int32_t RuleBasedBreakIterator::handleNext() { if (result == initialPosition) { utext_setNativeIndex(&fText, initialPosition); utext_next32(&fText); - result = (int32_t)utext_getNativeIndex(&fText); + result = static_cast<int32_t>(utext_getNativeIndex(&fText)); fRuleStatusIndex = 0; } @@ -1027,7 +1027,7 @@ int32_t RuleBasedBreakIterator::handleSafePrevious(int32_t fromPosition) { } // The state machine is done. Check whether it found a match... - result = (int32_t)UTEXT_GETNATIVEINDEX(&fText); + result = static_cast<int32_t>(UTEXT_GETNATIVEINDEX(&fText)); #ifdef RBBI_DEBUG if (gTrace) { RBBIDebugPrintf("result = %d\n\n", result); @@ -1091,7 +1091,7 @@ const uint8_t *RuleBasedBreakIterator::getBinaryRules(uint32_t &length) { length = 0; if (fData != nullptr) { - retPtr = (const uint8_t *)fData->fHeader; + retPtr = reinterpret_cast<const uint8_t*>(fData->fHeader); length = fData->fHeader->fLength; } return retPtr; @@ -1187,7 +1187,7 @@ getLanguageBreakEngineFromFactory(UChar32 c, const char* locale) int32_t i = gLanguageBreakFactories->size(); const LanguageBreakEngine *lbe = nullptr; while (--i >= 0) { - LanguageBreakFactory *factory = (LanguageBreakFactory *)(gLanguageBreakFactories->elementAt(i)); + LanguageBreakFactory* factory = static_cast<LanguageBreakFactory*>(gLanguageBreakFactories->elementAt(i)); lbe = factory->getEngineFor(c, locale); if (lbe != nullptr) { break; @@ -1219,7 +1219,7 @@ RuleBasedBreakIterator::getLanguageBreakEngine(UChar32 c, const char* locale) { int32_t i = fLanguageBreakEngines->size(); while (--i >= 0) { - lbe = (const LanguageBreakEngine *)(fLanguageBreakEngines->elementAt(i)); + lbe = static_cast<const LanguageBreakEngine*>(fLanguageBreakEngines->elementAt(i)); if (lbe->handles(c, locale)) { return lbe; } diff --git a/thirdparty/icu4c/common/rbbi_cache.cpp b/thirdparty/icu4c/common/rbbi_cache.cpp index 239345998b..3ef030cb91 100644 --- a/thirdparty/icu4c/common/rbbi_cache.cpp +++ b/thirdparty/icu4c/common/rbbi_cache.cpp @@ -146,7 +146,7 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo uint32_t dictStart = fBI->fData->fForwardTable->fDictCategoriesStart; while(U_SUCCESS(status)) { - while((current = (int32_t)UTEXT_GETNATIVEINDEX(text)) < rangeEnd + while ((current = static_cast<int32_t>(UTEXT_GETNATIVEINDEX(text))) < rangeEnd && (category < dictStart)) { utext_next32(text); // TODO: cleaner loop structure. c = utext_current32(text); @@ -221,7 +221,7 @@ void RuleBasedBreakIterator::BreakCache::reset(int32_t pos, int32_t ruleStatus) fTextIdx = pos; fBufIdx = 0; fBoundaries[0] = pos; - fStatuses[0] = (uint16_t)ruleStatus; + fStatuses[0] = static_cast<uint16_t>(ruleStatus); } diff --git a/thirdparty/icu4c/common/rbbidata.cpp b/thirdparty/icu4c/common/rbbidata.cpp index 49603b6193..edfa1bf0d8 100644 --- a/thirdparty/icu4c/common/rbbidata.cpp +++ b/thirdparty/icu4c/common/rbbidata.cpp @@ -104,10 +104,10 @@ void RBBIDataWrapper::init(const RBBIDataHeader *data, UErrorCode &status) { fDontFreeData = false; if (data->fFTableLen != 0) { - fForwardTable = (RBBIStateTable *)((char *)data + fHeader->fFTable); + fForwardTable = reinterpret_cast<const RBBIStateTable*>(reinterpret_cast<const char*>(data) + fHeader->fFTable); } if (data->fRTableLen != 0) { - fReverseTable = (RBBIStateTable *)((char *)data + fHeader->fRTable); + fReverseTable = reinterpret_cast<const RBBIStateTable*>(reinterpret_cast<const char*>(data) + fHeader->fRTable); } fTrie = ucptrie_openFromBinary(UCPTRIE_TYPE_FAST, @@ -130,7 +130,7 @@ void RBBIDataWrapper::init(const RBBIDataHeader *data, UErrorCode &status) { fRuleString = UnicodeString::fromUTF8(StringPiece(fRuleSource, fHeader->fRuleSourceLen)); U_ASSERT(data->fRuleSourceLen > 0); - fRuleStatusTable = (int32_t *)((char *)data + fHeader->fStatusTable); + fRuleStatusTable = reinterpret_cast<const int32_t*>(reinterpret_cast<const char*>(data) + fHeader->fStatusTable); fStatusMaxIdx = data->fStatusTableLen / sizeof(int32_t); fRefCount = 1; diff --git a/thirdparty/icu4c/common/rbbirb.cpp b/thirdparty/icu4c/common/rbbirb.cpp index 1b2ee67187..4fd789970c 100644 --- a/thirdparty/icu4c/common/rbbirb.cpp +++ b/thirdparty/icu4c/common/rbbirb.cpp @@ -103,7 +103,7 @@ RBBIRuleBuilder::~RBBIRuleBuilder() { int i; for (i=0; ; i++) { - RBBINode *n = (RBBINode *)fUSetNodes->elementAt(i); + RBBINode* n = static_cast<RBBINode*>(fUSetNodes->elementAt(i)); if (n==nullptr) { break; } @@ -182,12 +182,12 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { } #endif - RBBIDataHeader *data = (RBBIDataHeader *)uprv_malloc(totalSize); - if (data == nullptr) { + LocalMemory<RBBIDataHeader> data(static_cast<RBBIDataHeader*>(uprv_malloc(totalSize))); + if (data.isNull()) { *fStatus = U_MEMORY_ALLOCATION_ERROR; return nullptr; } - uprv_memset(data, 0, totalSize); + uprv_memset(data.getAlias(), 0, totalSize); data->fMagic = 0xb1a0; @@ -213,23 +213,23 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { uprv_memset(data->fReserved, 0, sizeof(data->fReserved)); - fForwardTable->exportTable((uint8_t *)data + data->fFTable); - fForwardTable->exportSafeTable((uint8_t *)data + data->fRTable); - fSetBuilder->serializeTrie ((uint8_t *)data + data->fTrie); + fForwardTable->exportTable(reinterpret_cast<uint8_t*>(data.getAlias()) + data->fFTable); + fForwardTable->exportSafeTable(reinterpret_cast<uint8_t*>(data.getAlias()) + data->fRTable); + fSetBuilder->serializeTrie(reinterpret_cast<uint8_t*>(data.getAlias()) + data->fTrie); - int32_t *ruleStatusTable = (int32_t *)((uint8_t *)data + data->fStatusTable); + int32_t* ruleStatusTable = reinterpret_cast<int32_t*>(reinterpret_cast<uint8_t*>(data.getAlias()) + data->fStatusTable); for (i=0; i<fRuleStatusVals->size(); i++) { ruleStatusTable[i] = fRuleStatusVals->elementAti(i); } - u_strToUTF8WithSub((char *)data+data->fRuleSource, rulesSize, &rulesLengthInUTF8, + u_strToUTF8WithSub(reinterpret_cast<char*>(data.getAlias()) + data->fRuleSource, rulesSize, &rulesLengthInUTF8, fStrippedRules.getBuffer(), fStrippedRules.length(), 0xfffd, nullptr, fStatus); if (U_FAILURE(*fStatus)) { return nullptr; } - return data; + return data.orphan(); } diff --git a/thirdparty/icu4c/common/rbbiscan.cpp b/thirdparty/icu4c/common/rbbiscan.cpp index f5fdba076f..cf2d63cd80 100644 --- a/thirdparty/icu4c/common/rbbiscan.cpp +++ b/thirdparty/icu4c/common/rbbiscan.cpp @@ -748,7 +748,7 @@ void RBBIRuleScanner::findSetFor(const UnicodeString &s, RBBINode *node, Unicode // First check whether we've already cached a set for this string. // If so, just use the cached set in the new node. // delete any set provided by the caller, since we own it. - el = (RBBISetTableEl *)uhash_get(fSetTable, &s); + el = static_cast<RBBISetTableEl*>(uhash_get(fSetTable, &s)); if (el != nullptr) { delete setToAdopt; node->fLeftChild = el->val; @@ -794,7 +794,7 @@ void RBBIRuleScanner::findSetFor(const UnicodeString &s, RBBINode *node, Unicode // // Add the new set to the set hash table. // - el = (RBBISetTableEl *)uprv_malloc(sizeof(RBBISetTableEl)); + el = static_cast<RBBISetTableEl*>(uprv_malloc(sizeof(RBBISetTableEl))); UnicodeString *tkey = new UnicodeString(s); if (tkey == nullptr || el == nullptr || setToAdopt == nullptr) { // Delete to avoid memory leak @@ -864,7 +864,7 @@ UChar32 RBBIRuleScanner::nextCharLL() { UChar32 ch; if (fNextIndex >= fRB->fRules.length()) { - return (UChar32)-1; + return static_cast<UChar32>(-1); } ch = fRB->fRules.char32At(fNextIndex); if (U_IS_SURROGATE(ch)) { @@ -939,7 +939,7 @@ void RBBIRuleScanner::nextChar(RBBIRuleChar &c) { } } - if (c.fChar == (UChar32)-1) { + if (c.fChar == static_cast<UChar32>(-1)) { return; } if (fQuoteMode) { @@ -958,7 +958,7 @@ void RBBIRuleScanner::nextChar(RBBIRuleChar &c) { int32_t commentStart = fScanIndex; for (;;) { c.fChar = nextCharLL(); - if (c.fChar == (UChar32)-1 || // EOF + if (c.fChar == static_cast<UChar32>(-1) || // EOF c.fChar == chCR || c.fChar == chLF || c.fChar == chNEL || @@ -968,7 +968,7 @@ void RBBIRuleScanner::nextChar(RBBIRuleChar &c) { fRB->fStrippedRules.setCharAt(i, u' '); } } - if (c.fChar == (UChar32)-1) { + if (c.fChar == static_cast<UChar32>(-1)) { return; } @@ -1065,14 +1065,14 @@ void RBBIRuleScanner::parse() { // Table row specified "escaped P" and the char is either 'p' or 'P'. break; } - if (tableEl->fCharClass == 252 && fC.fChar == (UChar32)-1) { + if (tableEl->fCharClass == 252 && fC.fChar == static_cast<UChar32>(-1)) { // Table row specified eof and we hit eof on the input. break; } if (tableEl->fCharClass >= 128 && tableEl->fCharClass < 240 && // Table specs a char class && fC.fEscaped == false && // char is not escaped && - fC.fChar != (UChar32)-1) { // char is not EOF + fC.fChar != static_cast<UChar32>(-1)) { // char is not EOF U_ASSERT((tableEl->fCharClass-128) < UPRV_LENGTHOF(fRuleSets)); if (fRuleSets[tableEl->fCharClass-128].contains(fC.fChar)) { // Table row specified a character class, or set of characters, @@ -1090,7 +1090,7 @@ void RBBIRuleScanner::parse() { // We've found the row of the state table that matches the current input // character from the rules string. // Perform any action specified by this row in the state table. - if (doParseActions((int32_t)tableEl->fAction) == false) { + if (doParseActions(static_cast<int32_t>(tableEl->fAction)) == false) { // Break out of the state machine loop if the // the action signalled some kind of error, or // the action was to exit, occurs on normal end-of-rules-input. diff --git a/thirdparty/icu4c/common/rbbisetb.cpp b/thirdparty/icu4c/common/rbbisetb.cpp index e6c72954bc..6c22cf470f 100644 --- a/thirdparty/icu4c/common/rbbisetb.cpp +++ b/thirdparty/icu4c/common/rbbisetb.cpp @@ -120,7 +120,7 @@ void RBBISetBuilder::buildRanges() { // int ni; for (ni=0; ; ni++) { // Loop over each of the UnicodeSets encountered in the input rules - usetNode = (RBBINode *)this->fRB->fUSetNodes->elementAt(ni); + usetNode = static_cast<RBBINode*>(this->fRB->fUSetNodes->elementAt(ni)); if (usetNode==nullptr) { break; } @@ -251,7 +251,7 @@ void RBBISetBuilder::buildRanges() { UnicodeString eofString(u"eof"); UnicodeString bofString(u"bof"); for (ni=0; ; ni++) { // Loop over each of the UnicodeSets encountered in the input rules - usetNode = (RBBINode *)this->fRB->fUSetNodes->elementAt(ni); + usetNode = static_cast<RBBINode*>(this->fRB->fUSetNodes->elementAt(ni)); if (usetNode==nullptr) { break; } @@ -369,7 +369,7 @@ void RBBISetBuilder::addValToSets(UVector *sets, uint32_t val) { int32_t ix; for (ix=0; ix<sets->size(); ix++) { - RBBINode *usetNode = (RBBINode *)sets->elementAt(ix); + RBBINode* usetNode = static_cast<RBBINode*>(sets->elementAt(ix)); addValToSet(usetNode, val); } } @@ -380,7 +380,7 @@ void RBBISetBuilder::addValToSet(RBBINode *usetNode, uint32_t val) { *fStatus = U_MEMORY_ALLOCATION_ERROR; return; } - leafNode->fVal = (unsigned short)val; + leafNode->fVal = static_cast<unsigned short>(val); if (usetNode->fLeftChild == nullptr) { usetNode->fLeftChild = leafNode; leafNode->fParent = usetNode; @@ -441,7 +441,7 @@ UBool RBBISetBuilder::sawBOF() const { //------------------------------------------------------------------------ UChar32 RBBISetBuilder::getFirstChar(int32_t category) const { RangeDescriptor *rlRange; - UChar32 retVal = (UChar32)-1; + UChar32 retVal = static_cast<UChar32>(-1); for (rlRange = fRangeList; rlRange!=nullptr; rlRange=rlRange->fNext) { if (rlRange->fNum == category) { retVal = rlRange->fStartChar; @@ -674,7 +674,7 @@ void RangeDescriptor::split(UChar32 where, UErrorCode &status) { bool RangeDescriptor::isDictionaryRange() { static const char16_t *dictionary = u"dictionary"; for (int32_t i=0; i<fIncludesSets->size(); i++) { - RBBINode *usetNode = (RBBINode *)fIncludesSets->elementAt(i); + RBBINode* usetNode = static_cast<RBBINode*>(fIncludesSets->elementAt(i)); RBBINode *setRef = usetNode->fParent; if (setRef != nullptr) { RBBINode *varRef = setRef->fParent; diff --git a/thirdparty/icu4c/common/rbbistbl.cpp b/thirdparty/icu4c/common/rbbistbl.cpp index bfaacf6425..27f31a9d55 100644 --- a/thirdparty/icu4c/common/rbbistbl.cpp +++ b/thirdparty/icu4c/common/rbbistbl.cpp @@ -41,7 +41,7 @@ U_CDECL_END U_NAMESPACE_BEGIN RBBISymbolTable::RBBISymbolTable(RBBIRuleScanner *rs, const UnicodeString &rules, UErrorCode &status) - :fRules(rules), fRuleScanner(rs), ffffString(char16_t(0xffff)) + : fRules(rules), fRuleScanner(rs), ffffString(static_cast<char16_t>(0xffff)) { fHashTable = nullptr; fCachedSetLookup = nullptr; @@ -76,9 +76,9 @@ const UnicodeString *RBBISymbolTable::lookup(const UnicodeString& s) const RBBINode *exprNode; RBBINode *usetNode; const UnicodeString *retString; - RBBISymbolTable *This = (RBBISymbolTable *)this; // cast off const + RBBISymbolTable *This = const_cast<RBBISymbolTable*>(this); // cast off const - el = (RBBISymbolTableEntry *)uhash_get(fHashTable, &s); + el = static_cast<RBBISymbolTableEntry*>(uhash_get(fHashTable, &s)); if (el == nullptr) { return nullptr; } @@ -119,7 +119,7 @@ const UnicodeString *RBBISymbolTable::lookup(const UnicodeString& s) const const UnicodeFunctor *RBBISymbolTable::lookupMatcher(UChar32 ch) const { UnicodeSet *retVal = nullptr; - RBBISymbolTable *This = (RBBISymbolTable *)this; // cast off const + RBBISymbolTable *This = const_cast<RBBISymbolTable*>(this); // cast off const if (ch == 0xffff) { retVal = fCachedSetLookup; This->fCachedSetLookup = nullptr; @@ -170,7 +170,7 @@ RBBINode *RBBISymbolTable::lookupNode(const UnicodeString &key) const{ RBBINode *retNode = nullptr; RBBISymbolTableEntry *el; - el = (RBBISymbolTableEntry *)uhash_get(fHashTable, &key); + el = static_cast<RBBISymbolTableEntry*>(uhash_get(fHashTable, &key)); if (el != nullptr) { retNode = el->val; } @@ -190,7 +190,7 @@ void RBBISymbolTable::addEntry (const UnicodeString &key, RBBINode * if (U_FAILURE(err)) { return; } - e = (RBBISymbolTableEntry *)uhash_get(fHashTable, &key); + e = static_cast<RBBISymbolTableEntry*>(uhash_get(fHashTable, &key)); if (e != nullptr) { err = U_BRK_VARIABLE_REDFINITION; return; diff --git a/thirdparty/icu4c/common/rbbitblb.cpp b/thirdparty/icu4c/common/rbbitblb.cpp index 96a0b0338d..4d95137601 100644 --- a/thirdparty/icu4c/common/rbbitblb.cpp +++ b/thirdparty/icu4c/common/rbbitblb.cpp @@ -51,7 +51,7 @@ RBBITableBuilder::RBBITableBuilder(RBBIRuleBuilder *rb, RBBINode **rootNode, UEr RBBITableBuilder::~RBBITableBuilder() { int i; for (i=0; i<fDStates->size(); i++) { - delete (RBBIStateDescriptor *)fDStates->elementAt(i); + delete static_cast<RBBIStateDescriptor*>(fDStates->elementAt(i)); } delete fDStates; delete fSafeTable; @@ -361,8 +361,8 @@ void RBBITableBuilder::calcFollowPos(RBBINode *n) { UVector *LastPosOfLeftChild = n->fLeftChild->fLastPosSet; - for (ix=0; ix<(uint32_t)LastPosOfLeftChild->size(); ix++) { - i = (RBBINode *)LastPosOfLeftChild->elementAt(ix); + for (ix = 0; ix < static_cast<uint32_t>(LastPosOfLeftChild->size()); ix++) { + i = static_cast<RBBINode*>(LastPosOfLeftChild->elementAt(ix)); setAdd(i->fFollowPos, n->fRightChild->fFirstPosSet); } } @@ -373,8 +373,8 @@ void RBBITableBuilder::calcFollowPos(RBBINode *n) { RBBINode *i; // again, n and i are the names from Aho's description. uint32_t ix; - for (ix=0; ix<(uint32_t)n->fLastPosSet->size(); ix++) { - i = (RBBINode *)n->fLastPosSet->elementAt(ix); + for (ix = 0; ix < static_cast<uint32_t>(n->fLastPosSet->size()); ix++) { + i = static_cast<RBBINode*>(n->fLastPosSet->elementAt(ix)); setAdd(i->fFollowPos, n->fFirstPosSet); } } @@ -445,7 +445,7 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree, RBBINode *endMarkNod int32_t startNodeIx; for (endNodeIx=0; endNodeIx<leafNodes.size(); endNodeIx++) { - RBBINode *endNode = (RBBINode *)leafNodes.elementAt(endNodeIx); + RBBINode* endNode = static_cast<RBBINode*>(leafNodes.elementAt(endNodeIx)); // Identify leaf nodes that correspond to overall rule match positions. // These include the endMarkNode in their followPos sets. @@ -465,7 +465,7 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree, RBBINode *endMarkNod // with the same char class as our ending node. RBBINode *startNode; for (startNodeIx = 0; startNodeIx<matchStartNodes.size(); startNodeIx++) { - startNode = (RBBINode *)matchStartNodes.elementAt(startNodeIx); + startNode = static_cast<RBBINode*>(matchStartNodes.elementAt(startNodeIx)); if (startNode->fType != RBBINode::leafChar) { continue; } @@ -525,7 +525,7 @@ void RBBITableBuilder::bofFixup() { RBBINode *startNode; int startNodeIx; for (startNodeIx = 0; startNodeIx<matchStartNodes->size(); startNodeIx++) { - startNode = (RBBINode *)matchStartNodes->elementAt(startNodeIx); + startNode = static_cast<RBBINode*>(matchStartNodes->elementAt(startNodeIx)); if (startNode->fType != RBBINode::leafChar) { continue; } @@ -605,7 +605,7 @@ void RBBITableBuilder::buildStateTable() { int32_t tx; for (tx=1; tx<fDStates->size(); tx++) { RBBIStateDescriptor *temp; - temp = (RBBIStateDescriptor *)fDStates->elementAt(tx); + temp = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(tx)); if (temp->fMarked == false) { T = temp; break; @@ -628,7 +628,7 @@ void RBBITableBuilder::buildStateTable() { RBBINode *p; int32_t px; for (px=0; px<T->fPositions->size(); px++) { - p = (RBBINode *)T->fPositions->elementAt(px); + p = static_cast<RBBINode*>(T->fPositions->elementAt(px)); if ((p->fType == RBBINode::leafChar) && (p->fVal == a)) { if (U == nullptr) { U = new UVector(*fStatus); @@ -649,7 +649,7 @@ void RBBITableBuilder::buildStateTable() { int ix; for (ix=0; ix<fDStates->size(); ix++) { RBBIStateDescriptor *temp2; - temp2 = (RBBIStateDescriptor *)fDStates->elementAt(ix); + temp2 = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(ix)); if (setEquals(U, temp2->fPositions)) { delete U; U = temp2->fPositions; @@ -705,7 +705,7 @@ void RBBITableBuilder::mapLookAheadRules() { fLookAheadRuleMap->setSize(fRB->fScanner->numRules() + 1); for (int32_t n=0; n<fDStates->size(); n++) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(n)); int32_t laSlotForState = 0; // Establish the look-ahead slot for this state, if the state covers @@ -789,9 +789,9 @@ void RBBITableBuilder::flagAcceptingStates() { } for (i=0; i<endMarkerNodes.size(); i++) { - endMarker = (RBBINode *)endMarkerNodes.elementAt(i); + endMarker = static_cast<RBBINode*>(endMarkerNodes.elementAt(i)); for (n=0; n<fDStates->size(); n++) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(n)); if (sd->fPositions->indexOf(endMarker) >= 0) { // Any non-zero value for fAccepting means this is an accepting node. // The value is what will be returned to the user as the break status. @@ -837,11 +837,11 @@ void RBBITableBuilder::flagLookAheadStates() { return; } for (i=0; i<lookAheadNodes.size(); i++) { - lookAheadNode = (RBBINode *)lookAheadNodes.elementAt(i); + lookAheadNode = static_cast<RBBINode*>(lookAheadNodes.elementAt(i)); U_ASSERT(lookAheadNode->fType == RBBINode::NodeType::lookAhead); for (n=0; n<fDStates->size(); n++) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(n)); int32_t positionsIdx = sd->fPositions->indexOf(lookAheadNode); if (positionsIdx >= 0) { U_ASSERT(lookAheadNode == sd->fPositions->elementAt(positionsIdx)); @@ -882,10 +882,10 @@ void RBBITableBuilder::flagTaggedStates() { return; } for (i=0; i<tagNodes.size(); i++) { // For each tag node t (all of 'em) - tagNode = (RBBINode *)tagNodes.elementAt(i); + tagNode = static_cast<RBBINode*>(tagNodes.elementAt(i)); for (n=0; n<fDStates->size(); n++) { // For each state s (row in the state table) - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(n)); if (sd->fPositions->indexOf(tagNode) >= 0) { // if s include the tag node t sortedAdd(&sd->fTagVals, tagNode->fVal); } @@ -923,12 +923,12 @@ void RBBITableBuilder::mergeRuleStatusVals() { // We will need this as a default, for rule sets with no explicit tagging. if (fRB->fRuleStatusVals->size() == 0) { fRB->fRuleStatusVals->addElement(1, *fStatus); // Num of statuses in group - fRB->fRuleStatusVals->addElement((int32_t)0, *fStatus); // and our single status of zero + fRB->fRuleStatusVals->addElement(static_cast<int32_t>(0), *fStatus); // and our single status of zero } // For each state for (n=0; n<fDStates->size(); n++) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(n)); UVector *thisStatesTagValues = sd->fTagVals; if (thisStatesTagValues == nullptr) { // No tag values are explicitly associated with this state. @@ -1154,9 +1154,9 @@ bool RBBITableBuilder::findDuplCharClassFrom(IntPair *categories) { uint16_t table_base = 0; uint16_t table_dupl = 1; for (int32_t state=0; state<numStates; state++) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state); - table_base = (uint16_t)sd->fDtran->elementAti(categories->first); - table_dupl = (uint16_t)sd->fDtran->elementAti(categories->second); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(state)); + table_base = static_cast<uint16_t>(sd->fDtran->elementAti(categories->first)); + table_dupl = static_cast<uint16_t>(sd->fDtran->elementAti(categories->second)); if (table_base != table_dupl) { break; } @@ -1176,7 +1176,7 @@ bool RBBITableBuilder::findDuplCharClassFrom(IntPair *categories) { void RBBITableBuilder::removeColumn(int32_t column) { int32_t numStates = fDStates->size(); for (int32_t state=0; state<numStates; state++) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(state)); U_ASSERT(column < sd->fDtran->size()); sd->fDtran->removeElementAt(column); } @@ -1190,9 +1190,9 @@ bool RBBITableBuilder::findDuplicateState(IntPair *states) { int32_t numCols = fRB->fSetBuilder->getNumCharCategories(); for (; states->first<numStates-1; states->first++) { - RBBIStateDescriptor *firstSD = (RBBIStateDescriptor *)fDStates->elementAt(states->first); + RBBIStateDescriptor* firstSD = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(states->first)); for (states->second=states->first+1; states->second<numStates; states->second++) { - RBBIStateDescriptor *duplSD = (RBBIStateDescriptor *)fDStates->elementAt(states->second); + RBBIStateDescriptor* duplSD = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(states->second)); if (firstSD->fAccepting != duplSD->fAccepting || firstSD->fLookAhead != duplSD->fLookAhead || firstSD->fTagsIdx != duplSD->fTagsIdx) { @@ -1252,14 +1252,14 @@ void RBBITableBuilder::removeState(IntPair duplStates) { U_ASSERT(keepState < duplState); U_ASSERT(duplState < fDStates->size()); - RBBIStateDescriptor *duplSD = (RBBIStateDescriptor *)fDStates->elementAt(duplState); + RBBIStateDescriptor* duplSD = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(duplState)); fDStates->removeElementAt(duplState); delete duplSD; int32_t numStates = fDStates->size(); int32_t numCols = fRB->fSetBuilder->getNumCharCategories(); for (int32_t state=0; state<numStates; ++state) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(state)); for (int32_t col=0; col<numCols; col++) { int32_t existingVal = sd->fDtran->elementAti(col); int32_t newVal = existingVal; @@ -1283,7 +1283,7 @@ void RBBITableBuilder::removeSafeState(IntPair duplStates) { // and will auto-delete the removed element. int32_t numStates = fSafeTable->size(); for (int32_t state=0; state<numStates; ++state) { - UnicodeString *sd = (UnicodeString *)fSafeTable->elementAt(state); + UnicodeString* sd = static_cast<UnicodeString*>(fSafeTable->elementAt(state)); int32_t numCols = sd->length(); for (int32_t col=0; col<numCols; col++) { int32_t existingVal = sd->charAt(col); @@ -1357,7 +1357,7 @@ bool RBBITableBuilder::use8BitsForTable() const { // //----------------------------------------------------------------------------- void RBBITableBuilder::exportTable(void *where) { - RBBIStateTable *table = (RBBIStateTable *)where; + RBBIStateTable* table = static_cast<RBBIStateTable*>(where); uint32_t state; int col; @@ -1390,13 +1390,13 @@ void RBBITableBuilder::exportTable(void *where) { } for (state=0; state<table->fNumStates; state++) { - RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state); - RBBIStateTableRow *row = (RBBIStateTableRow *)(table->fTableData + state*table->fRowLen); + RBBIStateDescriptor* sd = static_cast<RBBIStateDescriptor*>(fDStates->elementAt(state)); + RBBIStateTableRow* row = reinterpret_cast<RBBIStateTableRow*>(table->fTableData + state * table->fRowLen); if (use8BitsForTable()) { U_ASSERT (sd->fAccepting <= 255); U_ASSERT (sd->fLookAhead <= 255); U_ASSERT (0 <= sd->fTagsIdx && sd->fTagsIdx <= 255); - RBBIStateTableRow8 *r8 = (RBBIStateTableRow8*)row; + RBBIStateTableRow8* r8 = reinterpret_cast<RBBIStateTableRow8*>(row); r8->fAccepting = sd->fAccepting; r8->fLookAhead = sd->fLookAhead; r8->fTagsIdx = sd->fTagsIdx; @@ -1472,8 +1472,8 @@ void RBBITableBuilder::buildSafeReverseTable(UErrorCode &status) { } } if (wantedEndState == endState) { - safePairs.append((char16_t)c1); - safePairs.append((char16_t)c2); + safePairs.append(static_cast<char16_t>(c1)); + safePairs.append(static_cast<char16_t>(c2)); // printf("(%d, %d) ", c1, c2); } } @@ -1579,7 +1579,7 @@ bool RBBITableBuilder::use8BitsForSafeTable() const { // //----------------------------------------------------------------------------- void RBBITableBuilder::exportSafeTable(void *where) { - RBBIStateTable *table = (RBBIStateTable *)where; + RBBIStateTable* table = static_cast<RBBIStateTable*>(where); uint32_t state; int col; @@ -1604,10 +1604,10 @@ void RBBITableBuilder::exportSafeTable(void *where) { } for (state=0; state<table->fNumStates; state++) { - UnicodeString *rowString = (UnicodeString *)fSafeTable->elementAt(state); - RBBIStateTableRow *row = (RBBIStateTableRow *)(table->fTableData + state*table->fRowLen); + UnicodeString* rowString = static_cast<UnicodeString*>(fSafeTable->elementAt(state)); + RBBIStateTableRow* row = reinterpret_cast<RBBIStateTableRow*>(table->fTableData + state * table->fRowLen); if (use8BitsForSafeTable()) { - RBBIStateTableRow8 *r8 = (RBBIStateTableRow8*)row; + RBBIStateTableRow8* r8 = reinterpret_cast<RBBIStateTableRow8*>(row); r8->fAccepting = 0; r8->fLookAhead = 0; r8->fTagsIdx = 0; diff --git a/thirdparty/icu4c/common/resbund_cnv.cpp b/thirdparty/icu4c/common/resbund_cnv.cpp index 7f83f06f0e..a109609189 100644 --- a/thirdparty/icu4c/common/resbund_cnv.cpp +++ b/thirdparty/icu4c/common/resbund_cnv.cpp @@ -49,7 +49,7 @@ ResourceBundle::constructForLocale(const UnicodeString& path, } else { UnicodeString nullTerminatedPath(path); - nullTerminatedPath.append((char16_t)0); + nullTerminatedPath.append(static_cast<char16_t>(0)); fResource = ures_openU(nullTerminatedPath.getBuffer(), locale.getName(), &error); } } diff --git a/thirdparty/icu4c/common/ruleiter.cpp b/thirdparty/icu4c/common/ruleiter.cpp index 0e665435a7..39bea52e78 100644 --- a/thirdparty/icu4c/common/ruleiter.cpp +++ b/thirdparty/icu4c/common/ruleiter.cpp @@ -139,7 +139,7 @@ UChar32 RuleCharacterIterator::_current() const { return buf->char32At(bufPos); } else { int i = pos.getIndex(); - return (i < text.length()) ? text.char32At(i) : (UChar32)DONE; + return (i < text.length()) ? text.char32At(i) : static_cast<UChar32>(DONE); } } diff --git a/thirdparty/icu4c/common/serv.cpp b/thirdparty/icu4c/common/serv.cpp index 5248f7c192..3a4aee5797 100644 --- a/thirdparty/icu4c/common/serv.cpp +++ b/thirdparty/icu4c/common/serv.cpp @@ -424,7 +424,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer return handleDefault(key, actualReturn, status); } - ICUService* ncthis = (ICUService*)this; // cast away semantic const + ICUService* ncthis = const_cast<ICUService*>(this); // cast away semantic const CacheEntry* result = nullptr; { @@ -462,7 +462,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer if (factory != nullptr) { for (int32_t i = 0; i < limit; ++i) { - if (factory == (const ICUServiceFactory*)factories->elementAt(i)) { + if (factory == static_cast<const ICUServiceFactory*>(factories->elementAt(i))) { startIndex = i + 1; break; } @@ -478,7 +478,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer do { currentDescriptor.remove(); key.currentDescriptor(currentDescriptor); - result = (CacheEntry*)serviceCache->get(currentDescriptor); + result = static_cast<CacheEntry*>(serviceCache->get(currentDescriptor)); if (result != nullptr) { break; } @@ -490,7 +490,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer int32_t index = startIndex; while (index < limit) { - ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(index++); + ICUServiceFactory* f = static_cast<ICUServiceFactory*>(factories->elementAt(index++)); LocalPointer<UObject> service(f->create(key, this, status)); if (U_FAILURE(status)) { return nullptr; @@ -543,7 +543,7 @@ outerEnd: if (cacheDescriptorList.isValid()) { for (int32_t i = cacheDescriptorList->size(); --i >= 0;) { - UnicodeString* desc = (UnicodeString*)cacheDescriptorList->elementAt(i); + UnicodeString* desc = static_cast<UnicodeString*>(cacheDescriptorList->elementAt(i)); serviceCache->put(*desc, result, status); if (U_FAILURE(status)) { @@ -558,7 +558,7 @@ outerEnd: if (actualReturn != nullptr) { // strip null prefix - if (result->actualDescriptor.indexOf((char16_t)0x2f) == 0) { // U+002f=slash (/) + if (result->actualDescriptor.indexOf(static_cast<char16_t>(0x2f)) == 0) { // U+002f=slash (/) actualReturn->remove(); actualReturn->append(result->actualDescriptor, 1, @@ -618,7 +618,7 @@ ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorC break; } - const UnicodeString* id = (const UnicodeString*)e->key.pointer; + const UnicodeString* id = static_cast<const UnicodeString*>(e->key.pointer); if (fallbackKey != nullptr) { if (!fallbackKey->isFallbackOf(*id)) { continue; @@ -644,14 +644,14 @@ ICUService::getVisibleIDMap(UErrorCode& status) const { // must only be called when lock is already held - ICUService* ncthis = (ICUService*)this; // cast away semantic const + ICUService* ncthis = const_cast<ICUService*>(this); // cast away semantic const if (idCache == nullptr) { ncthis->idCache = new Hashtable(status); if (idCache == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; } else if (factories != nullptr) { for (int32_t pos = factories->size(); --pos >= 0;) { - ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(pos); + ICUServiceFactory* f = static_cast<ICUServiceFactory*>(factories->elementAt(pos)); f->updateVisibleIDs(*idCache, status); } if (U_FAILURE(status)) { @@ -679,7 +679,7 @@ ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const Mutex mutex(&lock); const Hashtable* map = getVisibleIDMap(status); if (map != nullptr) { - ICUServiceFactory* f = (ICUServiceFactory*)map->get(id); + ICUServiceFactory* f = static_cast<ICUServiceFactory*>(map->get(id)); if (f != nullptr) { f->getDisplayName(id, locale, result); return result; @@ -691,7 +691,7 @@ ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const while (fallbackKey != nullptr && fallbackKey->fallback()) { UnicodeString us; fallbackKey->currentID(us); - f = (ICUServiceFactory*)map->get(us); + f = static_cast<ICUServiceFactory*>(map->get(us)); if (f != nullptr) { f->getDisplayName(id, locale, result); delete fallbackKey; @@ -727,7 +727,7 @@ ICUService::getDisplayNames(UVector& result, result.removeAllElements(); result.setDeleter(userv_deleteStringPair); if (U_SUCCESS(status)) { - ICUService* ncthis = (ICUService*)this; // cast away semantic const + ICUService* ncthis = const_cast<ICUService*>(this); // cast away semantic const Mutex mutex(&lock); if (dnCache != nullptr && dnCache->locale != locale) { @@ -749,8 +749,8 @@ ICUService::getDisplayNames(UVector& result, int32_t pos = UHASH_FIRST; const UHashElement* entry = nullptr; while ((entry = m->nextElement(pos)) != nullptr) { - const UnicodeString* id = (const UnicodeString*)entry->key.pointer; - ICUServiceFactory* f = (ICUServiceFactory*)entry->value.pointer; + const UnicodeString* id = static_cast<const UnicodeString*>(entry->key.pointer); + ICUServiceFactory* f = static_cast<ICUServiceFactory*>(entry->value.pointer); UnicodeString dname; f->getDisplayName(*id, locale, dname); if (dname.isBogus()) { @@ -776,11 +776,11 @@ ICUService::getDisplayNames(UVector& result, int32_t pos = UHASH_FIRST; const UHashElement *entry = nullptr; while ((entry = dnCache->cache.nextElement(pos)) != nullptr) { - const UnicodeString* id = (const UnicodeString*)entry->value.pointer; + const UnicodeString* id = static_cast<const UnicodeString*>(entry->value.pointer); if (matchKey != nullptr && !matchKey->isFallbackOf(*id)) { continue; } - const UnicodeString* dn = (const UnicodeString*)entry->key.pointer; + const UnicodeString* dn = static_cast<const UnicodeString*>(entry->key.pointer); StringPair* sp = StringPair::create(*id, *dn, status); result.adoptElement(sp, status); if (U_FAILURE(status)) { diff --git a/thirdparty/icu4c/common/servlkf.cpp b/thirdparty/icu4c/common/servlkf.cpp index f5bb0418c4..7ca5e7adc9 100644 --- a/thirdparty/icu4c/common/servlkf.cpp +++ b/thirdparty/icu4c/common/servlkf.cpp @@ -76,7 +76,7 @@ LocaleKeyFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const const UHashElement* elem = nullptr; int32_t pos = UHASH_FIRST; while ((elem = supported->nextElement(pos)) != nullptr) { - const UnicodeString& id = *((const UnicodeString*)elem->key.pointer); + const UnicodeString& id = *static_cast<const UnicodeString*>(elem->key.pointer); if (!visible) { result.remove(id); } else { diff --git a/thirdparty/icu4c/common/servls.cpp b/thirdparty/icu4c/common/servls.cpp index 978a956df7..33a1138962 100644 --- a/thirdparty/icu4c/common/servls.cpp +++ b/thirdparty/icu4c/common/servls.cpp @@ -179,7 +179,7 @@ private: length = other._ids.size(); for(i = 0; i < length; ++i) { - LocalPointer<UnicodeString> clonedId(((UnicodeString *)other._ids.elementAt(i))->clone(), status); + LocalPointer<UnicodeString> clonedId(static_cast<UnicodeString*>(other._ids.elementAt(i))->clone(), status); _ids.adoptElement(clonedId.orphan(), status); } @@ -228,7 +228,7 @@ public: virtual const UnicodeString* snext(UErrorCode& status) override { if (upToDate(status) && (_pos < _ids.size())) { - return (const UnicodeString*)_ids[_pos++]; + return static_cast<const UnicodeString*>(_ids[_pos++]); } return nullptr; } @@ -263,7 +263,7 @@ const UnicodeString& ICULocaleService::validateFallbackLocale() const { const Locale& loc = Locale::getDefault(); - ICULocaleService* ncThis = (ICULocaleService*)this; + ICULocaleService* ncThis = const_cast<ICULocaleService*>(this); static UMutex llock; { Mutex mutex(&llock); diff --git a/thirdparty/icu4c/common/servnotf.cpp b/thirdparty/icu4c/common/servnotf.cpp index b2ad663a48..3106152467 100644 --- a/thirdparty/icu4c/common/servnotf.cpp +++ b/thirdparty/icu4c/common/servnotf.cpp @@ -56,7 +56,7 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status) listeners = lpListeners.orphan(); } else { for (int i = 0, e = listeners->size(); i < e; ++i) { - const EventListener* el = (const EventListener*)(listeners->elementAt(i)); + const EventListener* el = static_cast<const EventListener*>(listeners->elementAt(i)); if (l == el) { return; } @@ -88,7 +88,7 @@ ICUNotifier::removeListener(const EventListener *l, UErrorCode& status) if (listeners != nullptr) { // identity equality check for (int i = 0, e = listeners->size(); i < e; ++i) { - const EventListener* el = (const EventListener*)listeners->elementAt(i); + const EventListener* el = static_cast<const EventListener*>(listeners->elementAt(i)); if (l == el) { listeners->removeElementAt(i); if (listeners->size() == 0) { @@ -109,7 +109,7 @@ ICUNotifier::notifyChanged() Mutex lmx(¬ifyLock); if (listeners != nullptr) { for (int i = 0, e = listeners->size(); i < e; ++i) { - EventListener* el = (EventListener*)listeners->elementAt(i); + EventListener* el = static_cast<EventListener*>(listeners->elementAt(i)); notifyListener(*el); } } diff --git a/thirdparty/icu4c/common/servrbf.cpp b/thirdparty/icu4c/common/servrbf.cpp index a4feca2c3b..7f130d55aa 100644 --- a/thirdparty/icu4c/common/servrbf.cpp +++ b/thirdparty/icu4c/common/servrbf.cpp @@ -61,8 +61,8 @@ ICUResourceBundleFactory::handleCreate(const Locale& loc, int32_t /* kind */, co // who made this change? -- dlf char pkg[20]; int32_t length; - length=_bundleName.extract(0, INT32_MAX, pkg, (int32_t)sizeof(pkg), US_INV); - if(length>=(int32_t)sizeof(pkg)) { + length = _bundleName.extract(0, INT32_MAX, pkg, static_cast<int32_t>(sizeof(pkg)), US_INV); + if (length >= static_cast<int32_t>(sizeof(pkg))) { return nullptr; } return new ResourceBundle(pkg, loc, status); diff --git a/thirdparty/icu4c/common/simpleformatter.cpp b/thirdparty/icu4c/common/simpleformatter.cpp index 1625627072..6607493894 100644 --- a/thirdparty/icu4c/common/simpleformatter.cpp +++ b/thirdparty/icu4c/common/simpleformatter.cpp @@ -73,7 +73,7 @@ UBool SimpleFormatter::applyPatternMinMaxArguments( const char16_t *patternBuffer = pattern.getBuffer(); int32_t patternLength = pattern.length(); // Reserve the first char for the number of arguments. - compiledPattern.setTo((char16_t)0); + compiledPattern.setTo(static_cast<char16_t>(0)); int32_t textLength = 0; int32_t maxArg = -1; UBool inQuote = false; @@ -98,7 +98,7 @@ UBool SimpleFormatter::applyPatternMinMaxArguments( } else if (!inQuote && c == OPEN_BRACE) { if (textLength > 0) { compiledPattern.setCharAt(compiledPattern.length() - textLength - 1, - (char16_t)(ARG_NUM_LIMIT + textLength)); + static_cast<char16_t>(ARG_NUM_LIMIT + textLength)); textLength = 0; } int32_t argNumber; @@ -129,7 +129,7 @@ UBool SimpleFormatter::applyPatternMinMaxArguments( if (argNumber > maxArg) { maxArg = argNumber; } - compiledPattern.append((char16_t)argNumber); + compiledPattern.append(static_cast<char16_t>(argNumber)); continue; } // else: c is part of literal text // Append c and track the literal-text segment length. @@ -144,14 +144,14 @@ UBool SimpleFormatter::applyPatternMinMaxArguments( } if (textLength > 0) { compiledPattern.setCharAt(compiledPattern.length() - textLength - 1, - (char16_t)(ARG_NUM_LIMIT + textLength)); + static_cast<char16_t>(ARG_NUM_LIMIT + textLength)); } int32_t argCount = maxArg + 1; if (argCount < min || max < argCount) { errorCode = U_ILLEGAL_ARGUMENT_ERROR; return false; } - compiledPattern.setCharAt(0, (char16_t)argCount); + compiledPattern.setCharAt(0, static_cast<char16_t>(argCount)); return true; } diff --git a/thirdparty/icu4c/common/stringtriebuilder.cpp b/thirdparty/icu4c/common/stringtriebuilder.cpp index 2a40dc88fd..6867039062 100644 --- a/thirdparty/icu4c/common/stringtriebuilder.cpp +++ b/thirdparty/icu4c/common/stringtriebuilder.cpp @@ -328,7 +328,7 @@ StringTrieBuilder::registerNode(Node *newNode, UErrorCode &errorCode) { const UHashElement *old=uhash_find(nodes, newNode); if(old!=nullptr) { delete newNode; - return (Node *)old->key.pointer; + return static_cast<Node*>(old->key.pointer); } // If uhash_puti() returns a non-zero value from an equivalent, previously // registered node, then uhash_find() failed to find that and we will leak newNode. @@ -352,7 +352,7 @@ StringTrieBuilder::registerFinalValue(int32_t value, UErrorCode &errorCode) { FinalValueNode key(value); const UHashElement *old=uhash_find(nodes, &key); if(old!=nullptr) { - return (Node *)old->key.pointer; + return static_cast<Node*>(old->key.pointer); } Node *newNode=new FinalValueNode(value); if(newNode==nullptr) { @@ -375,12 +375,12 @@ StringTrieBuilder::registerFinalValue(int32_t value, UErrorCode &errorCode) { int32_t StringTrieBuilder::hashNode(const void *node) { - return ((const Node *)node)->hashCode(); + return static_cast<const Node*>(node)->hashCode(); } UBool StringTrieBuilder::equalNodes(const void *left, const void *right) { - return *(const Node *)left==*(const Node *)right; + return *static_cast<const Node*>(left) == *static_cast<const Node*>(right); } bool diff --git a/thirdparty/icu4c/common/ubidi.cpp b/thirdparty/icu4c/common/ubidi.cpp index fcf82fa97a..400e049d78 100644 --- a/thirdparty/icu4c/common/ubidi.cpp +++ b/thirdparty/icu4c/common/ubidi.cpp @@ -304,7 +304,7 @@ ubidi_setReorderingMode(UBiDi *pBiDi, UBiDiReorderingMode reorderingMode) UPRV_N if ((pBiDi!=nullptr) && (reorderingMode >= UBIDI_REORDER_DEFAULT) && (reorderingMode < UBIDI_REORDER_COUNT)) { pBiDi->reorderingMode = reorderingMode; - pBiDi->isInverse = (UBool)(reorderingMode == UBIDI_REORDER_INVERSE_NUMBERS_AS_L); + pBiDi->isInverse = reorderingMode == UBIDI_REORDER_INVERSE_NUMBERS_AS_L; } } @@ -381,7 +381,7 @@ firstL_R_AL(UBiDi *pBiDi) { for(i=0; i<length; ) { /* i is incremented by U16_NEXT */ U16_NEXT(text, i, length, uchar); - dirProp=(DirProp)ubidi_getCustomizedClass(pBiDi, uchar); + dirProp = static_cast<DirProp>(ubidi_getCustomizedClass(pBiDi, uchar)); if(result==ON) { if(dirProp==L || dirProp==R || dirProp==AL) { result=dirProp; @@ -436,13 +436,13 @@ getDirProps(UBiDi *pBiDi) { UBool isDefaultLevel=IS_DEFAULT_LEVEL(pBiDi->paraLevel); /* for inverse BiDi, the default para level is set to RTL if there is a strong R or AL character at either end of the text */ - UBool isDefaultLevelInverse=isDefaultLevel && (UBool) - (pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_LIKE_DIRECT || - pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL); + UBool isDefaultLevelInverse = isDefaultLevel && static_cast<UBool>( + pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_LIKE_DIRECT || + pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL); int32_t lastArabicPos=-1; int32_t controlCount=0; - UBool removeBiDiControls = (UBool)(pBiDi->reorderingOptions & - UBIDI_OPTION_REMOVE_CONTROLS); + UBool removeBiDiControls = + static_cast<UBool>(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS); enum State { NOT_SEEKING_STRONG, /* 0: not contextual paraLevel, not after FSI */ @@ -676,7 +676,7 @@ bracketInit(UBiDi *pBiDi, BracketData *bd) { bd->isoRuns[0].level=GET_PARALEVEL(pBiDi, 0); UBiDiLevel t = GET_PARALEVEL(pBiDi, 0) & 1; bd->isoRuns[0].lastStrong = bd->isoRuns[0].lastBase = t; - bd->isoRuns[0].contextDir = (UBiDiDirection)t; + bd->isoRuns[0].contextDir = static_cast<UBiDiDirection>(t); bd->isoRuns[0].contextPos=0; if(pBiDi->openingsMemory) { bd->openings=pBiDi->openingsMemory; @@ -696,7 +696,7 @@ bracketProcessB(BracketData *bd, UBiDiLevel level) { bd->isoRuns[0].limit=0; bd->isoRuns[0].level=level; bd->isoRuns[0].lastStrong=bd->isoRuns[0].lastBase=level&1; - bd->isoRuns[0].contextDir=(UBiDiDirection)(level&1); + bd->isoRuns[0].contextDir = static_cast<UBiDiDirection>(level & 1); bd->isoRuns[0].contextPos=0; } @@ -713,8 +713,8 @@ bracketProcessBoundary(BracketData *bd, int32_t lastCcPos, pLastIsoRun->limit=pLastIsoRun->start; pLastIsoRun->level=embeddingLevel; pLastIsoRun->lastStrong=pLastIsoRun->lastBase=contextLevel&1; - pLastIsoRun->contextDir=(UBiDiDirection)(contextLevel&1); - pLastIsoRun->contextPos=(UBiDiDirection)lastCcPos; + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(contextLevel & 1); + pLastIsoRun->contextPos = static_cast<UBiDiDirection>(lastCcPos); } /* LRI or RLI */ @@ -729,7 +729,7 @@ bracketProcessLRI_RLI(BracketData *bd, UBiDiLevel level) { pLastIsoRun->start=pLastIsoRun->limit=lastLimit; pLastIsoRun->level=level; pLastIsoRun->lastStrong=pLastIsoRun->lastBase=level&1; - pLastIsoRun->contextDir=(UBiDiDirection)(level&1); + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(level & 1); pLastIsoRun->contextPos=0; } @@ -803,7 +803,7 @@ bracketProcessClosing(BracketData *bd, int32_t openIdx, int32_t position) { UBool stable; DirProp newProp; pOpening=&bd->openings[openIdx]; - direction=(UBiDiDirection)(pLastIsoRun->level&1); + direction = static_cast<UBiDiDirection>(pLastIsoRun->level & 1); stable=true; /* assume stable until proved otherwise */ /* The stable flag is set when brackets are paired and their @@ -896,7 +896,7 @@ bracketProcessChar(BracketData *bd, int32_t position) { break; } pLastIsoRun->lastBase=ON; - pLastIsoRun->contextDir=(UBiDiDirection)newProp; + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(newProp); pLastIsoRun->contextPos=position; level=bd->pBiDi->levels[position]; if(level&UBIDI_LEVEL_OVERRIDE) { /* X4, X5 */ @@ -944,14 +944,14 @@ bracketProcessChar(BracketData *bd, int32_t position) { dirProps[position]=newProp; pLastIsoRun->lastBase=newProp; pLastIsoRun->lastStrong=newProp; - pLastIsoRun->contextDir=(UBiDiDirection)newProp; + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(newProp); pLastIsoRun->contextPos=position; } else if(dirProp<=R || dirProp==AL) { newProp= static_cast<DirProp>(DIR_FROM_STRONG(dirProp)); pLastIsoRun->lastBase=dirProp; pLastIsoRun->lastStrong=dirProp; - pLastIsoRun->contextDir=(UBiDiDirection)newProp; + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(newProp); pLastIsoRun->contextPos=position; } else if(dirProp==EN) { @@ -960,7 +960,7 @@ bracketProcessChar(BracketData *bd, int32_t position) { newProp=L; /* W7 */ if(!bd->isNumbersSpecial) dirProps[position]=ENL; - pLastIsoRun->contextDir=(UBiDiDirection)L; + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(L); pLastIsoRun->contextPos=position; } else { @@ -969,14 +969,14 @@ bracketProcessChar(BracketData *bd, int32_t position) { dirProps[position]=AN; /* W2 */ else dirProps[position]=ENR; - pLastIsoRun->contextDir=(UBiDiDirection)R; + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(R); pLastIsoRun->contextPos=position; } } else if(dirProp==AN) { newProp=R; /* N0 */ pLastIsoRun->lastBase=AN; - pLastIsoRun->contextDir=(UBiDiDirection)R; + pLastIsoRun->contextDir = static_cast<UBiDiDirection>(R); pLastIsoRun->contextPos=position; } else if(dirProp==NSM) { @@ -1177,10 +1177,10 @@ resolveExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { levels[i]=previousLevel; if (dirProp==LRE || dirProp==LRO) /* least greater even level */ - newLevel=(UBiDiLevel)((embeddingLevel+2)&~(UBIDI_LEVEL_OVERRIDE|1)); + newLevel = static_cast<UBiDiLevel>((embeddingLevel + 2) & ~(UBIDI_LEVEL_OVERRIDE | 1)); else /* least greater odd level */ - newLevel=(UBiDiLevel)((NO_OVERRIDE(embeddingLevel)+1)|1); + newLevel = static_cast<UBiDiLevel>((NO_OVERRIDE(embeddingLevel) + 1) | 1); if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL && overflowIsolateCount==0 && overflowEmbeddingCount==0) { lastCcPos=i; @@ -1213,7 +1213,7 @@ resolveExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { if(stackLast>0 && stack[stackLast]<ISOLATE) { /* not an isolate entry */ lastCcPos=i; stackLast--; - embeddingLevel=(UBiDiLevel)stack[stackLast]; + embeddingLevel = static_cast<UBiDiLevel>(stack[stackLast]); } break; case LRI: @@ -1229,10 +1229,10 @@ resolveExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { /* (X5a, X5b) */ if(dirProp==LRI) /* least greater even level */ - newLevel=(UBiDiLevel)((embeddingLevel+2)&~(UBIDI_LEVEL_OVERRIDE|1)); + newLevel = static_cast<UBiDiLevel>((embeddingLevel + 2) & ~(UBIDI_LEVEL_OVERRIDE | 1)); else /* least greater odd level */ - newLevel=(UBiDiLevel)((NO_OVERRIDE(embeddingLevel)+1)|1); + newLevel = static_cast<UBiDiLevel>((NO_OVERRIDE(embeddingLevel) + 1) | 1); if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL && overflowIsolateCount==0 && overflowEmbeddingCount==0) { flags|=DIRPROP_FLAG(dirProp); @@ -1276,7 +1276,7 @@ resolveExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { } else /* make it WS so that it is handled by adjustWSLevels() */ dirProps[i]=WS; - embeddingLevel=(UBiDiLevel)stack[stackLast]&~ISOLATE; + embeddingLevel = static_cast<UBiDiLevel>(stack[stackLast]) & ~ISOLATE; flags|=(DIRPROP_FLAG(ON)|DIRPROP_FLAG_LR(embeddingLevel)); previousLevel=embeddingLevel; levels[i]=NO_OVERRIDE(embeddingLevel); @@ -1315,7 +1315,7 @@ resolveExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { previousLevel=embeddingLevel; levels[i]=embeddingLevel; if(!bracketProcessChar(&bracketData, i)) - return (UBiDiDirection)-1; + return static_cast<UBiDiDirection>(-1); /* the dirProp may have been changed in bracketProcessChar() */ flags|=DIRPROP_FLAG(dirProps[i]); break; @@ -1386,7 +1386,7 @@ checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { } else { // Treat explicit level 0 as a wildcard for the paragraph level. // Avoid making the caller guess what the paragraph level would be. - level = (UBiDiLevel)currentParaLevel; + level = static_cast<UBiDiLevel>(currentParaLevel); levels[i] = level | overrideFlag; } } else { @@ -1868,7 +1868,7 @@ processPropertySeq(UBiDi *pBiDi, LevState *pLevState, uint8_t _prop, int32_t start0, k; start0=start; /* save original start position */ - oldStateSeq=(uint8_t)pLevState->state; + oldStateSeq = static_cast<uint8_t>(pLevState->state); cell=(*pImpTab)[oldStateSeq][_prop]; pLevState->state=GET_STATE(cell); /* isolate the new state */ actionSeq=(*pImpAct)[GET_ACTION(cell)]; /* isolate the action */ @@ -2076,7 +2076,7 @@ lastL_R_AL(UBiDi *pBiDi) { for(i=length; i>0; ) { /* i is decremented by U16_PREV */ U16_PREV(text, 0, i, uchar); - dirProp=(DirProp)ubidi_getCustomizedClass(pBiDi, uchar); + dirProp = static_cast<DirProp>(ubidi_getCustomizedClass(pBiDi, uchar)); if(dirProp==L) { return DirProp_L; } @@ -2104,7 +2104,7 @@ firstL_R_AL_EN_AN(UBiDi *pBiDi) { for(i=0; i<length; ) { /* i is incremented by U16_NEXT */ U16_NEXT(text, i, length, uchar); - dirProp=(DirProp)ubidi_getCustomizedClass(pBiDi, uchar); + dirProp = static_cast<DirProp>(ubidi_getCustomizedClass(pBiDi, uchar)); if(dirProp==L) { return DirProp_L; } @@ -2142,18 +2142,18 @@ resolveImplicitLevels(UBiDi *pBiDi, * actions) and different levels state tables (maybe very similar to the * LTR corresponding ones. */ - inverseRTL=(UBool) - ((start<pBiDi->lastArabicPos) && (GET_PARALEVEL(pBiDi, start) & 1) && - (pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_LIKE_DIRECT || - pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)); + inverseRTL = + static_cast<UBool>((start < pBiDi->lastArabicPos) && (GET_PARALEVEL(pBiDi, start) & 1) && + (pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_LIKE_DIRECT || + pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)); /* initialize for property and levels state tables */ levState.startL2EN=-1; /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */ levState.lastStrongRTL=-1; /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */ levState.runStart=start; levState.runLevel=pBiDi->levels[start]; - levState.pImpTab=(const ImpTab*)((pBiDi->pImpTabPair)->pImpTab)[levState.runLevel&1]; - levState.pImpAct=(const ImpAct*)((pBiDi->pImpTabPair)->pImpAct)[levState.runLevel&1]; + levState.pImpTab = static_cast<const ImpTab*>(((pBiDi->pImpTabPair)->pImpTab)[levState.runLevel & 1]); + levState.pImpAct = static_cast<const ImpAct*>(((pBiDi->pImpTabPair)->pImpAct)[levState.runLevel & 1]); if(start==0 && pBiDi->proLength>0) { DirProp lastStrong=lastL_R_AL(pBiDi); if(lastStrong!=DirProp_ON) { @@ -2391,8 +2391,8 @@ setParaRunsOnly(UBiDi *pBiDi, const char16_t *text, int32_t length, goto cleanup3; } visualMap=runsOnlyMemory; - visualText=(char16_t *)&visualMap[length]; - saveLevels=(UBiDiLevel *)&visualText[length]; + visualText = reinterpret_cast<char16_t*>(&visualMap[length]); + saveLevels = reinterpret_cast<UBiDiLevel*>(&visualText[length]); saveOptions=pBiDi->reorderingOptions; if(saveOptions & UBIDI_OPTION_INSERT_MARKS) { pBiDi->reorderingOptions&=~UBIDI_OPTION_INSERT_MARKS; diff --git a/thirdparty/icu4c/common/ubidi_props.cpp b/thirdparty/icu4c/common/ubidi_props.cpp index 8f3f6a65c4..1ac4ab12a2 100644 --- a/thirdparty/icu4c/common/ubidi_props.cpp +++ b/thirdparty/icu4c/common/ubidi_props.cpp @@ -51,7 +51,7 @@ _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 end, uint32 (void)end; (void)value; /* add the start code point to the USet */ - const USetAdder *sa=(const USetAdder *)context; + const USetAdder* sa = static_cast<const USetAdder*>(context); sa->add(sa->set, start); return true; } @@ -139,7 +139,7 @@ ubidi_getClass(UChar32 c) { U_CFUNC UBool ubidi_isMirrored(UChar32 c) { uint16_t props=UTRIE2_GET16(&ubidi_props_singleton.trie, c); - return (UBool)UBIDI_GET_FLAG(props, UBIDI_IS_MIRRORED_SHIFT); + return UBIDI_GET_FLAG(props, UBIDI_IS_MIRRORED_SHIFT); } static UChar32 @@ -183,13 +183,13 @@ ubidi_getMirror(UChar32 c) { U_CFUNC UBool ubidi_isBidiControl(UChar32 c) { uint16_t props=UTRIE2_GET16(&ubidi_props_singleton.trie, c); - return (UBool)UBIDI_GET_FLAG(props, UBIDI_BIDI_CONTROL_SHIFT); + return UBIDI_GET_FLAG(props, UBIDI_BIDI_CONTROL_SHIFT); } U_CFUNC UBool ubidi_isJoinControl(UChar32 c) { uint16_t props=UTRIE2_GET16(&ubidi_props_singleton.trie, c); - return (UBool)UBIDI_GET_FLAG(props, UBIDI_JOIN_CONTROL_SHIFT); + return UBIDI_GET_FLAG(props, UBIDI_JOIN_CONTROL_SHIFT); } U_CFUNC UJoiningType diff --git a/thirdparty/icu4c/common/ubidi_props_data.h b/thirdparty/icu4c/common/ubidi_props_data.h index f85dc09675..bfd664a1b9 100644 --- a/thirdparty/icu4c/common/ubidi_props_data.h +++ b/thirdparty/icu4c/common/ubidi_props_data.h @@ -9,681 +9,694 @@ #ifdef INCLUDED_FROM_UBIDI_PROPS_C -static const UVersionInfo ubidi_props_dataVersion={0xf,1,0,0}; +static const UVersionInfo ubidi_props_dataVersion={0x10,0,0,0}; -static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x6ba0,0x65b0,0x28,0x620,0x8cc,0x10ac0,0x10d24,0,0,0,0,0,0,0,0x6702b6}; +static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x6f08,0x6778,0x28,0x620,0x8cb,0x10ac0,0x10ec5,0,0,0,0,0,0,0,0x6802b6}; -static const uint16_t ubidi_props_trieIndex[13008]={ -0x387,0x38f,0x397,0x39f,0x3b7,0x3bf,0x3c7,0x3cf,0x3a7,0x3af,0x3a7,0x3af,0x3a7,0x3af,0x3a7,0x3af, -0x3a7,0x3af,0x3a7,0x3af,0x3d5,0x3dd,0x3e5,0x3ed,0x3f5,0x3fd,0x3f9,0x401,0x409,0x411,0x40c,0x414, -0x3a7,0x3af,0x3a7,0x3af,0x41c,0x424,0x3a7,0x3af,0x3a7,0x3af,0x3a7,0x3af,0x42a,0x432,0x43a,0x442, -0x44a,0x452,0x45a,0x462,0x468,0x470,0x478,0x480,0x488,0x490,0x496,0x49e,0x4a6,0x4ae,0x4b6,0x4be, -0x4ca,0x4c6,0x4d2,0x4da,0x4e2,0x4f2,0x4f9,0x4ea,0x501,0x503,0x50b,0x513,0x51b,0x51c,0x524,0x52c, -0x534,0x51c,0x53c,0x541,0x534,0x51c,0x549,0x551,0x51b,0x559,0x561,0x513,0x569,0x3a7,0x571,0x575, -0x57d,0x57f,0x587,0x58f,0x51b,0x597,0x59f,0x513,0x41e,0x5a3,0x524,0x513,0x51b,0x3a7,0x5ab,0x3a7, -0x3a7,0x5b1,0x5b9,0x3a7,0x3a7,0x5bd,0x5c5,0x3a7,0x5c9,0x5d0,0x3a7,0x5d8,0x5e0,0x5e7,0x568,0x3a7, -0x3a7,0x5ef,0x5f7,0x5ff,0x607,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x60f,0x3a7,0x617,0x3a7,0x3a7,0x3a7, -0x61f,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x627,0x3a7,0x3a7,0x3a7,0x62f,0x528,0x528,0x528,0x3a7,0x635,0x63d,0x617, -0x653,0x645,0x645,0x65b,0x662,0x64b,0x3a7,0x3a7,0x3a7,0x66a,0x672,0x3a7,0x3a7,0x3a7,0x674,0x67c, -0x684,0x3a7,0x68b,0x693,0x3a7,0x69b,0x4fe,0x3a7,0x558,0x6a3,0x569,0x6ab,0x41e,0x6b3,0x3a7,0x6ba, -0x3a7,0x6bf,0x3a7,0x3a7,0x3a7,0x3a7,0x6c5,0x6cd,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3f5,0x3f5, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x6d4,0x6dc,0x6e0, -0x6f8,0x6fe,0x6e8,0x6f0,0x706,0x70e,0x712,0x5ea,0x71a,0x722,0x72a,0x3a7,0x732,0x67c,0x67c,0x67c, -0x742,0x74a,0x752,0x75a,0x75f,0x767,0x76f,0x73a,0x777,0x77f,0x3a7,0x785,0x78c,0x67c,0x67c,0x67c, -0x67c,0x595,0x792,0x67c,0x79a,0x3a7,0x3a7,0x679,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c, -0x67c,0x67c,0x67c,0x67c,0x67c,0x7a2,0x67c,0x67c,0x67c,0x67c,0x67c,0x7a8,0x67c,0x67c,0x7b0,0x7b8, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x67c,0x67c,0x67c,0x67c,0x7c8,0x7d0,0x7d8,0x7c0, -0x7e8,0x7f0,0x7f8,0x7ff,0x806,0x80e,0x812,0x7e0,0x67c,0x67c,0x67c,0x81a,0x820,0x67c,0x67c,0x826, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x82e,0x3a7,0x3a7,0x3a7,0x836,0x3a7,0x3a7,0x3a7,0x3f5, -0x83e,0x846,0x849,0x3a7,0x851,0x67c,0x67c,0x67f,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x858,0x85e, -0x86e,0x866,0x3a7,0x3a7,0x876,0x61f,0x3a7,0x3ce,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x67c,0x87e, -0x3dc,0x3a7,0x85e,0x882,0x3a7,0x88a,0x892,0x3a7,0x3a7,0x3a7,0x3a7,0x896,0x3a7,0x3a7,0x674,0x3cd, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x67c,0x67c, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x85e,0x67c,0x595,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x89d,0x3a7,0x3a7,0x8a2,0x8aa,0x3a7,0x3a7,0x5cb,0x67c,0x673,0x3a7,0x3a7,0x8b2,0x3a7,0x3a7,0x3a7, -0x8ba,0x8c1,0x645,0x8c9,0x3a7,0x3a7,0x5a1,0x8d1,0x3a7,0x8d9,0x8e0,0x3a7,0x501,0x8e5,0x3a7,0x51a, -0x3a7,0x8ed,0x8f5,0x51c,0x3a7,0x8f9,0x51b,0x901,0x3a7,0x3a7,0x3a7,0x907,0x3a7,0x3a7,0x3a7,0x90e, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x922,0x916,0x91a,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6, -0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x92a,0x932,0x4a6,0x4a6,0x4a6,0x937,0x93b, -0x943,0x94b,0x94f,0x957,0x4a6,0x4a6,0x4a6,0x95b,0x963,0x397,0x96b,0x973,0x3a7,0x3a7,0x3a7,0x97b, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xe9c,0xe9c,0xedc,0xf1c,0xe9c,0xe9c,0xe9c,0xe9c,0xe9c,0xe9c,0xf54,0xf94,0xfd4,0xfe4,0x1024,0x1030, -0xe9c,0xe9c,0x1070,0xe9c,0xe9c,0xe9c,0x10a8,0x10e8,0x1128,0x1168,0x11a0,0x11e0,0x1220,0x1258,0x1298,0x12d8, -0xa40,0xa80,0xac0,0xaff,0x1a0,0x1a0,0xb3f,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xb68,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xba8,0x1a0,0xbce,0xc09,0xc49,0xc89,0xcc9,0xd09,0xd49, +static const uint16_t ubidi_props_trieIndex[13236]={ +0x395,0x39d,0x3a5,0x3ad,0x3c5,0x3cd,0x3d5,0x3dd,0x3b5,0x3bd,0x3b5,0x3bd,0x3b5,0x3bd,0x3b5,0x3bd, +0x3b5,0x3bd,0x3b5,0x3bd,0x3e3,0x3eb,0x3f3,0x3fb,0x403,0x40b,0x407,0x40f,0x417,0x41f,0x41a,0x422, +0x3b5,0x3bd,0x3b5,0x3bd,0x42a,0x432,0x3b5,0x3bd,0x3b5,0x3bd,0x3b5,0x3bd,0x438,0x440,0x448,0x450, +0x458,0x460,0x468,0x470,0x476,0x47e,0x486,0x48e,0x496,0x49e,0x4a4,0x4ac,0x4b4,0x4bc,0x4c4,0x4cc, +0x4d8,0x4d4,0x4e0,0x4e8,0x4f0,0x500,0x507,0x4f8,0x50f,0x511,0x519,0x521,0x529,0x52a,0x532,0x53a, +0x542,0x52a,0x54a,0x54f,0x542,0x52a,0x557,0x55f,0x529,0x567,0x56f,0x521,0x577,0x3b5,0x57f,0x583, +0x58b,0x58d,0x595,0x59d,0x529,0x5a5,0x5ad,0x521,0x42c,0x5b1,0x532,0x521,0x529,0x3b5,0x5b9,0x3b5, +0x3b5,0x5bf,0x5c7,0x3b5,0x3b5,0x5cb,0x5d3,0x3b5,0x5d7,0x5de,0x3b5,0x5e6,0x5ee,0x5f5,0x576,0x3b5, +0x3b5,0x5fd,0x605,0x60d,0x615,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x61d,0x3b5,0x625,0x3b5,0x3b5,0x3b5, +0x62d,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x635,0x3b5,0x3b5,0x3b5,0x63d,0x536,0x536,0x536,0x3b5,0x643,0x64b,0x625, +0x661,0x653,0x653,0x669,0x670,0x659,0x3b5,0x3b5,0x3b5,0x678,0x680,0x3b5,0x3b5,0x3b5,0x682,0x68a, +0x692,0x3b5,0x699,0x6a1,0x3b5,0x6a9,0x50c,0x3b5,0x566,0x6b1,0x577,0x6b9,0x42c,0x6c1,0x3b5,0x6c8, +0x3b5,0x6cd,0x3b5,0x3b5,0x3b5,0x3b5,0x6d3,0x6db,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x403,0x403, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x6e2,0x6ea,0x6ee, +0x706,0x70c,0x6f6,0x6fe,0x714,0x71c,0x720,0x5f8,0x728,0x730,0x738,0x3b5,0x740,0x68a,0x68a,0x68a, +0x750,0x758,0x760,0x768,0x76d,0x775,0x77d,0x748,0x785,0x78d,0x3b5,0x793,0x79a,0x68a,0x68a,0x68a, +0x68a,0x790,0x7a0,0x68a,0x7a8,0x3b5,0x3b5,0x687,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, +0x68a,0x68a,0x68a,0x68a,0x68a,0x7b0,0x68a,0x68a,0x68a,0x68a,0x68a,0x7b6,0x68a,0x68a,0x7be,0x7c6, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x68a,0x68a,0x68a,0x68a,0x7d6,0x7de,0x7e6,0x7ce, +0x7f6,0x7fe,0x806,0x80d,0x814,0x81c,0x820,0x7ee,0x68a,0x68a,0x68a,0x828,0x82e,0x68a,0x68a,0x834, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x83c,0x3b5,0x3b5,0x3b5,0x844,0x3b5,0x3b5,0x3b5,0x403, +0x84c,0x854,0x857,0x3b5,0x85f,0x68a,0x68a,0x68d,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x866,0x86c, +0x87c,0x874,0x3b5,0x3b5,0x884,0x62d,0x3b5,0x3dc,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x68a,0x88c, +0x3ea,0x3b5,0x86c,0x890,0x3b5,0x898,0x8a0,0x3b5,0x3b5,0x3b5,0x3b5,0x8a4,0x3b5,0x3b5,0x682,0x3db, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x68a,0x68a, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x86c,0x68a,0x5a3,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x8ab,0x3b5,0x3b5,0x8b0,0x8b8,0x3b5,0x3b5,0x5d9,0x68a,0x681,0x3b5,0x3b5,0x8c0,0x3b5,0x3b5,0x3b5, +0x8c8,0x8cf,0x653,0x8d7,0x3b5,0x3b5,0x5af,0x8df,0x3b5,0x8e7,0x8ee,0x3b5,0x50f,0x8f3,0x3b5,0x528, +0x3b5,0x8fb,0x903,0x52a,0x3b5,0x907,0x529,0x90f,0x3b5,0x3b5,0x3b5,0x915,0x3b5,0x3b5,0x3b5,0x91c, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x930,0x924,0x928,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4, +0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0x938,0x940,0x4b4,0x4b4,0x4b4,0x945,0x949, +0x951,0x959,0x95d,0x965,0x4b4,0x4b4,0x4b4,0x969,0x971,0x3a5,0x979,0x981,0x3b5,0x3b5,0x3b5,0x989, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0xed4,0xed4,0xf14,0xf54,0xed4,0xed4,0xed4,0xed4,0xed4,0xed4,0xf8c,0xfcc,0x100c,0x101c,0x105c,0x1068, +0xed4,0xed4,0x10a8,0xed4,0xed4,0xed4,0x10e0,0x1120,0x1160,0x11a0,0x11d8,0x1218,0x1258,0x1290,0x12d0,0x1310, +0xa40,0xa80,0xac0,0xaff,0x1a0,0x1a0,0xb3f,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xb77,0xba0,0x1a0,0x1a0, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xbe0,0x1a0,0xc06,0xc41,0xc81,0xcc1,0xd01,0xd41,0xd81, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, -0xdc9,0xdd9,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, +0xe01,0xe11,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x983,0x3a7,0x67c,0x67c,0x98b,0x61f,0x3a7,0x514, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x993,0x3a7,0x3a7,0x3a7,0x99a,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x9a2,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, -0x9aa,0x9ae,0x43c,0x43c,0x43c,0x43c,0x9be,0x9b6,0x43c,0x9c6,0x43c,0x43c,0x9ce,0x9d4,0x43c,0x43c, -0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x9e4,0x9dc,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, -0x43c,0x43c,0x43c,0x9ec,0x43c,0x9f4,0x4a6,0x9fc,0x43c,0xa04,0xa0b,0xa11,0xa19,0xa1d,0xa25,0x43c, -0x51b,0xa2d,0xa34,0xa3b,0x41e,0xa43,0x569,0x3a7,0x501,0xa4a,0x3a7,0xa50,0x41e,0xa55,0xa5d,0x3a7, -0x3a7,0xa62,0x51b,0x3a7,0x3a7,0x3a7,0x836,0xa6a,0x41e,0x5a3,0x57e,0xa71,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0xa2d,0xa79,0x3a7,0x3a7,0xa81,0xa89,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xa8d,0xa95,0x3a7, -0x3a7,0xa9d,0x57e,0xaa5,0x3a7,0xaab,0x3a7,0x3a7,0x60f,0xab3,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xab8,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xabf,0xac7,0x3a7,0x3a7,0x3a7,0xaca,0x57e,0xad2, -0xad6,0xade,0x3a7,0xae5,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xaec,0x3a7,0x3a7,0xafa,0xaf4,0x3a7,0x3a7,0x3a7,0xb02,0xb0a,0x3a7,0xb0e,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x5a5,0x41e,0x99a,0xb16,0x3a7,0x3a7,0x3a7,0xb23,0xb1e,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xb2b,0xb33,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xb39, -0x3a7,0xb3f,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0xa51,0x3a7,0xb45,0x3a7,0x3a7,0xb4d,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x535,0xb55,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3f5,0xb5d,0x500,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0xb65,0xb6d,0xb73,0x3a7,0xb79,0x67c,0x67c,0xb81,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x67c,0x67c,0xb89,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xb8f, -0x3a7,0xb96,0x3a7,0xb92,0x3a7,0xb99,0x3a7,0xba1,0xba5,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3f5,0xbad,0x3f5,0xbb4,0xbbb,0xbc3,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xbcb,0xbd3,0x3a7,0x3a7,0xa51,0x3a7,0x3a7, -0x3a7,0x3a7,0xb3f,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xa7d,0x3a7, -0xbd8,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xbe0,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0xbe8, -0x43c,0xbf0,0xbf0,0xbf7,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, -0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x91a,0x4a6,0x4a6,0x43c, -0x43c,0x4a6,0x4a6,0xbff,0x43c,0x43c,0x43c,0x43c,0x43c,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6, -0xc07,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x67c,0xc0f,0x67c,0x67c,0x67f,0xc14,0xc18, -0x858,0xc20,0x3c9,0x3a7,0xc26,0x3a7,0xc2b,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x783,0x3a7,0x3a7,0x3a7, -0x3a7,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c, -0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0xc33, -0x98b,0x67c,0x67c,0x67c,0xc3a,0x67c,0x67c,0xc41,0xc49,0xc0f,0x67c,0xc51,0x67c,0xc59,0xc5e,0x3a7, -0x3a7,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67f,0xc66,0xc6f,0xc73,0xc7b, -0xc6b,0x67c,0x67c,0x67c,0x67c,0xc83,0x67c,0x792,0xc8b,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xc92,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xc92,0xca2,0xc9a,0xc9a,0xc9a,0xca3,0xca3,0xca3, -0xca3,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0xcab,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, -0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, -0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, -0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, -0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0x386,0x386,0x386,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,8,7,8,9,7,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,7,7,7,8,9,0xa,0xa,4, -4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6,2,2,2,2, -2,2,2,2,2,2,6,0xa,0x500a,0xa,0xd00a,0xa,0xa,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0xa,0xa,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0x12,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x12,0x12,0x12,0x12, -0x12,7,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,6,0xa,4,4, -4,4,0xa,0xa,0xa,0xa,0,0x900a,0xa,0xb2,0xa,0xa,4,4,2,2, -0xa,0,0xa,0xa,0xa,2,0,0x900a,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xdc1, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x991,0x3b5,0x68a,0x68a,0x999,0x62d,0x3b5,0x522, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x9a1,0x3b5,0x3b5,0x3b5,0x9a8,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x9b0,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a, +0x9b8,0x9bc,0x44a,0x44a,0x44a,0x44a,0x9cc,0x9c4,0x44a,0x9d4,0x44a,0x44a,0x9dc,0x9e2,0x44a,0x44a, +0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x9f2,0x9ea,0xa02,0x9fa,0x44a,0x44a,0x44a,0x44a, +0x44a,0x44a,0x44a,0xa0a,0x44a,0xa12,0xa22,0xa1a,0x44a,0xa2a,0xa31,0xa37,0xa3f,0xa43,0xa4b,0x44a, +0x529,0xa53,0xa5a,0xa61,0x42c,0xa69,0x577,0x3b5,0x50f,0xa70,0x3b5,0xa76,0x42c,0xa7b,0xa83,0x3b5, +0x3b5,0xa88,0x529,0x3b5,0x3b5,0x3b5,0x844,0xa90,0x42c,0x5b1,0x58c,0xa97,0x3b5,0xa9d,0xaa5,0x542, +0x3b5,0xa53,0xaad,0x3b5,0x3b5,0xab5,0xabd,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xac1,0xac9,0x3b5, +0x3b5,0xad1,0x58c,0xad9,0x3b5,0xadf,0x3b5,0x3b5,0xae5,0xaed,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0xaf2,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xaf9,0xb01,0x3b5,0x3b5,0x3b5,0xb04,0x58c,0xb0c, +0xb10,0xb18,0x3b5,0xb1f,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0xb26,0x3b5,0x3b5,0xb34,0xb2e,0x3b5,0x3b5,0x3b5,0xb3c,0xae3,0x3b5,0xb44,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x5b3,0x42c,0x9a8,0xaae,0x3b5,0x3b5,0x3b5,0xb51,0xb4c,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0xb59,0xb61,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x8b8, +0xb69,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xb6d,0x3b5,0xb73,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xa77,0x3b5,0xb79,0x3b5,0x3b5,0xb81, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x543,0xb89,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x866,0xb8d,0x68a,0x68a, +0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68d,0x3b5,0x3b5,0x403,0xb95, +0x50e,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xb9d,0xba5,0xbab,0x3b5, +0xbb1,0x68a,0x68a,0xbb9,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x68a,0x68a,0xbc1,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xbc9,0x3dc,0xbd0,0xbd6,0xbcc,0x3d7,0xbd3,0xbc7,0xbde, +0xbe2,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x403,0xbea,0x403,0xbf1,0xbf8,0xc00,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0xc08,0xc10,0x3b5,0x3b5,0xa77,0x3b5,0x3b5,0x3b5,0x3b5,0xb73,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xab1,0x3b5,0xc15,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0xc1d,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0xc22,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0xc2a,0x44a,0xc32,0xc32,0xc39,0x44a,0x44a,0x44a,0x44a, +0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a, +0x44a,0x44a,0x44a,0x44a,0x928,0x4b4,0x4b4,0x44a,0x44a,0x4b4,0x4b4,0xa26,0x44a,0x44a,0x44a,0x44a, +0x44a,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0x4b4,0xc41,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a, +0x44a,0x68a,0xc49,0x68a,0x68a,0x68d,0xc4e,0xc52,0x866,0xc5a,0x3d7,0x3b5,0xc60,0x3b5,0xc65,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x791,0x3b5,0x3b5,0x3b5,0x3b5,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, +0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, +0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0xc6d,0x999,0x68a,0x68a,0x68a,0xc74,0x68a,0x68a,0xc7b, +0xc83,0xc49,0x68a,0xc8b,0x68a,0xc93,0xc98,0x681,0x3b5,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, +0x68a,0x68a,0x68a,0x68d,0xca0,0xca8,0x68a,0xcaf,0xcb7,0x68a,0x68a,0x68a,0x68a,0xcbf,0x68a,0x68a, +0xcc4,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0xccb,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5,0x3b5, +0xccb,0xcdb,0xcd3,0xcd3,0xcd3,0xcdc,0xcdc,0xcdc,0xcdc,0x403,0x403,0x403,0x403,0x403,0x403,0x403, +0xce4,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc, +0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc, +0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc, +0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc,0xcdc, +0xcdc,0x394,0x394,0x394,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,8,7,8, +9,7,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +7,7,7,8,9,0xa,0xa,4,4,4,0xa,0xa,0x310a,0xf20a,0xa,3, +6,3,6,6,2,2,2,2,2,2,2,2,2,2,6,0xa, +0x500a,0xa,0xd00a,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x510a, +0xa,0xd20a,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x510a, +0xa,0xd20a,0xa,0x12,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x12,0x12,0x12,0x12,0x12,7,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,6,0xa,4,4,4,4,0xa,0xa,0xa,0xa,0,0x900a, +0xa,0xb2,0xa,0xa,4,4,2,2,0xa,0,0xa,0xa,0xa,2,0,0x900a, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xa,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xa,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0, -0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0,0,0,0,0,0,0,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, +0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xa,0xa,0,0,0,0,0,0, -0,0,0xa,0,0,0,0,0,0xa,0xa,0,0xa,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, +0xa,0xa,0,0,0,0,0,0,0,0,0xa,0,0,0,0,0, +0xa,0xa,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xa,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xa,0,0,0xa,0xa,4,1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0xa,0,0,0xa,0xa,4, +1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,0xb1,1,0xb1,0xb1,1,0xb1,0xb1,1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,0xb1, +1,0xb1,0xb1,1,0xb1,0xb1,1,0xb1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,5,5,5,5,5,5,0xa,0xa, -0xd,4,4,0xd,6,0xd,0xa,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xd,0x8ad,0xd,0xd,0xd,0x4d,0xd,0x8d,0x8d,0x8d,0x8d,0x4d,0x8d, -0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x2d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x8d,0x4d,0x4d,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,5,5,5,5,5,5,5,5, -5,5,4,5,5,0xd,0x4d,0x4d,0xb1,0x8d,0x8d,0x8d,0xd,0x8d,0x8d,0x8d, -0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, -0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x8d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x8d,0x4d,0x8d, -0x4d,0x4d,0x8d,0x8d,0xd,0x8d,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,5,0xa,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xb1,0xb1,0xa,0xb1,0xb1,0xb1,0xb1,0x8d,0x8d, -2,2,2,2,2,2,2,2,2,2,0x4d,0x4d,0x4d,0xd,0xd,0x4d, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xad, -0x8d,0xb1,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d,0x8d, +5,5,5,5,5,5,0xa,0xa,0xd,4,4,0xd,6,0xd,0xa,0xa, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0x8ad,0xd,0xd,0xd, +0x4d,0xd,0x8d,0x8d,0x8d,0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d, +0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x2d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xd,0xd,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d, -0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +5,5,5,5,5,5,5,5,5,5,4,5,5,0xd,0x4d,0x4d, +0xb1,0x8d,0x8d,0x8d,0xd,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, +0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d, +0x8d,0x8d,0x8d,0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d,0x8d,0x8d,0xd,0x8d,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,5,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xb1, +0xb1,0xa,0xb1,0xb1,0xb1,0xb1,0x8d,0x8d,2,2,2,2,2,2,2,2, +2,2,0x4d,0x4d,0x4d,0xd,0xd,0x4d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xad,0x8d,0xb1,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d, +0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d,0x8d,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0x8d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d, +0x4d,0x8d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1, -1,1,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +1,1,1,1,1,1,1,1,1,1,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, -0x41,0x41,0x41,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,0xa,0xa, -0xa,0xa,0x21,1,1,0xb1,1,1,0xb1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1, -1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xb1,0xb1, -0xb1,0xb1,1,0xb1,0xb1,0xb1,0xb1,0xb1,0x81,0x41,0x41,0x41,0x41,0x41,0x81,0x81, -0x41,0x81,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x81,0x41,0x81,0x81, -0x81,0xb1,0xb1,0xb1,1,1,1,1,0x4d,0xd,0x4d,0x4d,0x4d,0x4d,0xd,0x8d, -0x4d,0x8d,0x8d,0xd,0xd,0xd,0xd,0xd,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, -0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x2d,0x2d,0x2d,0x4d,0xd, -0xd,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0xd,5,5,0xd,0xd,0xd,0xd,0xd,0xd, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,5,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x8d,0x8d,0x8d,0xd,0x8d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xb1,0xb1, +0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,1,1,0xa,0xa,0xa,0xa,0x21,1,1,0xb1,1,1, +0xb1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xb1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1,0xb1,0xb1, +0x81,0x41,0x41,0x41,0x41,0x41,0x81,0x81,0x41,0x81,0x41,0x41,0x41,0x41,0x41,0x41, +0x41,0x41,0x41,0x41,0x81,0x41,0x81,0x81,0x81,0xb1,0xb1,0xb1,1,1,1,1, +0x4d,0xd,0x4d,0x4d,0x4d,0x4d,0xd,0x8d,0x4d,0x8d,0x8d,0xd,0xd,0xd,0xd,0xd, +0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, +0x8d,0x8d,0x8d,0x2d,0x2d,0x2d,0x4d,0xd,0xd,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0xd, +5,5,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,5,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0,0xb1,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0xd,0x8d,0x4d, +0x4d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0, -0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,4,0,0,0,0,0,0,0,4,0,0,0xb1,0, -0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0,0, -0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0, -0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, +0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, 0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0xb1,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,4,0xa,0, -0,0,0,0,0xb1,0,0,0,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0,0,0, -0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0, +0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0,0,0xa0,0,0,0,0, -0,0,0xa0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0, +0,0,0,0,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0, +0,0,0,4,0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0,0,4,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0xb1, +0xb1,0,0,0xb1,0xb1,0xb1,0,0,0,0xb1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0xb1,0,0xb1,0x310a,0xf20a,0x310a,0xf20a,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, +0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, -0,0xb1,0xb1,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0, 0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, +0xa,0xa,0xa,0xa,0xa,4,0xa,0,0,0,0,0,0xb1,0,0,0, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0, +0xb1,0,0xb1,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0, +0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x310a,0xf20a,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0xb1,0,0,0xa0,0,0,0,0,0,0,0xa0,0,0,0,0,0, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,4,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1, +0,0xb1,0x310a,0xf20a,0x310a,0xf20a,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1, +0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,4, -0,0xb1,0,0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0xb1,0x40,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0x4a,0xa,0xa,0x2a,0xb1,0xb1,0xb1,0x12,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x40,0x40,0x40,0x40, +0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0, +0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0, +0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, +0,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x310a, +0xf20a,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,4,0,0xb1,0,0,0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0,0,0,0,0,0,0,0,0xb1,0xb1,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xb1,0x40,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x4a,0xa,0xa,0x2a,0xb1, +0xb1,0xb1,0x12,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0,0,0, +0,0,0,0,0,0xb1,0xb1,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xb1,0xb1,0xb1,0,0,0,0,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, -0,0xb1,0xb1,0xb1,0,0,0,0,0xa,0,0,0,0xa,0xa,0,0, +0xb1,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0, +0xa,0,0,0,0xa,0xa,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa, +0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0,0,0,0xb1,0,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0,0,0,0,0,0, +0xb1,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0,0xa,0xa,0xa,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0,0xa,0xa,0xa,0xa,6,0x310a,0xf20a,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,9,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0x814,0x815, +0x813,0x816,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,2,0,0,0,2,2,2,2, +2,2,3,3,0xa,0x310a,0xf20a,0,9,9,9,9,9,9,9,9, +9,9,9,0xb2,0x412,0x432,0x8a0,0x8a1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,9,7,0x8ab,0x8ae,0x8b0,0x8ac,0x8af,6, +4,4,4,4,4,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa, +2,2,2,2,2,2,2,2,2,2,3,3,0xa,0x310a,0xf20a,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0,0,0xb1,0,0,0,0, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xa,0xa,0,0xa,0xa,0xa,0xa,0,0xa,0xa,0,0,0,0,0,0, +0,0,0,0,0xa,0,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa, +0xa,0xa,0xa,0xa,0,0xa,0,0xa,0,0xa,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,0,0xa,0xa,0,0,0,0, +0x100a,0xa,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa, +0x300a,0xf00a,0x900a,0x900a,0x900a,0x100a,0x900a,0x900a,0x100a,0x100a,0x900a,0x900a,0x900a,0x900a,0x900a,0x100a, +0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0x700a,0x700a,0x700a,0xb00a,0xb00a,0xb00a,0xa,0xa, +0xa,0x100a,3,4,0xa,0x900a,0x100a,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x900a, +0x900a,0x900a,0x900a,0xa,0x900a,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a, +0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a,0x300a,0xf00a,0x100a,0x100a, +0x100a,0x100a,0x100a,0x900a,0x100a,0x900a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x900a,0xa,0xa,0xa, +0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a, +0x100a,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x100a,0x300a,0xf00a, +0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0x900a,0x100a,0x900a,0x900a,0x100a,0x900a, +0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa,0xa, +0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a, +0xf00a,0x900a,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0xb1,0, -0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, -0xb1,0xb1,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, -0,0xb1,0,0,0,0,0,0,0xb1,0,0,0,0xb1,0xb1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0,0xa, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0, -0xa,0xa,0xa,0xa,6,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,9, -0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0x814,0x815,0x813,0x816,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, -2,0,0,0,2,2,2,2,2,2,3,3,0xa,0x310a,0xf20a,0, -9,9,9,9,9,9,9,9,9,9,9,0xb2,0x412,0x432,0x8a0,0x8a1, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -9,7,0x8ab,0x8ae,0x8b0,0x8ac,0x8af,6,4,4,4,4,4,0xa,0xa,0xa, -0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2, -2,2,3,3,0xa,0x310a,0xf20a,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0,0xa,0xa,0xa,0xa,0, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0xa,0,0xa,0xa, -0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0,0xa, -0,0xa,0,0,0,0,4,0,0,0,0,0,0,0,0,0, -0,0,0xa,0xa,0,0,0,0,0x100a,0xa,0xa,0xa,0xa,0,0,0, -0,0,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x900a,0x900a,0x900a,0x100a,0x900a,0x900a, -0x100a,0x100a,0x900a,0x900a,0x900a,0x900a,0x900a,0x100a,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa, -0x700a,0x700a,0x700a,0xb00a,0xb00a,0xb00a,0xa,0xa,0xa,0x100a,3,4,0xa,0x900a,0x100a,0xa, -0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x900a,0x900a,0x900a,0x900a,0xa,0x900a,0xa,0x100a,0xa, -0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0xa, -0xa,0x100a,0xa,0x100a,0x300a,0xf00a,0x100a,0x100a,0x100a,0x100a,0x100a,0x900a,0x100a,0x900a,0x100a,0x100a, -0x100a,0x100a,0x100a,0x100a,0x900a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a, -0xa,0xa,0x900a,0x100a,0x900a,0x900a,0x100a,0x900a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa,0x300a,0xf00a,0xa,0xa, -0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, +0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0xa, +0x300a,0xf00a,0xa,0x500a,0x100a,0xd00a,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0x300a,0xf00a,0xa, +0xa,0xa,0xa,0xa,0x900a,0x300a,0xf00a,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x310a,0xf20a, +0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a,0x100a,0x100a,0xa,0xa, +0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x900a,0x100a,0x100a, +0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a, +0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x710a,0x320a,0xf10a,0xb20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a, +0xf20a,0xa,0xa,0x900a,0x100a,0x100a,0x100a,0x100a,0x900a,0xa,0x100a,0x900a,0x300a,0xf00a,0x100a,0x100a, +0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa, +0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa, +0x310a,0xf20a,0x310a,0xf20a,0x100a,0xa,0xa,0xa,0xa,0xa,0x100a,0x900a,0x900a,0x900a,0x100a,0xa, +0xa,0xa,0xa,0xa,0x300a,0xf00a,0x900a,0xa,0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0x300a, +0xf00a,0x300a,0xf00a,0x100a,0xa,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, +0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0x100a,0xa,0x100a,0xa, +0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa, +0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a, +0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0x100a,0x100a, +0x100a,0x100a,0xa,0x100a,0x100a,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x900a,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x100a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0xa,0x300a,0xf00a,0xa,0x500a,0x100a,0xd00a,0xa,0xa, -0xa,0xa,0xa,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x900a,0x300a,0xf00a,0xa, -0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, +0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0x100a,0xa,0x100a,0x100a,0x100a,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x100a,0x900a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0xa,0xa, -0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x710a,0x320a,0xf10a, -0xb20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x900a,0x100a,0x100a,0x100a,0x100a, -0x900a,0xa,0x100a,0x900a,0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x300a, -0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x100a,0xa,0xa,0xa, -0xa,0xa,0x100a,0x900a,0x900a,0x900a,0x100a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x900a,0xa, -0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0x100a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, -0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a, -0x100a,0x100a,0xa,0xa,0x100a,0xa,0x100a,0xa,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0xa, +0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa, +0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x300a,0xf00a,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0xa,0xa,0x100a, -0x100a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, -0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, -0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, -0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x100a,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa, +0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0,0,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0,0,0,0,0,0xa,0xa,0xa, -0xa,0xa,0xa,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa, -0xa,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a, -0xf20a,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0, -0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xa,0,0,0,0,0,0xa,0xa, -0,0,0,0,0,0xa,0xa,0xa,9,0xa,0xa,0xa,0xa,0,0,0, -0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0xb1,0xa,0xa,0,0,0,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0,0,0,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, -0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xa,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0,0,0,0,0,0,0,0, +0xa,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0, +0xa,0,0,0,0,0,0xa,0xa,0,0,0,0,0,0xa,0xa,0xa, +9,0xa,0xa,0xa,0xa,0,0,0,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, +0x310a,0xf20a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, -0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0xb1,0, -0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0xa,0xa,0xa,0xa, -0xb1,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, -0,0,0,0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x60,0,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0,0, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0, -0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, -0xb1,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, -1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xa,0xa,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0,0,0,0,0,0,0,0,0xa,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0,0,0,0xb1,0,0,0,0,0xb1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,1,0xb1,1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0,0xb1,0xb1,0,0xa,0xa,0xa,0xa,0xb1,0,0,0,0,0,0,0, +0,0,0,0,4,4,0,0,0,0,0,0,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60,0, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0, +0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1, +0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0, +0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0,0,0xb1,0,0,0,0,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1,0xb1,1, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa,0xa,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,6,0xa,6,0, -0xa,6,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,4,0xa,0xa,3,3, -0x300a,0xf00a,0xa,0,0xa,4,4,0xa,0,0,0,0,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xa,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xa,0xa,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,6,0xa,6,0,0xa,6,0xa,0xa,0xa,0x310a,0xf20a,0x310a, +0xf20a,0x310a,0xf20a,4,0xa,0xa,3,3,0x300a,0xf00a,0xa,0,0xa,4,4,0xa, +0,0,0,0,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb2,0,0xa,0xa,4, -4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6,2,2,2,2, -2,2,2,2,2,2,6,0xa,0x500a,0xa,0xd00a,0xa,0xa,0,0,0, +0xd,0xd,0xd,0xb2,0,0xa,0xa,4,4,4,0xa,0xa,0x310a,0xf20a,0xa,3, +6,3,6,6,2,2,2,2,2,2,2,2,2,2,6,0xa, +0x500a,0xa,0xd00a,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x510a, +0xa,0xd20a,0xa,0x310a,0xf20a,0xa,0x310a,0xf20a,0xa,0xa,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0x310a,0xf20a,0xa,0x310a,0xf20a, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,0xa,0xa, -0xa,4,4,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0xaa,0xaa,0xaa,0xa,0xa,0x12,0x12,0,0xa,0,0, +0,0,0,0,4,4,0xa,0xa,0xa,4,4,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xaa,0xaa,0xaa, +0xa,0xa,0x12,0x12,0,0xa,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0xb1,2,2,2, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0,0,0xb1,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,1,1,1,1,1,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xa,1,0xb1,0xb1,0xb1,1,0xb1,0xb1,1, -1,1,1,1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xa, +1,0xb1,0xb1,0xb1,1,0xb1,0xb1,1,1,1,1,1,0xb1,0xb1,0xb1,0xb1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xb1,0xb1,0xb1,1,1,1,1,0xb1,0x41,0x81,1,1,0x81,0xb1,0xb1,1, -1,1,1,0x41,0x41,0x41,0x41,0x81,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0x41,0x41,0x41,0x41,0x41,0x81,1,0x81, -1,0x81,0x81,1,1,0x61,0x81,0x81,0x81,0x81,0x81,0x41,0x41,0x41,0x41,0x61, -0x41,0x41,0x41,0x41,0x41,0x81,0x41,0x41,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xb1,0xb1,0xb1,1,1,1,1,0xb1, +0x41,0x81,1,1,0x81,0xb1,0xb1,1,1,1,1,0x41,0x41,0x41,0x41,0x81, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x41,0x81,0x41,0x81,0x81,0x81,0x41,0x41, -0x41,0x81,0x41,0x41,0x81,0x41,0x81,0x81,0x41,0x81,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0x81,0x81,0x81,0x81,0x41,0x41,1, +0x41,0x41,0x41,0x41,0x41,0x81,1,0x81,1,0x81,0x81,1,1,0x61,0x81,0x81, +0x81,0x81,0x81,0x41,0x41,0x41,0x41,0x61,0x41,0x41,0x41,0x41,0x41,0x81,0x41,0x41, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x4d,0x4d,0x8d,0x4d,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -5,5,5,5,5,5,5,5,5,5,0xd,0xd,0xd,0xd,0xd,0xd, -0x6d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +1,1,1,1,1,1,1,1,1,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x41,0x81,0x41,0x81,0x81,0x81,0x41,0x41,0x41,0x81,0x41,0x41,0x81,0x41,0x81,0x81, +0x41,0x81,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x81,0x81,0x81,0x81,0x41,0x41,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x4d,0x4d,0x8d,0x4d,0xb1,0xb1,0xb1,0xb1, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,5,5,5,5,5,5,5,5, +5,5,0xd,0xd,0xd,0xd,0xd,0xd,0x6d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, 0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,1,1,1,1,1,1,1,1, +1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, +5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, -1,1,1,1,1,1,1,1,1,1,1,0xb1,0xb1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +5,5,5,5,5,5,5,1,1,1,1,1,1,1,1,1, +1,1,1,0xb1,0xb1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x4d,0x4d,0x4d, -0x8d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0x41,0x41,0x41,0x41,0x81,0x81,0x41,0x41,0x41,0x41,0x41,0x41, -0x41,0x41,0x41,0x41,0x41,0x41,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x41,1,0x41,0x41,0x81,0x81,0x81,1,0x41,0x81,0x81,0x41, -0x41,0x81,0x41,0x41,1,0x41,0x81,0x81,0x41,1,1,1,1,0x81,0x41,0x61, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0, +0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0x8d,0x4d,0x4d,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0x4d,0x4d,0x4d,0x8d,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0x41,0x41,0x41,0x41, +0x81,0x81,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0xb1,0xb1, +0xb1,0xb1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0x41,1,0x41,0x41, +0x81,0x81,0x81,1,0x41,0x81,0x81,0x41,0x41,0x81,0x41,0x41,1,0x41,0x81,0x81, +0x41,1,1,1,1,0x81,0x41,0x61,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, +0,0,0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0xb1,0xb1,0,0,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0xb1,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0xb1,0,0xb1,0xb1, -0,0,0,0,0,0,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0,0xb1,0,0xb1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -698,41 +711,41 @@ static const uint16_t ubidi_props_trieIndex[13008]={ 0,0xb1,0,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0, +0xb1,0,0xb1,0,0,0,0,0xb1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0,0xb1,0,0,0,0,0xb1, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa0,0xa0,0xb1,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa0, -0xa0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xa0, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0,0xb1,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0, +0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xa0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0xb1,0xb1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0xb1,0,0xb1, -0,0,0,0,0,0,0,0,0xb1,0,0xb1,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0xb1,0,0xb1,0xb1,0,0xb1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,4,4,4,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa0,0xa0,0xa0,0xa0, -0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xb1,0,0,0, -0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0,0,0xb1,0,0xb1,0,0,0,0,0,0,0,0, +4,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0, +0xa0,0xa0,0xa0,0xa0,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, +0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -741,6 +754,7 @@ static const uint16_t ubidi_props_trieIndex[13008]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0xb2,0xb2,0xb2,0xb2,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0, 0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0, @@ -754,79 +768,80 @@ static const uint16_t ubidi_props_trieIndex[13008]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0, +0,0,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x100a, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x100a,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0x100a,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x100a,0,0,0,0,0,0,0,0, -0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +0,0,0,0,0,0x100a,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x100a,0,0,0,0, +0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, -0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1, -0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, +2,2,2,2,2,2,2,2,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, +0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1,1,1,1, -0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1, +1,1,1,1,1,1,1,1,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -2,2,2,2,2,2,2,2,2,2,2,0xa,0xa,0xa,0xa,0xa, +0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xa,0xa,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2, +2,2,2,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xa,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, -0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xa,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2, -2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x12,0x12,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, +0,0,0,0,0,0,0,0,0,0,0x12,0x12,0xb2,0xb2,0xb2,0xb2, 0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, -0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0xb2,0x12,0x12,0x12,0x12,0x12,0x12, +0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0xb2,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0,0,0,0 +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0,0,0,0 }; static const uint32_t ubidi_props_mirrors[40]={ @@ -835,8 +850,8 @@ static const uint32_t ubidi_props_mirrors[40]={ 0x16029b8,0x4029f5,0x1802ade,0x1c02ae3,0x1a02ae4,0x1e02ae5,0xe02aee,0x602bfe }; -static const uint8_t ubidi_props_jgArray[684]={ -0x2d,0,3,3,0x2c,3,0x2d,3,4,0x2a,4,4,0xd,0xd,0xd,6, +static const uint8_t ubidi_props_jgArray[683]={ +0x68,0,3,3,0x2c,3,0x2d,3,4,0x2a,4,4,0xd,0xd,0xd,6, 6,0x1f,0x1f,0x23,0x23,0x21,0x21,0x28,0x28,1,1,0xb,0xb,0x37,0x37,0x37, 0,9,0x1d,0x13,0x16,0x18,0x1a,0x10,0x2c,0x2d,0x2d,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -878,10 +893,10 @@ static const uint8_t ubidi_props_jgArray[684]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,4,0xd,0x28,9,0x1d,0x16,0x18,0x2d,0x2d,0x1f,0x2c,0x39,0,6,0x21, 0xb,0x55,0x1f,1,0x13,0x1d,4,4,4,0x1f,0x2d,0x56,0x58,0x57,4,4, -4,0xd,0xb,1,0x58,0xd,0xd,0x16,0xb,0,0,0 +4,0xd,0xb,1,0x58,0xd,0xd,0x16,0xb,0,0 }; -static const uint8_t ubidi_props_jgArray2[612]={ +static const uint8_t ubidi_props_jgArray2[1029]={ 0x3a,0x3c,0x3c,0x40,0x40,0x3d,0,0x52,0,0x54,0x54,0,0,0x41,0x4f,0x53, 0x43,0x43,0x43,0x44,0x3e,0x50,0x45,0x46,0x4c,0x3b,0x3b,0x48,0x48,0x4b,0x49,0x49, 0x49,0x4a,0,0,0x4d,0,0,0,0,0,0,0x47,0x3f,0x4e,0x51,0x42, @@ -920,7 +935,33 @@ static const uint8_t ubidi_props_jgArray2[612]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0x65,0,0,0,0,0,0,0x65,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0x64,0,0,0x65,0,0x64,0, -0x64,0,0,0x64 +0x64,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,6,0x28,0x13 }; static const UBiDiProps ubidi_props_singleton={ @@ -931,16 +972,16 @@ static const UBiDiProps ubidi_props_singleton={ ubidi_props_jgArray2, { ubidi_props_trieIndex, - ubidi_props_trieIndex+3612, + ubidi_props_trieIndex+3668, nullptr, - 3612, - 9396, + 3668, + 9568, 0x1a0, - 0xe9c, + 0xed4, 0x0, 0x0, 0x110000, - 0x32cc, + 0x33b0, nullptr, 0, false, false, 0, nullptr }, { 2,2,0,0 } diff --git a/thirdparty/icu4c/common/ubiditransform.cpp b/thirdparty/icu4c/common/ubiditransform.cpp index 01f5901a2c..a39cc3100d 100644 --- a/thirdparty/icu4c/common/ubiditransform.cpp +++ b/thirdparty/icu4c/common/ubiditransform.cpp @@ -233,7 +233,7 @@ updateSrc(UBiDiTransform *pTransform, const char16_t *newSrc, uint32_t newLength uprv_free(pTransform->src); pTransform->src = nullptr; } - pTransform->src = (char16_t *)uprv_malloc(newSize * sizeof(char16_t)); + pTransform->src = static_cast<char16_t*>(uprv_malloc(newSize * sizeof(char16_t))); if (pTransform->src == nullptr) { *pErrorCode = U_MEMORY_ALLOCATION_ERROR; //pTransform->srcLength = pTransform->srcSize = 0; @@ -499,7 +499,7 @@ ubiditransform_transform(UBiDiTransform *pBiDiTransform, /* Checking for U_SUCCESS() within the loop to bail out on first failure. */ for (action = pBiDiTransform->pActiveScheme->actions; *action && U_SUCCESS(*pErrorCode); action++) { if ((*action)(pBiDiTransform, pErrorCode)) { - if (action + 1) { + if (action[1] != nullptr) { updateSrc(pBiDiTransform, pBiDiTransform->dest, *pBiDiTransform->pDestLength, *pBiDiTransform->pDestLength, pErrorCode); } diff --git a/thirdparty/icu4c/common/ubidiwrt.cpp b/thirdparty/icu4c/common/ubidiwrt.cpp index 969807c243..209b140722 100644 --- a/thirdparty/icu4c/common/ubidiwrt.cpp +++ b/thirdparty/icu4c/common/ubidiwrt.cpp @@ -501,7 +501,10 @@ ubidi_writeReordered(UBiDi *pBiDi, destSize-=runLength; if((pBiDi->isInverse) && - (/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L)) { + (/*run<runCount-1 &&*/ + runLength > 0 && // doWriteForward may return 0 if src + // only include bidi control chars + dirProps[logicalStart+runLength-1]!=L)) { markFlag |= LRM_AFTER; } if (markFlag & LRM_AFTER) { @@ -632,7 +635,10 @@ ubidi_writeReordered(UBiDi *pBiDi, } destSize-=runLength; - if(/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1]))) { + if(/*run>0 &&*/ + runLength > 0 && // doWriteForward may return 0 if src + // only include bidi control chars + !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1]))) { if(destSize>0) { *dest++=RLM_CHAR; } diff --git a/thirdparty/icu4c/common/ucase.cpp b/thirdparty/icu4c/common/ucase.cpp index 4fd23fc935..5a2feaee84 100644 --- a/thirdparty/icu4c/common/ucase.cpp +++ b/thirdparty/icu4c/common/ucase.cpp @@ -38,7 +38,7 @@ static UBool U_CALLCONV _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 /*end*/, uint32_t /*value*/) { /* add the start code point to the USet */ - const USetAdder *sa=(const USetAdder *)context; + const USetAdder* sa = static_cast<const USetAdder*>(context); sa->add(sa->set, start); return true; } @@ -696,17 +696,17 @@ getDotType(UChar32 c) { U_CAPI UBool U_EXPORT2 ucase_isSoftDotted(UChar32 c) { - return (UBool)(getDotType(c)==UCASE_SOFT_DOTTED); + return getDotType(c)==UCASE_SOFT_DOTTED; } U_CAPI UBool U_EXPORT2 ucase_isCaseSensitive(UChar32 c) { uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); if(!UCASE_HAS_EXCEPTION(props)) { - return (UBool)((props&UCASE_SENSITIVE)!=0); + return (props&UCASE_SENSITIVE)!=0; } else { const uint16_t *pe=GET_EXCEPTIONS(&ucase_props_singleton, props); - return (UBool)((*pe&UCASE_EXC_SENSITIVE)!=0); + return (*pe&UCASE_EXC_SENSITIVE)!=0; } } @@ -1623,12 +1623,12 @@ ucase_toFullFolding(UChar32 c, U_CAPI UBool U_EXPORT2 u_isULowercase(UChar32 c) { - return (UBool)(UCASE_LOWER==ucase_getType(c)); + return UCASE_LOWER==ucase_getType(c); } U_CAPI UBool U_EXPORT2 u_isUUppercase(UChar32 c) { - return (UBool)(UCASE_UPPER==ucase_getType(c)); + return UCASE_UPPER==ucase_getType(c); } /* Transforms the Unicode character to its lower case equivalent.*/ diff --git a/thirdparty/icu4c/common/ucase_props_data.h b/thirdparty/icu4c/common/ucase_props_data.h index 92b59520cc..ce61f5c064 100644 --- a/thirdparty/icu4c/common/ucase_props_data.h +++ b/thirdparty/icu4c/common/ucase_props_data.h @@ -9,145 +9,145 @@ #ifdef INCLUDED_FROM_UCASE_CPP -static const UVersionInfo ucase_props_dataVersion={0xf,1,0,0}; +static const UVersionInfo ucase_props_dataVersion={0x10,0,0,0}; -static const int32_t ucase_props_indexes[UCASE_IX_TOP]={0x10,0x76ec,0x66c8,0x680,0x172,0,0,0,0,0,0,0,0,0,0,3}; +static const int32_t ucase_props_indexes[UCASE_IX_TOP]={0x10,0x78bc,0x6888,0x688,0x172,0,0,0,0,0,0,0,0,0,0,3}; -static const uint16_t ucase_props_trieIndex[13148]={ -0x355,0x35d,0x365,0x36d,0x37b,0x383,0x38b,0x393,0x39b,0x3a3,0x3aa,0x3b2,0x3ba,0x3c2,0x3ca,0x3d2, -0x3d8,0x3e0,0x3e8,0x3f0,0x3f8,0x400,0x408,0x410,0x418,0x420,0x428,0x430,0x438,0x440,0x448,0x450, -0x458,0x460,0x468,0x470,0x478,0x480,0x488,0x490,0x48c,0x494,0x499,0x4a1,0x4a8,0x4b0,0x4b8,0x4c0, -0x4c8,0x4d0,0x4d8,0x4e0,0x374,0x37c,0x4e5,0x4ed,0x4f2,0x4fa,0x502,0x50a,0x509,0x511,0x516,0x51e, -0x526,0x52d,0x531,0x374,0x538,0x355,0x548,0x540,0x550,0x552,0x55a,0x562,0x566,0x567,0x56f,0x577, -0x57f,0x567,0x587,0x58c,0x57f,0x567,0x594,0x59c,0x566,0x5a4,0x5ac,0x5b4,0x5bc,0x374,0x5c4,0x374, -0x5cc,0x5ce,0x5d6,0x5b4,0x566,0x5a4,0x5dd,0x5b4,0x5e5,0x5e7,0x56f,0x5b4,0x566,0x374,0x5ef,0x374, -0x374,0x5f5,0x5fc,0x374,0x374,0x600,0x608,0x374,0x60c,0x613,0x374,0x61a,0x622,0x629,0x631,0x374, -0x374,0x636,0x63e,0x646,0x64e,0x656,0x65d,0x665,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x66d,0x374,0x374,0x67d,0x67d,0x675, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x685,0x68b,0x573,0x573,0x374,0x691,0x699,0x374, -0x6a1,0x374,0x6a9,0x374,0x6b0,0x6b6,0x374,0x374,0x374,0x6be,0x374,0x374,0x374,0x374,0x374,0x374, -0x6c5,0x374,0x6cc,0x6d4,0x374,0x6dc,0x6e4,0x374,0x5a3,0x6e8,0x6f0,0x6f6,0x5e5,0x6fe,0x374,0x705, -0x374,0x70a,0x374,0x710,0x718,0x71c,0x724,0x72c,0x734,0x739,0x73c,0x744,0x754,0x74c,0x764,0x75c, -0x39b,0x76c,0x39b,0x774,0x777,0x39b,0x77f,0x39b,0x787,0x78f,0x797,0x79f,0x7a7,0x7af,0x7b7,0x7bf, -0x7c7,0x7ce,0x374,0x7d6,0x7de,0x374,0x7e6,0x7ee,0x7f6,0x7fe,0x806,0x80e,0x816,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x819,0x81f,0x825,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x82d,0x831,0x835,0x83d,0x39b,0x39b,0x39b,0x845,0x84d,0x854,0x374,0x859,0x374,0x374,0x374,0x861, -0x374,0x6a6,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x565,0x869,0x374,0x374,0x870,0x374,0x374,0x878,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x880,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x710,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x886,0x374,0x88e,0x893,0x89b,0x374,0x374,0x8a3,0x8ab,0x8b3,0x39b,0x8b8,0x8c0,0x8c6,0x8cd,0x8d4, -0x8dc,0x8e3,0x374,0x374,0x374,0x374,0x8ea,0x8f2,0x374,0x8fa,0x901,0x374,0x550,0x906,0x90e,0x6b0, -0x374,0x914,0x91c,0x920,0x374,0x928,0x930,0x938,0x374,0x93e,0x942,0x94a,0x95a,0x952,0x374,0x962, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x96a,0x374,0x374,0x374,0x374,0x972,0x550,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x977,0x97f,0x983,0x374,0x374,0x374,0x374,0x357,0x35d,0x98b,0x993,0x99a,0x50b,0x374,0x374,0x9a2, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0xdd4,0xdd4,0xdec,0xe2c,0xe6c,0xea8,0xee8,0xf28,0xf60,0xfa0,0xfe0,0x1020,0x1060,0x10a0,0x10e0,0x1120, -0x1160,0x11a0,0x11e0,0x1220,0x1230,0x1264,0x12a0,0x12e0,0x1320,0x1360,0xdd0,0x1394,0x13c8,0x1408,0x1424,0x1458, -0x9e1,0xa1f,0xa5f,0xa9e,0x188,0x188,0xad9,0x188,0x188,0x188,0x188,0x188,0x188,0xb02,0x188,0x188, -0x188,0x188,0x188,0x188,0x188,0xb42,0x188,0xb82,0x188,0xba8,0xbe3,0xc22,0xc62,0xc9c,0xcd3,0x188, +static const uint16_t ucase_props_trieIndex[13372]={ +0x363,0x36b,0x373,0x37b,0x389,0x391,0x399,0x3a1,0x3a9,0x3b1,0x3b8,0x3c0,0x3c8,0x3d0,0x3d8,0x3e0, +0x3e6,0x3ee,0x3f6,0x3fe,0x406,0x40e,0x416,0x41e,0x426,0x42e,0x436,0x43e,0x446,0x44e,0x456,0x45e, +0x466,0x46e,0x476,0x47e,0x486,0x48e,0x496,0x49e,0x49a,0x4a2,0x4a7,0x4af,0x4b6,0x4be,0x4c6,0x4ce, +0x4d6,0x4de,0x4e6,0x4ee,0x382,0x38a,0x4f3,0x4fb,0x500,0x508,0x510,0x518,0x517,0x51f,0x524,0x52c, +0x534,0x53b,0x53f,0x382,0x546,0x363,0x556,0x54e,0x55e,0x560,0x568,0x570,0x574,0x575,0x57d,0x585, +0x58d,0x575,0x595,0x59a,0x58d,0x575,0x5a2,0x5aa,0x574,0x5b2,0x5ba,0x5c2,0x5ca,0x382,0x5d2,0x382, +0x5da,0x5dc,0x5e4,0x5c2,0x574,0x5b2,0x5eb,0x5c2,0x5f3,0x5f5,0x57d,0x5c2,0x574,0x382,0x5fd,0x382, +0x382,0x603,0x60a,0x382,0x382,0x60e,0x616,0x382,0x61a,0x621,0x382,0x628,0x630,0x637,0x63f,0x382, +0x382,0x644,0x64c,0x654,0x65c,0x664,0x66b,0x673,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x67b,0x382,0x382,0x68b,0x68b,0x683, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x693,0x699,0x581,0x581,0x382,0x69f,0x6a7,0x382, +0x6af,0x382,0x6b7,0x382,0x6be,0x6c4,0x382,0x382,0x382,0x6cc,0x382,0x382,0x382,0x382,0x382,0x382, +0x6d3,0x382,0x6da,0x6e2,0x382,0x6ea,0x6f2,0x382,0x5b1,0x6f6,0x6fe,0x704,0x5f3,0x70c,0x382,0x713, +0x382,0x718,0x382,0x71e,0x726,0x72a,0x732,0x73a,0x742,0x747,0x74a,0x752,0x762,0x75a,0x772,0x76a, +0x3a9,0x77a,0x3a9,0x782,0x785,0x3a9,0x78d,0x3a9,0x795,0x79d,0x7a5,0x7ad,0x7b5,0x7bd,0x7c5,0x7cd, +0x7d5,0x7dc,0x382,0x7e4,0x7ec,0x382,0x7f4,0x7fc,0x804,0x80c,0x814,0x81c,0x824,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x827,0x82d,0x833,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x83b,0x83f,0x843,0x84b,0x3a9,0x3a9,0x3a9,0x853,0x85b,0x862,0x382,0x867,0x382,0x382,0x382,0x86f, +0x382,0x6b4,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x573,0x877,0x382,0x382,0x87e,0x382,0x382,0x886,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x88e,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x71e,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x894,0x382,0x89c,0x8a1,0x8a9,0x382,0x382,0x8b1,0x8b9,0x8c1,0x3a9,0x8c6,0x8ce,0x8d4,0x8db,0x8e3, +0x8eb,0x8f2,0x382,0x382,0x382,0x382,0x8f9,0x901,0x382,0x909,0x910,0x382,0x55e,0x915,0x91d,0x6be, +0x382,0x923,0x92b,0x92f,0x382,0x937,0x93f,0x947,0x382,0x94d,0x951,0x959,0x969,0x961,0x382,0x971, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x979,0x382,0x382,0x382,0x382,0x981,0x55e,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x986,0x98e,0x992,0x382,0x382,0x382,0x382,0x365,0x36b,0x99a,0x9a2,0x9a9,0x519,0x382,0x382,0x9b1, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0xe0c,0xe0c,0xe24,0xe64,0xea4,0xee0,0xf20,0xf60,0xf98,0xfd8,0x1018,0x1058,0x1098,0x10d8,0x1118,0x1158, +0x1198,0x11d8,0x1218,0x1258,0x1268,0x129c,0x12d8,0x1318,0x1358,0x1398,0xe08,0x13cc,0x1400,0x1440,0x145c,0x1490, +0x9e1,0xa1f,0xa5f,0xa9e,0x188,0x188,0xad9,0x188,0x188,0x188,0x188,0x188,0xb11,0xb3a,0x188,0x188, +0x188,0x188,0x188,0x188,0x188,0xb7a,0x188,0xbba,0x188,0xbe0,0xc1b,0xc5a,0xc9a,0xcd4,0xd0b,0x188, 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, @@ -172,657 +172,671 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, -0xd13,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x9a9,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x9b1,0x374,0x374,0x374,0x9b4,0x374,0x374,0x374, -0x374,0x9bc,0x9c2,0x9c6,0x374,0x374,0x9ca,0x9ce,0x9d4,0x374,0x374,0x374,0x9db,0x9df,0x9e7,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x9f7,0x9ef,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x9ff, -0xa03,0x374,0x374,0x374,0x374,0x374,0xa0b,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0xa13,0xa17,0xa1f,0xa23,0x374,0xa2a,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0xa30,0x374,0xa34,0x374,0x374,0xa3c,0x374,0xa44,0x374,0x374,0x374,0x566, -0xa46,0xa4d,0xa51,0x5e5,0xa59,0xa61,0x374,0xa69,0xa70,0x374,0xa76,0x5e5,0xa7b,0xa83,0x374,0x374, -0xa88,0x566,0x374,0x374,0x374,0x357,0xa90,0x5e5,0x5e7,0xa98,0xa9f,0x374,0x374,0x374,0x374,0x374, -0xa46,0xaa7,0x374,0x374,0xaaf,0xab7,0x374,0x374,0x374,0x374,0x374,0x374,0xabb,0xac3,0x374,0x374, -0xacb,0x4cf,0x374,0x374,0xad3,0x374,0x374,0xad9,0xae1,0x374,0x374,0x374,0x374,0x374,0x374,0xae6, -0x374,0x374,0x374,0xaee,0xaf6,0x374,0x374,0xafe,0xb06,0x374,0x374,0x374,0xb09,0x9b1,0xb11,0xb15, -0xb1d,0x374,0xb24,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xb2b, -0x374,0x374,0x972,0xb33,0x374,0x374,0x374,0xb39,0xb41,0x374,0xb45,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0xb4b,0x5e5,0xb51,0xb59,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xb5d,0xb65,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xb6b,0x374,0xb71,0x5a3,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0xaee,0xaf6,0x374,0x374,0x374,0x374,0x374,0x374,0x6a6,0x374,0xb77,0x374, -0x374,0xb7f,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0xb84,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0xb8c,0x5a3,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x8ab,0xb94,0xb9b,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xba2,0xbaa, -0xbb0,0x374,0x374,0x374,0x374,0xbb8,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0xbc0,0xbc8,0xbcd,0xbd3,0xbdb,0xbe3,0xbeb,0xbc4,0xbf3,0xbfb,0xc03,0xc0a,0xbc5, -0xbc0,0xbc8,0xbc3,0xbd3,0xbc6,0xbc1,0xc12,0xbc4,0xc1a,0xc22,0xc2a,0xc31,0xc1d,0xc25,0xc2d,0xc34, -0xc20,0xc3c,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x8ab,0xc44,0x8ab,0xc4b,0xc52,0xc5a,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xc6a,0xc72,0x374,0x374,0x374,0x374, -0x374,0x374,0xc62,0xc7a,0xc8d,0xc80,0xc85,0x374,0x374,0x374,0x374,0xc95,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xaab,0x374,0xa28,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xc9d,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0xca1,0x374,0xca9,0xcb1,0xcb8,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0xbbc,0xcc0,0xcc0,0xcc6, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0xa6b,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x566,0x8ab,0x8ab,0x8ab,0x374,0x374,0x374,0x374,0x8ab,0x8ab,0x8ab,0x8ab,0x8ab, -0x8ab,0x8ab,0xcce,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374,0x374, -0x374,0x374,0x374,0x354,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0, -0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0, -0,0,0,0,0,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0xa,0x5a,0x7a, -0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0xba,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0, -0,0,4,0,4,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf9,0xf031,0x149, -0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0x189,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xd4b,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x9b8,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x9c0,0x382,0x382,0x382,0x9c3,0x382,0x382,0x382, +0x382,0x9cb,0x9d1,0x9d5,0x382,0x382,0x9d9,0x9dd,0x9e3,0x382,0x382,0x382,0x9ea,0x9ee,0x9f6,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xa06,0x9fe,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xa0e, +0xa12,0x382,0x382,0x382,0x382,0x382,0xa1a,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0xa22,0xa26,0xa2e,0xa32,0x382,0xa39,0xa3e,0xa45,0xa4c,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0xa52,0x382,0xa56,0x382,0x382,0xa5e,0x382,0xa66,0x382,0x382,0x382,0x574, +0xa68,0xa6f,0xa73,0x5f3,0xa7b,0xa83,0x382,0xa8b,0xa92,0x382,0xa98,0x5f3,0xa9d,0xaa5,0x382,0x382, +0xaaa,0x574,0x382,0x382,0x382,0x365,0xab2,0x5f3,0x5f5,0xaba,0xac1,0x382,0xa8d,0xac9,0x58d,0x382, +0xa68,0xad1,0x382,0x382,0xad9,0xae1,0x382,0x382,0x382,0x382,0x382,0x382,0xae5,0xaed,0x382,0x382, +0xaf5,0x4dd,0x382,0x382,0xafd,0x382,0x382,0xb03,0xb0b,0x382,0x382,0x382,0x382,0x382,0x382,0xb10, +0x382,0x382,0x382,0xb18,0xb20,0x382,0x382,0xb28,0xb30,0x382,0x382,0x382,0xb33,0x9c0,0xb3b,0xb3f, +0xb47,0x382,0xb4e,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xb55, +0x382,0x382,0x981,0xb5d,0x382,0x382,0x382,0xb63,0xb6b,0x382,0xb6f,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0xb75,0x5f3,0xb7b,0xb83,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xb8a,0xb92,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x519,0xb9a,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0xb9e,0x382,0xba4,0x5b1,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x55e,0xb77,0x382,0x382,0x382,0x382,0x382,0x382,0xb18,0xb20,0x382,0x382, +0x382,0x382,0x382,0x382,0x6b4,0x382,0xbaa,0x382,0x382,0xbb2,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xbb7,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xbbf,0x5b1, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x8b9,0xbc7,0xbce,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0xbd5,0xbdd,0xbe3,0x382,0x382,0x382,0x382,0xbeb,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xbf3,0xbfb,0xc00,0xc06,0xc0e, +0xc16,0xc1e,0xbf7,0xc26,0xc2e,0xc36,0xc3d,0xbf8,0xbf3,0xbfb,0xbf6,0xc06,0xbf9,0xbf4,0xc45,0xbf7, +0xc4d,0xc55,0xc5d,0xc64,0xc50,0xc58,0xc60,0xc67,0xc53,0xc6f,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x8b9,0xc77,0x8b9,0xc7e,0xc85,0xc8d, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0xc9d,0xca5,0x382,0x382,0x382,0x382,0x382,0x382,0xc95,0xcad,0xcc0,0xcb3,0xcb8,0x382, +0x382,0x382,0x382,0xcc8,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xad5, +0x382,0xa37,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0xcd0,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xcd5,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xcd9,0x382,0xce1,0xce9,0xcf0,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0xbef,0xcf8,0xcf8,0xcfe,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0xa8d,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x574,0x8b9,0x8b9,0x8b9,0x382, +0x382,0x382,0x382,0x8b9,0x8b9,0x8b9,0x8b9,0x8b9,0x8b9,0x8b9,0xd06,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382, +0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x382,0x362,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,4,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,0,0,0,0,0x1012,0x1012,0x1012, +0x1012,0x1012,0x1012,0x1012,0x1012,0xa,0x5a,0x7a,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0xba, +0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0,0,0,4,0,4,0xf011,0xf011,0xf011, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf9,0xf031,0x149,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0x189, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,0,1,0,0,4,0,4,0,0,0,0, -4,0x1c9,0,4,4,0,1,0,0,0,0,0,0x1012,0x1012,0x1012,0x1012, -0x1012,0x1fa,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x5a,0x5a,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, -0x1012,0x1012,0x1012,0,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x239,0xf011,0xf011,0xf011,0xf011, -0xf011,0x2d9,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, -0xf011,0xf011,0xf011,0,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0x3c91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0,0,0,0,0,0,0,0,0,0,0,0,4,0,1,0, +0,4,0,4,0,0,0,0,4,0x1c9,0,4,4,0,1,0, +0,0,0,0,0x1012,0x1012,0x1012,0x1012,0x1012,0x1fa,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, +0x5a,0x5a,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0,0x1012,0x1012,0x1012,0x1012, +0x1012,0x1012,0x1012,0x239,0xf011,0xf011,0xf011,0xf011,0xf011,0x2d9,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0,0xf011,0xf011,0xf011,0xf011, +0xf011,0xf011,0xf011,0x3c91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x31a,0xff91,0x92,0xff91,0x92,0xff91,0x31a,0xffb1,0x33a,0x389,0x92,0xff91, -0x92,0xff91,0x92,0xff91,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92, -0xff91,0x3d9,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x31a,0xff91,0x92,0xff91, +0x92,0xff91,0x31a,0xffb1,0x33a,0x389,0x92,0xff91,0x92,0xff91,0x92,0xff91,1,0x92,0xff91,0x92, +0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x3d9,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0xc392,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x459,0x6191,0x6912,0x92,0xff91,0x92,0xff91,0x6712,0x92, -0xff91,0x6692,0x6692,0x92,0xff91,1,0x2792,0x6512,0x6592,0x92,0xff91,0x6692,0x6792,0x3091,0x6992,0x6892, -0x92,0xff91,0x5191,1,0x6992,0x6a92,0x4111,0x6b12,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x6d12,0x92, -0xff91,0x6d12,1,1,0x92,0xff91,0x6d12,0x92,0xff91,0x6c92,0x6c92,0x92,0xff91,0x92,0xff91,0x6d92, -0x92,0xff91,1,0,0x92,0xff91,1,0x1c11,0,0,0,0,0x48a,0x4bb,0x4f9,0x52a, -0x55b,0x599,0x5ca,0x5fb,0x639,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92, -0xff91,0x92,0xff91,0x92,0xff91,0xd891,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x669,0x6ea,0x71b,0x759,0x92,0xff91,0xcf92,0xe412, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xc392,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x459, +0x6191,0x6912,0x92,0xff91,0x92,0xff91,0x6712,0x92,0xff91,0x6692,0x6692,0x92,0xff91,1,0x2792,0x6512, +0x6592,0x92,0xff91,0x6692,0x6792,0x3091,0x6992,0x6892,0x92,0xff91,0x5191,0x489,0x6992,0x6a92,0x4111,0x6b12, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x6d12,0x92,0xff91,0x6d12,1,1,0x92,0xff91,0x6d12,0x92, +0xff91,0x6c92,0x6c92,0x92,0xff91,0x92,0xff91,0x6d92,0x92,0xff91,1,0,0x92,0xff91,1,0x1c11, +0,0,0,0,0x4aa,0x4db,0x519,0x54a,0x57b,0x5b9,0x5ea,0x61b,0x659,0x92,0xff91,0x92, +0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xd891,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x689,0x70a,0x73b,0x779,0x92,0xff91,0xcf92,0xe412,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0xbf12,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,1,1,1,1,1,1,0x78a,0x92,0xff91,0xae92,0x7aa,0x7c9, -0x7c9,0x92,0xff91,0x9e92,0x2292,0x2392,0x92,0xff91,0x92,0xffb1,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x7e9,0x809,0x829,0x9711,0x9911,1,0x9991,0x9991,1,0x9b11,1,0x9a91,0x849,1,1,1, -0x9991,0x869,1,0x9891,1,0x889,0x8a9,1,0x97b1,0x9691,0x8a9,0x8c9,0x8e9,1,1,0x9691, -1,0x909,0x9591,1,1,0x9511,1,1,1,1,1,1,1,0x929,1,1, -0x9311,1,0x949,0x9311,1,1,1,0x969,0x9311,0xdd91,0x9391,0x9391,0xdc91,1,1,1, -1,1,0x9291,1,0,1,1,1,1,1,1,1,1,0x989,0x9a9,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -5,5,0x25,5,5,5,5,5,5,4,4,4,0x14,4,0x14,4, -5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xbf12,1,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,1,1,1,1, +1,1,0x7aa,0x92,0xff91,0xae92,0x7ca,0x7e9,0x7e9,0x92,0xff91,0x9e92,0x2292,0x2392,0x92,0xff91, +0x92,0xffb1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x809,0x829,0x849,0x9711,0x9911,1,0x9991,0x9991, +1,0x9b11,1,0x9a91,0x869,1,1,1,0x9991,0x889,1,0x9891,0x8a9,0x8c9,0x8e9,1, +0x97b1,0x9691,0x8e9,0x909,0x929,1,1,0x9691,1,0x949,0x9591,1,1,0x9511,1,1, +1,1,1,1,1,0x969,1,1,0x9311,1,0x989,0x9311,1,1,1,0x9a9, +0x9311,0xdd91,0x9391,0x9391,0xdc91,1,1,1,1,1,0x9291,1,0,1,1,1, +1,1,1,1,1,0x9c9,0x9e9,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,5,5,0x25,5,5,5,5,5, +5,4,4,4,0x14,4,0x14,4,5,5,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,5,5,5,5,5,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -0x54,0x54,0x44,0x44,0x44,0x44,0x44,0x9cc,0x54,0x44,0x54,0x44,0x54,0x44,0x44,0x44, -0x44,0x44,0x44,0x54,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +4,4,4,4,4,4,4,4,0x54,0x54,0x44,0x44,0x44,0x44,0x44,0xa0c, +0x54,0x44,0x54,0x44,0x54,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x44,0x64,0x64,0x64, 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, -0x64,0x74,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x44, -0x44,0x44,0x54,0x44,0x44,0x9dd,0x44,0x64,0x64,0x64,0x44,0x44,0x44,0x64,0x64,4, -0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x44,0x64,0x64,0x64,0x44,0x64,0x64,0x64,0x64, -0x64,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x92,0xff91,0x92,0xff91,4,4,0x92,0xff91,0,0,5,0x4111,0x4111,0x4111,0,0x3a12, -0,0,0,0,4,4,0x1312,4,0x1292,0x1292,0x1292,0,0x2012,0,0x1f92,0x1f92, -0xa29,0x1012,0xafa,0x1012,0x1012,0xb3a,0x1012,0x1012,0xb7a,0xbca,0xc1a,0x1012,0xc5a,0x1012,0x1012,0x1012, -0xc9a,0xcda,0,0xd1a,0x1012,0x1012,0xd5a,0x1012,0x1012,0xd9a,0x1012,0x1012,0xed11,0xed91,0xed91,0xed91, -0xdd9,0xf011,0xea9,0xf011,0xf011,0xee9,0xf011,0xf011,0xf29,0xf79,0xfc9,0xf011,0x1009,0xf011,0xf011,0xf011, -0x1049,0x1089,0x10c9,0x10f9,0xf011,0xf011,0x1139,0xf011,0xf011,0x1179,0xf011,0xf011,0xe011,0xe091,0xe091,0x412, -0x11b9,0x11e9,2,2,2,0x1239,0x1269,0xfc11,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x1299,0x12c9,0x391,0xc631,0x12fa,0x1349,0,0x92,0xff91,0xfc92,0x92,0xff91,1,0xbf12,0xbf12,0xbf12, -0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812, -0x1012,0x1012,0x137a,0x1012,0x13ba,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x13fa,0x1012, -0x1012,0x143a,0x147a,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x14ca,0x1012,0x1012,0x1012,0x1012,0x1012, -0xf011,0xf011,0x1509,0xf011,0x1549,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0x1589,0xf011, -0xf011,0x15c9,0x1609,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0x1659,0xf011,0xf011,0xf011,0xf011,0xf011, -0xd811,0xd811,0xd811,0xd811,0xd811,0xd811,0xd831,0xd811,0xd831,0xd811,0xd811,0xd811,0xd811,0xd811,0xd811,0xd811, -0x92,0xff91,0x169a,0x16d9,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0,0x44,0x44,0x44,0x44,0x44,4,4,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x74,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x54,0x44,0x44,0xa1d,0x44,0x64, +0x64,0x64,0x44,0x44,0x44,0x64,0x64,4,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x44, +0x64,0x64,0x64,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x92,0xff91,0x92,0xff91,4,4,0x92,0xff91, +0,0,5,0x4111,0x4111,0x4111,0,0x3a12,0,0,0,0,4,4,0x1312,4, +0x1292,0x1292,0x1292,0,0x2012,0,0x1f92,0x1f92,0xa69,0x1012,0xb3a,0x1012,0x1012,0xb7a,0x1012,0x1012, +0xbba,0xc0a,0xc5a,0x1012,0xc9a,0x1012,0x1012,0x1012,0xcda,0xd1a,0,0xd5a,0x1012,0x1012,0xd9a,0x1012, +0x1012,0xdda,0x1012,0x1012,0xed11,0xed91,0xed91,0xed91,0xe19,0xf011,0xee9,0xf011,0xf011,0xf29,0xf011,0xf011, +0xf69,0xfb9,0x1009,0xf011,0x1049,0xf011,0xf011,0xf011,0x1089,0x10c9,0x1109,0x1139,0xf011,0xf011,0x1179,0xf011, +0xf011,0x11b9,0xf011,0xf011,0xe011,0xe091,0xe091,0x412,0x11f9,0x1229,2,2,2,0x1279,0x12a9,0xfc11, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x12d9,0x1309,0x391,0xc631,0x133a,0x1389,0,0x92, +0xff91,0xfc92,0x92,0xff91,1,0xbf12,0xbf12,0xbf12,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812, +0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x2812,0x1012,0x1012,0x13ba,0x1012,0x13fa,0x1012,0x1012,0x1012, +0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x143a,0x1012,0x1012,0x147a,0x14ba,0x1012,0x1012,0x1012,0x1012,0x1012, +0x1012,0x1012,0x150a,0x1012,0x1012,0x1012,0x1012,0x1012,0xf011,0xf011,0x1549,0xf011,0x1589,0xf011,0xf011,0xf011, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0x15c9,0xf011,0xf011,0x1609,0x1649,0xf011,0xf011,0xf011,0xf011,0xf011, +0xf011,0xf011,0x1699,0xf011,0xf011,0xf011,0xf011,0xf011,0xd811,0xd811,0xd811,0xd811,0xd811,0xd811,0xd831,0xd811, +0xd831,0xd811,0xd811,0xd811,0xd811,0xd811,0xd811,0xd811,0x92,0xff91,0x16da,0x1719,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0,0x44,0x44,0x44,0x44,0x44, +4,4,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x792,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xf891, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x792,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92, +0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xf891,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, -0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0,0,4,0,0, -0,0,0,4,1,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, +0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, +0x1812,0x1812,0x1812,0,0,4,0,0,0,0,0,4,1,0xe811,0xe811,0xe811, 0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, -0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0x1719,1,0,0,0,0,0,0,0, -0,0x64,0x44,0x44,0x44,0x44,0x64,0x44,0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44, -0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x44, -0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0,0x64, -0,0x64,0x64,0,0x44,0x64,0,0x64,0,0,0,0,0,0,0,0, +0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0x1759, +1,0,0,0,0,0,0,0,0,0x64,0x44,0x44,0x44,0x44,0x64,0x44, +0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64, +0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0,0x64,0,0x64,0x64,0,0x44,0x64,0,0x64, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0,4,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0, +0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x64,0x64,0x64,0,4,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x64,0x64,0x44, +0x44,0x44,0x44,0x44,0x64,0x44,0x44,0x64,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x64,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,0,0,0,0,0,0,0,0,0,0,0x64,0x64,0x64,0x64,0x64, -0x64,0x64,0x64,0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x64,0x44,0x44,0x64, +0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,4,0,0x44,0x44,0x44,0x44,0x64, +0x44,4,4,0x44,0x44,0,0x64,0x44,0x44,0x64,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,4,0,0x44,0x44,0x44,0x44,0x64,0x44,4,4,0x44,0x44,0,0x64,0x44, -0x44,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,0,0x64,0,0,0,0,0,0, +0x44,0x64,0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x64,0x44,0x64,0x64,0x44,0x64,0x44, +0x44,0x44,0x64,0x44,0x64,0x44,0x64,0x44,0x64,0x44,0x44,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x64,0x44,0x44,0x64,0x44,0x44,0x64, -0x64,0x64,0x44,0x64,0x64,0x44,0x64,0x44,0x44,0x44,0x64,0x44,0x64,0x44,0x64,0x44, -0x64,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, -4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,4,4,4,4,4,4,4,4,4,4,4,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x44,4,4,0,0, -0,0,4,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44, -0x44,0x44,4,0x44,0x44,0x44,0x44,0x44,4,0x44,0x44,0x44,4,0x44,0x44,0x44, -0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0x64,0x64, -0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, -4,4,0,0,0,0,0,0,0x44,0x64,0x64,0x64,0x44,0x44,0x44,0x44, -0x44,0x44,4,0x64,0x44,0x44,0x64,0x44,0x44,0x64,0x44,0x44,0x44,0x64,0x64,0x64, -0x64,0x64,0x64,0x44,0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x44, -0,0,0,0,0,0,0,0,0,4,0x44,0x44,0x44,0x44,0x44,0x64, -0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,0,0x64,0,0,0,0,4,4,4,4,4,4,4, -4,0,0,0,0,0x64,0,0,0,0x44,0x64,0x44,0x44,4,4,4, -0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0, -0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x64,0,0,0,0,4,4,4, -4,0,0,0,0,0,0,0,0,0x64,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4, +0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x64,0x44,4,4,0,0,0,0,4,0,0,0x64,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x44,0,0,4,4,0, +0,0,0,0,0,0,0x44,0x44,0x44,0x44,4,0x44,0x44,0x44,0x44,0x44, +4,0x44,0x44,0x44,4,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0, -0,0,0,4,4,0,0,4,4,0x64,0,0,0,4,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0, -0,4,4,4,4,4,0,4,4,0,0,0,0,0x64,0,0, +0,0,0,0,0,0x64,0x64,0x64,0,0,0,0,0,0,0,0, +4,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0x44, +0x44,0x64,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x44,4,0x64,0x44,0x44,0x64,0x44, +0x44,0x64,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x64,0x44, +0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0, +0,4,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,4,4,4,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,0,0x64,0,0,0, +0,4,4,4,4,4,4,4,4,0,0,0,0,0x64,0,0, +0,0x44,0x64,0x44,0x44,4,4,4,0,0,0,0,0,0,0,0, 0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, +0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,0,4, -0,4,4,4,4,0,0,0,0,0,0,0,0,0x64,0,0, -0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0, -0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0, +0x64,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0, +0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x44,0,0,4,4,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,0, +0,0,0,0,0,4,4,0,0,0,0,4,4,0,0,4, +4,0x64,0,0,0,4,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,0,0,0,4,0,0, +0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,4, +4,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x64,0,4,4,4,0,0,0,0,0,4,4, -4,0,4,4,4,0x64,0,0,0,0,0,0,0,0x64,0x64,0, -0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, -4,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x64,0,0,4,0,4,4,4,4,0,0,0, +0,0,0,0,0,0x64,0,0,0,0,0,0,0,4,4,0, +0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x64,0x64,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x64,0,0,0,0,0,0,0,4,4, -4,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,0,0,4,4,4,4,0x64,0x64,0x64,0, -0,0,0,0,0,0,4,4,0x64,0x64,0x64,0x64,4,4,4,0, +0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,0,0,4,4,4,4,0x64,0x64,0x64,4,4,0,0,0, -0,0,0,0,0,0,4,0,0x64,0x64,0x64,0x64,4,4,4,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x64,0x64,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,4,4, +4,0,0,0,0,0,4,4,4,0,4,4,4,0x64,0,0, +0,0,0,0,0,0x64,0x64,0,0,0,0,0,0,0,0,0, +0,0,4,0,0,0,0,0,4,0x64,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x64,0,0x64,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0x64,0x64,4,0x64,4,4,4, -4,4,0x64,0x64,0x64,0x64,4,0,0x64,4,0x44,0x44,0x64,0,0x44,0x44, -0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4, -0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x64, +0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0, +0,0,0,0,0,0,4,4,4,0,4,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +4,4,4,4,0x64,0x64,0x64,0,0,0,0,0,0,0,4,4, +0x64,0x64,0x64,0x64,4,4,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,0,0,4,4,4,4, +0x64,0x64,0x64,4,4,0,0,0,0,0,0,0,0,0,4,0, +0x64,0x64,0x64,0x64,4,4,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x64,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x64,0,0x64,0,0x64,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x64,0x64,4,0x64,4,4,4,4,4,0x64,0x64,0x64,0x64,4,0, +0x64,4,0x44,0x44,0x64,0,0x44,0x44,0,0,0,0,0,4,4,4, +4,4,4,4,4,4,4,4,0,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,0,0,0,0,0,0,0,0,0,0x64,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,4,4,4,0,4,4,4,4,4,0x64, -0,0x64,0x64,0,0,4,4,0,0,0,0,0,0,0,0,0, +4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0, +0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4, +4,0,4,4,4,4,4,0x64,0,0x64,0x64,0,0,4,4,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,0,0,0,0,4,4,4,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,0,0,4,4,0, -0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,0,0,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a, -0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a, -0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0x175a,0,0x175a,0,0,0,0, -0,0x175a,0,0,0x1779,0x17a9,0x17d9,0x1809,0x1839,0x1869,0x1899,0x18c9,0x18f9,0x1929,0x1959,0x1989, -0x19b9,0x19e9,0x1a19,0x1a49,0x1a79,0x1aa9,0x1ad9,0x1b09,0x1b39,0x1b69,0x1b99,0x1bc9,0x1bf9,0x1c29,0x1c59,0x1c89, -0x1cb9,0x1ce9,0x1d19,0x1d49,0x1d79,0x1da9,0x1dd9,0x1e09,0x1e39,0x1e69,0x1e99,0x1ec9,0x1ef9,0x1f29,0x1f59,0, -5,0x1f89,0x1fb9,0x1fe9,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x44,0x44,0x44,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a, -0x201a,0x201a,0x201a,0x201a,0x203a,0x203a,0x203a,0x203a,0x203a,0x203a,0,0,0x2059,0x2089,0x20b9,0x20e9, -0x2119,0x2149,0,0,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a, -0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a,0x201a, -0x201a,0x201a,0x201a,0x201a,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,4,4,0x64,0x60,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,0,0,0,0,4,4, +4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,4,0,0,4,4,0,0,0,0,0,0,0x64,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, +0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, +0x179a,0x179a,0,0x179a,0,0,0,0,0,0x179a,0,0,0x17b9,0x17e9,0x1819,0x1849, +0x1879,0x18a9,0x18d9,0x1909,0x1939,0x1969,0x1999,0x19c9,0x19f9,0x1a29,0x1a59,0x1a89,0x1ab9,0x1ae9,0x1b19,0x1b49, +0x1b79,0x1ba9,0x1bd9,0x1c09,0x1c39,0x1c69,0x1c99,0x1cc9,0x1cf9,0x1d29,0x1d59,0x1d89,0x1db9,0x1de9,0x1e19,0x1e49, +0x1e79,0x1ea9,0x1ed9,0x1f09,0x1f39,0x1f69,0x1f99,0,5,0x1fc9,0x1ff9,0x2029,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x205a,0x205a,0x205a,0x205a, +0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x207a,0x207a,0x207a,0x207a, +0x207a,0x207a,0,0,0x2099,0x20c9,0x20f9,0x2129,0x2159,0x2189,0,0,0x205a,0x205a,0x205a,0x205a, +0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a, +0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4, -0x60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,0,4,4,4,4,4, -4,4,0,0,0,0,0,0,0,0,4,0,0,4,4,4, -4,4,4,4,4,4,0x64,4,0,0,0,4,0,0,0,0, -0,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0, +0x64,0x60,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,4,0x60,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,0,0,0,0,4, -4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, -0,0x64,0x44,0x64,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x44,0x64,0,0,4, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,4,0,4,4,4,4,4,4,4,0, -0x64,0,4,0,0,4,4,4,4,4,4,4,4,0,0,0, -0,0,0,4,4,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0x64, -0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0, -0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x64,4,0x64, -0x64,0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x64,0x44,0x44,0x44,0x44,0, +4,4,0,4,4,4,4,4,4,4,0,0,0,0,0,0, +0,0,4,0,0,4,4,4,4,4,4,4,4,4,0x64,4, +0,0,0,4,0,0,0,0,0,0x44,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x64,0,4,4,4,4,4,0,4,0,0,0, -0,0,4,0,0x60,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x44,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0, -4,4,0x60,0x64,4,4,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x64,0,4,4,0,0, -0,4,0,4,4,4,0x60,0x60,0,0,0,0,0,0,0,0, -0,0,0,0,4,4,4,4,4,4,4,4,0,0,4,0x64, +0,0,0,0,0,0,0,0,0,0x64,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0, -0x2179,0x21a9,0x21d9,0x2209,0x2239,0x2289,0x22d9,0x2309,0x2339,0,0,0,0,0,0,0, -0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a, -0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0x236a,0,0,0x236a,0x236a,0x236a, +4,4,4,0,0,0,0,4,4,0,0,0,0,0,0,0, +0,0,4,0,0,0,0,0,0,0x64,0x44,0x64,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x44,0x44,0x44,0,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x64,0x64,0x64,0x64, -0x44,0,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0,0,0,0,0x64,0,0, -0,0,0,0,0x44,0,0,0,0x44,0x44,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0,0,0,0x44,0x64,0,0,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, +4,4,4,4,4,4,4,0,0x64,0,4,0,0,4,4,4, +4,4,4,4,4,0,0,0,0,0,0,4,4,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0,0,0x64,0,0,0,0,0,0,0,4, +0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64, +0x64,0x64,0x64,0x44,0x44,0x64,4,0x64,0x64,0x44,0x44,0x64,0x64,0x44,0x44,0x44, +0x44,0x44,0x64,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,4,4, +4,4,4,0,4,0,0,0,0,0,4,0,0x60,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x44,0x64,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,4,4,4,4,0,0,4,4,0x60,0x64,4,4,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x64,0,4,4,0,0,0,4,0,4,4,4,0x60,0x60, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, +4,4,4,4,0,0,4,0x64,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,4,4,4,4,4,0,0,0x21b9,0x21e9,0x2219,0x2249,0x2279,0x22c9,0x2319,0x2349, +0x2379,0x92,0xff91,0,0,0,0,0,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa, +0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa, +0x23aa,0x23aa,0x23aa,0,0,0x23aa,0x23aa,0x23aa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x44,0x44,0x44,0,0x64,0x64,0x64,0x64, +0x64,0x64,0x44,0x44,0x64,0x64,0x64,0x64,0x44,0,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0,0,0,0,0x64,0,0,0,0,0,0,0x44,0,0,0, +0x44,0x44,0,0,0,0,0,0,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0x25,5,5,5,5,5,5,5,5,1,1,1,1,1, -1,1,1,1,1,1,1,1,5,0x2389,1,1,1,0x23a9,1,1, -5,5,5,5,0x25,5,5,5,0x25,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x23c9,1, -1,1,1,1,1,1,0x21,1,1,1,1,5,5,5,5,5, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x44,0x64,0x64,0x44,0x64, -0x44,0x44,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x64, -0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xffb1,0x92,0xff91, +5,5,5,5,5,5,5,5,5,5,0x25,5,5,5,5,5, +5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1, +5,0x23c9,1,1,1,0x23e9,1,1,5,5,5,5,0x25,5,5,5, +0x25,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x2409,1,1,1,1,1,1,1,0x21,1, +1,1,1,5,5,5,5,5,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x64, +0x64,0x64,0x64,0x44,0x64,0x64,0x44,0x64,0x44,0x44,0x64,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xffb1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x242a,0x2469,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x23ea,0x2429,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x24a9,0x2529,0x25a9,0x2629,0x26a9,0x2729, +1,1,0x275a,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xffb1, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x2469,0x24e9,0x2569,0x25e9,0x2669,0x26e9,1,1,0x271a,1,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xffb1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x411,0x411,0x411,0x411, -0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411, -0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0,0,0x411,0x411,0x411,0x411, -0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411, -0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411, -0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0,0,0x2769,0x411,0x27e9,0x411, -0x2899,0x411,0x2949,0x411,0,0xfc12,0,0xfc12,0,0xfc12,0,0xfc12,0x411,0x411,0x411,0x411, -0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x2511,0x2511,0x2b11,0x2b11, -0x2b11,0x2b11,0x3211,0x3211,0x4011,0x4011,0x3811,0x3811,0x3f11,0x3f11,0,0,0x29f9,0x2a69,0x2ad9,0x2b49, -0x2bb9,0x2c29,0x2c99,0x2d09,0x2d7b,0x2deb,0x2e5b,0x2ecb,0x2f3b,0x2fab,0x301b,0x308b,0x30f9,0x3169,0x31d9,0x3249, -0x32b9,0x3329,0x3399,0x3409,0x347b,0x34eb,0x355b,0x35cb,0x363b,0x36ab,0x371b,0x378b,0x37f9,0x3869,0x38d9,0x3949, -0x39b9,0x3a29,0x3a99,0x3b09,0x3b7b,0x3beb,0x3c5b,0x3ccb,0x3d3b,0x3dab,0x3e1b,0x3e8b,0x411,0x411,0x3ef9,0x3f79, -0x3fe9,0,0x4069,0x40e9,0xfc12,0xfc12,0xdb12,0xdb12,0x419b,4,0x4209,4,4,4,0x4259,0x42d9, -0x4349,0,0x43c9,0x4449,0xd512,0xd512,0xd512,0xd512,0x44fb,4,4,4,0x411,0x411,0x4569,0x4619, -0,0,0x46d9,0x4759,0xfc12,0xfc12,0xce12,0xce12,0,4,4,4,0x411,0x411,0x4809,0x48b9, -0x4979,0x391,0x49f9,0x4a79,0xfc12,0xfc12,0xc812,0xc812,0xfc92,4,4,4,0,0,0x4b29,0x4ba9, -0x4c19,0,0x4c99,0x4d19,0xc012,0xc012,0xc112,0xc112,0x4dcb,4,4,0,0,0,0,0, -0,0,0,0,0,0,0,4,4,4,4,4,0,0,0,0, -0,0,0,0,4,4,0,0,0,0,0,0,4,0,0,4, -0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,4,4,0,4,4, -4,4,4,4,4,4,4,4,0,0x25,0,0,0,0,0,0, -0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44, -0x64,0x64,0x64,0x44,0x44,4,4,4,4,0x44,4,4,4,0x64,0x64,0x44, -0x64,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,2, -0,0,1,2,2,2,1,1,2,2,2,1,0,2,0,0, -0,2,2,2,2,2,0,0,0,0,0,0,2,0,0x4e3a,0, -2,0,0x4e7a,0x4eba,2,2,0,1,2,2,0xe12,2,1,0,0,0, -0,1,0,0,1,1,2,2,0,0,0,0,0,2,1,1, -0x21,0x21,0,0,0,0,0xf211,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812, -0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811, -0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0,0,0,0x92,0xff91,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12, -0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xf311,0xf311,0xf311,0xf311, -0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, +0x92,0xff91,0x92,0xff91,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, +0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12, +0xfc12,0xfc12,0,0,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, +0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, +0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12, +0xfc12,0xfc12,0,0,0x27a9,0x411,0x2829,0x411,0x28d9,0x411,0x2989,0x411,0,0xfc12,0,0xfc12, +0,0xfc12,0,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, +0xfc12,0xfc12,0xfc12,0xfc12,0x2511,0x2511,0x2b11,0x2b11,0x2b11,0x2b11,0x3211,0x3211,0x4011,0x4011,0x3811,0x3811, +0x3f11,0x3f11,0,0,0x2a39,0x2aa9,0x2b19,0x2b89,0x2bf9,0x2c69,0x2cd9,0x2d49,0x2dbb,0x2e2b,0x2e9b,0x2f0b, +0x2f7b,0x2feb,0x305b,0x30cb,0x3139,0x31a9,0x3219,0x3289,0x32f9,0x3369,0x33d9,0x3449,0x34bb,0x352b,0x359b,0x360b, +0x367b,0x36eb,0x375b,0x37cb,0x3839,0x38a9,0x3919,0x3989,0x39f9,0x3a69,0x3ad9,0x3b49,0x3bbb,0x3c2b,0x3c9b,0x3d0b, +0x3d7b,0x3deb,0x3e5b,0x3ecb,0x411,0x411,0x3f39,0x3fb9,0x4029,0,0x40a9,0x4129,0xfc12,0xfc12,0xdb12,0xdb12, +0x41db,4,0x4249,4,4,4,0x4299,0x4319,0x4389,0,0x4409,0x4489,0xd512,0xd512,0xd512,0xd512, +0x453b,4,4,4,0x411,0x411,0x45a9,0x4659,0,0,0x4719,0x4799,0xfc12,0xfc12,0xce12,0xce12, +0,4,4,4,0x411,0x411,0x4849,0x48f9,0x49b9,0x391,0x4a39,0x4ab9,0xfc12,0xfc12,0xc812,0xc812, +0xfc92,4,4,4,0,0,0x4b69,0x4be9,0x4c59,0,0x4cd9,0x4d59,0xc012,0xc012,0xc112,0xc112, +0x4e0b,4,4,0,0,0,0,0,0,0,0,0,0,0,0,4, +4,4,4,4,0,0,0,0,0,0,0,0,4,4,0,0, +0,0,0,0,4,0,0,4,0,0,4,4,4,4,4,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4, +0,0x25,0,0,0,0,0,0,0,0,0,0,0,0,0,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x44,0x44,4,4,4, +4,0x44,4,4,4,0x64,0x64,0x44,0x64,0x44,0x64,0x64,0x64,0x64,0x64,0x64, +0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,2,0,0,1,2,2,2,1,1, +2,2,2,1,0,2,0,0,0,2,2,2,2,2,0,0, +0,0,0,0,2,0,0x4e7a,0,2,0,0x4eba,0x4efa,2,2,0,1, +2,2,0xe12,2,1,0,0,0,0,1,0,0,1,1,2,2, +0,0,0,0,0,2,1,1,0x21,0x21,0,0,0,0,0xf211,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812, +0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811, +0,0,0,0x92,0xff91,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12, +0xd12,0xd12,0xd12,0xd12,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311, +0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1812,0x1812,0x1812,0x1812, 0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, -0x1812,0x1812,0x1812,0x1812,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, +0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0xe811,0xe811,0xe811,0xe811, 0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, -0xe811,0xe811,0xe811,0xe811,0x92,0xff91,0x4efa,0x4f1a,0x4f3a,0x4f59,0x4f79,0x92,0xff91,0x92,0xff91,0x92, -0xff91,0x4f9a,0x4fba,0x4fda,0x4ffa,1,0x92,0xff91,1,0x92,0xff91,1,1,1,1,1, -0x25,5,0x501a,0x501a,0x92,0xff91,0x92,0xff91,1,0,0,0,0,0,0,0x92, -0xff91,0x92,0xff91,0x44,0x44,0x44,0x92,0xff91,0,0,0,0,0,0,0,0, -0,0,0,0,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039, -0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039, -0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0,0x5039,0,0,0,0,0,0x5039,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0x92,0xff91,0x4f3a,0x4f5a, +0x4f7a,0x4f99,0x4fb9,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x4fda,0x4ffa,0x501a,0x503a,1,0x92,0xff91, +1,0x92,0xff91,1,1,1,1,1,0x25,5,0x505a,0x505a,0x92,0xff91,0x92,0xff91, +1,0,0,0,0,0,0,0x92,0xff91,0x92,0xff91,0x44,0x44,0x44,0x92,0xff91, +0,0,0,0,0,0,0,0,0,0,0,0,0x5079,0x5079,0x5079,0x5079, +0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079, +0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0x5079,0,0x5079, +0,0,0,0,0,0x5079,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x64,0x44,0x44,0x44,0x44, 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0x64,0x64, -0x64,0x64,0x60,0x60,0,4,4,4,4,4,0,0,0,0,0,4, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0, +0,0,0,0,0,0,0x64,0x64,0x64,0x64,0x60,0x60,0,4,4,4, +4,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0x64,0x64,4,4,4,4,0, +0,0x64,0x64,4,4,4,4,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,0, +0,0,0,0,4,4,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x505a,0x5099,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0,0x44,4,4,4,0, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,4,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x509a,0x50d9,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,5,5,0x44,0x44,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,1,1,0x92,0xff91, +0x92,0xff91,0,0x44,4,4,4,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0,4,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -5,1,1,1,1,1,1,1,1,0x92,0xff91,0x92,0xff91,0x50da,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,4,4,4,0x92,0xff91,0x50fa,1,0, -0x92,0xff91,0x92,0xff91,0x1811,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x511a,0x513a,0x515a,0x517a,0x511a,1,0x519a,0x51ba,0x51da,0x51fa,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xe812,0x521a,0x523a,0x92,0xff91,0x92,0xff91,0, -0,0,0,0,0x92,0xff91,0,1,0,1,0x92,0xff91,0x92,0xff91,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,5,5,5,0x92,0xff91,0,5,5,1,0,0,0,0,0, -0,0,4,0,0,0,0x64,0,0,0,0,4,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,4,0,0,0,0,0,0x64,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x64,4,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,0,0,0,0,0,0,4,4, -4,4,4,0x64,0x64,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4, -4,4,4,4,4,4,0,0x60,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x64,0,0,4,4, -4,4,0,0,4,4,0,0,0x60,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0, -0,4,4,0,0,4,4,0,0,0,0,0,0,0,0,0, -0,0,0,4,0,0,0,0,0,0,0,0,4,0,0,0, +5,5,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x44,0x44,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,1,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,5,1,1,1,1,1,1,1, +1,0x92,0xff91,0x92,0xff91,0x511a,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +4,4,4,0x92,0xff91,0x513a,1,0,0x92,0xff91,0x92,0xff91,0x1811,1,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x515a,0x517a,0x519a,0x51ba,0x515a,1, +0x51da,0x51fa,0x521a,0x523a,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0xe812,0x525a,0x527a,0x92,0xff91,0x92,0xff91,0x529a,0x92,0xff91,0,0,0x92,0xff91,0,1, +0,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x52ba,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5, +5,0x92,0xff91,0,5,5,1,0,0,0,0,0,0,0,4,0, +0,0,0x64,0,0,0,0,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0, +0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x64,4,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, +0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,4,4,4,4,4,0x64, +0x64,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4, +4,4,0,0x60,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x64,0,0,4,4,4,4,0,0, +4,4,0,0,0x60,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,4,4,4,4,4,4,0,0,4,4,0, +0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,4, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x44,0,0x44,0x44, +0x64,0,0,0x44,0x44,0,0,0,0,0,0x44,0x44,0,0x44,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x44,0,0x44,0x44,0x64,0,0,0x44,0x44,0,0,0,0,0,0x44,0x44, -0,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, -0,0,0,4,4,0,0x64,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x5259,1,1,1,1, -1,1,1,4,5,5,5,5,1,1,1,1,1,1,1,1, -1,5,4,4,0,0,0,0,0x5279,0x52a9,0x52d9,0x5309,0x5339,0x5369,0x5399,0x53c9, -0x53f9,0x5429,0x5459,0x5489,0x54b9,0x54e9,0x5519,0x5549,0x5b79,0x5ba9,0x5bd9,0x5c09,0x5c39,0x5c69,0x5c99,0x5cc9, -0x5cf9,0x5d29,0x5d59,0x5d89,0x5db9,0x5de9,0x5e19,0x5e49,0x5e79,0x5ea9,0x5ed9,0x5f09,0x5f39,0x5f69,0x5f99,0x5fc9, -0x5ff9,0x6029,0x6059,0x6089,0x60b9,0x60e9,0x6119,0x6149,0x5579,0x55a9,0x55d9,0x5609,0x5639,0x5669,0x5699,0x56c9, -0x56f9,0x5729,0x5759,0x5789,0x57b9,0x57e9,0x5819,0x5849,0x5879,0x58a9,0x58d9,0x5909,0x5939,0x5969,0x5999,0x59c9, -0x59f9,0x5a29,0x5a59,0x5a89,0x5ab9,0x5ae9,0x5b19,0x5b49,0,0,0,0,0,4,0,0, -4,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x6179,0x61f9,0x6279,0x62f9,0x63a9,0x6459,0x64e9,0, -0,0,0,0,0,0,0,0,0,0,0,0x6589,0x6609,0x6689,0x6709,0x6789, -0,0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,4, -0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, -0,4,0,0,0,0,0,0,0,0,0,0,0,0x1012,0x1012,0x1012, +0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,4, +4,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0x52d9,1,1,1,1,1,1,1,4, +5,5,5,5,1,1,1,1,1,1,1,1,1,5,4,4, +0,0,0,0,0x52f9,0x5329,0x5359,0x5389,0x53b9,0x53e9,0x5419,0x5449,0x5479,0x54a9,0x54d9,0x5509, +0x5539,0x5569,0x5599,0x55c9,0x5bf9,0x5c29,0x5c59,0x5c89,0x5cb9,0x5ce9,0x5d19,0x5d49,0x5d79,0x5da9,0x5dd9,0x5e09, +0x5e39,0x5e69,0x5e99,0x5ec9,0x5ef9,0x5f29,0x5f59,0x5f89,0x5fb9,0x5fe9,0x6019,0x6049,0x6079,0x60a9,0x60d9,0x6109, +0x6139,0x6169,0x6199,0x61c9,0x55f9,0x5629,0x5659,0x5689,0x56b9,0x56e9,0x5719,0x5749,0x5779,0x57a9,0x57d9,0x5809, +0x5839,0x5869,0x5899,0x58c9,0x58f9,0x5929,0x5959,0x5989,0x59b9,0x59e9,0x5a19,0x5a49,0x5a79,0x5aa9,0x5ad9,0x5b09, +0x5b39,0x5b69,0x5b99,0x5bc9,0,0,0,0,0,4,0,0,4,0,0,0, +0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x61f9,0x6279,0x62f9,0x6379,0x6429,0x64d9,0x6569,0,0,0,0,0, +0,0,0,0,0,0,0,0x6609,0x6689,0x6709,0x6789,0x6809,0,0,0,0, +0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,0,0,0,4,0,0,0,0, +0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,0,0,4,0,0, +0,0,0,0,0,0,0,0,0,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, 0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, -0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0,0,0,4,0,4,0xf011,0xf011,0xf011, +0x1012,0x1012,0x1012,0,0,0,4,0,4,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, 0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, -0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0, +0xf011,0xf011,0xf011,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x64,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,0, +0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0, -0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, +0,0,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0x1412,0x1412,0x1412,0x1412, 0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, +0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0xec11,0xec11,0xec11,0xec11, 0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11, -0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, -0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0,0,0,0, +0xec11,0xec11,0xec11,0xec11,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, +0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0,0,0,0,0xec11,0xec11,0xec11,0xec11, 0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11, -0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1392,0x1392,0x1392,0x1392, -0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0, -0x1392,0x1392,0,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0,0xec91, -0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0,0xec91, -0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0,0xec91,0xec91,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, -5,5,5,5,5,5,5,0,0,0,0,0,5,4,4,5, -5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,4,4,4, -0,4,4,0,0,0,0,0,4,0x64,4,0x44,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x44,0x64,0x64,0,0,0,0,0x64,0,0,0,0, -0,0x44,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x2012,0x2012,0x2012,0x2012, -0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012, -0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xe011,0xe011,0xe011,0xe011, -0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011, -0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44, +0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392, +0x1392,0x1392,0x1392,0,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0,0x1392,0x1392,0,0xec91, +0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0,0xec91,0xec91,0xec91,0xec91,0xec91, +0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0xec91,0,0xec91,0xec91,0xec91,0xec91,0xec91, +0xec91,0xec91,0,0xec91,0xec91,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5, +5,5,5,0,0,0,0,0,5,4,4,5,5,5,0,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,4,4,4,0,4,4,0, +0,0,0,0,4,0x64,4,0x44,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0,0,0, +0x44,0x64,0x64,0,0,0,0,0x64,0,0,0,0,0,0x44,0x64,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0x64,0x64, -0,0,0,0,0,0,0x64,0x64,0x44,0x44,0x44,0x64,0x44,0x64,0x64,0x64, -0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0x44,0x64,0x44,0x64,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012, +0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012, +0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011, +0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011, +0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,4,4,4,4,4,4,0x64,0,0,0,0,0, +0,0,0,0,0,0,4,0,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, +0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0,0,0,0x44,0x44,0x44, +0x44,0x44,0,4,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x64,0,0,4,4,0,0,0,0,0,0,0, -0,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,4,4,4,0,0,0x64,0x64,0, -0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0, -0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0, +0,0,0,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,4,4,4,4,0,4,4,4, -4,4,4,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x64,0,0,0,0, +0,0,0,0,4,0x64,0x64,0x64,0,0,0,0,0,0,0x64,0x64, +0x44,0x44,0x44,0x64,0x44,0x64,0x64,0x64,0x64,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x44,0x64,0x44,0x64,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,4,4,4,4,4,4,4,4,0,0x60,0,0,0, -0,0,0,0,0,4,0x64,4,4,0,0,4,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, +4,4,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,0,4, +4,0,0,0,0,0,0,0,0,0,0,0x64,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -4,4,0,0,4,0x60,0x64,4,0,0,0,0,0,0,4,0, -0,0,0,4,4,4,4,4,4,0x64,0x64,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,0,0,0,0,0,0,0,0,0,0,0,0,0x60,0,0, +4,4,4,0,0,0x64,0x64,0,0,4,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0x44,0x44,0x44,0x44, -0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,4, -4,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x44,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -4,4,4,4,4,0,4,0,0,0,0,4,4,0,0x64,0x64, +4,4,4,4,0,4,4,4,4,4,4,0x64,0x64,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4, -4,4,0,0,0,0,0,0,4,4,0,0x64,0x64,0,0,0, +0,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, +4,4,4,0,0x60,0,0,0,0,0,0,0,0,4,0x64,4, +4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,0,0,4,0x60,0x64,4, +0,0,0,0,0,0,4,0,0,0,0,4,4,4,4,4, +4,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0x60,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0,0,0,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0, +0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x64,0x60,0x64,0,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x64,4,4,0,0x64,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -4,4,4,4,4,4,4,0,0,4,0,0x64,0,0,0,0, -0,0,0,0,0,0,0,4,0,4,0,0,4,4,4,4, -4,4,0x60,0x64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,4,0,4,0, +0,0,0,4,4,0,0x64,0x64,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,4,4,0,0,4,4,4,4,0,4,4,4,4,0x64, +0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0, +4,4,0,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4, -0,0x64,0x64,0,0,0,0,0,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, +4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,0, +0,4,0,0x64,0,0,0,0,0,0,0,0,0,0,0,4, +0,4,0,0,4,4,4,4,4,4,0x60,0x64,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,0,4,0,0,4,4, +4,4,0,4,4,4,4,0x64,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +4,4,4,4,4,4,4,4,0,0x64,0x64,0,0,0,0,0, +0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, 0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, -0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, 0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, -0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,4,4,0x60,0x64,0,0,0,0,0x64,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,4,0,0,4,4, -0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,0, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,0x64,4,4,4,4,0,0,4, -4,4,4,0,0,0,0,0,0,0,0,0x64,0,0,0,0, -0,0,0,0,0,4,4,4,4,4,4,0,0,4,4,4, -0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, -4,4,4,4,4,4,4,0,4,0x64,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, -4,4,4,0,4,4,4,4,4,4,0,0x64,4,4,4,4, -4,4,4,4,0,0,4,4,4,4,4,4,4,0,4,4, -0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,4,4,4,4,4,0,0,0,4,0, -4,4,0,4,4,4,0x64,4,0x64,0x64,0,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,4,4,0x60,0x64,0, +0,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,4,0,0,0,4,0,0x64,0,0,0,0, +4,4,4,4,0,0,4,4,0,0,0,0,0,4,4,4, +4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,0, -0,0,0,0,4,0x60,0x64,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,0,0,0,0,0,0,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x64,0x64,0x64,0x64, -0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4, -4,0,0,0,0,0,0,0,0,0,0,0,0x60,0x60,0,0, +0x64,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0, +0,0,0,0x64,0,0,0,0,0,0,0,0,0,4,4,4, +4,4,4,0,0,4,4,4,0,0,0,0,0,0,0,0, +0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,0, +4,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,4,4,4,4,4,4,0,4,4,4,4, +4,4,0,0x64,4,4,4,4,4,4,4,4,0,0,4,4, +4,4,4,4,4,0,4,4,0,4,4,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4, +4,4,4,0,0,0,4,0,4,4,0,4,4,4,0x64,4, +0x64,0x64,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, +0,4,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,0,4,4,4,4,4,4,4,0,4,4,0, +0,0,4,4,4,4,4,0,0,0,0,0,4,0x60,0x64,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,4,0x64,0, +0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0x60,0x60,0x64, -0x64,0x64,0,0,0,0x60,0x60,0x60,0x60,0x60,0x60,4,4,4,4,4, -4,4,4,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0,0,0x44,0x44,0x44, -0x44,0x44,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, +4,4,0,0,0,4,4,0x64,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x64,0x64,0x64,0x64,0x64,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,0,4,4,0,0,0, +0,0,0,0,0,0,0,0,0x60,0x60,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, +0,4,4,4,4,4,4,4,0,4,4,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,0x64,0,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x60,0x60,0x64,0x64,0x64,0,0, +0,0x60,0x60,0x60,0x60,0x60,0x60,4,4,4,4,4,4,4,4,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0,0,0x44,0x44,0x44,0x44,0x44,0x64,0x64, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x44,0x44,0x44,0x44,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44, +0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1, -1,1,0x21,0x21,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,1,1,1,1,1,1,1,0,0x21,0x21,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,1,1,1,1,1,1,1,1,0x21,0x21, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1, -1,1,1,1,1,1,0x21,0x21,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,2,0,2,2,0,0,2,0, -0,2,2,0,0,2,2,2,2,0,2,2,2,2,2,2, -2,2,1,1,1,1,0,1,0,1,0x21,0x21,1,1,1,1, -0,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1, -2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2, -2,0,2,2,2,2,2,2,2,0,1,1,1,1,1,1, +1,1,1,1,1,0,0x21,0x21,1,1,1,1,1,1,1,1, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1, 1,1,0x21,0x21,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,2,2,0,2,2,2,2,0,2,2,2,2, -2,0,2,0,0,0,2,2,2,2,2,2,2,0,1,1, -1,1,1,1,1,1,0x21,0x21,1,1,1,1,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, +1,1,1,1,2,0,2,2,0,0,2,0,0,2,2,0, +0,2,2,2,2,0,2,2,2,2,2,2,2,2,1,1, +1,1,0,1,0,1,0x21,0x21,1,1,1,1,0,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,1,1,1,1,1,1,0,0, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,0,1,1,1,1,1,1, +2,2,2,2,2,2,2,2,1,1,1,1,2,2,0,2, +2,2,2,0,0,2,2,2,2,2,2,2,2,0,2,2, +2,2,2,2,2,0,1,1,1,1,1,1,1,1,0x21,0x21, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0,1,1,1,1,1,1,2,2,2,2,2,2, +2,2,0,2,2,2,2,0,2,2,2,2,2,0,2,0, +0,0,2,2,2,2,2,2,2,0,1,1,1,1,1,1, +1,1,0x21,0x21,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,0,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1, +2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,1,1,1,1,1,1,0,0,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -1,1,1,0,1,1,1,1,1,1,2,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,0,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, +1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0,1,1,1,1,1,1,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,0, +1,1,1,1,1,1,2,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,0,0,0,0,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0, -0,4,0,0,0,0,0,0,0,0,0,0,4,0,0,0, +4,4,4,0,0,0,0,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,0,0,0,0,0,0,0,0,4,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0x44, +0x44,0x44,0x44,0x44,1,1,1,1,1,1,1,1,1,1,0,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x21,1, +1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,4,4,4,4,4,0,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,0,0,0x44,0x44,0x44,0x44,0x44,1,1,1,1,1,1,1,1, -1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0x21,1,1,1,1,0,0,0,0,0,0,1,1,1, -1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x44,0,0x44,0x44,0,0x44,0x44, -0x44,0x44,0x44,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0x25,5,5,5,5,5,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x44,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x44,0x44,0,0x44,0x44,0,0x44,0x44,0x44,0x44,0x44,0, 0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -0x25,0x25,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,4,4,4,4,4, -4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -0x64,0x64,0x64,0x44,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,0x25,5,5,5,5,5,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x44, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,0x25,0x25,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,4,4,4,4,4,4,4,0,0, +0,0,0,0,0,0,0,0,0,0,0,4,0x64,0x64,0x64,0x44, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x44,0x64,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0,0,0,0,0, 0,0,0,0,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112, 0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112,0x1112, @@ -838,111 +852,112 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0,0,0,0,0,0,0,0,0,0,0,0 }; -static const uint16_t ucase_props_exceptions[1664]={ +static const uint16_t ucase_props_exceptions[1672]={ 0xc850,0x20,2,0x130,0x131,0x4810,0x20,0x841,0x6b,1,0x212a,0x841,0x73,1,0x17f,0x5c50, 0x20,2,0x130,0x131,0x844,0x4b,1,0x212a,0x844,0x53,1,0x17f,0x806,0x3bc,0x39c,0x841, 0xe5,1,0x212b,0x8c0,1,0x2220,0x73,0x73,0x53,0x53,0x53,0x73,0x1e9e,0x844,0xc5,1, 0x212b,0x4810,1,0xce50,0xc7,2,0x49,0x131,0x844,0x49,2,0x69,0x130,0x880,0x2220,0x2bc, -0x6e,0x2bc,0x4e,0x2bc,0x4e,0x806,0x73,0x53,0x809,0x1c6,0x1c5,0x80d,0x1c6,0x1c4,0x1c5,0x80c, -0x1c4,0x1c5,0x809,0x1c9,0x1c8,0x80d,0x1c9,0x1c7,0x1c8,0x80c,0x1c7,0x1c8,0x809,0x1cc,0x1cb,0x80d, -0x1cc,0x1ca,0x1cb,0x80c,0x1ca,0x1cb,0x880,0x2220,0x6a,0x30c,0x4a,0x30c,0x4a,0x30c,0x809,0x1f3, -0x1f2,0x80d,0x1f3,0x1f1,0x1f2,0x80c,0x1f1,0x1f2,0x810,0x2a2b,0x810,0x2a28,0x810,0x2a3f,0x810,0x2a1f, -0x810,0x2a1c,0x810,0x2a1e,0x810,0xa54f,0x810,0xa54b,0x810,0xa528,0x810,0xa544,0x810,0x29f7,0x810,0xa541, -0x810,0x29fd,0x810,0x29e7,0x810,0xa543,0x810,0xa52a,0x1810,0xa515,0x810,0xa512,0x6800,0x3846,0x3b9,0x399, -1,0x1fbe,0x8c0,1,0x3330,0x3b9,0x308,0x301,0x399,0x308,0x301,0x399,0x308,0x301,0x1fd3,0x841, -0x3b2,1,0x3d0,0x841,0x3b5,1,0x3f5,0x841,0x3b8,2,0x3d1,0x3f4,0x841,0x3b9,2,0x345, -0x1fbe,0x841,0x3ba,1,0x3f0,0x841,0x3bc,1,0xb5,0x841,0x3c0,1,0x3d6,0x841,0x3c1,1, -0x3f1,0x4850,0x20,1,0x3c2,0x841,0x3c6,1,0x3d5,0x841,0x3c9,1,0x2126,0x8c0,1,0x3330, -0x3c5,0x308,0x301,0x3a5,0x308,0x301,0x3a5,0x308,0x301,0x1fe3,0x844,0x392,1,0x3d0,0x844,0x395, -1,0x3f5,0x844,0x398,2,0x3d1,0x3f4,0x844,0x399,2,0x345,0x1fbe,0x844,0x39a,1,0x3f0, -0x844,0x39c,1,0xb5,0x844,0x3a0,1,0x3d6,0x844,0x3a1,1,0x3f1,0x806,0x3c3,0x3a3,0x844, -0x3a3,1,0x3c2,0x844,0x3a6,1,0x3d5,0x844,0x3a9,1,0x2126,0x806,0x3b2,0x392,0x846,0x3b8, -0x398,1,0x3f4,0x806,0x3c6,0x3a6,0x806,0x3c0,0x3a0,0x806,0x3ba,0x39a,0x806,0x3c1,0x3a1,0x841, -0x3b8,2,0x398,0x3d1,0x806,0x3b5,0x395,0x841,0x432,1,0x1c80,0x841,0x434,1,0x1c81,0x841, -0x43e,1,0x1c82,0x841,0x441,1,0x1c83,0x841,0x442,2,0x1c84,0x1c85,0x841,0x44a,1,0x1c86, -0x844,0x412,1,0x1c80,0x844,0x414,1,0x1c81,0x844,0x41e,1,0x1c82,0x844,0x421,1,0x1c83, -0x844,0x422,2,0x1c84,0x1c85,0x844,0x42a,1,0x1c86,0x841,0x463,1,0x1c87,0x844,0x462,1, -0x1c87,0x4880,0x20,0x565,0x582,0x810,0x1c60,0x80c,0x1c90,0x10d0,0x80c,0x1c91,0x10d1,0x80c,0x1c92,0x10d2, -0x80c,0x1c93,0x10d3,0x80c,0x1c94,0x10d4,0x80c,0x1c95,0x10d5,0x80c,0x1c96,0x10d6,0x80c,0x1c97,0x10d7,0x80c, -0x1c98,0x10d8,0x80c,0x1c99,0x10d9,0x80c,0x1c9a,0x10da,0x80c,0x1c9b,0x10db,0x80c,0x1c9c,0x10dc,0x80c,0x1c9d, -0x10dd,0x80c,0x1c9e,0x10de,0x80c,0x1c9f,0x10df,0x80c,0x1ca0,0x10e0,0x80c,0x1ca1,0x10e1,0x80c,0x1ca2,0x10e2, -0x80c,0x1ca3,0x10e3,0x80c,0x1ca4,0x10e4,0x80c,0x1ca5,0x10e5,0x80c,0x1ca6,0x10e6,0x80c,0x1ca7,0x10e7,0x80c, -0x1ca8,0x10e8,0x80c,0x1ca9,0x10e9,0x80c,0x1caa,0x10ea,0x80c,0x1cab,0x10eb,0x80c,0x1cac,0x10ec,0x80c,0x1cad, -0x10ed,0x80c,0x1cae,0x10ee,0x80c,0x1caf,0x10ef,0x80c,0x1cb0,0x10f0,0x80c,0x1cb1,0x10f1,0x80c,0x1cb2,0x10f2, -0x80c,0x1cb3,0x10f3,0x80c,0x1cb4,0x10f4,0x80c,0x1cb5,0x10f5,0x80c,0x1cb6,0x10f6,0x80c,0x1cb7,0x10f7,0x80c, -0x1cb8,0x10f8,0x80c,0x1cb9,0x10f9,0x80c,0x1cba,0x10fa,0x80c,0x1cbd,0x10fd,0x80c,0x1cbe,0x10fe,0x80c,0x1cbf, -0x10ff,0xa10,0x97d0,0xa10,8,0x806,0x13f0,0x13f0,0x806,0x13f1,0x13f1,0x806,0x13f2,0x13f2,0x806,0x13f3, -0x13f3,0x806,0x13f4,0x13f4,0x806,0x13f5,0x13f5,0x806,0x432,0x412,0x806,0x434,0x414,0x806,0x43e,0x41e, -0x806,0x441,0x421,0x846,0x442,0x422,1,0x1c85,0x846,0x442,0x422,1,0x1c84,0x806,0x44a,0x42a, -0x806,0x463,0x462,0x806,0xa64b,0xa64a,0xc10,0xbc0,0x810,0x8a04,0x810,0xee6,0x810,0x8a38,0x841,0x1e61, -1,0x1e9b,0x844,0x1e60,1,0x1e9b,0x880,0x2220,0x68,0x331,0x48,0x331,0x48,0x331,0x880,0x2220, -0x74,0x308,0x54,0x308,0x54,0x308,0x880,0x2220,0x77,0x30a,0x57,0x30a,0x57,0x30a,0x880,0x2220, -0x79,0x30a,0x59,0x30a,0x59,0x30a,0x880,0x2220,0x61,0x2be,0x41,0x2be,0x41,0x2be,0x806,0x1e61, -0x1e60,0xc90,0x1dbf,0x20,0x73,0x73,0x880,0x2220,0x3c5,0x313,0x3a5,0x313,0x3a5,0x313,0x880,0x3330, -0x3c5,0x313,0x300,0x3a5,0x313,0x300,0x3a5,0x313,0x300,0x880,0x3330,0x3c5,0x313,0x301,0x3a5,0x313, -0x301,0x3a5,0x313,0x301,0x880,0x3330,0x3c5,0x313,0x342,0x3a5,0x313,0x342,0x3a5,0x313,0x342,0x890, -8,0x220,0x1f00,0x3b9,0x1f08,0x399,0x890,8,0x220,0x1f01,0x3b9,0x1f09,0x399,0x890,8,0x220, -0x1f02,0x3b9,0x1f0a,0x399,0x890,8,0x220,0x1f03,0x3b9,0x1f0b,0x399,0x890,8,0x220,0x1f04,0x3b9, -0x1f0c,0x399,0x890,8,0x220,0x1f05,0x3b9,0x1f0d,0x399,0x890,8,0x220,0x1f06,0x3b9,0x1f0e,0x399, -0x890,8,0x220,0x1f07,0x3b9,0x1f0f,0x399,0xc90,8,0x220,0x1f00,0x3b9,0x1f08,0x399,0xc90,8, -0x220,0x1f01,0x3b9,0x1f09,0x399,0xc90,8,0x220,0x1f02,0x3b9,0x1f0a,0x399,0xc90,8,0x220,0x1f03, -0x3b9,0x1f0b,0x399,0xc90,8,0x220,0x1f04,0x3b9,0x1f0c,0x399,0xc90,8,0x220,0x1f05,0x3b9,0x1f0d, -0x399,0xc90,8,0x220,0x1f06,0x3b9,0x1f0e,0x399,0xc90,8,0x220,0x1f07,0x3b9,0x1f0f,0x399,0x890, -8,0x220,0x1f20,0x3b9,0x1f28,0x399,0x890,8,0x220,0x1f21,0x3b9,0x1f29,0x399,0x890,8,0x220, -0x1f22,0x3b9,0x1f2a,0x399,0x890,8,0x220,0x1f23,0x3b9,0x1f2b,0x399,0x890,8,0x220,0x1f24,0x3b9, -0x1f2c,0x399,0x890,8,0x220,0x1f25,0x3b9,0x1f2d,0x399,0x890,8,0x220,0x1f26,0x3b9,0x1f2e,0x399, -0x890,8,0x220,0x1f27,0x3b9,0x1f2f,0x399,0xc90,8,0x220,0x1f20,0x3b9,0x1f28,0x399,0xc90,8, -0x220,0x1f21,0x3b9,0x1f29,0x399,0xc90,8,0x220,0x1f22,0x3b9,0x1f2a,0x399,0xc90,8,0x220,0x1f23, -0x3b9,0x1f2b,0x399,0xc90,8,0x220,0x1f24,0x3b9,0x1f2c,0x399,0xc90,8,0x220,0x1f25,0x3b9,0x1f2d, -0x399,0xc90,8,0x220,0x1f26,0x3b9,0x1f2e,0x399,0xc90,8,0x220,0x1f27,0x3b9,0x1f2f,0x399,0x890, -8,0x220,0x1f60,0x3b9,0x1f68,0x399,0x890,8,0x220,0x1f61,0x3b9,0x1f69,0x399,0x890,8,0x220, -0x1f62,0x3b9,0x1f6a,0x399,0x890,8,0x220,0x1f63,0x3b9,0x1f6b,0x399,0x890,8,0x220,0x1f64,0x3b9, -0x1f6c,0x399,0x890,8,0x220,0x1f65,0x3b9,0x1f6d,0x399,0x890,8,0x220,0x1f66,0x3b9,0x1f6e,0x399, -0x890,8,0x220,0x1f67,0x3b9,0x1f6f,0x399,0xc90,8,0x220,0x1f60,0x3b9,0x1f68,0x399,0xc90,8, -0x220,0x1f61,0x3b9,0x1f69,0x399,0xc90,8,0x220,0x1f62,0x3b9,0x1f6a,0x399,0xc90,8,0x220,0x1f63, -0x3b9,0x1f6b,0x399,0xc90,8,0x220,0x1f64,0x3b9,0x1f6c,0x399,0xc90,8,0x220,0x1f65,0x3b9,0x1f6d, -0x399,0xc90,8,0x220,0x1f66,0x3b9,0x1f6e,0x399,0xc90,8,0x220,0x1f67,0x3b9,0x1f6f,0x399,0x880, -0x2220,0x1f70,0x3b9,0x1fba,0x399,0x1fba,0x345,0x890,9,0x220,0x3b1,0x3b9,0x391,0x399,0x880,0x2220, -0x3ac,0x3b9,0x386,0x399,0x386,0x345,0x880,0x2220,0x3b1,0x342,0x391,0x342,0x391,0x342,0x880,0x3330, -0x3b1,0x342,0x3b9,0x391,0x342,0x399,0x391,0x342,0x345,0xc90,9,0x220,0x3b1,0x3b9,0x391,0x399, -0x846,0x3b9,0x399,1,0x345,0x880,0x2220,0x1f74,0x3b9,0x1fca,0x399,0x1fca,0x345,0x890,9,0x220, -0x3b7,0x3b9,0x397,0x399,0x880,0x2220,0x3ae,0x3b9,0x389,0x399,0x389,0x345,0x880,0x2220,0x3b7,0x342, -0x397,0x342,0x397,0x342,0x880,0x3330,0x3b7,0x342,0x3b9,0x397,0x342,0x399,0x397,0x342,0x345,0xc90, -9,0x220,0x3b7,0x3b9,0x397,0x399,0x880,0x3330,0x3b9,0x308,0x300,0x399,0x308,0x300,0x399,0x308, -0x300,0x882,0x390,0x3330,0x3b9,0x308,0x301,0x399,0x308,0x301,0x399,0x308,0x301,0x880,0x2220,0x3b9, -0x342,0x399,0x342,0x399,0x342,0x880,0x3330,0x3b9,0x308,0x342,0x399,0x308,0x342,0x399,0x308,0x342, -0x880,0x3330,0x3c5,0x308,0x300,0x3a5,0x308,0x300,0x3a5,0x308,0x300,0x882,0x3b0,0x3330,0x3c5,0x308, -0x301,0x3a5,0x308,0x301,0x3a5,0x308,0x301,0x880,0x2220,0x3c1,0x313,0x3a1,0x313,0x3a1,0x313,0x880, -0x2220,0x3c5,0x342,0x3a5,0x342,0x3a5,0x342,0x880,0x3330,0x3c5,0x308,0x342,0x3a5,0x308,0x342,0x3a5, -0x308,0x342,0x880,0x2220,0x1f7c,0x3b9,0x1ffa,0x399,0x1ffa,0x345,0x890,9,0x220,0x3c9,0x3b9,0x3a9, -0x399,0x880,0x2220,0x3ce,0x3b9,0x38f,0x399,0x38f,0x345,0x880,0x2220,0x3c9,0x342,0x3a9,0x342,0x3a9, -0x342,0x880,0x3330,0x3c9,0x342,0x3b9,0x3a9,0x342,0x399,0x3a9,0x342,0x345,0xc90,9,0x220,0x3c9, -0x3b9,0x3a9,0x399,0xc50,0x1d5d,1,0x3a9,0xc50,0x20bf,1,0x4b,0xc50,0x2046,1,0xc5,0xc10, -0x29f7,0xc10,0xee6,0xc10,0x29e7,0xc10,0x2a2b,0xc10,0x2a28,0xc10,0x2a1c,0xc10,0x29fd,0xc10,0x2a1f,0xc10, -0x2a1e,0xc10,0x2a3f,0xc10,0x1c60,0x841,0xa64b,1,0x1c88,0x844,0xa64a,1,0x1c88,0xc10,0x8a04,0xc10, -0xa528,0xc10,0xa544,0xc10,0xa54f,0xc10,0xa54b,0xc10,0xa541,0xc10,0xa512,0xc10,0xa52a,0xc10,0xa515,0x810, -0x3a0,0xc10,0xa543,0xc10,0x8a38,0xc10,0x3a0,0x806,0x13a0,0x13a0,0x806,0x13a1,0x13a1,0x806,0x13a2,0x13a2, -0x806,0x13a3,0x13a3,0x806,0x13a4,0x13a4,0x806,0x13a5,0x13a5,0x806,0x13a6,0x13a6,0x806,0x13a7,0x13a7,0x806, -0x13a8,0x13a8,0x806,0x13a9,0x13a9,0x806,0x13aa,0x13aa,0x806,0x13ab,0x13ab,0x806,0x13ac,0x13ac,0x806,0x13ad, -0x13ad,0x806,0x13ae,0x13ae,0x806,0x13af,0x13af,0x806,0x13b0,0x13b0,0x806,0x13b1,0x13b1,0x806,0x13b2,0x13b2, -0x806,0x13b3,0x13b3,0x806,0x13b4,0x13b4,0x806,0x13b5,0x13b5,0x806,0x13b6,0x13b6,0x806,0x13b7,0x13b7,0x806, -0x13b8,0x13b8,0x806,0x13b9,0x13b9,0x806,0x13ba,0x13ba,0x806,0x13bb,0x13bb,0x806,0x13bc,0x13bc,0x806,0x13bd, -0x13bd,0x806,0x13be,0x13be,0x806,0x13bf,0x13bf,0x806,0x13c0,0x13c0,0x806,0x13c1,0x13c1,0x806,0x13c2,0x13c2, -0x806,0x13c3,0x13c3,0x806,0x13c4,0x13c4,0x806,0x13c5,0x13c5,0x806,0x13c6,0x13c6,0x806,0x13c7,0x13c7,0x806, -0x13c8,0x13c8,0x806,0x13c9,0x13c9,0x806,0x13ca,0x13ca,0x806,0x13cb,0x13cb,0x806,0x13cc,0x13cc,0x806,0x13cd, -0x13cd,0x806,0x13ce,0x13ce,0x806,0x13cf,0x13cf,0x806,0x13d0,0x13d0,0x806,0x13d1,0x13d1,0x806,0x13d2,0x13d2, -0x806,0x13d3,0x13d3,0x806,0x13d4,0x13d4,0x806,0x13d5,0x13d5,0x806,0x13d6,0x13d6,0x806,0x13d7,0x13d7,0x806, -0x13d8,0x13d8,0x806,0x13d9,0x13d9,0x806,0x13da,0x13da,0x806,0x13db,0x13db,0x806,0x13dc,0x13dc,0x806,0x13dd, -0x13dd,0x806,0x13de,0x13de,0x806,0x13df,0x13df,0x806,0x13e0,0x13e0,0x806,0x13e1,0x13e1,0x806,0x13e2,0x13e2, -0x806,0x13e3,0x13e3,0x806,0x13e4,0x13e4,0x806,0x13e5,0x13e5,0x806,0x13e6,0x13e6,0x806,0x13e7,0x13e7,0x806, -0x13e8,0x13e8,0x806,0x13e9,0x13e9,0x806,0x13ea,0x13ea,0x806,0x13eb,0x13eb,0x806,0x13ec,0x13ec,0x806,0x13ed, -0x13ed,0x806,0x13ee,0x13ee,0x806,0x13ef,0x13ef,0x880,0x2220,0x66,0x66,0x46,0x46,0x46,0x66,0x880, -0x2220,0x66,0x69,0x46,0x49,0x46,0x69,0x880,0x2220,0x66,0x6c,0x46,0x4c,0x46,0x6c,0x880, -0x3330,0x66,0x66,0x69,0x46,0x46,0x49,0x46,0x66,0x69,0x880,0x3330,0x66,0x66,0x6c,0x46, -0x46,0x4c,0x46,0x66,0x6c,0x882,0xfb06,0x2220,0x73,0x74,0x53,0x54,0x53,0x74,0x8c0,1, -0x2220,0x73,0x74,0x53,0x54,0x53,0x74,0xfb05,0x880,0x2220,0x574,0x576,0x544,0x546,0x544,0x576, -0x880,0x2220,0x574,0x565,0x544,0x535,0x544,0x565,0x880,0x2220,0x574,0x56b,0x544,0x53b,0x544,0x56b, -0x880,0x2220,0x57e,0x576,0x54e,0x546,0x54e,0x576,0x880,0x2220,0x574,0x56d,0x544,0x53d,0x544,0x56d +0x6e,0x2bc,0x4e,0x2bc,0x4e,0x806,0x73,0x53,0x810,0xa641,0x809,0x1c6,0x1c5,0x80d,0x1c6,0x1c4, +0x1c5,0x80c,0x1c4,0x1c5,0x809,0x1c9,0x1c8,0x80d,0x1c9,0x1c7,0x1c8,0x80c,0x1c7,0x1c8,0x809,0x1cc, +0x1cb,0x80d,0x1cc,0x1ca,0x1cb,0x80c,0x1ca,0x1cb,0x880,0x2220,0x6a,0x30c,0x4a,0x30c,0x4a,0x30c, +0x809,0x1f3,0x1f2,0x80d,0x1f3,0x1f1,0x1f2,0x80c,0x1f1,0x1f2,0x810,0x2a2b,0x810,0x2a28,0x810,0x2a3f, +0x810,0x2a1f,0x810,0x2a1c,0x810,0x2a1e,0x810,0xa54f,0x810,0xa54b,0x810,0xa567,0x810,0xa528,0x810,0xa544, +0x810,0x29f7,0x810,0xa541,0x810,0x29fd,0x810,0x29e7,0x810,0xa543,0x810,0xa52a,0x1810,0xa515,0x810,0xa512, +0x6800,0x3846,0x3b9,0x399,1,0x1fbe,0x8c0,1,0x3330,0x3b9,0x308,0x301,0x399,0x308,0x301,0x399, +0x308,0x301,0x1fd3,0x841,0x3b2,1,0x3d0,0x841,0x3b5,1,0x3f5,0x841,0x3b8,2,0x3d1,0x3f4, +0x841,0x3b9,2,0x345,0x1fbe,0x841,0x3ba,1,0x3f0,0x841,0x3bc,1,0xb5,0x841,0x3c0,1, +0x3d6,0x841,0x3c1,1,0x3f1,0x4850,0x20,1,0x3c2,0x841,0x3c6,1,0x3d5,0x841,0x3c9,1, +0x2126,0x8c0,1,0x3330,0x3c5,0x308,0x301,0x3a5,0x308,0x301,0x3a5,0x308,0x301,0x1fe3,0x844,0x392, +1,0x3d0,0x844,0x395,1,0x3f5,0x844,0x398,2,0x3d1,0x3f4,0x844,0x399,2,0x345,0x1fbe, +0x844,0x39a,1,0x3f0,0x844,0x39c,1,0xb5,0x844,0x3a0,1,0x3d6,0x844,0x3a1,1,0x3f1, +0x806,0x3c3,0x3a3,0x844,0x3a3,1,0x3c2,0x844,0x3a6,1,0x3d5,0x844,0x3a9,1,0x2126,0x806, +0x3b2,0x392,0x846,0x3b8,0x398,1,0x3f4,0x806,0x3c6,0x3a6,0x806,0x3c0,0x3a0,0x806,0x3ba,0x39a, +0x806,0x3c1,0x3a1,0x841,0x3b8,2,0x398,0x3d1,0x806,0x3b5,0x395,0x841,0x432,1,0x1c80,0x841, +0x434,1,0x1c81,0x841,0x43e,1,0x1c82,0x841,0x441,1,0x1c83,0x841,0x442,2,0x1c84,0x1c85, +0x841,0x44a,1,0x1c86,0x844,0x412,1,0x1c80,0x844,0x414,1,0x1c81,0x844,0x41e,1,0x1c82, +0x844,0x421,1,0x1c83,0x844,0x422,2,0x1c84,0x1c85,0x844,0x42a,1,0x1c86,0x841,0x463,1, +0x1c87,0x844,0x462,1,0x1c87,0x4880,0x20,0x565,0x582,0x810,0x1c60,0x80c,0x1c90,0x10d0,0x80c,0x1c91, +0x10d1,0x80c,0x1c92,0x10d2,0x80c,0x1c93,0x10d3,0x80c,0x1c94,0x10d4,0x80c,0x1c95,0x10d5,0x80c,0x1c96,0x10d6, +0x80c,0x1c97,0x10d7,0x80c,0x1c98,0x10d8,0x80c,0x1c99,0x10d9,0x80c,0x1c9a,0x10da,0x80c,0x1c9b,0x10db,0x80c, +0x1c9c,0x10dc,0x80c,0x1c9d,0x10dd,0x80c,0x1c9e,0x10de,0x80c,0x1c9f,0x10df,0x80c,0x1ca0,0x10e0,0x80c,0x1ca1, +0x10e1,0x80c,0x1ca2,0x10e2,0x80c,0x1ca3,0x10e3,0x80c,0x1ca4,0x10e4,0x80c,0x1ca5,0x10e5,0x80c,0x1ca6,0x10e6, +0x80c,0x1ca7,0x10e7,0x80c,0x1ca8,0x10e8,0x80c,0x1ca9,0x10e9,0x80c,0x1caa,0x10ea,0x80c,0x1cab,0x10eb,0x80c, +0x1cac,0x10ec,0x80c,0x1cad,0x10ed,0x80c,0x1cae,0x10ee,0x80c,0x1caf,0x10ef,0x80c,0x1cb0,0x10f0,0x80c,0x1cb1, +0x10f1,0x80c,0x1cb2,0x10f2,0x80c,0x1cb3,0x10f3,0x80c,0x1cb4,0x10f4,0x80c,0x1cb5,0x10f5,0x80c,0x1cb6,0x10f6, +0x80c,0x1cb7,0x10f7,0x80c,0x1cb8,0x10f8,0x80c,0x1cb9,0x10f9,0x80c,0x1cba,0x10fa,0x80c,0x1cbd,0x10fd,0x80c, +0x1cbe,0x10fe,0x80c,0x1cbf,0x10ff,0xa10,0x97d0,0xa10,8,0x806,0x13f0,0x13f0,0x806,0x13f1,0x13f1,0x806, +0x13f2,0x13f2,0x806,0x13f3,0x13f3,0x806,0x13f4,0x13f4,0x806,0x13f5,0x13f5,0x806,0x432,0x412,0x806,0x434, +0x414,0x806,0x43e,0x41e,0x806,0x441,0x421,0x846,0x442,0x422,1,0x1c85,0x846,0x442,0x422,1, +0x1c84,0x806,0x44a,0x42a,0x806,0x463,0x462,0x806,0xa64b,0xa64a,0xc10,0xbc0,0x810,0x8a04,0x810,0xee6, +0x810,0x8a38,0x841,0x1e61,1,0x1e9b,0x844,0x1e60,1,0x1e9b,0x880,0x2220,0x68,0x331,0x48,0x331, +0x48,0x331,0x880,0x2220,0x74,0x308,0x54,0x308,0x54,0x308,0x880,0x2220,0x77,0x30a,0x57,0x30a, +0x57,0x30a,0x880,0x2220,0x79,0x30a,0x59,0x30a,0x59,0x30a,0x880,0x2220,0x61,0x2be,0x41,0x2be, +0x41,0x2be,0x806,0x1e61,0x1e60,0xc90,0x1dbf,0x20,0x73,0x73,0x880,0x2220,0x3c5,0x313,0x3a5,0x313, +0x3a5,0x313,0x880,0x3330,0x3c5,0x313,0x300,0x3a5,0x313,0x300,0x3a5,0x313,0x300,0x880,0x3330,0x3c5, +0x313,0x301,0x3a5,0x313,0x301,0x3a5,0x313,0x301,0x880,0x3330,0x3c5,0x313,0x342,0x3a5,0x313,0x342, +0x3a5,0x313,0x342,0x890,8,0x220,0x1f00,0x3b9,0x1f08,0x399,0x890,8,0x220,0x1f01,0x3b9,0x1f09, +0x399,0x890,8,0x220,0x1f02,0x3b9,0x1f0a,0x399,0x890,8,0x220,0x1f03,0x3b9,0x1f0b,0x399,0x890, +8,0x220,0x1f04,0x3b9,0x1f0c,0x399,0x890,8,0x220,0x1f05,0x3b9,0x1f0d,0x399,0x890,8,0x220, +0x1f06,0x3b9,0x1f0e,0x399,0x890,8,0x220,0x1f07,0x3b9,0x1f0f,0x399,0xc90,8,0x220,0x1f00,0x3b9, +0x1f08,0x399,0xc90,8,0x220,0x1f01,0x3b9,0x1f09,0x399,0xc90,8,0x220,0x1f02,0x3b9,0x1f0a,0x399, +0xc90,8,0x220,0x1f03,0x3b9,0x1f0b,0x399,0xc90,8,0x220,0x1f04,0x3b9,0x1f0c,0x399,0xc90,8, +0x220,0x1f05,0x3b9,0x1f0d,0x399,0xc90,8,0x220,0x1f06,0x3b9,0x1f0e,0x399,0xc90,8,0x220,0x1f07, +0x3b9,0x1f0f,0x399,0x890,8,0x220,0x1f20,0x3b9,0x1f28,0x399,0x890,8,0x220,0x1f21,0x3b9,0x1f29, +0x399,0x890,8,0x220,0x1f22,0x3b9,0x1f2a,0x399,0x890,8,0x220,0x1f23,0x3b9,0x1f2b,0x399,0x890, +8,0x220,0x1f24,0x3b9,0x1f2c,0x399,0x890,8,0x220,0x1f25,0x3b9,0x1f2d,0x399,0x890,8,0x220, +0x1f26,0x3b9,0x1f2e,0x399,0x890,8,0x220,0x1f27,0x3b9,0x1f2f,0x399,0xc90,8,0x220,0x1f20,0x3b9, +0x1f28,0x399,0xc90,8,0x220,0x1f21,0x3b9,0x1f29,0x399,0xc90,8,0x220,0x1f22,0x3b9,0x1f2a,0x399, +0xc90,8,0x220,0x1f23,0x3b9,0x1f2b,0x399,0xc90,8,0x220,0x1f24,0x3b9,0x1f2c,0x399,0xc90,8, +0x220,0x1f25,0x3b9,0x1f2d,0x399,0xc90,8,0x220,0x1f26,0x3b9,0x1f2e,0x399,0xc90,8,0x220,0x1f27, +0x3b9,0x1f2f,0x399,0x890,8,0x220,0x1f60,0x3b9,0x1f68,0x399,0x890,8,0x220,0x1f61,0x3b9,0x1f69, +0x399,0x890,8,0x220,0x1f62,0x3b9,0x1f6a,0x399,0x890,8,0x220,0x1f63,0x3b9,0x1f6b,0x399,0x890, +8,0x220,0x1f64,0x3b9,0x1f6c,0x399,0x890,8,0x220,0x1f65,0x3b9,0x1f6d,0x399,0x890,8,0x220, +0x1f66,0x3b9,0x1f6e,0x399,0x890,8,0x220,0x1f67,0x3b9,0x1f6f,0x399,0xc90,8,0x220,0x1f60,0x3b9, +0x1f68,0x399,0xc90,8,0x220,0x1f61,0x3b9,0x1f69,0x399,0xc90,8,0x220,0x1f62,0x3b9,0x1f6a,0x399, +0xc90,8,0x220,0x1f63,0x3b9,0x1f6b,0x399,0xc90,8,0x220,0x1f64,0x3b9,0x1f6c,0x399,0xc90,8, +0x220,0x1f65,0x3b9,0x1f6d,0x399,0xc90,8,0x220,0x1f66,0x3b9,0x1f6e,0x399,0xc90,8,0x220,0x1f67, +0x3b9,0x1f6f,0x399,0x880,0x2220,0x1f70,0x3b9,0x1fba,0x399,0x1fba,0x345,0x890,9,0x220,0x3b1,0x3b9, +0x391,0x399,0x880,0x2220,0x3ac,0x3b9,0x386,0x399,0x386,0x345,0x880,0x2220,0x3b1,0x342,0x391,0x342, +0x391,0x342,0x880,0x3330,0x3b1,0x342,0x3b9,0x391,0x342,0x399,0x391,0x342,0x345,0xc90,9,0x220, +0x3b1,0x3b9,0x391,0x399,0x846,0x3b9,0x399,1,0x345,0x880,0x2220,0x1f74,0x3b9,0x1fca,0x399,0x1fca, +0x345,0x890,9,0x220,0x3b7,0x3b9,0x397,0x399,0x880,0x2220,0x3ae,0x3b9,0x389,0x399,0x389,0x345, +0x880,0x2220,0x3b7,0x342,0x397,0x342,0x397,0x342,0x880,0x3330,0x3b7,0x342,0x3b9,0x397,0x342,0x399, +0x397,0x342,0x345,0xc90,9,0x220,0x3b7,0x3b9,0x397,0x399,0x880,0x3330,0x3b9,0x308,0x300,0x399, +0x308,0x300,0x399,0x308,0x300,0x882,0x390,0x3330,0x3b9,0x308,0x301,0x399,0x308,0x301,0x399,0x308, +0x301,0x880,0x2220,0x3b9,0x342,0x399,0x342,0x399,0x342,0x880,0x3330,0x3b9,0x308,0x342,0x399,0x308, +0x342,0x399,0x308,0x342,0x880,0x3330,0x3c5,0x308,0x300,0x3a5,0x308,0x300,0x3a5,0x308,0x300,0x882, +0x3b0,0x3330,0x3c5,0x308,0x301,0x3a5,0x308,0x301,0x3a5,0x308,0x301,0x880,0x2220,0x3c1,0x313,0x3a1, +0x313,0x3a1,0x313,0x880,0x2220,0x3c5,0x342,0x3a5,0x342,0x3a5,0x342,0x880,0x3330,0x3c5,0x308,0x342, +0x3a5,0x308,0x342,0x3a5,0x308,0x342,0x880,0x2220,0x1f7c,0x3b9,0x1ffa,0x399,0x1ffa,0x345,0x890,9, +0x220,0x3c9,0x3b9,0x3a9,0x399,0x880,0x2220,0x3ce,0x3b9,0x38f,0x399,0x38f,0x345,0x880,0x2220,0x3c9, +0x342,0x3a9,0x342,0x3a9,0x342,0x880,0x3330,0x3c9,0x342,0x3b9,0x3a9,0x342,0x399,0x3a9,0x342,0x345, +0xc90,9,0x220,0x3c9,0x3b9,0x3a9,0x399,0xc50,0x1d5d,1,0x3a9,0xc50,0x20bf,1,0x4b,0xc50, +0x2046,1,0xc5,0xc10,0x29f7,0xc10,0xee6,0xc10,0x29e7,0xc10,0x2a2b,0xc10,0x2a28,0xc10,0x2a1c,0xc10, +0x29fd,0xc10,0x2a1f,0xc10,0x2a1e,0xc10,0x2a3f,0xc10,0x1c60,0x841,0xa64b,1,0x1c88,0x844,0xa64a,1, +0x1c88,0xc10,0x8a04,0xc10,0xa528,0xc10,0xa544,0xc10,0xa54f,0xc10,0xa54b,0xc10,0xa541,0xc10,0xa512,0xc10, +0xa52a,0xc10,0xa515,0x810,0x3a0,0xc10,0xa543,0xc10,0x8a38,0xc10,0xa567,0xc10,0xa641,0xc10,0x3a0,0x806, +0x13a0,0x13a0,0x806,0x13a1,0x13a1,0x806,0x13a2,0x13a2,0x806,0x13a3,0x13a3,0x806,0x13a4,0x13a4,0x806,0x13a5, +0x13a5,0x806,0x13a6,0x13a6,0x806,0x13a7,0x13a7,0x806,0x13a8,0x13a8,0x806,0x13a9,0x13a9,0x806,0x13aa,0x13aa, +0x806,0x13ab,0x13ab,0x806,0x13ac,0x13ac,0x806,0x13ad,0x13ad,0x806,0x13ae,0x13ae,0x806,0x13af,0x13af,0x806, +0x13b0,0x13b0,0x806,0x13b1,0x13b1,0x806,0x13b2,0x13b2,0x806,0x13b3,0x13b3,0x806,0x13b4,0x13b4,0x806,0x13b5, +0x13b5,0x806,0x13b6,0x13b6,0x806,0x13b7,0x13b7,0x806,0x13b8,0x13b8,0x806,0x13b9,0x13b9,0x806,0x13ba,0x13ba, +0x806,0x13bb,0x13bb,0x806,0x13bc,0x13bc,0x806,0x13bd,0x13bd,0x806,0x13be,0x13be,0x806,0x13bf,0x13bf,0x806, +0x13c0,0x13c0,0x806,0x13c1,0x13c1,0x806,0x13c2,0x13c2,0x806,0x13c3,0x13c3,0x806,0x13c4,0x13c4,0x806,0x13c5, +0x13c5,0x806,0x13c6,0x13c6,0x806,0x13c7,0x13c7,0x806,0x13c8,0x13c8,0x806,0x13c9,0x13c9,0x806,0x13ca,0x13ca, +0x806,0x13cb,0x13cb,0x806,0x13cc,0x13cc,0x806,0x13cd,0x13cd,0x806,0x13ce,0x13ce,0x806,0x13cf,0x13cf,0x806, +0x13d0,0x13d0,0x806,0x13d1,0x13d1,0x806,0x13d2,0x13d2,0x806,0x13d3,0x13d3,0x806,0x13d4,0x13d4,0x806,0x13d5, +0x13d5,0x806,0x13d6,0x13d6,0x806,0x13d7,0x13d7,0x806,0x13d8,0x13d8,0x806,0x13d9,0x13d9,0x806,0x13da,0x13da, +0x806,0x13db,0x13db,0x806,0x13dc,0x13dc,0x806,0x13dd,0x13dd,0x806,0x13de,0x13de,0x806,0x13df,0x13df,0x806, +0x13e0,0x13e0,0x806,0x13e1,0x13e1,0x806,0x13e2,0x13e2,0x806,0x13e3,0x13e3,0x806,0x13e4,0x13e4,0x806,0x13e5, +0x13e5,0x806,0x13e6,0x13e6,0x806,0x13e7,0x13e7,0x806,0x13e8,0x13e8,0x806,0x13e9,0x13e9,0x806,0x13ea,0x13ea, +0x806,0x13eb,0x13eb,0x806,0x13ec,0x13ec,0x806,0x13ed,0x13ed,0x806,0x13ee,0x13ee,0x806,0x13ef,0x13ef,0x880, +0x2220,0x66,0x66,0x46,0x46,0x46,0x66,0x880,0x2220,0x66,0x69,0x46,0x49,0x46,0x69,0x880, +0x2220,0x66,0x6c,0x46,0x4c,0x46,0x6c,0x880,0x3330,0x66,0x66,0x69,0x46,0x46,0x49,0x46, +0x66,0x69,0x880,0x3330,0x66,0x66,0x6c,0x46,0x46,0x4c,0x46,0x66,0x6c,0x882,0xfb06,0x2220, +0x73,0x74,0x53,0x54,0x53,0x74,0x8c0,1,0x2220,0x73,0x74,0x53,0x54,0x53,0x74,0xfb05, +0x880,0x2220,0x574,0x576,0x544,0x546,0x544,0x576,0x880,0x2220,0x574,0x565,0x544,0x535,0x544,0x565, +0x880,0x2220,0x574,0x56b,0x544,0x53b,0x544,0x56b,0x880,0x2220,0x57e,0x576,0x54e,0x546,0x54e,0x576, +0x880,0x2220,0x574,0x56d,0x544,0x53d,0x544,0x56d }; static const uint16_t ucase_props_unfold[370]={ @@ -979,16 +994,16 @@ static const UCaseProps ucase_props_singleton={ ucase_props_unfold, { ucase_props_trieIndex, - ucase_props_trieIndex+3412, + ucase_props_trieIndex+3468, nullptr, - 3412, - 9736, + 3468, + 9904, 0x188, - 0xdd0, + 0xe08, 0x0, 0x0, 0xe0800, - 0x3358, + 0x3438, nullptr, 0, false, false, 0, nullptr }, { 4,0,0,0 } diff --git a/thirdparty/icu4c/common/ucasemap.cpp b/thirdparty/icu4c/common/ucasemap.cpp index f419f65c32..928c524215 100644 --- a/thirdparty/icu4c/common/ucasemap.cpp +++ b/thirdparty/icu4c/common/ucasemap.cpp @@ -160,12 +160,12 @@ appendResult(int32_t cpLength, int32_t result, const char16_t *s, } // See unicode/utf8.h U8_APPEND_UNSAFE(). -inline uint8_t getTwoByteLead(UChar32 c) { return (uint8_t)((c >> 6) | 0xc0); } -inline uint8_t getTwoByteTrail(UChar32 c) { return (uint8_t)((c & 0x3f) | 0x80); } +inline uint8_t getTwoByteLead(UChar32 c) { return static_cast<uint8_t>((c >> 6) | 0xc0); } +inline uint8_t getTwoByteTrail(UChar32 c) { return static_cast<uint8_t>((c & 0x3f) | 0x80); } UChar32 U_CALLCONV utf8_caseContextIterator(void *context, int8_t dir) { - UCaseContext *csc=(UCaseContext *)context; + UCaseContext* csc = static_cast<UCaseContext*>(context); UChar32 c; if(dir<0) { @@ -234,7 +234,7 @@ void toLower(int32_t caseLocale, uint32_t options, if (d == 0) { continue; } ByteSinkUtil::appendUnchanged(src + prev, srcIndex - 1 - prev, sink, options, edits, errorCode); - char ascii = (char)(lead + d); + char ascii = static_cast<char>(lead + d); sink.Append(&ascii, 1); if (edits != nullptr) { edits->addReplace(1, 1); @@ -342,7 +342,7 @@ void toUpper(int32_t caseLocale, uint32_t options, if (d == 0) { continue; } ByteSinkUtil::appendUnchanged(src + prev, srcIndex - 1 - prev, sink, options, edits, errorCode); - char ascii = (char)(lead + d); + char ascii = static_cast<char>(lead + d); sink.Append(&ascii, 1); if (edits != nullptr) { edits->addReplace(1, 1); @@ -747,14 +747,14 @@ void toUpper(uint32_t options, int32_t i2 = i + 2; if ((data & HAS_EITHER_DIALYTIKA) != 0) { change |= (i2 + 2) > nextIndex || - src[i2] != (uint8_t)u8"\u0308"[0] || - src[i2 + 1] != (uint8_t)u8"\u0308"[1]; + src[i2] != static_cast<uint8_t>(u8"\u0308"[0]) || + src[i2 + 1] != static_cast<uint8_t>(u8"\u0308"[1]); i2 += 2; } if (addTonos) { change |= (i2 + 2) > nextIndex || - src[i2] != (uint8_t)u8"\u0301"[0] || - src[i2 + 1] != (uint8_t)u8"\u0301"[1]; + src[i2] != static_cast<uint8_t>(u8"\u0301"[0]) || + src[i2 + 1] != static_cast<uint8_t>(u8"\u0301"[1]); i2 += 2; } int32_t oldLength = nextIndex - i; @@ -867,14 +867,14 @@ ucasemap_mapUTF8(int32_t caseLocale, uint32_t options, UCASEMAP_BREAK_ITERATOR_P // Get the string length. if (srcLength == -1) { - srcLength = (int32_t)uprv_strlen((const char *)src); + srcLength = static_cast<int32_t>(uprv_strlen(src)); } if (edits != nullptr && (options & U_EDITS_NO_RESET) == 0) { edits->reset(); } stringCaseMapper(caseLocale, options, UCASEMAP_BREAK_ITERATOR - (const uint8_t *)src, srcLength, sink, edits, errorCode); + reinterpret_cast<const uint8_t*>(src), srcLength, sink, edits, errorCode); sink.Flush(); if (U_SUCCESS(errorCode)) { if (edits != nullptr) { @@ -904,7 +904,7 @@ ucasemap_mapUTF8(int32_t caseLocale, uint32_t options, UCASEMAP_BREAK_ITERATOR_P /* get the string length */ if(srcLength==-1) { - srcLength=(int32_t)uprv_strlen((const char *)src); + srcLength = static_cast<int32_t>(uprv_strlen(src)); } /* check for overlapping source and destination */ @@ -923,7 +923,7 @@ ucasemap_mapUTF8(int32_t caseLocale, uint32_t options, UCASEMAP_BREAK_ITERATOR_P dest, destCapacity, [&](ByteSink& sink, UErrorCode& status) { stringCaseMapper(caseLocale, options, UCASEMAP_BREAK_ITERATOR - (const uint8_t *)src, srcLength, sink, edits, status); + reinterpret_cast<const uint8_t*>(src), srcLength, sink, edits, status); }, errorCode); if (U_SUCCESS(errorCode) && edits != nullptr) { diff --git a/thirdparty/icu4c/common/ucasemap_titlecase_brkiter.cpp b/thirdparty/icu4c/common/ucasemap_titlecase_brkiter.cpp index c2b44a2c78..ebc952a979 100644 --- a/thirdparty/icu4c/common/ucasemap_titlecase_brkiter.cpp +++ b/thirdparty/icu4c/common/ucasemap_titlecase_brkiter.cpp @@ -107,7 +107,7 @@ ucasemap_utf8ToTitle(UCaseMap *csm, return 0; } UText utext=UTEXT_INITIALIZER; - utext_openUTF8(&utext, (const char *)src, srcLength, pErrorCode); + utext_openUTF8(&utext, src, srcLength, pErrorCode); if (U_FAILURE(*pErrorCode)) { return 0; } diff --git a/thirdparty/icu4c/common/uchar.cpp b/thirdparty/icu4c/common/uchar.cpp index ff12962baa..3b2ae8c8af 100644 --- a/thirdparty/icu4c/common/uchar.cpp +++ b/thirdparty/icu4c/common/uchar.cpp @@ -23,6 +23,7 @@ #include "unicode/utypes.h" #include "unicode/uchar.h" +#include "unicode/ucptrie.h" #include "unicode/uscript.h" #include "unicode/udata.h" #include "uassert.h" @@ -67,9 +68,9 @@ _enumTypeValue(const void *context, uint32_t value) { static UBool U_CALLCONV _enumTypeRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { /* just cast the value to UCharCategory */ - return ((struct _EnumTypeCallback *)context)-> - enumRange(((struct _EnumTypeCallback *)context)->context, - start, end+1, (UCharCategory)value); + return static_cast<const _EnumTypeCallback*>(context)-> + enumRange(static_cast<const _EnumTypeCallback*>(context)->context, + start, end + 1, static_cast<UCharCategory>(value)); } U_CAPI void U_EXPORT2 @@ -90,7 +91,7 @@ U_CAPI UBool U_EXPORT2 u_islower(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)==U_LOWERCASE_LETTER); + return GET_CATEGORY(props)==U_LOWERCASE_LETTER; } /* Checks if ch is an upper case letter.*/ @@ -98,7 +99,7 @@ U_CAPI UBool U_EXPORT2 u_isupper(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)==U_UPPERCASE_LETTER); + return GET_CATEGORY(props)==U_UPPERCASE_LETTER; } /* Checks if ch is a title case letter; usually upper case letters.*/ @@ -106,7 +107,7 @@ U_CAPI UBool U_EXPORT2 u_istitle(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)==U_TITLECASE_LETTER); + return GET_CATEGORY(props)==U_TITLECASE_LETTER; } /* Checks if ch is a decimal digit. */ @@ -114,7 +115,7 @@ U_CAPI UBool U_EXPORT2 u_isdigit(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)==U_DECIMAL_DIGIT_NUMBER); + return GET_CATEGORY(props)==U_DECIMAL_DIGIT_NUMBER; } U_CAPI UBool U_EXPORT2 @@ -130,7 +131,7 @@ u_isxdigit(UChar32 c) { } GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)==U_DECIMAL_DIGIT_NUMBER); + return GET_CATEGORY(props)==U_DECIMAL_DIGIT_NUMBER; } /* Checks if the Unicode character is a letter.*/ @@ -138,7 +139,7 @@ U_CAPI UBool U_EXPORT2 u_isalpha(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&U_GC_L_MASK)!=0); + return (CAT_MASK(props)&U_GC_L_MASK)!=0; } U_CAPI UBool U_EXPORT2 @@ -151,7 +152,7 @@ U_CAPI UBool U_EXPORT2 u_isalnum(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&(U_GC_L_MASK|U_GC_ND_MASK))!=0); + return (CAT_MASK(props)&(U_GC_L_MASK|U_GC_ND_MASK))!=0; } /** @@ -160,7 +161,7 @@ u_isalnum(UChar32 c) { */ U_CFUNC UBool u_isalnumPOSIX(UChar32 c) { - return (UBool)(u_isUAlphabetic(c) || u_isdigit(c)); + return u_isUAlphabetic(c) || u_isdigit(c); } /* Checks if ch is a unicode character with assigned character type.*/ @@ -168,7 +169,7 @@ U_CAPI UBool U_EXPORT2 u_isdefined(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)!=0); + return GET_CATEGORY(props)!=0; } /* Checks if the Unicode character is a base form character that can take a diacritic.*/ @@ -176,7 +177,7 @@ U_CAPI UBool U_EXPORT2 u_isbase(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&(U_GC_L_MASK|U_GC_N_MASK|U_GC_MC_MASK|U_GC_ME_MASK))!=0); + return (CAT_MASK(props)&(U_GC_L_MASK|U_GC_N_MASK|U_GC_MC_MASK|U_GC_ME_MASK))!=0; } /* Checks if the Unicode character is a control character.*/ @@ -184,7 +185,7 @@ U_CAPI UBool U_EXPORT2 u_iscntrl(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&(U_GC_CC_MASK|U_GC_CF_MASK|U_GC_ZL_MASK|U_GC_ZP_MASK))!=0); + return (CAT_MASK(props)&(U_GC_CC_MASK|U_GC_CF_MASK|U_GC_ZL_MASK|U_GC_ZP_MASK))!=0; } U_CAPI UBool U_EXPORT2 @@ -205,14 +206,14 @@ U_CAPI UBool U_EXPORT2 u_isspace(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&U_GC_Z_MASK)!=0 || IS_THAT_CONTROL_SPACE(c)); + return (CAT_MASK(props)&U_GC_Z_MASK)!=0 || IS_THAT_CONTROL_SPACE(c); } U_CAPI UBool U_EXPORT2 u_isJavaSpaceChar(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&U_GC_Z_MASK)!=0); + return (CAT_MASK(props)&U_GC_Z_MASK)!=0; } /* Checks if the Unicode character is a whitespace character.*/ @@ -220,11 +221,9 @@ U_CAPI UBool U_EXPORT2 u_isWhitespace(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)( - ((CAT_MASK(props)&U_GC_Z_MASK)!=0 && - c!=NBSP && c!=FIGURESP && c!=NNBSP) || /* exclude no-break spaces */ - IS_THAT_ASCII_CONTROL_SPACE(c) - ); + return ((CAT_MASK(props)&U_GC_Z_MASK)!=0 && + c!=NBSP && c!=FIGURESP && c!=NNBSP) || /* exclude no-break spaces */ + IS_THAT_ASCII_CONTROL_SPACE(c); } U_CAPI UBool U_EXPORT2 @@ -235,7 +234,7 @@ u_isblank(UChar32 c) { /* Zs */ uint32_t props; GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)==U_SPACE_SEPARATOR); + return GET_CATEGORY(props)==U_SPACE_SEPARATOR; } } @@ -250,7 +249,7 @@ u_isprint(UChar32 c) { uint32_t props; GET_PROPS(c, props); /* comparing ==0 returns false for the categories mentioned */ - return (UBool)((CAT_MASK(props)&U_GC_C_MASK)==0); + return (CAT_MASK(props)&U_GC_C_MASK)==0; } /** @@ -266,7 +265,7 @@ u_isprintPOSIX(UChar32 c) { * The only cntrl character in graph+blank is TAB (in blank). * Here we implement (blank-TAB)=Zs instead of calling u_isblank(). */ - return (UBool)((GET_CATEGORY(props)==U_SPACE_SEPARATOR) || u_isgraphPOSIX(c)); + return (GET_CATEGORY(props)==U_SPACE_SEPARATOR) || u_isgraphPOSIX(c); } U_CAPI UBool U_EXPORT2 @@ -274,9 +273,9 @@ u_isgraph(UChar32 c) { uint32_t props; GET_PROPS(c, props); /* comparing ==0 returns false for the categories mentioned */ - return (UBool)((CAT_MASK(props)& - (U_GC_CC_MASK|U_GC_CF_MASK|U_GC_CS_MASK|U_GC_CN_MASK|U_GC_Z_MASK)) - ==0); + return (CAT_MASK(props)& + (U_GC_CC_MASK|U_GC_CF_MASK|U_GC_CS_MASK|U_GC_CN_MASK|U_GC_Z_MASK)) + ==0; } /** @@ -292,16 +291,16 @@ u_isgraphPOSIX(UChar32 c) { GET_PROPS(c, props); /* \p{space}\p{gc=Control} == \p{gc=Z}\p{Control} */ /* comparing ==0 returns false for the categories mentioned */ - return (UBool)((CAT_MASK(props)& - (U_GC_CC_MASK|U_GC_CS_MASK|U_GC_CN_MASK|U_GC_Z_MASK)) - ==0); + return (CAT_MASK(props)& + (U_GC_CC_MASK|U_GC_CS_MASK|U_GC_CN_MASK|U_GC_Z_MASK)) + ==0; } U_CAPI UBool U_EXPORT2 u_ispunct(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&U_GC_P_MASK)!=0); + return (CAT_MASK(props)&U_GC_P_MASK)!=0; } /*Checks if the Unicode character can be ignorable in a Java or Unicode identifier.*/ @@ -312,7 +311,7 @@ u_isIDIgnorable(UChar32 c) { } else { uint32_t props; GET_PROPS(c, props); - return (UBool)(GET_CATEGORY(props)==U_FORMAT_CHAR); + return GET_CATEGORY(props)==U_FORMAT_CHAR; } } @@ -321,7 +320,7 @@ U_CAPI UBool U_EXPORT2 u_isJavaIDStart(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)((CAT_MASK(props)&(U_GC_L_MASK|U_GC_SC_MASK|U_GC_PC_MASK))!=0); + return (CAT_MASK(props)&(U_GC_L_MASK|U_GC_SC_MASK|U_GC_PC_MASK))!=0; } /*Checks if the Unicode character can be a Java identifier part other than starting the @@ -331,14 +330,13 @@ U_CAPI UBool U_EXPORT2 u_isJavaIDPart(UChar32 c) { uint32_t props; GET_PROPS(c, props); - return (UBool)( - (CAT_MASK(props)& + return (CAT_MASK(props)& (U_GC_ND_MASK|U_GC_NL_MASK| U_GC_L_MASK| U_GC_SC_MASK|U_GC_PC_MASK| U_GC_MC_MASK|U_GC_MN_MASK) )!=0 || - u_isIDIgnorable(c)); + u_isIDIgnorable(c); } U_CAPI int32_t U_EXPORT2 @@ -515,6 +513,8 @@ uprv_getMaxValues(int32_t column) { return indexes[UPROPS_MAX_VALUES_INDEX]; case 2: return indexes[UPROPS_MAX_VALUES_2_INDEX]; + case UPROPS_MAX_VALUES_OTHER_INDEX: + return indexes[column]; default: return 0; } @@ -524,8 +524,8 @@ U_CAPI void U_EXPORT2 u_charAge(UChar32 c, UVersionInfo versionArray) { if(versionArray!=nullptr) { uint32_t version=u_getUnicodeProperties(c, 0)>>UPROPS_AGE_SHIFT; - versionArray[0]=(uint8_t)(version>>4); - versionArray[1]=(uint8_t)(version&0xf); + versionArray[0]=(uint8_t)(version>>2); + versionArray[1]=(uint8_t)(version&3); versionArray[2]=versionArray[3]=0; } } @@ -540,7 +540,7 @@ uscript_getScript(UChar32 c, UErrorCode *pErrorCode) { return USCRIPT_INVALID_CODE; } uint32_t scriptX=u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_X_MASK; - uint32_t codeOrIndex=uprops_mergeScriptCodeOrIndex(scriptX); + uint32_t codeOrIndex=scriptX&UPROPS_MAX_SCRIPT; if(scriptX<UPROPS_SCRIPT_X_WITH_COMMON) { return (UScriptCode)codeOrIndex; } else if(scriptX<UPROPS_SCRIPT_X_WITH_INHERITED) { @@ -555,7 +555,7 @@ uscript_getScript(UChar32 c, UErrorCode *pErrorCode) { U_CAPI UBool U_EXPORT2 uscript_hasScript(UChar32 c, UScriptCode sc) UPRV_NO_SANITIZE_UNDEFINED { uint32_t scriptX=u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_X_MASK; - uint32_t codeOrIndex=uprops_mergeScriptCodeOrIndex(scriptX); + uint32_t codeOrIndex=scriptX&UPROPS_MAX_SCRIPT; if(scriptX<UPROPS_SCRIPT_X_WITH_COMMON) { return sc==(UScriptCode)codeOrIndex; } @@ -587,7 +587,7 @@ uscript_getScriptExtensions(UChar32 c, return 0; } uint32_t scriptX=u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_X_MASK; - uint32_t codeOrIndex=uprops_mergeScriptCodeOrIndex(scriptX); + uint32_t codeOrIndex=scriptX&UPROPS_MAX_SCRIPT; if(scriptX<UPROPS_SCRIPT_X_WITH_COMMON) { if(capacity==0) { *pErrorCode=U_BUFFER_OVERFLOW_ERROR; @@ -618,7 +618,15 @@ uscript_getScriptExtensions(UChar32 c, U_CAPI UBlockCode U_EXPORT2 ublock_getCode(UChar32 c) { - return (UBlockCode)((u_getUnicodeProperties(c, 0)&UPROPS_BLOCK_MASK)>>UPROPS_BLOCK_SHIFT); + // We store Block values indexed by the code point shifted right 4 bits + // and use a "small" UCPTrie=CodePointTrie for minimal data size. + // This works because blocks have xxx0..xxxF ranges. + uint32_t c4 = c; // unsigned so that shifting right does not worry the compiler + // Shift unless out of range, in which case we fetch the trie's error value. + if (c4 <= 0x10ffff) { + c4 >>= 4; + } + return (UBlockCode)ucptrie_get(&block_trie, c4); } /* property starts for UnicodeSet ------------------------------------------- */ @@ -626,7 +634,7 @@ ublock_getCode(UChar32 c) { static UBool U_CALLCONV _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { /* add the start code point to the USet */ - const USetAdder *sa=(const USetAdder *)context; + const USetAdder* sa = static_cast<const USetAdder*>(context); sa->add(sa->set, start); (void)end; (void)value; @@ -706,3 +714,18 @@ upropsvec_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { /* add the start code point of each same-value range of the properties vectors trie */ utrie2_enum(&propsVectorsTrie, nullptr, _enumPropertyStartsRange, sa); } + +U_CFUNC void U_EXPORT2 +ublock_addPropertyStarts(const USetAdder *sa, UErrorCode & /*errorCode*/) { + // Add the start code point of each same-value range of the trie. + // We store Block values indexed by the code point shifted right 4 bits; + // see ublock_getCode(). + UChar32 start = 0, end; + uint32_t value; + while (start < 0x11000 && // limit: (max code point + 1) >> 4 + (end = ucptrie_getRange(&block_trie, start, UCPMAP_RANGE_NORMAL, 0, + nullptr, nullptr, &value)) >= 0) { + sa->add(sa->set, start << 4); + start = end + 1; + } +} diff --git a/thirdparty/icu4c/common/uchar_props_data.h b/thirdparty/icu4c/common/uchar_props_data.h index 0cacf142af..215afd1a52 100644 --- a/thirdparty/icu4c/common/uchar_props_data.h +++ b/thirdparty/icu4c/common/uchar_props_data.h @@ -9,146 +9,146 @@ #ifdef INCLUDED_FROM_UCHAR_C -static const UVersionInfo dataVersion={0xf,1,0,0}; +static const UVersionInfo dataVersion={0x10,0,0,0}; -static const uint16_t propsTrie_index[23156]={ -0x495,0x49d,0x4a5,0x4ad,0x4c5,0x4cd,0x4d5,0x4dd,0x4e5,0x4ed,0x4f3,0x4fb,0x503,0x50b,0x513,0x51b, -0x521,0x529,0x531,0x539,0x53c,0x544,0x54c,0x554,0x55c,0x564,0x560,0x568,0x570,0x578,0x57d,0x585, -0x58d,0x595,0x599,0x5a1,0x5a9,0x5b1,0x5b9,0x5c1,0x5bd,0x5c5,0x5ca,0x5d2,0x5d8,0x5e0,0x5e8,0x5f0, -0x5f8,0x600,0x608,0x610,0x615,0x61d,0x620,0x628,0x630,0x638,0x63e,0x646,0x645,0x64d,0x655,0x65d, -0x66d,0x665,0x675,0x67d,0x683,0x600,0x693,0x68b,0x6a3,0x6a5,0x6ad,0x69b,0x6bd,0x6c3,0x6cb,0x6b5, -0x6db,0x6e1,0x6e9,0x6d3,0x6f9,0x6ff,0x707,0x6f1,0x717,0x71d,0x725,0x70f,0x735,0x73d,0x745,0x72d, -0x755,0x75b,0x763,0x74d,0x773,0x779,0x781,0x76b,0x791,0x796,0x79e,0x789,0x7ae,0x7b5,0x7bd,0x7a6, -0x641,0x7c5,0x7cd,0x4b5,0x7d5,0x7dc,0x7e4,0x4b5,0x7ec,0x7f4,0x7fc,0x801,0x809,0x810,0x818,0x4b5, -0x600,0x820,0x828,0x830,0x838,0x58d,0x848,0x840,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x850,0x600,0x858,0x85c,0x864,0x600,0x86a,0x600,0x870,0x878,0x880,0x58d,0x58d,0x888, -0x890,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x895,0x89d,0x600,0x600,0x8a5,0x8ad,0x8b5,0x8bd,0x8c5,0x600,0x8cd,0x8d5,0x8dd, -0x8ed,0x600,0x8f5,0x8f7,0x8ff,0x8e5,0x600,0x902,0x916,0x90a,0x912,0x91e,0x600,0x926,0x92c,0x934, -0x93c,0x600,0x94c,0x954,0x95c,0x944,0x96c,0x4b5,0x974,0x977,0x97f,0x964,0x98f,0x987,0x600,0x996, -0x600,0x9a5,0x99e,0x9ad,0x9b5,0x9b9,0x9c1,0x9c9,0x535,0x9d1,0x9d4,0x9da,0x9e1,0x9d4,0x55c,0x55c, -0x4e5,0x4e5,0x4e5,0x4e5,0x9e9,0x4e5,0x4e5,0x4e5,0x9f9,0xa01,0xa09,0xa11,0xa19,0xa1d,0xa25,0x9f1, -0xa3d,0xa45,0xa2d,0xa35,0xa4d,0xa55,0xa5d,0xa65,0xa7d,0xa6d,0xa75,0xa85,0xa8d,0xa9c,0xaa1,0xa94, -0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0xab1,0xab9,0x934,0xabc,0xac4,0xacb,0xad0,0xad8, -0x934,0xadf,0xade,0xaef,0xaf2,0x934,0x934,0xae7,0x934,0x934,0x934,0x934,0x934,0xb01,0xb09,0xaf9, -0x934,0x934,0x934,0xb0e,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0xb14,0xb1c,0x934,0xb24,0xb2b, -0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0xaa9,0xaa9,0xaa9,0xaa9,0xb33,0xaa9,0xb3a,0xb41, -0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0xaa9,0x934,0xb49,0xb50,0xb54,0xb5a,0x934,0x934,0x934, -0x58d,0x595,0x535,0xb62,0x4e5,0x4e5,0x4e5,0xb6a,0x535,0xb72,0x600,0xb78,0xb88,0xb80,0xb80,0x55c, -0xb90,0xb98,0xba0,0x4b5,0xba8,0x934,0x934,0xbaf,0x934,0x934,0x934,0x934,0x934,0x934,0xbb7,0xbbd, -0xbcd,0xbc5,0x641,0x600,0xbd5,0x890,0x600,0xbdd,0xbe5,0xbe9,0x600,0x600,0xbee,0x600,0x934,0xbf5, -0xad9,0xbfd,0xc03,0x934,0xbfd,0xc0b,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934, -0xc13,0x600,0x600,0x600,0xc1b,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0xc21,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc26,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x934,0x934, -0xc2e,0xc35,0xc37,0x600,0xc3f,0xc45,0xc4d,0xc55,0xc5a,0x600,0x600,0xc5e,0x600,0x600,0x600,0xc64, -0xc6b,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc72,0x600,0xc79,0xc7f,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc87,0x600,0x600,0x600,0xc8f,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0xc91,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc98,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0xc9f,0x600,0x600,0x600,0xca6,0xcae,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0xcb3,0xcb8,0x600,0x600,0xcc0,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcc4,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcc9,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcc7,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcd1,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0xcd7,0xcdf,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xce5, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0xcec,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0xcf1,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0xcf6,0x600,0x600,0x600,0xc32,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0xcd3,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0xcfc,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0xd04,0xd0b,0xd0f,0x600,0x600,0x600,0xccb,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0xd1e,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0xd16,0x934,0xd26,0x9ad,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0xd2b,0xd33,0x4e5,0xd43,0xd3b,0x600,0x600,0xd4b,0xd53,0xd63,0x4e5,0xd68,0xd70,0xd76,0xd7d,0xd5b, -0xd85,0xd8d,0x600,0xd95,0xda5,0xda8,0xd9d,0xdb0,0x655,0xdb8,0xdbf,0x8f6,0x6a3,0xdcf,0xdc7,0xdd7, -0x600,0xddf,0xde7,0xdef,0x600,0xdf7,0xdff,0xe07,0xe0f,0xe17,0xe1b,0xe23,0x535,0x535,0x600,0xe2b, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe33,0xe3f,0xe37, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, -0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0x600,0x600,0x600,0xe57,0x600,0xccc,0xe5e,0xe63, -0x600,0x600,0x600,0xe6b,0x600,0x600,0x901,0x4b5,0xe81,0xe71,0xe79,0x600,0x600,0xe89,0xe91,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe96,0x938,0x600,0xe9e,0x600,0xea4,0xea8, -0xeb0,0xeb8,0xebf,0xec7,0x600,0x600,0x600,0xecd,0xee5,0x4a5,0xeed,0xef5,0xefa,0x916,0xed5,0xedd, -0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, -0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, -0x12d4,0x12d4,0x1314,0x1354,0x1394,0x13cc,0x140c,0x144c,0x1484,0x14c4,0x14f0,0x1530,0x1570,0x1580,0x15c0,0x15f4, -0x1634,0x1664,0x16a4,0x16e4,0x16f4,0x1728,0x1760,0x17a0,0x17e0,0x1820,0x1854,0x1880,0x18c0,0x18f8,0x1914,0x1954, -0xa80,0xac0,0xb00,0xb40,0xb80,0xbab,0xbeb,0xa40,0xc0e,0xa40,0xa40,0xa40,0xa40,0xc4e,0x1db,0x1db, -0xc8e,0xcce,0xa40,0xa40,0xa40,0xcf7,0xd37,0xd57,0xa40,0xd7d,0xdbd,0xdfd,0xe3d,0xe7d,0xebd,0xefd, -0xf3d,0xf74,0x1db,0x1db,0xf98,0xfcc,0x1db,0xff4,0x1db,0x1db,0x1db,0x1db,0x1021,0x1db,0x1db,0x1db, -0x1db,0x1db,0x1db,0x1db,0x1035,0x1db,0x106d,0x10ad,0x1db,0x10b8,0x1db,0x1db,0x1db,0x10ee,0xa40,0x112e, -0x1db,0x1db,0x116e,0x1db,0x1191,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, +static const uint16_t propsTrie_index[23796]={ +0x4a3,0x4ab,0x4b3,0x4bb,0x4d3,0x4db,0x4e3,0x4eb,0x4f3,0x4fb,0x501,0x509,0x511,0x519,0x521,0x529, +0x52f,0x537,0x53f,0x547,0x54a,0x552,0x55a,0x562,0x56a,0x572,0x56e,0x576,0x57e,0x586,0x58b,0x593, +0x59b,0x5a3,0x5a7,0x5af,0x5b7,0x5bf,0x5c7,0x5cf,0x5cb,0x5d3,0x5d8,0x5e0,0x5e6,0x5ee,0x5f6,0x5fe, +0x606,0x60e,0x616,0x61e,0x623,0x62b,0x62e,0x636,0x63e,0x646,0x64c,0x654,0x653,0x65b,0x663,0x66b, +0x67b,0x673,0x683,0x68b,0x691,0x60e,0x6a1,0x699,0x6b1,0x6b3,0x6bb,0x6a9,0x6cb,0x6d1,0x6d9,0x6c3, +0x6e9,0x6ef,0x6f7,0x6e1,0x707,0x70d,0x715,0x6ff,0x725,0x72b,0x733,0x71d,0x743,0x74b,0x753,0x73b, +0x763,0x769,0x771,0x75b,0x781,0x787,0x78f,0x779,0x79f,0x7a4,0x7ac,0x797,0x7bc,0x7c3,0x7cb,0x7b4, +0x64f,0x7d3,0x7db,0x4c3,0x7e3,0x7ea,0x7f2,0x4c3,0x7fa,0x802,0x80a,0x80f,0x817,0x81e,0x826,0x4c3, +0x60e,0x82e,0x836,0x83e,0x846,0x59b,0x856,0x84e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x85e,0x60e,0x866,0x86a,0x872,0x60e,0x878,0x60e,0x87e,0x886,0x88e,0x59b,0x59b,0x896, +0x89e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x8a3,0x8ab,0x60e,0x60e,0x8b3,0x8bb,0x8c3,0x8cb,0x8d3,0x60e,0x8db,0x8e3,0x8eb, +0x8fb,0x60e,0x903,0x905,0x90d,0x8f3,0x60e,0x910,0x924,0x918,0x920,0x92c,0x60e,0x934,0x93a,0x942, +0x94a,0x60e,0x95a,0x962,0x96a,0x952,0x97a,0x4c3,0x982,0x985,0x98d,0x972,0x99d,0x995,0x60e,0x9a4, +0x60e,0x9b3,0x9ac,0x9bb,0x9c3,0x9c7,0x9cf,0x9d7,0x543,0x9df,0x9e2,0x9e8,0x9ef,0x9e2,0x56a,0x56a, +0x4f3,0x4f3,0x4f3,0x4f3,0x9f7,0x4f3,0x4f3,0x4f3,0xa07,0xa0f,0xa17,0xa1f,0xa27,0xa2b,0xa33,0x9ff, +0xa4b,0xa53,0xa3b,0xa43,0xa5b,0xa63,0xa6b,0xa73,0xa8b,0xa7b,0xa83,0xa93,0xa9b,0xaaa,0xaaf,0xaa2, +0xab7,0xab7,0xab7,0xab7,0xab7,0xab7,0xab7,0xab7,0xabf,0xac7,0x942,0xaca,0xad2,0xad9,0xade,0xae6, +0x942,0xaec,0xaf4,0xb04,0xb07,0x942,0x942,0xafc,0x942,0x942,0x942,0x942,0x942,0xb16,0xb1e,0xb0e, +0x942,0x942,0x942,0xb23,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0xb29,0xb31,0x942,0xb39,0xb40, +0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0xab7,0xab7,0xab7,0xab7,0xb48,0xab7,0xb4f,0xb56, +0xab7,0xab7,0xab7,0xab7,0xab7,0xab7,0xab7,0xab7,0x942,0xb5e,0xb65,0xb69,0xb6f,0x942,0x942,0x942, +0x59b,0x5a3,0x543,0xb77,0x4f3,0x4f3,0x4f3,0xb7f,0x543,0xb87,0x60e,0xb8d,0xb9d,0xb95,0xb95,0x56a, +0xba5,0xbad,0xbb5,0x4c3,0xbbd,0x942,0x942,0xbc4,0x942,0x942,0x942,0x942,0x942,0x942,0xae9,0xbc9, +0xbd9,0xbd1,0x64f,0x60e,0xbe1,0x89e,0x60e,0xbe9,0xbf1,0xbf5,0x60e,0x60e,0xbfa,0x60e,0x942,0xc01, +0xc09,0xc11,0xc17,0x942,0xc11,0xc1f,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942, +0xc27,0x60e,0x60e,0x60e,0xc2f,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0xc35,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xc3a,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x942,0x942, +0xc42,0xc49,0xc4b,0x60e,0xc53,0xc59,0xc61,0xc69,0xc6e,0x60e,0x60e,0xc72,0x60e,0x60e,0x60e,0xc78, +0xc7f,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xc86,0x60e,0xc8d,0xc93,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xc9b,0x60e,0x60e,0x60e,0xca3,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xca5,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xcac,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0xcb3,0x60e,0x60e,0x60e,0xcba,0xcc2,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xcc7,0xccc,0x60e,0x60e,0xcd4,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xcd8,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xcdd,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xcdb,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xce5,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0xceb,0xcf3,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xcf9, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0xd00,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0xd05,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0xd0a,0x60e,0x60e,0x60e,0xc46,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0xce7,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0xd10,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0xd18,0xd1f,0xd23,0x60e,0x60e,0x60e,0xcdf,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0xd32,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0xd2a,0x942,0xd3a,0x9bb,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0xd3f,0xd47,0x4f3,0xd57,0xd4f,0x60e,0x60e,0xd5f,0xd67,0xd77,0x4f3,0xd7c,0xd84,0xd8a,0xd91,0xd6f, +0xd99,0xda1,0x60e,0xda9,0xdb9,0xdbc,0xdb1,0xdc4,0x663,0xdcc,0xdd3,0x904,0x6b1,0xde3,0xddb,0xdeb, +0x60e,0xdf3,0xdfb,0xe03,0x60e,0xe0b,0xe13,0xe1b,0xe23,0xe2b,0xe2f,0xe37,0x543,0x543,0x60e,0xe3f, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xe47,0xe53,0xe4b, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, +0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0x60e,0x60e,0x60e,0xe6b,0x60e,0xce0,0xe72,0xe77, +0x60e,0x60e,0x60e,0xe7f,0x60e,0x60e,0x90f,0x4c3,0xe95,0xe85,0xe8d,0x60e,0x60e,0xe9d,0xea5,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xeaa,0x946,0x60e,0xeb2,0x60e,0xeb8,0xebc, +0xec4,0xecc,0xed3,0xedb,0x60e,0x60e,0x60e,0xee1,0xef9,0x4b3,0xf01,0xf09,0xf0e,0x924,0xee9,0xef1, +0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, +0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, +0x130c,0x130c,0x134c,0x138c,0x13cc,0x1404,0x1444,0x1484,0x14bc,0x14fc,0x1528,0x1568,0x15a8,0x15b8,0x15f8,0x162c, +0x166c,0x169c,0x16dc,0x171c,0x172c,0x1760,0x1798,0x17d8,0x1818,0x1858,0x188c,0x18b8,0x18f8,0x1930,0x194c,0x198c, +0xa80,0xac0,0xb00,0xb40,0xb80,0xbab,0xbeb,0x1db,0xc0e,0xa40,0xa40,0xa40,0xc46,0xc86,0x1db,0x1db, +0xcc6,0xd06,0xa40,0xa40,0xa40,0xd2f,0xd6f,0xd8f,0xa40,0xdb5,0xdf5,0xe35,0xe75,0xeb5,0xef5,0xf35, +0xf75,0xfac,0x1db,0x1db,0xfd0,0x1004,0x1db,0x102c,0x1db,0x1db,0x1db,0x1db,0x1059,0x1db,0x1db,0x1db, +0x1db,0x1db,0x1db,0x1db,0x106d,0x1db,0x10a5,0x10e5,0x1db,0x10f0,0x1db,0x1db,0x1db,0x1126,0xa40,0x1166, +0x1db,0x1db,0x11a6,0x1db,0x11c9,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, @@ -170,600 +170,603 @@ static const uint16_t propsTrie_index[23156]={ 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0x11d1,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, +0x1209,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700, -0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x1211, +0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x1249, 0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700, -0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x1211, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0xf02,0xf09,0xf11,0x4b5,0x600,0x600,0x600,0xf19,0xf29,0xf21,0xf40,0xf31,0xf38,0xf48,0xbbd,0xf50, -0x4b5,0x4b5,0x4b5,0x4b5,0x8f6,0x600,0xf58,0xf60,0x600,0xf68,0xf70,0xf74,0xf7c,0x600,0xf84,0x4b5, -0x58d,0x597,0xf8c,0x600,0xf90,0xf98,0xfa8,0xfa0,0x600,0xfb0,0x600,0xfb7,0xfc7,0xfbf,0x4b5,0x4b5, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xb88,0x902,0xfcf,0xfdf,0xfd7,0x4b5,0x4b5, -0xfef,0xfe7,0xff2,0xffa,0x916,0x1002,0x4b5,0x100a,0x1012,0x101a,0x4b5,0x4b5,0x600,0x102a,0x1032,0x1022, -0x1042,0x1049,0x103a,0x1051,0x1059,0x4b5,0x1069,0x1061,0x600,0x106c,0x1074,0x107c,0x1084,0x108c,0x4b5,0x4b5, -0x600,0x600,0x1094,0x4b5,0x58d,0x109c,0x535,0x10a4,0x600,0x10ac,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x10b4,0x600,0x10bc,0x4b5,0x10c1,0x10c9,0x10d1,0x10d8,0x1006,0x10e0,0x1006,0x10e8,0xb88, -0x10f8,0x636,0x1100,0x10f0,0x98f,0x1108,0x1110,0x1116,0x112e,0x111e,0x1126,0x1132,0x98f,0x1142,0x113a,0x114a, -0x1162,0x1152,0x115a,0x4b5,0x1169,0x1171,0x658,0x1179,0x1189,0x118f,0x1197,0x1181,0x4b5,0x4b5,0x4b5,0x4b5, -0x600,0x119f,0x11a7,0x10c0,0x600,0x11af,0x11b7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x11bf,0x11c7,0x4b5, -0x600,0x11cf,0x11d7,0x11df,0x600,0x11ef,0x11e7,0x4b5,0x870,0x11f7,0x11ff,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x600,0x1207,0x4b5,0x4b5,0x4b5,0x58d,0x535,0x120f,0x121f,0x1225,0x1217,0x4b5,0x4b5,0x1235,0x1239,0x122d, -0x1251,0x1241,0x1249,0x600,0x125f,0x1259,0x600,0x8f7,0x126f,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x127d,0x1282,0x1267,0x1277,0x1292,0x128a,0x4b5,0x4b5,0x12a1,0x12a5,0x1299,0x12b5,0x12ad,0x11e7,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x12b9,0x12c9,0x12ce,0x12c1,0x4b5,0x4b5,0x12d6,0x12e6,0x12de, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x901,0x4b5,0x4b5,0x4b5, -0x12f6,0x12fe,0x1306,0x12ee,0x600,0x600,0x600,0x600,0x600,0x600,0x130e,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1006,0x600,0x600,0x1316,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x131e,0x1326,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x11ff,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x8f7, -0x916,0xdcb,0x600,0x916,0x132e,0x1333,0x600,0x1343,0x134b,0x1353,0x133b,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x58d,0x535,0x135b,0x4b5,0x4b5,0x4b5,0x600,0x600,0x1363,0x1368,0x136e,0x4b5,0x4b5,0x1376,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x137e,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x902,0x4b5,0x1094,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1384,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x138c,0x1391,0x1398,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe37,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600,0x600,0x139e,0x13a3,0x13ab,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x55c,0x13bb,0x13c2,0x934,0x934,0x934,0x13b3,0x4b5,0x934,0x934,0x934, -0x934,0x934,0x934,0x934,0xbb7,0x934,0x13c9,0x934,0x13d0,0x13d8,0x13de,0x934,0xade,0x934,0x934,0x13e6, -0x4b5,0x4b5,0x4b5,0x13ee,0x13ee,0x934,0x934,0xadb,0x13f6,0x4b5,0x4b5,0x4b5,0x4b5,0x1406,0x140d,0x1412, -0x1418,0x1420,0x1428,0x1430,0x140a,0x1438,0x1440,0x1448,0x144d,0x141f,0x1406,0x140d,0x1409,0x1418,0x1455,0x1407, -0x1458,0x140a,0x1460,0x1468,0x1470,0x1477,0x1463,0x146b,0x1473,0x147a,0x1466,0x1482,0x13fe,0x934,0x934,0x934, -0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x55c,0x1492,0x55c, -0x1499,0x14a0,0x148a,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x14af,0x14b7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x14a7,0x14bf,0x9d4, -0x14cf,0x14c7,0x4b5,0x4b5,0x4b5,0x600,0x14df,0x14d7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x1006,0x14e7,0x600,0x14ef,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x1006,0x14f7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x14ff,0x600,0x600,0x600, -0x600,0x600,0x600,0x1507,0x4b5,0x58d,0x1517,0x150f,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x151f,0x152f,0x1527,0x4b5,0x4b5,0x153f,0x1537,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x154f,0x1557,0x155f, -0x1567,0x156f,0x1577,0x4b5,0x1547,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x934,0x157f,0x934, -0x934,0xbaf,0x13c7,0x1587,0xbb7,0x158f,0x934,0x934,0x934,0x934,0xbb9,0x4b5,0x1597,0x159f,0x15a3,0x15ab, -0x15b3,0x4b5,0x4b5,0x4b5,0x4b5,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x15bb,0x934,0x934,0x934, -0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934, -0x934,0x934,0x934,0x15a4,0x15c3,0x934,0x934,0x934,0x15cb,0x934,0x934,0x15d2,0x15da,0x157f,0x934,0x15e2, -0x934,0x15ea,0x15ef,0x4b5,0x4b5,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0xbaf, -0x15f7,0x1600,0x1604,0x160c,0x15fc,0x934,0x934,0x934,0x934,0x1614,0x934,0xade,0x11e3,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x161c,0x600,0x600, -0x1623,0x600,0x600,0x600,0x162b,0x600,0x1633,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xca3,0x600,0x600, -0x163b,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1643,0x164b,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0xc32,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1652,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1659,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x1660,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x4b5,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x901,0x600,0x600,0x600,0x600,0x600,0x600,0xf90,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1668,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1670,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0xf90,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, -0x600,0x600,0x1674,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xf90,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x67d,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x133b,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x1684,0x167c,0x167c,0x167c,0x4b5,0x4b5,0x4b5,0x4b5,0x55c,0x55c,0x55c,0x55c,0x55c,0x55c,0x55c, -0x168c,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, -0x1694,0x494,0x494,0x494,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x700,0x1249, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0xf16,0xf1d,0xf25,0x4c3,0x60e,0x60e,0x60e,0xf2d,0xf3d,0xf35,0xf54,0xf45,0xf4c,0xf5c,0xbc9,0xf64, +0x4c3,0x4c3,0x4c3,0x4c3,0x904,0x60e,0xf6c,0xf74,0x60e,0xf7c,0xf84,0xf88,0xf90,0x60e,0xf98,0x4c3, +0x59b,0x5a5,0xfa0,0x60e,0xfa4,0xfac,0xfbc,0xfb4,0x60e,0xfc4,0x60e,0xfcb,0xfdb,0xfd3,0x60e,0xfe3, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xb9d,0x910,0xfe6,0xff6,0xfee,0x4c3,0x4c3, +0x1006,0xffe,0x1009,0x1011,0x924,0x1019,0x4c3,0x1021,0x1029,0x1031,0x4c3,0x4c3,0x60e,0x1041,0x1049,0x1039, +0x1059,0x1060,0x1051,0x1068,0x1070,0x4c3,0x1080,0x1078,0x60e,0x1083,0x108b,0x1093,0x109b,0x10a3,0x4c3,0x4c3, +0x60e,0x60e,0x10ab,0x4c3,0x59b,0x10b3,0x543,0x10bb,0x60e,0x10c3,0x10da,0x10cb,0x10d2,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x10e2,0x60e,0x10ea,0x10f7,0x10ef,0x10ff,0x1107,0x110e,0x101d,0x1116,0x101d,0x111e,0xb9d, +0x112e,0x644,0x1136,0x1126,0x99d,0x113e,0x1146,0x114c,0x1164,0x1154,0x115c,0x1168,0x99d,0x1178,0x1170,0x1180, +0x1198,0x1188,0x1190,0x4c3,0x119f,0x11a7,0x666,0x11af,0x11bf,0x11c5,0x11cd,0x11b7,0x11dd,0x11e1,0x11e9,0x11d5, +0x60e,0x11f1,0x11f9,0x10ee,0x60e,0x1201,0x1209,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x60e,0x1211,0x1219,0x4c3, +0x60e,0x1221,0x1229,0x1231,0x60e,0x1241,0x1239,0x1249,0x1261,0x1251,0x1259,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x60e,0x1269,0x4c3,0x4c3,0x4c3,0x59b,0x543,0x1271,0x1281,0x1287,0x1279,0x4c3,0x4c3,0x1297,0x129b,0x128f, +0x12b3,0x12a3,0x12ab,0x60e,0x12c1,0x12bb,0x60e,0x905,0x12c9,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x60e,0x12d1, +0x12e7,0x12ec,0x12d9,0x12e1,0x12fc,0x12f4,0x4c3,0x4c3,0x130b,0x130f,0x1303,0x1327,0x1317,0x131f,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x132b,0x133b,0x1340,0x1333,0x4c3,0x4c3,0x1348,0x1358,0x1350, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x90f,0x4c3,0x4c3,0x4c3, +0x1368,0x1370,0x1378,0x1360,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x1380,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x101d,0x60e,0x60e,0x1388,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x1390,0x1398,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xf2d,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x1259,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x655,0x13a0, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x905,0x924,0xddf,0x60e,0x924,0x13a4,0x13a9,0x60e,0x13b1, +0x13b9,0x13c1,0xfe4,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x13d1,0x13c9,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x59b,0x543,0x13d9,0x4c3,0x4c3,0x4c3,0x60e,0x60e, +0x13e1,0x13e6,0x13ec,0x4c3,0x4c3,0x13f4,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x13fc,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x910,0x1402,0x10ab,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x140a,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x1412,0x1417,0x141e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xe4b,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x60e, +0x60e,0x60e,0x1424,0x1429,0x1431,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x1439,0x942,0x942,0x942, +0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0xbc4,0x4c3,0x4c3,0x56a,0x1449,0x1450, +0x942,0x942,0x942,0x1441,0x4c3,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0xae9,0x942,0x1457,0x942, +0x145e,0x1466,0x146c,0x942,0xaf4,0x942,0x942,0x1474,0x4c3,0x4c3,0x4c3,0x147c,0x147c,0x942,0x942,0x1484, +0x148c,0x4c3,0x4c3,0x4c3,0x4c3,0x149c,0x14a3,0x14a8,0x14ae,0x14b6,0x14be,0x14c6,0x14a0,0x14ce,0x14d6,0x14de, +0x14e3,0x14b5,0x149c,0x14a3,0x149f,0x14ae,0x14eb,0x149d,0x14ee,0x14a0,0x14f6,0x14fe,0x1506,0x150d,0x14f9,0x1501, +0x1509,0x1510,0x14fc,0x1518,0x1494,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942, +0x942,0x942,0x942,0x942,0x942,0x56a,0x1528,0x56a,0x152f,0x1536,0x1520,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x1545,0x154d,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x153d,0x1555,0x9e2,0x1565,0x155d,0x4c3,0x4c3,0x4c3,0x60e,0x1575,0x156d, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x101d,0x157d,0x60e,0x1585,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x101d,0x158d,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x101d,0x1595,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x159d,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x15a5,0x4c3,0x59b,0x15b5,0x15ad, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x15bd,0x15cd,0x15c5,0x4c3,0x4c3,0x15dd,0x15d5,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x15ed,0x15f5,0x15fd,0x1605,0x160d,0x1615,0x4c3,0x15e5,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x942,0x161d,0x942,0x942,0xbc4,0x1455,0x1625,0xae9,0x162d,0x942,0x942, +0x942,0x942,0xaeb,0x4c3,0x1635,0x163d,0x1641,0x1649,0x1651,0x4c3,0x4c3,0x4c3,0x4c3,0x942,0x942,0x942, +0x942,0x942,0x942,0x942,0x1659,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942, +0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x942,0x1642,0x1661,0x942,0x942,0x942, +0x1669,0x942,0x942,0xae8,0x1670,0x161d,0x942,0x1678,0x942,0x1680,0x1685,0x168d,0x4c3,0x942,0x942,0x942, +0x942,0x942,0x942,0x942,0x942,0x942,0x942,0xbc4,0x1695,0x169d,0x942,0x16a4,0x16ac,0x942,0x942,0x942, +0x942,0x16b4,0x942,0x942,0x1439,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x16bc,0x60e,0x60e,0x16c3,0x60e,0x60e,0x60e,0x16cb,0x60e,0x16d3,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0xcb7,0x60e,0x60e,0x16db,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x16e3,0x16eb,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xc46,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x16f2,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x16f9,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x1700,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x4c3,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x90f,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0xfa4,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x1708,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x1710,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xfa4,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x60e,0x60e,0x60e,0x60e,0x1714,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xfa4,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x68b,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0x60e, +0x60e,0x60e,0x60e,0x60e,0x60e,0x60e,0xfe4,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x1724,0x171c,0x171c,0x171c,0x4c3,0x4c3,0x4c3, +0x4c3,0x56a,0x56a,0x56a,0x56a,0x56a,0x56a,0x56a,0x172c,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3, +0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0x4c3,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63, +0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0xe63,0x1734,0x4a2,0x4a2,0x4a2,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, -0xf,0xf,0xf,0xf,0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18, -0x17,0x13,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17, -0x18,0x18,0x18,0x17,0x17,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x14, -0x17,0x15,0x1a,0x16,0x1a,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0x14, -0x18,0x15,0x18,0xf,0,0,0,0,0,0,0,0,0,0,0,0, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xc,0x17,0x17,0x17, +0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0x18,0x18,0x18,0x17,0x17,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0x14,0x17,0x15,0x1a,0x16,0x1a,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,0x14,0x18,0x15,0x18,0xf,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0,0,0,0,0,0,0,0,0,0,0,0,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, -0xf,0xf,0xf,0xf,0xc,0x17,0x19,0x19,0x19,0x19,0x1b,0x17,0x1a,0x1b,5,0x1c, -0x18,0x10,0x1b,0x1a,0x1b,0x18,0x34b,0x38b,0x1a,2,0x17,0x17,0x1a,0x30b,5,0x1d, -0x34cb,0x344b,0x3ccb,0x17,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x18,1,1,1,1, -1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,0x18,2,2,2,2, -2,2,2,2,1,2,1,2,1,2,1,2,1,2,1,2, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xc,0x17,0x19,0x19, +0x19,0x19,0x1b,0x17,0x1a,0x1b,5,0x1c,0x18,0x10,0x1b,0x1a,0x1b,0x18,0x34b,0x38b, +0x1a,2,0x17,0x17,0x1a,0x30b,5,0x1d,0x34cb,0x344b,0x3ccb,0x17,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x18,1,1,1,1,1,1,1,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,0x18,2,2,2,2,2,2,2,2,1,2,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,2,1,2,1,2,1,2,2,1,2,1, -2,1,2,1,2,2,1,2,1,2,1,2,1,2,1,2, +1,2,1,2,2,1,2,1,2,1,2,1,2,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,1,2,1,2,1,2,2,2,1,1,2, -1,2,1,1,2,1,1,1,2,2,1,1,1,1,2,1, -1,2,1,1,1,2,2,2,1,1,2,1,1,2,1,2, -1,2,1,1,2,1,2,2,1,2,1,1,2,1,1,1, -2,1,2,1,1,2,2,5,1,2,2,2,5,5,5,5, -1,3,2,1,3,2,1,3,2,1,2,1,2,1,2,1, -2,1,2,1,2,1,2,1,2,2,1,2,1,2,1,2, -1,2,1,2,1,2,1,2,1,2,1,2,2,1,3,2, -1,2,1,1,1,2,1,2,1,2,1,2,1,2,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,1,1,2,1, +2,1,2,2,2,1,1,2,1,2,1,1,2,1,1,1, +2,2,1,1,1,1,2,1,1,2,1,1,1,2,2,2, +1,1,2,1,1,2,1,2,1,2,1,1,2,1,2,2, +1,2,1,1,2,1,1,1,2,1,2,1,1,2,2,5, +1,2,2,2,5,5,5,5,1,3,2,1,3,2,1,3, +2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, +2,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, +1,2,1,2,2,1,3,2,1,2,1,1,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,2,1,2,2,2,2,2,2,2,1,1, -2,1,1,2,2,1,2,1,1,1,1,2,1,2,1,2, -1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2, +1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, +2,2,2,2,2,2,1,1,2,1,1,2,2,1,2,1, +1,1,1,2,1,2,1,2,1,2,1,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,5,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,5,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,0x1a,0x1a,0x1a,0x1a,4,4,4,4,4,4,4,4,4,4, -4,4,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, -4,4,4,4,4,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,0x1a,4,0x1a, -0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, +2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,0x1a,0x1a,0x1a,0x1a,4,4, +4,4,4,4,4,4,4,4,4,4,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, +0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,4,4,4,4,0x1a,0x1a,0x1a, +0x1a,0x1a,0x1a,0x1a,4,0x1a,4,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, +0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -1,2,1,2,4,0x1a,1,2,0,0,4,2,2,2,0x17,1, -0,0,0,0,0x1a,0x1a,1,0x17,1,1,1,0,1,0,1,1, -2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0,1,1,1,1,1,1,1,1,1,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,1,2,2,1,1,1,2,2,2,1,2,1,2, -1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,2,2,2,2,1,2,0x18,1,2,1,1,2, -2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +6,6,6,6,6,6,6,6,1,2,1,2,4,0x1a,1,2, +0,0,4,2,2,2,0x17,1,0,0,0,0,0x1a,0x1a,1,0x17, +1,1,1,0,1,0,1,1,2,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1, +1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,1, +1,2,2,2,1,2,1,2,1,2,1,2,1,2,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,2,2,2,2, +1,2,0x18,1,2,1,1,2,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, +1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,1,2,1,2,1,2,1,2,1,2,1,2, +2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,2,0x1b,6,6,6,6,6,7,7,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,1,2,0x1b,6, +6,6,6,6,7,7,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,1,1,2,1, +2,1,2,1,2,1,2,1,2,1,2,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,1,2,1,2,1,2,1,2,1,2,1, -2,1,2,2,1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,0,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, -0,4,0x17,0x17,0x17,0x17,0x17,0x17,2,2,2,2,2,2,2,2, +1,2,1,2,1,2,1,2,1,2,1,2,0,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0,0,4,0x17,0x17,0x17,0x17,0x17,0x17, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,0x17,0x13,0,0,0x1b,0x1b,0x19, -0,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,0x17,0x13,0,0,0x1b,0x1b,0x19,0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,0x13,6, -0x17,6,6,0x17,6,6,0x17,6,0,0,0,0,0,0,0,0, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,0x13,6,0x17,6,6,0x17,6,6,0x17,6, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,5, -5,5,5,0x17,0x17,0,0,0,0,0,0,0,0,0,0,0, -0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x18,0x18,0x17,0x17,0x19,0x17,0x17,0x1b,0x1b, -6,6,6,6,6,6,6,6,6,6,6,0x17,0x10,0x17,0x17,0x17, +5,5,5,0,0,0,0,5,5,5,5,0x17,0x17,0,0,0, +0,0,0,0,0,0,0,0,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x18, +0x18,0x17,0x17,0x19,0x17,0x17,0x1b,0x1b,6,6,6,6,6,6,6,6, +6,6,6,0x17,0x10,0x17,0x17,0x17,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,4,5,5,5,5,5,5,5, +5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,6,6,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0x17,0x17,0x17,0x17,5,5,6,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -4,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0x17,0x17,5,5, -6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x17,5,6,6, +6,6,6,6,6,0x10,0x1b,6,6,6,6,6,6,4,4,6, +6,0x1b,6,6,6,6,5,5,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,5,5,5,0x1b,0x1b,5,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0,0x10,5,6,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x17,5,6,6,6,6,6,6,6,0x10,0x1b,6, -6,6,6,6,6,4,4,6,6,0x1b,6,6,6,6,5,5, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,5,0x1b,0x1b,5, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0x10, -5,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,6,6,6,6,6,0,0,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,0,0,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6, -6,6,6,6,6,5,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5, +5,5,6,6,6,6,6,6,6,6,6,6,6,5,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, -6,6,6,6,6,6,6,6,4,4,0x1b,0x17,0x17,0x17,4,0, -0,6,0x19,0x19,6,6,6,6,4,6,6,6,4,6,6,6, -6,6,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,6,6,6,6,4,6, -6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6, -0,0,0x17,0,5,5,5,5,5,5,5,5,5,5,5,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x1a,5,5,5,5,5,5,0,0x10,0x10,0,0, -0,0,0,0,6,6,6,6,6,6,6,6,6,6,0x10,6, +5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6, +4,4,0x1b,0x17,0x17,0x17,4,0,0,6,0x19,0x19,6,6,6,6, +4,6,6,6,4,6,6,6,6,6,0,0,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,6,6,6,6,4,6,6,6,6,6,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,6,6,6,0,0,0x17,0,5,5,5,5, +5,5,5,5,5,5,5,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x1a,5,5,5, +5,5,5,0,0x10,0x10,0,0,0,0,0,6,6,6,6,6, +6,6,6,6,6,6,0x10,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5, -5,5,5,5,5,4,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,5,5,6,6, -0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,4,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,8, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,8, -6,5,8,8,8,6,6,6,6,6,6,6,6,8,8,8, -8,6,8,8,5,6,6,6,6,6,6,6,5,5,5,5, -5,5,5,5,5,5,6,6,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,5,5,0x19,0x19,0x37cb,0x35cb,0x3fcb,0x34cb,0x3ccb,0x94b,0x1b,0x19, -5,0x17,6,0,5,6,8,8,0,5,5,5,5,5,5,5, -5,0,0,5,5,0,0,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,5,5,5,5,5,5,5,0,5,0, -0,0,5,5,5,5,0,0,6,5,8,8,8,6,6,6, -6,0,0,8,8,0,0,8,8,6,5,0,0,0,0,0, -0,0,0,8,0,0,0,0,5,5,0,5,0,0,0,0, -0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,6,6,5,5, -5,6,0x17,0,0,0,0,0,0,0,0,0,0,6,6,8, -0,5,5,5,5,5,5,0,0,0,0,5,5,0,0,5, +6,6,6,6,5,5,5,5,5,5,5,5,5,4,6,6, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,6,6,5,5,6,6,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189, +0x1c9,0x209,0x249,0x289,0x17,4,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,6,6,6,8,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,6,8,6,5,8,8,8,6,6,6, +6,6,6,6,6,8,8,8,8,6,8,8,5,6,6,6, +6,6,6,6,5,5,5,5,5,5,5,5,5,5,6,6, +0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,0x19,0x19, +0x37cb,0x35cb,0x3fcb,0x34cb,0x3ccb,0x94b,0x1b,0x19,5,0x17,6,0,5,6,8,8, +0,5,5,5,5,5,5,5,5,0,0,5,5,0,0,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, -5,5,5,5,5,0,5,5,0,5,5,0,5,5,0,0, -6,0,8,8,8,6,6,0,0,0,0,6,6,0,0,6, -6,6,0,0,0,6,0,0,0,0,0,0,0,5,5,5, -5,0,5,0,5,5,6,6,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,0x17,0x19,0,0,0,0,0,0,0,5,6,6, -6,6,6,6,0,6,6,8,0,5,5,5,5,5,5,5, -5,5,0,5,5,5,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,5,0,0,0,5,5,5,5,0,0, +6,5,8,8,8,6,6,6,6,0,0,8,8,0,0,8, +8,6,5,0,0,0,0,0,0,0,0,8,0,0,0,0, +5,5,0,5,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, +0x1c9,0x209,0x249,0x289,6,6,5,5,5,6,0x17,0,0,0,0,0, +0,0,0,0,0,6,6,8,0,5,5,5,5,5,5,0, +0,0,0,5,5,0,0,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,0,5,5,5,5,5,5,5,0,5,5, -0,5,5,5,5,5,0,0,6,5,8,8,8,6,6,6, -6,6,0,6,6,8,0,8,8,6,0,0,5,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,6,6, -0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x1b,5,0x34cb,0x344b, -0x3ccb,0x37cb,0x35cb,0x3fcb,0,0,0,0,0,0,0,0,0,6,8,8, -0,5,5,5,5,5,5,5,5,0,0,5,5,0,0,5, +0,5,5,0,5,5,0,0,6,0,8,8,8,6,6,0, +0,0,0,6,6,0,0,6,6,6,0,0,0,6,0,0, +0,0,0,0,0,5,5,5,5,0,5,0,5,5,6,6, +0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x19,0,0, +0,0,0,0,0,5,6,6,6,6,6,6,0,6,6,8, +0,5,5,5,5,5,5,5,5,5,0,5,5,5,0,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, 5,5,5,5,5,0,5,5,0,5,5,5,5,5,0,0, -6,5,8,6,8,6,6,6,6,0,0,8,8,0,0,8, -8,6,0,0,0,0,0,0,0,6,6,8,0,0,0,0, -5,5,0,5,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,0x7cb,0x1e4b,0x784b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x1b,0, -0,0,0,0,0,0,6,5,0,5,5,5,5,5,5,0, -0,0,5,5,5,0,5,5,5,5,0,0,0,5,5,0, -5,0,5,5,0,0,0,5,5,0,0,0,5,5,5,0, -0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0, -0,0,8,8,6,8,8,0,0,0,8,8,8,0,8,8, -8,6,0,0,5,0,0,0,0,0,0,8,0,0,0,0, +6,5,8,8,8,6,6,6,6,6,0,6,6,8,0,8, +8,6,0,0,5,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,5,5,6,6,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0,0x17,0x54b,0x58b,0x5cb,0x60b, -0x58b,0x5cb,0x60b,0x1b,6,8,8,8,6,5,5,5,5,5,5,5, -5,0,5,5,5,0,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,6,5,6,6,6,8,8,8, -8,0,6,6,6,0,6,6,6,6,0,0,0,0,0,0, -0,6,6,0,5,5,5,0,0,5,0,0,5,5,6,6, -0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,5,5,8, -0,0,0,0,0,0,0,0,0,0,0,0,5,6,8,8, -0x17,5,5,5,5,5,5,5,5,0,5,5,5,0,5,5, +0x1c9,0x209,0x249,0x289,0x1b,5,0x34cb,0x344b,0x3ccb,0x37cb,0x35cb,0x3fcb,0,0,0,0, +0,0,0,0,0,6,8,8,0,5,5,5,5,5,5,5, +5,0,0,5,5,0,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,5,5,5,5,5,5,5,0,5,5, +0,5,5,5,5,5,0,0,6,5,8,6,8,6,6,6, +6,0,0,8,8,0,0,8,8,6,0,0,0,0,0,0, +0,6,6,8,0,0,0,0,5,5,0,5,0,0,0,0, +0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0x1e4b,0x784b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x1b,0,0,0,0,0,0,0,6,5, +0,5,5,5,5,5,5,0,0,0,5,5,5,0,5,5, +5,5,0,0,0,5,5,0,5,0,5,5,0,0,0,5, +5,0,0,0,5,5,5,0,0,0,5,5,5,5,5,5, +5,5,5,5,5,5,0,0,0,0,8,8,6,8,8,0, +0,0,8,8,8,0,8,8,8,6,0,0,5,0,0,0, +0,0,0,8,0,0,0,0,0,0,0,0,5,5,6,6, +0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0, +0,0,0,0x17,0x54b,0x58b,0x5cb,0x60b,0x58b,0x5cb,0x60b,0x1b,6,8,8,8, +6,5,5,5,5,5,5,5,5,0,5,5,5,0,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, -5,5,5,5,5,5,5,5,0,5,5,5,5,5,0,0, -6,5,8,6,8,8,8,8,8,0,6,8,8,0,8,8, -6,6,0,0,0,0,0,0,0,8,8,0,0,0,0,0, -0,5,5,0,5,5,6,6,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,0x7cb,0x1e4b,0x784b,0x34cb,0x344b,0x3ccb,0x37cb,0x35cb,0x3fcb,0x1b,5,5, -5,5,5,5,6,6,8,8,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, +6,5,6,6,6,8,8,8,8,0,6,6,6,0,6,6, +6,6,0,0,0,0,0,0,0,6,6,0,5,5,5,0, +0,5,0,0,5,5,6,6,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, +0x1c9,0x209,0x249,0x289,0,5,5,8,0,0,0,0,0,0,0,0, +0,0,0,0,5,6,8,8,0x17,5,5,5,5,5,5,5, 5,0,5,5,5,0,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5, +0,5,5,5,5,5,0,0,6,5,8,6,8,8,8,8, +8,0,6,8,8,0,8,8,6,6,0,0,0,0,0,0, +0,8,8,0,0,0,0,0,0,5,5,0,5,5,6,6, +0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0x1e4b,0x784b,0x34cb, +0x344b,0x3ccb,0x37cb,0x35cb,0x3fcb,0x1b,5,5,5,5,5,5,6,6,8,8, +5,5,5,5,5,5,5,5,5,0,5,5,5,0,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,6,6,5,8,8,8,6,6,6,6,0,8,8, -8,0,8,8,8,6,5,0x1b,0,0,0,0,5,5,5,8, -0xcc0b,0xca0b,0xcb4b,0xc90b,0x364b,0xc94b,0x350b,5,0,0,0,0,0,0,0x49,0x89, -0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,8,8,0x17,0,0,0, -0,0,0,0,0,0,0,0,0,6,8,8,0,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, -0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, -0,5,0,0,5,5,5,5,5,5,5,0,0,0,6,0, -0,0,0,8,8,8,6,6,6,0,6,0,8,8,8,8, -8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,6,5,5,6,6,6,6,6,6,6,0, -0,0,0,0x19,5,5,5,5,5,5,4,6,6,6,6,6, -6,6,6,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17, -0,0,0,0,0,5,5,0,5,0,5,5,5,5,5,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0,5,0,5,5,5,5,5,5,5,5,5, -5,6,5,5,6,6,6,6,6,6,6,6,6,5,0,0, -5,5,5,5,5,0,4,0,6,6,6,6,6,6,6,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,5,5,5,5, -5,0x1b,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x1b,0x17,0x1b,0x1b,0x1b,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x344b,0x3c4b,0x444b,0x4c4b,0x544b,0x5c4b, -0x644b,0x6c4b,0x744b,0x2c4b,0x1b,6,0x1b,6,0x1b,6,0x14,0x15,0x14,0x15,8,8, -5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0,0,0,0,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,8,6,6,6,6,6,0x17,6,6,5,5,5,5, -5,6,6,6,6,6,6,6,6,6,6,6,0,6,6,6, +5,5,5,5,5,5,5,5,5,5,5,6,6,5,8,8, +8,6,6,6,6,0,8,8,8,0,8,8,8,6,5,0x1b, +0,0,0,0,5,5,5,8,0xcc0b,0xca0b,0xcb4b,0xc90b,0x364b,0xc94b,0x350b,5, +0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, +0,0,8,8,0x17,0,0,0,0,0,0,0,0,0,0,0, +0,6,8,8,0,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,0,0,0,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5, +5,5,5,5,5,5,5,5,0,5,0,0,5,5,5,5, +5,5,5,0,0,0,6,0,0,0,0,8,8,8,6,6, +6,0,6,0,8,8,8,8,8,8,8,8,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,6,5,5, +6,6,6,6,6,6,6,0,0,0,0,0x19,5,5,5,5, +5,5,4,6,6,6,6,6,6,6,6,0x17,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0,0,0,0,0,5,5,0, +5,0,5,5,5,5,5,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0,5,0,5, +5,5,5,5,5,5,5,5,5,6,5,5,6,6,6,6, +6,6,6,6,6,5,0,0,5,5,5,5,5,0,4,0, +6,6,6,6,6,6,6,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0,0,5,5,5,5,5,0x1b,0x1b,0x1b,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1b,0x17,0x1b,0x1b,0x1b, +6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0x344b,0x3c4b,0x444b,0x4c4b,0x544b,0x5c4b,0x644b,0x6c4b,0x744b,0x2c4b,0x1b,6,0x1b,6, +0x1b,6,0x14,0x15,0x14,0x15,8,8,5,5,5,5,5,5,5,5, +0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0,0,0,0,6,6,6, +6,6,6,6,6,6,6,6,6,6,6,8,6,6,6,6, +6,0x17,6,6,5,5,5,5,5,6,6,6,6,6,6,6, +6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,0,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b, -0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,8,8,6,6,6, -6,8,6,6,6,6,6,6,8,6,6,8,8,6,6,5, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0x17,0x17,0x17,0x17, -5,5,5,5,5,5,8,8,6,6,5,5,5,5,6,6, -6,5,8,8,8,5,5,8,8,8,8,8,8,8,5,5, -5,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5, -5,5,6,8,8,6,6,8,8,8,8,8,8,6,5,8, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,8,8,8,6,0x1b,0x1b, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,0x17,4,2,2,2, -1,1,1,1,1,1,0,1,0,0,0,0,0,1,0,0, +6,6,6,6,6,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x1b, +0x1b,0x17,0x17,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,8,8,6,6,6,6,8,6,6,6,6,6,6, +8,6,6,8,8,6,6,5,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5,5,5,8,8, +6,6,5,5,5,5,6,6,6,5,8,8,8,5,5,8, +8,8,8,8,8,8,5,5,5,6,6,6,6,5,5,5, +5,5,5,5,5,5,5,5,5,5,6,8,8,6,6,8, +8,8,8,8,8,6,5,8,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,8,8,8,6,0x1b,0x1b,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,0x17,4,2,2,2,1,1,1,1,1,1,0,1, +0,0,0,0,0,1,0,0,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5, +5,0,5,5,5,5,0,0,5,5,5,5,5,5,5,0, +5,0,5,5,5,5,0,0,5,5,5,5,5,5,5,5, +5,0,5,5,5,5,0,0,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,0,5,5,5,5,0,0, 5,5,5,5,5,5,5,0,5,0,5,5,5,5,0,0, -5,5,5,5,5,5,5,5,5,0,5,5,5,5,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0,5,5,5,5,0,0,5,5,5,5,5,5,5,0, 5,0,5,5,5,5,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,0,5,5,5,5,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,0,0,6,6,6, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b, -0x4cb,0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x788b,0,0,0, +5,5,5,0,0,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b, +0x16cb,0x194b,0x1bcb,0x1e4b,0x788b,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0,0,0,0,0,0,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, +2,2,2,2,2,2,0,0,0x13,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0,0,2,2,2,2,2,2,0,0, -0x13,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x1b,0x17,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0xc,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x14, -0x15,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0x17, -0x17,0x17,0x98a,0x9ca,0xa0a,5,5,5,5,5,5,5,5,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,6,6,6,8,0,0,0,0,0,0, -0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,6,6,8,0x17,0x17,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,6,6,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,0,5,5,5,0,6,6,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,6,6,8,6,6,6,6,6, -6,6,8,8,8,8,8,8,8,8,6,8,8,6,6,6, -6,6,6,6,6,6,6,6,0x17,0x17,0x17,4,0x17,0x17,0x17,0x19, -5,6,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, -0,0,0,0,0x54b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,6,5,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x17,0x17,0x17,0x17,6, -6,6,0x10,6,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, -0,0,0,0,5,5,5,4,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x1b,0x17,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0xc,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,0x14,0x15,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,0x17,0x17,0x17,0x98a,0x9ca,0xa0a,5,5,5, 5,5,5,5,5,0,0,0,0,0,0,0,5,5,5,5, -5,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6, +6,8,0,0,0,0,0,0,0,0,0,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6, +8,0x17,0x17,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,0,5,5,5,0,6,6, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +6,6,8,6,6,6,6,6,6,6,8,8,8,8,8,8, +8,8,6,8,8,6,6,6,6,6,6,6,6,6,6,6, +0x17,0x17,0x17,4,0x17,0x17,0x17,0x19,5,6,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0x54b,0x58b,0x5cb,0x60b, +0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,6,5,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x17,0x17,0x17,0x17, +0x17,0x17,0x13,0x17,0x17,0x17,0x17,6,6,6,0x10,6,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,4, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, +0,0,0,0,5,5,5,5,5,6,6,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0, +6,6,6,8,8,8,8,6,6,8,8,8,0,0,0,0, +8,8,6,8,8,8,8,8,8,6,6,6,0,0,0,0, +0x1b,0,0,0,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, -0,0,0,0,0,0,0,0,6,6,6,8,8,8,8,6, -6,8,8,8,0,0,0,0,8,8,6,8,8,8,8,8, -8,6,6,6,0,0,0,0,0x1b,0,0,0,0x17,0x17,0x49,0x89, -0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,5,5,5,5,5,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x30b,0,0,0,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +5,5,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0x30b,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, +6,8,8,6,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,4, +0x17,0x17,0x17,0x17,0x17,0x17,0,0,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,7,6,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,8,6,8, +6,6,6,6,6,6,6,0,6,8,6,8,8,6,6,6, +6,6,6,6,6,8,8,8,8,8,8,6,6,6,6,6, +6,6,6,6,6,0,0,6,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0,0,0,0,0,0,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,6,6,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0x17,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,6,6,6,8,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,6,6,8,8,6,0,0,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,4,0x17,0x17,0x17,0x17,0x17,0x17,0,0, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,6, +5,5,5,5,5,5,5,5,6,8,6,6,6,6,6,8, +6,8,8,8,8,8,6,8,8,5,5,5,5,5,5,5, +5,0,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17, +0x17,0x17,0x17,0x17,5,8,6,6,6,6,8,8,6,6,8,6, +6,6,5,5,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5, +5,5,5,5,6,6,8,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,8,6,8,6,6,6,6,6,6,6,0, -6,8,6,8,8,6,6,6,6,6,6,6,6,8,8,8, -8,8,8,6,6,6,6,6,6,6,6,6,6,0,0,6, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,6,6,6,6, -6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -6,6,6,6,8,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -6,8,6,6,6,6,6,8,6,8,8,8,8,8,6,8, -8,5,5,5,5,5,5,5,5,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0x17,0x17,0x17,0x17,5,8,6,6, -6,6,8,8,6,6,8,6,6,6,5,5,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,5,5,5,5,6,6,8,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,8, -6,6,8,8,8,6,8,6,6,6,8,8,0,0,0,0, -0,0,0,0,0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0,0,0,5,5,5,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,5,5,5,5,5,5,8,8,8,8,8,8,8,8, -6,6,6,6,6,6,6,6,8,8,6,6,0,0,0,0x17, -0x17,0x17,0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4, -4,4,0x17,0x17,2,2,2,2,2,2,2,2,2,0,0,0, -0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, -0,1,1,1,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0, -0,0,0,0,6,6,6,0x17,6,6,6,6,6,6,6,6, -6,6,6,6,6,8,6,6,6,6,6,6,6,5,5,5, -5,6,5,5,5,5,5,5,6,5,5,8,6,6,5,0, -0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +5,5,5,5,5,5,6,8,6,6,8,8,8,6,8,6, +6,6,8,8,0,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17, +0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,5,5,5, +0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,5,5,5,5, +8,8,8,8,8,8,8,8,6,6,6,6,6,6,6,6, +8,8,6,6,0,0,0,0x17,0x17,0x17,0x17,0x17,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,4,4,4,4,4,4,0x17,0x17,2,2,2,2, +2,2,2,2,2,1,2,0,0,0,0,0,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0,0,1,1,1,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,6,6,6,0x17, +6,6,6,6,6,6,6,6,6,6,6,6,6,8,6,6, +6,6,6,6,6,5,5,5,5,6,5,5,5,5,5,5, +6,5,5,8,6,6,5,0,0,0,0,0,2,2,2,2, +2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2, -4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4, -4,4,4,4,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,2,1,2,1,2,2,2,2,2,2,2, -2,2,1,2,2,2,2,2,2,2,2,2,1,1,1,1, -1,0x1a,0x1a,0x1a,0,0,2,2,2,0,2,2,1,1,1,1, -3,0x1a,0x1a,0,2,2,2,2,2,2,2,2,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,0,0,1,1,1,1, -1,1,0,0,2,2,2,2,2,2,2,2,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,0,0,1,1,1,1, -1,1,0,0,2,2,2,2,2,2,2,2,0,1,0,1, -0,1,0,1,2,2,2,2,2,2,2,2,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,0,0,2,2,2,2,2,2,2,2,3,3,3,3, -3,3,3,3,2,2,2,2,2,2,2,2,3,3,3,3, -3,3,3,3,2,2,2,2,2,0,2,2,1,1,1,1, -3,0x1a,2,0x1a,0x1a,0x1a,2,2,2,0,2,2,1,1,1,1, -3,0x1a,0x1a,0x1a,2,2,2,2,0,0,2,2,1,1,1,1, -0,0x1a,0x1a,0x1a,0x16,0x17,0x17,0x17,0x18,0x14,0x15,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x17,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0xc,0x10,0x10,0x10,0x10,0x10,0,0x10,0x10,0x10,0x10,0x10,0x10, -0x10,0x10,0x10,0x10,0x2cb,4,0,0,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x18,0x18, -0x18,0x14,0x15,4,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x10, -0x10,0x10,0x10,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x17,0x17,0x1c,0x1d,0x14,0x1c, -0x1c,0x1d,0x14,0x1c,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0xd,0xe,0x10,0x10, -0x10,0x10,0x10,0xc,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1c,0x1d,0x17, -0x17,0x17,0x17,0x16,0x2cb,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x18,0x18, -0x18,0x14,0x15,0,4,4,4,4,4,4,4,4,4,4,4,4, -4,0,0,0,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, +4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2, +2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,4,4,4,4,4,1,2,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, +1,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, +2,2,2,2,1,1,1,1,1,0x1a,0x1a,0x1a,0,0,2,2, +2,0,2,2,1,1,1,1,3,0x1a,0x1a,0,2,2,2,2, +2,2,2,2,1,1,1,1,1,1,1,1,2,2,2,2, +2,2,0,0,1,1,1,1,1,1,0,0,2,2,2,2, +2,2,2,2,1,1,1,1,1,1,1,1,2,2,2,2, +2,2,2,2,1,1,1,1,1,1,1,1,2,2,2,2, +2,2,0,0,1,1,1,1,1,1,0,0,2,2,2,2, +2,2,2,2,0,1,0,1,0,1,0,1,2,2,2,2, +2,2,2,2,1,1,1,1,1,1,1,1,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2, +2,2,2,2,3,3,3,3,3,3,3,3,2,2,2,2, +2,2,2,2,3,3,3,3,3,3,3,3,2,2,2,2, +2,0,2,2,1,1,1,1,3,0x1a,2,0x1a,0x1a,0x1a,2,2, +2,0,2,2,1,1,1,1,3,0x1a,0x1a,0x1a,2,2,2,2, +0,0,2,2,1,1,1,1,0,0x1a,0x1a,0x1a,0x16,0x17,0x17,0x17, +0x18,0x14,0x15,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x17, +0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0xc,0x10,0x10,0x10,0x10, +0x10,0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x2cb,4,0,0, +0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x18,0x18,0x18,0x14,0x15,4,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x10,0x10,0x10,0x10,0x10,0x13,0x13,0x13,0x13, +0x13,0x13,0x17,0x17,0x1c,0x1d,0x14,0x1c,0x1c,0x1d,0x14,0x1c,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0xd,0xe,0x10,0x10,0x10,0x10,0x10,0xc,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x1c,0x1d,0x17,0x17,0x17,0x17,0x16,0x2cb,0x30b,0x34b,0x38b, +0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x18,0x18,0x18,0x14,0x15,0,4,4,4,4, +4,4,4,4,4,4,4,4,4,0,0,0,0x19,0x19,0x19,0x19, 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, -0x19,0x19,0x19,0x19,0x19,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6, -6,7,7,7,7,6,7,7,7,6,6,6,6,6,6,6, -6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1b,0x1b,0x1b,0x1b,1,0x1b,1,0x1b,1,0x1b,1,1, -1,1,0x1b,2,1,1,1,1,2,5,5,5,5,2,0x1b,0x1b, -2,2,1,1,0x18,0x18,0x18,0x18,0x18,1,2,2,2,2,0x1b,0x18, -0x1b,0x1b,2,0x1b,0x358b,0x360b,0x364b,0x348b,0x388b,0x350b,0x390b,0x3d0b,0x410b,0x354b,0x454b,0x35cb, -0x3dcb,0x45cb,0x4dcb,0x58b,0x1b,0x1b,1,0x1b,0x1b,0x1b,0x1b,1,0x1b,0x1b,2,1, -1,1,2,2,1,1,1,2,0x1b,1,0x1b,0x1b,0x18,1,1,1, -1,1,0x1b,0x1b,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x7ca,0x80a,0x84a, -0x11ca,0x1e4a,0x980a,0x784a,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x7ca,0x80a,0x84a, -0x11ca,0x1e4a,0x980a,0x784a,0x784a,0x984a,0x788a,1,2,0x6ca,0x11ca,0x988a,0x78ca,0x54b,0x1b,0x1b, -0,0,0,0,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x18,0x1b,0x1b,0x18,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x18,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6, +6,6,6,6,6,6,6,6,6,7,7,7,7,6,7,7, +7,6,6,6,6,6,6,6,6,6,6,6,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, +1,0x1b,1,0x1b,1,0x1b,1,1,1,1,0x1b,2,1,1,1,1, +2,5,5,5,5,2,0x1b,0x1b,2,2,1,1,0x18,0x18,0x18,0x18, +0x18,1,2,2,2,2,0x1b,0x18,0x1b,0x1b,2,0x1b,0x358b,0x360b,0x364b,0x348b, +0x388b,0x350b,0x390b,0x3d0b,0x410b,0x354b,0x454b,0x35cb,0x3dcb,0x45cb,0x4dcb,0x58b,0x1b,0x1b,1,0x1b, +0x1b,0x1b,0x1b,1,0x1b,0x1b,2,1,1,1,2,2,1,1,1,2, +0x1b,1,0x1b,0x1b,0x18,1,1,1,1,1,0x1b,0x1b,0x58a,0x5ca,0x60a,0x64a, +0x68a,0x6ca,0x70a,0x74a,0x78a,0x7ca,0x80a,0x84a,0x11ca,0x1e4a,0x980a,0x784a,0x58a,0x5ca,0x60a,0x64a, +0x68a,0x6ca,0x70a,0x74a,0x78a,0x7ca,0x80a,0x84a,0x11ca,0x1e4a,0x980a,0x784a,0x784a,0x984a,0x788a,1, +2,0x6ca,0x11ca,0x988a,0x78ca,0x54b,0x1b,0x1b,0,0,0,0,0x18,0x18,0x18,0x18, +0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x18,0x1b,0x1b,0x18,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x18,0x1b, +0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x14,0x15, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x1b, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x14,0x15,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18, -0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18, -0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x2cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b, -0xa4b,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x2cb,0x30b,0x34b,0x38b,0x3cb, -0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b,0xa4b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x2cb,0x80b,0x84b,0x88b,0x8cb,0x90b, +0x94b,0x98b,0x9cb,0xa0b,0xa4b,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x2cb, 0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b, -0x98b,0x9cb,0xa0b,0xa4b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18, -0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x98b,0x9cb,0xa0b,0xa4b,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x80b,0x84b, +0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b,0xa4b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15, -0x14,0x15,0x14,0x15,0x14,0x15,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb, -0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b, -0x48b,0x4cb,0x50b,0x7cb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x14,0x15, +0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b, +0x48b,0x4cb,0x50b,0x7cb,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x30b,0x34b, +0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x18,0x18,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x18,0x18,0x18,0x18, -0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x14, -0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14, -0x15,0x14,0x15,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14, +0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x14,0x15,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x14,0x15,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x14,0x15,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b, +0x18,0x18,0x18,0x18,0x14,0x15,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18, +0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,1,2,1,1, +1,2,2,1,2,1,2,1,2,1,1,1,1,2,1,2, +2,1,2,2,2,2,2,2,4,4,1,1,1,2,1,2, +2,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,1,2,1,2,6,6,6,1,2, +0,0,0,0,0,0x17,0x17,0x17,0x17,0x344b,0x17,0x17,2,2,2,2, +2,2,0,2,0,0,0,0,0,2,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, +0,0,0,4,0x17,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,6,5,5,5,5,5,5,5,0,5,5,5,5, +5,5,5,0,5,5,5,5,5,5,5,0,5,5,5,5, +5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0, +0,0,0,0,0x17,0x17,0x1c,0x1d,0x1c,0x1d,0x17,0x17,0x17,0x1c,0x1d,0x17, +0x1c,0x1d,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x17,0x17,0x13,0x17, +0x1c,0x1d,0x17,0x17,0x1c,0x1d,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x17,0x17, +0x17,0x17,0x17,4,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x13, +0x17,0x17,0x17,0x17,0x13,0x17,0x14,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x1b,0x1b,0x17,0x17,0x17,0x14,0x15,0x14,0x15,0x14,0x15,0x14, +0x15,0x13,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,1,2,1,1,1,2,2,1, -2,1,2,1,2,1,1,1,1,2,1,2,2,1,2,2, -2,2,2,2,4,4,1,1,1,2,1,2,2,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,1,2,1,2,6,6,6,1,2,0,0,0,0, -0,0x17,0x17,0x17,0x17,0x344b,0x17,0x17,2,2,2,2,2,2,0,2, -0,0,0,0,0,2,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,4, -0x17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, -5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,0, -5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, -0x17,0x17,0x1c,0x1d,0x1c,0x1d,0x17,0x17,0x17,0x1c,0x1d,0x17,0x1c,0x1d,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x17,0x17,0x13,0x17,0x1c,0x1d,0x17,0x17, -0x1c,0x1d,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x17,0x17,0x17,0x17,0x17,4, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x13,0x17,0x17,0x17,0x17, -0x13,0x17,0x14,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x1b,0x1b,0x17,0x17,0x17,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x13,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,6,6, 6,6,8,8,0x13,4,4,4,4,4,0x1b,0x1b,0x7ca,0xa4a,0xcca,4, @@ -777,9 +780,11 @@ static const uint16_t propsTrie_index[23156]={ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,0,0x1b,0x1b,0x58b,0x5cb,0x60b,0x64b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, 0,0,0,0x1b,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x1b,0x1b, +5,5,5,5,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1b,0xa8b,0xacb,0xb0b, 0xb4b,0xb8b,0xbcb,0xc0b,0xc4b,0xc8b,0xccb,0xd0b,0xd4b,0xd8b,0xdcb,0xe0b,0x1b,0x1b,0x1b,0x1b, @@ -875,9 +880,9 @@ static const uint16_t propsTrie_index[23156]={ 1,2,1,2,1,2,1,2,4,0x1a,0x1a,1,2,1,2,5, 1,2,1,2,2,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,1,1,1,1,2,1,1,1,1,1,2,1,2, -1,2,1,2,1,2,1,2,1,1,1,1,2,1,2,0, -0,0,0,0,1,2,0,2,0,2,1,2,1,2,0,0, -0,0,0,0,5,5,6,5,5,5,6,5,5,5,5,6, +1,2,1,2,1,2,1,2,1,1,1,1,2,1,2,1, +1,2,0,0,1,2,0,2,0,2,1,2,1,2,1,2, +1,0,0,0,5,5,6,5,5,5,6,5,5,5,5,6, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,8,8,6,6,8,0x1b,0x1b,0x1b,0x1b, 6,0,0,0,0x34cb,0x344b,0x3ccb,0x37cb,0x35cb,0x3fcb,0x1b,0x1b,0x19,0x1b,0,0, @@ -1024,408 +1029,443 @@ static const uint16_t propsTrie_index[23156]={ 2,2,2,2,2,2,0,2,2,0,0,0,1,1,1,1, 1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0, 1,1,0,2,2,2,2,2,2,2,2,2,5,5,5,5, -5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,4, -4,4,4,4,4,4,4,0,0,0,0,0,4,4,4,4, -4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0,5,5,0,0,0,5,0,0,5,5,5,5,5, -5,5,0,0,5,0,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0x17, -0x58b,0x5cb,0x60b,0x7cb,0xa4b,0x1e4b,0x784b,0x788b,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x1b, -0x1b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x7cb,0xa4b,0,0,0,0,0,0,0,0x58b, -0x5cb,0x60b,0x64b,0x64b,0x68b,0x7cb,0xa4b,0x1e4b,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,0,5,5,0,0, -0,0,0,0x58b,0x68b,0x7cb,0xa4b,0x1e4b,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x58b,0x7cb, -0xa4b,0x1e4b,0x5cb,0x60b,0,0,0,0x17,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0,0,0,0,0,0x17,0xa04b,0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b, -0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x78cb,0x80cb,0x88cb,0x90cb,0x98cb,0xa0cb,0xa8cb,0xb0cb,0xb8cb,0x36cb,0x354b, -0x34cb,0x348b,0x46cb,0x344b,0x4ecb,0x388b,0x3ccb,0x454b,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0,0,0,0,0x5ecb,0x344b,5,5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b, -0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0,0,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b, -0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0x984b,0x30b,0x34b,0x38b,0x3cb,0x7cb,0xa4b,0x1e4b,0x784b, -0x344b,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x17,0,0,0,0,0,0,0,5,6,6,6,0,6,6,0, -0,0,0,0,6,6,6,6,5,5,5,5,0,5,5,5, -0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0,0,6,6,6,0, -0,0,0,6,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x58b,0x11cb,0x17,5,5,5,5,5,5,5,5,5,5,5,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,0,4,4,4,4,4,4, +4,4,4,0,0,0,0,0,4,4,4,4,4,4,0,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5, +5,0,0,0,5,0,0,5,5,5,5,5,5,5,0,0, +5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,0x17,0x58b,0x5cb,0x60b,0x7cb, +0xa4b,0x1e4b,0x784b,0x788b,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0x1b,0x1b,0x58b,0x5cb,0x60b, +0x64b,0x68b,0x7cb,0xa4b,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x64b, +0x68b,0x7cb,0xa4b,0x1e4b,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,0,5,5,0,0,0,0,0,0x58b, +0x68b,0x7cb,0xa4b,0x1e4b,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0x58b,0x7cb,0xa4b,0x1e4b,0x5cb,0x60b, +0,0,0,0x17,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, +0,0,0,0x17,0xa04b,0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b, +0xb88b,0x78cb,0x80cb,0x88cb,0x90cb,0x98cb,0xa0cb,0xa8cb,0xb0cb,0xb8cb,0x36cb,0x354b,0x34cb,0x348b,0x46cb,0x344b, +0x4ecb,0x388b,0x3ccb,0x454b,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, +0x5ecb,0x344b,5,5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb, +0xf4b,0x11cb,0x144b,0x16cb,0,0,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b, +0x804b,0x884b,0x904b,0x984b,0x30b,0x34b,0x38b,0x3cb,0x7cb,0xa4b,0x1e4b,0x784b,0x344b,0,0,0, +0,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0, +0,0,0,0,5,6,6,6,0,6,6,0,0,0,0,0, +6,6,6,6,5,5,5,5,0,5,5,5,0,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x58b,0x7cb,0xa4b,5,5,5,5,5,6,6,0,0,0,0,0x58b, -0x68b,0x7cb,0xa4b,0x1e4b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,0x1b,5,5,5, +5,5,5,5,5,5,0,0,6,6,6,0,0,0,0,6, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x58b,0x11cb,0x17, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0x784b, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x58b,0x7cb,0xa4b, +5,5,5,5,5,6,6,0,0,0,0,0x58b,0x68b,0x7cb,0xa4b,0x1e4b, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,0x1b,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0x784b, +5,5,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17,0,0,0, -0,0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b, +5,5,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0x784b,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, +0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0x784b,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, +0,0,0,0,0,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0, +0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, +0,0,0,0,0,0,0x58b,0x68b,0x7cb,0x11cb,0x1e4b,0x784b,5,5,5,5, +6,6,6,6,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,1,1,1,1, +1,1,0,0,0,6,6,6,6,6,0x13,4,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0, +0,0,0,0,0,0,0x18,0x18,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,5,5,5,5,4,5,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb, +0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b, +0xa80b,0xb00b,0xb80b,0x344b,0x34cb,0x348b,0x388b,0,5,5,5,5,5,5,5,5, +5,5,0,6,6,0x13,0,0,5,5,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,6,6,6,0,0,5,5, +5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x7cb,0xa4b, +0xccb,0x1e4b,0x344b,5,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6, +6,6,6,6,6,6,6,6,6,0x58b,0x7cb,0xa4b,0x1e4b,0x17,0x17,0x17, +0x17,0x17,0,0,0,0,0,0,5,5,6,6,6,6,0x17,0x17, +0x17,0x17,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,0x58b,0x5cb,0x60b, +0x64b,0x7cb,0xa4b,0x1e4b,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x784b,0x49,0x89, +0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,6,5,5,6,6,5,0,0, +0,0,0,0,0,0,0,6,8,6,8,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b, +0x48b,0x4cb,0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,8,8,8,6,6,6,6,8, +8,6,6,0x17,0x17,0x10,0x17,0x17,0x17,0x17,6,0,0,0,0,0, +0,0,0,0,0,0x10,0,0,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,0,0,0,0,0,0,0,0x58b,0x68b,0x7cb,0x11cb,0x1e4b,0x784b, -5,5,5,5,6,6,6,6,0,0,0,0,0,0,0,0, 0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb, -0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x344b,0x34cb,0x348b,0x388b,0, -5,5,5,5,5,5,5,5,5,5,0,6,6,0x13,0,0, -5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,6,6,6,6,6,8,6,6,6, +6,6,6,6,6,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, +0x17,0x17,0x17,0x17,5,8,8,5,0,0,0,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x7cb,0xa4b,0xccb,0x1e4b,0x344b,5,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6, -6,0x58b,0x7cb,0xa4b,0x1e4b,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0, -5,5,6,6,6,6,0x17,0x17,0x17,0x17,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x784b,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, -6,5,5,6,6,5,0,0,0,0,0,0,0,0,0,6, -8,6,8,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -6,6,6,6,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0, -0,0,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb, +6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -8,8,8,6,6,6,6,8,8,6,6,0x17,0x17,0x10,0x17,0x17, -0x17,0x17,6,0,0,0,0,0,0,0,0,0,0,0x10,0,0, +5,5,5,6,0x17,0x17,5,0,0,0,0,0,0,0,0,0, +8,5,5,5,5,0x17,0x17,0x17,0x17,6,6,6,6,0x17,8,6, +0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,0x17,5,0x17,0x17,0x17, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0,0,0,0,0,0,5,5,5,5,5,5,5,6, -6,6,6,6,8,6,6,6,6,6,6,6,6,0,0x49,0x89, -0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0x17,0x17,5,8,8,5, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,6,6,6,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,6,0x17,0x17,5,0, -0,0,0,0,0,0,0,0,8,5,5,5,5,0x17,0x17,0x17, -0x17,6,6,6,6,0x17,8,6,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,5,0x17,5,0x17,0x17,0x17,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,8,8,8,6,6, -6,6,6,6,6,6,6,8,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b, -0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x784b,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,8,8,8,6,6,6,8,8,6,8,6,6, -0x17,0x17,0x17,0x17,0x17,0x17,6,5,5,6,0,0,0,0,0,0, +5,5,5,8,8,8,6,6,6,6,6,6,6,6,6,8, +0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b, +0x16cb,0x194b,0x1bcb,0x1e4b,0x784b,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,6, +6,6,8,8,6,8,6,6,0x17,0x17,0x17,0x17,0x17,0x17,6,5, +5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,0,5,0,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0,5,5,5,5,5,5,5,5,5,5,0x17,0,0, +5,5,5,0,5,0,5,5,5,5,0,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5, +5,5,5,5,5,0x17,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,6, +6,6,6,6,6,6,6,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,8,8, +0,0,6,6,6,6,6,6,6,0,0,0,6,6,6,6, +6,0,0,0,0,0,0,0,0,0,0,0,6,6,8,8, +0,5,5,5,5,5,5,5,5,0,0,5,5,0,0,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, +5,5,5,5,5,0,5,5,0,5,5,5,5,5,0,6, +6,5,8,8,6,8,8,8,8,0,0,8,8,0,0,8, +8,8,0,0,5,0,0,0,0,0,0,8,0,0,0,0, +0,5,5,5,0,6,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,0,5, +0,0,5,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,5,8,8,8,6, +6,6,6,6,6,0,8,0,0,8,0,8,8,8,8,0, +8,8,6,8,6,5,6,5,0x17,0x17,0,0x17,0x17,0,0,0, 0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,8,8,8,6,6,6,6,6,6,6,6,0, +5,5,5,5,5,5,5,5,5,8,8,8,6,6,6,6, +6,6,6,6,8,8,6,6,6,8,6,5,5,5,5,0x17, +0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17, +0,0x17,6,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,8,8,8,6,6,6,6,6,6,8,6,8, +8,8,8,6,6,8,6,6,5,5,0x17,5,0,0,0,0, 0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, -0,0,0,0,5,5,8,8,0,0,6,6,6,6,6,6, -6,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0, -0,0,0,0,6,6,8,8,0,5,5,5,5,5,5,5, -5,0,0,5,5,0,0,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,5,5,5,5,5,5,5,0,5,5, -0,5,5,5,5,5,0,6,6,5,8,8,6,8,8,8, -8,0,0,8,8,0,0,8,8,8,0,0,5,0,0,0, -0,0,0,8,0,0,0,0,0,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,8,8,8,6,6,6,6,6,6,6,6,8,8,6,6, -6,8,6,5,5,5,5,0x17,0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0,0x17,6,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,6, -6,6,6,6,6,8,6,8,8,8,8,6,6,8,6,6, -5,5,0x17,5,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,8,8,8,6,6, -6,6,0,0,8,8,8,8,6,6,8,6,6,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,5,5,5,5,6,6,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,6, -6,6,6,6,6,6,6,8,8,6,8,6,6,0x17,0x17,0x17, -5,0,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,8,8,8,6,6,6,6,0,0,8,8,8,8, +6,6,8,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5, +6,6,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,8,8,8,6,6,6,6,6,6,6,6,8, +8,6,8,6,6,0x17,0x17,0x17,5,0,0,0,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x49,0x89, +0xc9,0x109,0x149,0x189,5,5,5,5,5,5,5,5,5,5,5,6, +8,6,8,8,6,6,6,6,6,6,8,6,5,0x17,0,0, +0,0,0,0,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,8,8,6,6,6,6,8,6,6,6,6,6, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b, +0x17,0x17,0x17,0x1b,5,5,5,5,5,5,5,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, +0,6,8,6,5,5,5,5,5,5,5,5,5,5,5,5, +8,8,8,6,6,6,6,6,6,6,6,6,8,6,6,0x17, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b, +0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0,0,0,0,0,0,0,0,0, +0,0,0,5,8,5,8,6,0x17,0x17,0x17,0,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,5,5,5,5,5,5,5,0,0,5,0,0, +5,5,5,5,5,5,5,5,0,5,5,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,8, +8,8,0,8,8,0,0,6,6,8,6,5,6,5,0x17,5, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,6,8,6,8,8,6,6,6,6, -6,6,8,6,5,0x17,0,0,0,0,0,0,8,8,6,6, -6,6,8,6,6,6,6,6,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b,0x17,0x17,0x17,0x1b,5,5,5,5, -5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,0,0,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,8,8,8, +6,6,6,6,0,0,6,6,8,8,8,8,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, +6,6,6,6,6,8,5,6,6,6,6,0x17,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,6,0,0,0,0,0,0,0,0,5,6,6,6, +6,6,6,8,8,6,6,6,5,5,5,5,5,6,6,6, +6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x17,0x17,0x17,0, 0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,8,8,8,6,6,6,6,6, -6,6,6,6,8,6,6,0x17,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0, -0,0,0,0,0,0,0,0,0,0,0,5,8,5,8,6, -0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, -5,5,5,0,0,5,0,0,5,5,5,5,5,5,5,5, -0,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,8,8,8,8,8,8,0,8,8,0,0,6, -6,8,6,5,6,5,0x17,5,8,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6, +6,6,6,6,6,6,6,6,6,6,6,8,6,6,0x17,0x17, +0x17,5,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,0,0,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,8,8,8,6,6,6,6,0,0,6,6, -8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,6,6,6,6,6,6,8,5,6, -6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,6,0,0,0,0, -0,0,0,0,5,6,6,6,6,6,6,8,8,6,6,6, -5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,5, +0,0,0,0,5,0x17,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,5,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x58b,0x5cb, +0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb, +0x1e4b,0,0,0,0x17,0x17,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,8, +6,6,6,6,6,6,6,0,6,6,6,6,6,6,8,6, +6,6,6,6,6,6,6,6,0,8,6,6,6,6,6,6, +6,8,6,6,8,6,6,0,0,0,0,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6, -6,6,6,8,6,6,0x17,0x17,0x17,5,0x17,0x17,5,0x17,0x17,0x17, -0x17,0x17,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x70b,0x74b,0x78b,0x7cb, -0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0,0,0,0x17,0x17,5,5, +0,0,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,5,6,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, +5,5,5,0,5,5,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6, +6,6,6,0,0,0,6,0,6,6,0,6,5,5,5,5, +5,5,5,5,5,5,8,8,8,8,8,0,6,6,0,8, +8,6,8,6,5,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,0,5,5,0,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, +6,8,8,0x17,0x17,0,0,0,0,0,0,0,6,8,6,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,6,0,0,0,0,0,6,6,5,8, 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,8,6,6,6,6,6,6,6,0, -6,6,6,6,6,6,8,6,6,6,6,6,6,6,6,6, -0,8,6,6,6,6,6,6,6,8,6,6,8,6,6,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0,0,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,5,6,0,0,0,0, -0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, -0,0,0,0,5,5,5,5,5,5,5,0,5,5,0,5, +5,5,5,5,8,8,6,6,6,6,6,0,0,0,8,8, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0x17, +0xcd0b,0xcc0b,0xcb0b,0xd00b,0xca0b,0xcf0b,0xcb4b,0xd04b,0xc90b,0x37cb,0x37cb,0x364b,0x35cb,0xc94b,0x3fcb,0x350b, +0x34cb,0x344b,0x344b,0x3ccb,0xcd0b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x19,0x19, +0x34ca,0x354a,0x34ca,0x34ca,0x344a,0x348a,0x388a,0xf4a,0x11ca,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0, +0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0,0, +0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x64a, +0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca, +0x60a,0x64a,0x68a,0x5ca,0x60a,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x60a, +0x64a,0x68a,0xc08a,0xc18a,0x58a,0x5ca,0x60a,0x60a,0x64a,0x68a,0x60a,0x60a,0x64a,0x64a,0x64a,0x64a, +0x6ca,0x70a,0x70a,0x70a,0x74a,0x74a,0x78a,0x78a,0x78a,0x78a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x58a, +0x5ca,0x60a,0x64a,0x64a,0x68a,0x68a,0x5ca,0x60a,0x58a,0x5ca,0x348a,0x388a,0x454a,0x348a,0x388a,0x35ca, +5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,6,6,6,6,6,6,0,0,0,6,0, -6,6,0,6,5,5,5,5,5,5,5,5,5,5,8,8, -8,8,8,0,6,6,0,8,8,6,8,6,5,0,0,0, -0,0,0,0,5,5,5,5,5,5,0,5,5,0,5,5, +5,0x17,0x17,0,0,0,0,0,0,0,0,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,6,6,8,8,0x17,0x17,0,0,0, -0,0,0,0,6,8,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, -0,0,0,0,6,6,5,8,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,8,8,6,6, -6,6,6,0,0,0,8,8,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x17,0xcd0b,0xcc0b,0xcb0b,0xd00b,0xca0b,0xcf0b,0xcb4b,0xd04b, -0xc90b,0x37cb,0x37cb,0x364b,0x35cb,0xc94b,0x3fcb,0x350b,0x34cb,0x344b,0x344b,0x3ccb,0xcd0b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x19,0x19,0x34ca,0x354a,0x34ca,0x34ca,0x344a,0x348a,0x388a,0xf4a, -0x11ca,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0,0x17,0x17,0x17,0x17,0x17,0,0,0, -0,0,0,0,0,0,0,0,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a, -0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a, -0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x64a,0x68a,0x5ca,0x60a,0x60a,0x64a,0x68a, -0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x60a,0x64a,0x68a,0xc08a,0xc18a,0x58a,0x5ca,0x60a,0x60a, -0x64a,0x68a,0x60a,0x60a,0x64a,0x64a,0x64a,0x64a,0x6ca,0x70a,0x70a,0x70a,0x74a,0x74a,0x78a,0x78a, -0x78a,0x78a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x58a,0x5ca,0x60a,0x64a,0x64a,0x68a,0x68a,0x5ca,0x60a, -0x58a,0x5ca,0x348a,0x388a,0x454a,0x348a,0x388a,0x35ca,5,5,5,5,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,0x17,0x17,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, -0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6,5,5,5,5,5,5,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,0,0, -0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0,0,6,6,6,6, -6,0x17,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +6,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0, +6,6,6,6,6,6,6,6,6,6,8,8,8,6,6,6, +0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,0,0,6,6,6,6,6,0x17,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,6,6,6,6,6,6,6,0x17,0x17,0x17,0x17,0x17, +0x1b,0x1b,0x1b,0x1b,4,4,4,4,0x17,0x1b,0,0,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0x7cb, +0x1e4b,0x788b,0x790b,0x798b,0x7a0b,0x7a8b,0,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6, -6,6,6,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x1b,0x1b,4,4,4,4, -0x17,0x1b,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0x7cb,0x1e4b,0x788b,0x790b,0x798b,0x7a0b,0x7a8b,0,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0,0,0,0,0,5,5,5,0x54b,0x58b,0x5cb,0x60b, -0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b, -0x58b,0x5cb,0x60b,0x17,0x17,0x17,0x17,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,0,0,0,0,6,5,8,8,8, -8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4, +4,0x17,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,4,4,4,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,0x54b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x80b, +0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b,0x58b,0x5cb,0x60b,0x17,0x17,0x17,0x17,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0, +0,0,0,6,5,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -0,0,0,0,0,0,0,6,6,6,6,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,0x17,4,6,0,0,0, -0,0,0,0,0,0,0,0,8,8,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +8,8,8,8,8,8,8,8,0,0,0,0,0,0,0,6, +6,6,6,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,0x17,4,6,0,0,0,0,0,0,0,0,0,0,0, +8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,0,4,4,4,4,4,4,4,0,4,4,0, -5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,0,0,5,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,0,0,0x1b,6,6,0x17,0x10,0x10,0x10,0x10, +0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,0,4,4,4, +4,4,4,4,0,4,4,0,5,5,5,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0, +0,5,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,0,0, +0x1b,6,6,0x17,0x10,0x10,0x10,0x10,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,0,0,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0, -0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b, +0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,0,0,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,6,0,0,0,0,0,0,0,0,0, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,8,8,6,6,6,0x1b,0x1b,0x1b,8,8,8, -8,8,8,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6,6,6,6,6, -6,6,6,0x1b,0x1b,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,8,8,6, +6,6,0x1b,0x1b,0x1b,8,8,8,8,8,8,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,6,6,6,6,6,6,6,6,0x1b,0x1b,6,6,6, +6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,6,6,6,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,6,6,0x1b,0,0, +0x1b,0x1b,6,6,6,0x1b,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x54b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b, -0x74b,0x78b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b,0,0,0,0, -0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b, -0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x58b,0x5cb,0x60b,0x64b,0x68b,0x58b, -0x68b,0,0,0,0,0,0,0,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x49,0x89, -0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,1,1,1,1,1,1,1,1, +0x54b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b, +0x94b,0x98b,0x9cb,0xa0b,0,0,0,0,0,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0, +0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb, +0x194b,0x1bcb,0x58b,0x5cb,0x60b,0x64b,0x68b,0x58b,0x68b,0,0,0,0,0,0,0, +0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, +2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,1,0,1,1,0,0,1,0,0,1,1,0, +0,1,1,1,1,0,1,1,1,1,1,1,1,1,2,2, +2,2,0,2,0,2,2,2,2,2,2,2,0,2,2,2, 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,2,2,2,2,2,2,2,0,2,2, +1,1,1,1,1,1,1,1,2,2,2,2,1,1,0,1, +1,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1, +1,1,1,1,1,0,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,0, +0,0,1,1,1,1,1,1,1,0,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,1,0,1,1, -0,0,1,0,0,1,1,0,0,1,1,1,1,0,1,1, -1,1,1,1,1,1,2,2,2,2,0,2,0,2,2,2, -2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -2,2,2,2,1,1,0,1,1,1,1,0,0,1,1,1, -1,1,1,1,1,0,1,1,1,1,1,1,1,0,2,2, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,1,1,0,1,1,1,1,0, -1,1,1,1,1,0,1,0,0,0,1,1,1,1,1,1, -1,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, +1,1,1,1,1,1,1,1,1,0x18,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,0x18,2,2,2,2,2,2,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -2,2,2,2,2,2,0,0,1,1,1,1,1,1,1,1, +1,1,1,0x18,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,0x18,2,2,2,2,2,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0x18,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,0x18,2,2,2,2, -2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x18,2,2,2,2, +2,2,2,0x18,2,2,2,2,2,2,1,2,0,0,0x49,0x89, +0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,6,6,6,6,6, +6,6,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x17, +0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,6,6,6,6,6,6,6,6,0,6,6,6,6, +6,6,6,6,6,6,6,6,6,6,6,6,6,0,0,6, +6,6,6,6,2,2,2,2,2,2,2,2,2,2,5,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,0x18,2,2,2,2,2,2,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,2,2,2,0x18,2,2,2,2, -2,2,1,2,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0x1b, -0x1b,0x1b,0x1b,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6, -6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,0,0,6,6,6,6,6,2,2,2,2, -2,2,2,2,2,2,5,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0, -0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,6, -6,0,6,6,6,6,6,0,0,0,0,0,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,5,0x1b,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,0,0,0,6,6,6,6, -6,6,6,4,4,4,4,4,4,4,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,6,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,6,6,6,6,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0x19,5,5,5,5, -5,5,5,5,5,5,5,4,6,6,6,6,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, -5,5,5,0,5,5,5,5,0,5,5,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5, -5,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,6,6,6,6, -6,6,6,0,0,0,0,0,0,0,0,0,2,2,2,2, -6,6,6,6,6,6,6,4,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0x17,0x17,1,1,2,2, +2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,6,6,0,6,6,0,6,6,6,6,6,0, +0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,5,0x1b,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,0,0,0,6,6,6,6,6,6,6,4,4,4,4,4, +4,4,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +6,6,6,6,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0x19,5,5,5,5,5,5,5,5,5,5,5,4, +6,6,6,6,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,6,6,5,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0, +0,0,0,0x17,5,5,5,5,5,5,5,0,5,5,5,5, +0,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,0,5,5,5,5,5,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b, +0x6cb,0x70b,0x74b,0x78b,6,6,6,6,6,6,6,0,0,0,0,0, +0,0,0,0,2,2,2,2,6,6,6,6,6,6,6,4, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0x17,0x17,1,1,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b, -0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x78cb,0x794b,0x814b,0x58b, -0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x1b,0x34cb,0x344b,0x3ccb,0x19,0x58b,0x5cb,0x788b, -0x78cb,0,0,0,0,0,0,0,0,0,0,0,0x16cb,0x194b,0x1bcb,0x1e4b, -0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0x984b,0xa04b,0xa84b,0xb04b, -0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x78cb,0x80cb,0x984b,0xa04b,0xa84b,0xb04b, -0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x1b,0x5cb,0x60b,0x64b,0x68b,0x6cb, -0x70b,0x74b,0x78b,0x7cb,0x900b,0xa00b,0x804b,0x788b,0x344b,0x354b,0,0,0,0x58b,0x5cb,0x60b, -0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b, -0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x18,0x18,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,0, -5,0,0,5,0,5,5,5,5,5,5,5,5,5,5,0, -5,5,5,5,0,5,0,5,0,0,0,0,0,0,5,0, -0,0,0,5,0,5,0,5,0,5,5,5,0,5,5,0, -5,0,0,5,0,5,0,5,0,5,0,5,0,5,5,0, -5,0,0,5,5,5,5,0,5,5,5,5,5,5,5,0, -5,5,5,5,0,5,5,5,5,0,5,0,5,5,5,5, -5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0,0,0,0,0,5,5,5, -0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x2cb,0x2cb,0x30b,0x34b, -0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x54b,0x54b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0, -0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0x1b,0x1b,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, +2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b, +0xccb,0xf4b,0x11cb,0x144b,0x78cb,0x794b,0x814b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b, +0x1b,0x34cb,0x344b,0x3ccb,0x19,0x58b,0x5cb,0x788b,0x78cb,0,0,0,0,0,0,0, +0,0,0,0,0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b, +0x784b,0x804b,0x884b,0x904b,0x984b,0xa04b,0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b, +0xb08b,0xb88b,0x78cb,0x80cb,0x984b,0xa04b,0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b, +0xb08b,0xb88b,0x1b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x900b,0xa00b,0x804b,0x788b, +0x344b,0x354b,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b, +0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b, +0x784b,0x804b,0x884b,0x904b,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x18,0x18,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,0,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,0,5,5,0,5,0,0,5,0,5,5,5, +5,5,5,5,5,5,5,0,5,5,5,5,0,5,0,5, +0,0,0,0,0,0,5,0,0,0,0,5,0,5,0,5, +0,5,5,5,0,5,5,0,5,0,0,5,0,5,0,5, +0,5,0,5,0,5,5,0,5,0,0,5,5,5,5,0, +5,5,5,5,5,5,5,0,5,5,5,5,0,5,5,5, +5,0,5,0,5,5,5,5,5,5,5,5,5,5,0,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +0,0,0,0,0,5,5,5,0,5,5,5,5,5,0,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x2cb,0x2cb,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x54b, +0x54b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0, +0,0,0,0,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a, +0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0, +0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0, +0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0,0,0,0,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0, +0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 5,0x705,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -1464,2580 +1504,2759 @@ static const uint16_t propsTrie_index[23156]={ static const UTrie2 propsTrie={ propsTrie_index, - propsTrie_index+4692, + propsTrie_index+4748, nullptr, - 4692, - 18464, + 4748, + 19048, 0xa40, - 0x12d4, + 0x130c, 0x0, 0x0, 0x110000, - 0x5a70, + 0x5cf0, nullptr, 0, false, false, 0, nullptr }; -static const uint16_t propsVectorsTrie_index[32784]={ -0x53e,0x546,0x54e,0x556,0x56e,0x576,0x57e,0x586,0x58e,0x596,0x59e,0x5a6,0x5ae,0x5b6,0x5be,0x5c6, -0x5cd,0x5d5,0x5dd,0x5e5,0x5ed,0x5f5,0x5fd,0x605,0x60d,0x615,0x61d,0x625,0x62d,0x635,0x63d,0x645, -0x64d,0x655,0x65c,0x664,0x66c,0x674,0x67c,0x684,0x68c,0x694,0x699,0x6a1,0x6a8,0x6b0,0x6b8,0x6c0, -0x6c8,0x6d0,0x6d8,0x6e0,0x6e7,0x6ef,0x6f7,0x6ff,0x707,0x70f,0x717,0x71f,0x727,0x72f,0x737,0x73f, -0x1b48,0xd94,0xe60,0x1197,0x12d6,0x1d10,0x1eaf,0x1d08,0x13f5,0x1405,0x13ed,0x13fd,0x814,0x81a,0x822,0x82a, -0x832,0x838,0x840,0x848,0x850,0x856,0x85e,0x866,0x86e,0x874,0x87c,0x884,0x88c,0x894,0x89c,0x8a3, -0x8ab,0x8b1,0x8b9,0x8c1,0x8c9,0x8cf,0x8d7,0x8df,0x8e7,0x140d,0x8ef,0x8f7,0x8ff,0x906,0x90e,0x916, -0x91e,0x922,0x92a,0x931,0x939,0x941,0x949,0x951,0x1727,0x172f,0x959,0x961,0x969,0x971,0x979,0x980, -0x178d,0x177d,0x1785,0x1a82,0x1a8a,0x141d,0x988,0x1415,0x1670,0x1670,0x1672,0x1431,0x1432,0x1425,0x1427,0x1429, -0x1795,0x1797,0x990,0x1797,0x998,0x99d,0x9a5,0x179c,0x9ab,0x1797,0x9b1,0x9b9,0xc74,0x17a4,0x17a4,0x9c1, -0x17b4,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5,0x17b5, -0x17b5,0x17b5,0x17b5,0x17ac,0x9c9,0x17bd,0x17bd,0x9d1,0xb9c,0xba4,0xbac,0xbb4,0x17cd,0x17c5,0x9d9,0x9e1, -0x9e9,0x17d7,0x17df,0x9f1,0x17d5,0x9f9,0x1b50,0xd9c,0xbbc,0xbc4,0xbcc,0xbd1,0x19e8,0xc9b,0xca2,0x1944, -0xc4c,0x1b58,0xda4,0xdac,0xdb4,0xdbc,0xf6a,0xf6e,0x1a48,0x1a4d,0xcda,0xce2,0x1abe,0x1ac6,0x1c28,0xe68, -0x1ace,0xd28,0xd30,0x1ad6,0x110f,0x11bf,0xf42,0xdc4,0x1964,0x194c,0x195c,0x1954,0x1a00,0x19f8,0x19b4,0x1a40, -0x1442,0x1442,0x1442,0x1442,0x143a,0x1442,0x1442,0x1444,0xa01,0x144c,0xa05,0xa0d,0x144c,0xa15,0xa1d,0xa25, -0x145c,0x1454,0x1464,0xa2d,0xa35,0x146c,0xa3d,0xa45,0x1474,0x147c,0x1484,0x148c,0xa4d,0x1494,0x149b,0x14a3, -0x14ab,0x14b3,0x14bb,0x14c3,0x14cb,0x14d2,0x14da,0x14e2,0x14ea,0x14f2,0x14f5,0x14f7,0x17e7,0x18da,0x18e0,0x1a30, -0x14ff,0xa55,0xa5d,0x1625,0x162a,0x162d,0x1633,0x1507,0x163b,0x163b,0x1517,0x150f,0x151f,0x1527,0x152f,0x1537, -0x153f,0x1547,0x154f,0x1557,0x18e8,0x193c,0x1a92,0x1bf0,0x1567,0x156d,0x1575,0x157d,0x155f,0x1585,0x18f0,0x18f7, -0x17ef,0x17ef,0x17ef,0x17ef,0x17ef,0x17ef,0x17ef,0x17ef,0x18ff,0x18ff,0x18ff,0x18ff,0x1907,0x190e,0x1910,0x1917, -0x191f,0x1923,0x1923,0x1926,0x1923,0x1923,0x192c,0x1923,0x196c,0x1a38,0x1a9a,0xbd9,0xbdf,0x1d54,0x1d5c,0x1e3a, -0x19d8,0x19cc,0x19d0,0x1a55,0x19bc,0x19bc,0x19bc,0xc5c,0x19c4,0xc7c,0x1a18,0xcca,0xc64,0xc6c,0xc6c,0x1ade, -0x1a08,0x1aa2,0xcb2,0xcba,0xa65,0x17f7,0x17f7,0xa6d,0x17ff,0x17ff,0x17ff,0x17ff,0x17ff,0x17ff,0xa75,0x747, -0x1658,0x167a,0xa7d,0x1682,0xa85,0x168a,0x1692,0x169a,0xa8d,0xa92,0x16a2,0x16a9,0xa97,0x1807,0x1a28,0xc54, -0xa9f,0x1704,0x170b,0x16b1,0x1713,0x1717,0x16b9,0x16bd,0x16d6,0x16d6,0x16d8,0x16c5,0x16cd,0x16cd,0x16ce,0x171f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, -0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x1812,0x1974,0x1974, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, -0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e7,0x1b40,0x1f1b, -0x181a,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820, -0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820,0x1820, -0x1820,0x1820,0x1820,0x1820,0xaa7,0x1828,0xaaf,0x1b60,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb, -0x1ae6,0xd38,0x1afb,0x1af3,0x1afd,0x1b68,0x1b68,0xdcc,0x19e0,0x1a5d,0x1ab2,0x1ab6,0x1aaa,0x1c20,0xcea,0xcf1, -0x1a10,0xcc2,0x1a65,0xcf9,0x1b05,0x1b08,0xd40,0x1b70,0x1b18,0x1b10,0xd48,0xdd4,0x1b78,0x1b7c,0xddc,0x1019, -0x1b20,0xd50,0xd58,0x1b84,0x1b94,0x1b8c,0xde4,0xf12,0xe70,0xe78,0x1daa,0xfc9,0x1e57,0x1e57,0x1b9c,0xdec, -0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770, -0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772, -0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774, -0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f, -0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771, -0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773, -0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775, -0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770, -0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772, -0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774, -0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f, -0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771, -0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773, -0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775, -0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770, -0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772, -0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774, -0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f, -0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771, -0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773, -0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775, -0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x176f,0x1770,0x1771,0x1772,0x1773,0x1774,0xab7,0xdf4,0xdf7, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747, -0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747,0x1747, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643, -0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x1643,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef, -0x16f4,0x16fc,0x1934,0x13a2,0x1a20,0x1a20,0x13a6,0x13ad,0xabf,0xac7,0xacf,0x15a5,0x15ac,0x15b4,0xad7,0x15bc, -0x15fa,0x15fa,0x158d,0x1595,0x15c4,0x15f1,0x15f2,0x1602,0x15cc,0x15d1,0x15d9,0x15e1,0xadf,0x15e9,0xae7,0x159d, -0xcd2,0x160a,0xaef,0xaf7,0x1612,0x1618,0x161d,0xaff,0xb0f,0x1660,0x1668,0x164b,0x1650,0xb17,0xb1f,0xb07, -0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737, -0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x173f,0x173f,0x173f,0x173f, -0x1578,0x1578,0x15b8,0x15f8,0x1638,0x1678,0x16b8,0x16f8,0x1734,0x1774,0x17b4,0x17f4,0x1834,0x1874,0x18b4,0x18f4, -0x1934,0x1970,0x19b0,0x19f0,0x1a30,0x1a64,0x1aa0,0x1ae0,0x1b20,0x1b60,0x1b9c,0x1bdc,0x1c1c,0x1c5c,0x1c9c,0x1cdc, -0xe59,0xa80,0xac0,0xb00,0xb40,0xb6b,0xf99,0xa40,0xed9,0xa40,0xa40,0xa40,0xa40,0xbab,0x13f5,0x13f5, -0xf19,0xfd9,0xa40,0xa40,0xa40,0xbeb,0xf59,0xc2b,0xa40,0xc51,0xc91,0xcd1,0xd11,0xd51,0xe99,0xdc9, -0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335, -0x1335,0x1335,0x1335,0x1335,0x1019,0x1375,0x116a,0x11aa,0x13b5,0x11b5,0x1435,0x1435,0x1435,0x1059,0x108c,0x10cc, -0x1475,0x1475,0x11f5,0x14b5,0x110c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c, -0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x112a, +static const uint16_t propsVectorsTrie_index[32324]={ +0x51d,0x525,0x52d,0x535,0x54d,0x555,0x55d,0x565,0x56d,0x575,0x57d,0x585,0x58d,0x595,0x59d,0x5a5, +0x5ac,0x5b4,0x5bc,0x5c4,0x5cc,0x5d4,0x5dc,0x5e4,0x5ec,0x5f4,0x5fc,0x604,0x60c,0x614,0x61c,0x624, +0x62c,0x634,0x63b,0x643,0x64b,0x653,0x65b,0x663,0x66b,0x673,0x678,0x680,0x687,0x68f,0x697,0x69f, +0x6a7,0x6af,0x6b7,0x6bf,0x6c6,0x6ce,0x6d6,0x6de,0x6e6,0x6ee,0x6f6,0x6fe,0x706,0x70e,0x716,0x71e, +0x1b20,0x726,0x72e,0x736,0x73c,0x1c5c,0x1e3e,0x1ca0,0x1553,0x1559,0x1561,0x154b,0x744,0x74a,0x752,0x75a, +0x762,0x768,0x770,0x778,0x780,0x786,0x78e,0x796,0x79e,0x7a4,0x7ac,0x7b4,0x7bc,0x7c4,0x7cc,0x7d3, +0x7db,0x7e1,0x7e9,0x7f1,0x7f9,0x7ff,0x807,0x80f,0x817,0x15b0,0x81f,0x827,0x82f,0x836,0x83e,0x846, +0x84e,0x852,0x85a,0x53d,0x862,0x86a,0x872,0x53d,0x16c2,0x16ca,0x87a,0x882,0x88a,0x892,0x89a,0x53d, +0x174e,0x1746,0x173e,0x1a39,0x1a31,0x1571,0x8a2,0x1569,0x1650,0x1650,0x1652,0x158d,0x158e,0x1581,0x1583,0x1585, +0x1708,0x170a,0x8aa,0x170a,0x8b2,0x8b7,0x8bf,0x170f,0x8c5,0x170a,0x8cb,0x8d3,0x8db,0x1700,0x1700,0x8e3, +0x1766,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, +0x1767,0x1767,0x1767,0x175e,0x8eb,0x1756,0x1756,0x8f3,0x8fb,0x903,0x90b,0x913,0x171f,0x1717,0x91b,0x923, +0x92b,0x1727,0x172f,0x933,0x1736,0x93b,0x1ac0,0x93f,0x947,0x94f,0x957,0x95c,0x1967,0x964,0x96b,0x18d3, +0x973,0x1af8,0x97b,0x983,0x98b,0x993,0x99b,0x53d,0x19bf,0x19c4,0x9a3,0x19b7,0x1a90,0x1a88,0x1b8c,0x9ab, +0x1a58,0x9b3,0x9bb,0x1a75,0x9c3,0x9c7,0x9cf,0x9d7,0x18db,0x18bb,0x18cb,0x18c3,0x1943,0x193b,0x198f,0x19e1, +0x15a6,0x15a6,0x15a6,0x15a6,0x1596,0x15a6,0x15a6,0x15a8,0x9df,0x1579,0x9e3,0x9eb,0x1579,0x9f3,0x9fb,0xa03, +0x139e,0x1396,0x13d6,0xa0b,0xa13,0x13be,0x12fc,0xa1b,0x13ae,0x13b6,0x13ce,0x159e,0xa23,0x13e6,0x13ed,0x13f5, +0x147c,0x1484,0x148c,0x1494,0x149c,0x14a3,0x14ab,0x14b3,0x13fd,0x1405,0x1408,0x140a,0x16f8,0x1852,0x1858,0x199f, +0x1408,0x1315,0x131d,0x15c0,0x15c5,0x15c8,0x15ce,0x13c6,0x15d6,0x15d6,0x1412,0x13de,0x1416,0x141e,0x1426,0x142e, +0x1436,0x143e,0x1446,0x144e,0x1860,0x18ab,0x1a0b,0x1b6c,0x1456,0x145c,0x1464,0x146c,0x13a6,0x1474,0x1868,0x186f, +0x176f,0x176f,0x176f,0x176f,0x176f,0x176f,0x176f,0x176f,0x1873,0x1873,0x1873,0x1873,0x187b,0x1873,0x1882,0x1889, +0x1891,0x1873,0x1873,0x1895,0x1873,0x1873,0x189b,0x1873,0x18b3,0x19a7,0x19fb,0x1325,0x132b,0x1cd6,0x1cde,0x1d86, +0x1957,0x194b,0x194f,0x19af,0x1913,0x1913,0x1913,0xa2b,0x191b,0xa33,0x196f,0xa3a,0xa42,0xa4a,0xa4a,0x1aa0, +0x190b,0x1a03,0x1333,0x133b,0xa52,0x177f,0x177f,0xa5a,0x1787,0x1787,0x1787,0x1787,0x1787,0x1787,0xa62,0xa68, +0x1603,0x15b8,0xa70,0x1669,0xa78,0x1687,0x168f,0x1697,0xa80,0xa85,0x165a,0x1661,0xa8a,0x1777,0x1987,0xa92, +0xa9a,0x169f,0x16a6,0x160b,0x16b6,0x16ba,0x1671,0x1675,0x167d,0x167d,0x167f,0x161b,0x1623,0x1623,0x1624,0x16ae, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f, +0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x178f,0x1792,0x18f3,0x18f3, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1648,0x1a98,0x1e76, +0x17a2,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8, +0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8,0x17a8, +0x17a8,0x17a8,0x17a8,0x17a8,0xaa2,0x179a,0xaaa,0x1b3c,0x1a65,0x1a65,0x1a65,0x1a65,0x1a65,0x1a65,0x1a65,0x1a65, +0x1a60,0xab2,0x1a1b,0x1a13,0x1a1d,0x1b34,0x1b34,0xaba,0x1903,0x1997,0x1a25,0x1a29,0x19f3,0x1b84,0xac2,0xaca, +0x195f,0xad2,0x19cc,0xada,0x1a7d,0x1a80,0xae2,0x1ab0,0x1a49,0x1a50,0xaea,0xaf2,0x1ae4,0x1ae8,0xafa,0xb02, +0x1a41,0xb0a,0xb12,0x1ab8,0x1b28,0x1b2c,0xb1a,0xb22,0xb2a,0xb32,0x1cce,0xb3a,0x1d8e,0x1d8e,0x1b00,0xb42, +0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb, +0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed, +0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef, +0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea, +0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec, +0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee, +0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0, +0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb, +0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed, +0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef, +0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea, +0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec, +0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee, +0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0, +0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb, +0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed, +0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef, +0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea, +0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec, +0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee, +0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0, +0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0x16f0,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef,0xb4a,0xb51,0xb54, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, +0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de, +0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x15de,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c, +0x1631,0x1639,0x18a3,0x1343,0x197f,0x197f,0x1347,0x134e,0xb5c,0xb64,0xb6c,0x14d3,0x14da,0x14e2,0xb74,0x14ea, +0x153b,0x153b,0x14bb,0x14c3,0x14f2,0x1532,0x1533,0x1543,0x14fa,0x14ff,0x1507,0x150f,0xb7c,0x1517,0xb84,0x14cb, +0xb8c,0x1613,0xb94,0xb9c,0x151f,0x1525,0x152a,0xba4,0xbac,0x15f3,0x15fb,0x15e6,0x15eb,0xbb4,0xbbc,0xbc4, +0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, +0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, +0x14f4,0x14f4,0x1534,0x1574,0x15b4,0x15f4,0x1634,0x1674,0x16b0,0x16f0,0x1730,0x1770,0x17b0,0x17f0,0x1830,0x1870, +0x18b0,0x18ec,0x192c,0x196c,0x19ac,0x19e0,0x1a1c,0x1a5c,0x1a9c,0x1adc,0x1b18,0x1b58,0x1b98,0x1bd8,0x1c18,0x1c58, +0xa80,0xac0,0xb00,0xb40,0xb80,0xbab,0xbeb,0x1432,0xc0e,0xa40,0xa40,0xa40,0xc46,0xc86,0x1332,0x1332, +0xcc6,0xd06,0xa40,0xa40,0xa40,0xd2f,0xd6f,0xd8f,0xa40,0xdb5,0xdf5,0xe35,0xe75,0xeb5,0xf75,0xef5, +0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272, +0x1272,0x1272,0x1272,0x1272,0x1005,0x12b2,0x103d,0x107d,0x12f2,0x1088,0x1372,0x1372,0x1372,0x10be,0x10f1,0x1131, +0x13b2,0x13b2,0x1171,0x13f2,0x1194,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1, +0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x10f1,0x11b2, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, -0xe09,0xe19,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, -0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, -0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5, -0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x1235, -0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5, -0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x1275, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0xc31,0xc34,0xdff,0x1dfa,0x1021,0x74f,0x55e,0x10bb,0xd01,0xd80,0x55e,0x55e,0x1d20,0xf1a,0xf22,0x1e42, -0xc84,0xc8b,0xc93,0x1ba4,0x1dda,0x55e,0x1dba,0xff1,0x1bac,0xe07,0xe0f,0xe17,0x1049,0x757,0x55e,0x55e, -0x1bb4,0x1bb4,0x75f,0x55e,0x1e6f,0x10d3,0x1e67,0x10db,0x1f5b,0x11d5,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0xe1f,0x1fb3,0x12ce,0x1350,0x1351,0x1f7b,0x11fd,0x1204,0x120b,0x130d,0x1311,0x1285,0x121b, -0x1c30,0x1c32,0xe80,0xe87,0x1bbc,0x1bc4,0xe27,0xf3a,0x1d18,0xf02,0xf0a,0xfe9,0x1d38,0x1d3c,0x1d44,0x1069, -0xfb9,0x1d9a,0x767,0x55e,0x10c3,0x10cb,0x1da2,0xfc1,0xf9b,0xfa1,0xfa9,0xfb1,0x55e,0x55e,0x55e,0x55e, -0x1edf,0x1ed7,0x1145,0x114d,0x1e22,0x1e1a,0x1091,0x55e,0x55e,0x55e,0x55e,0x55e,0x1e0a,0x1051,0x1059,0x1061, -0x1dd2,0x1dca,0x1001,0x113d,0x1d4c,0xf4a,0x76f,0x55e,0x10a1,0x10a9,0x777,0x55e,0x55e,0x55e,0x55e,0x55e, -0x1f53,0x11b7,0x77f,0x55e,0x55e,0x1e32,0x1e2a,0x1099,0x128d,0x1293,0x129b,0x55e,0x55e,0x1223,0x1227,0x122f, -0x1f13,0x1f0b,0x119f,0x1f03,0x1efb,0x118f,0x1e02,0x1041,0x1361,0x1364,0x1364,0x55e,0x55e,0x55e,0x55e,0x55e, -0x10f3,0x10f8,0x1100,0x1107,0x112f,0x1135,0x55e,0x55e,0x1173,0x1177,0x117f,0x11c7,0x11cd,0x787,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x11e5,0x1374,0x1379,0x1381,0x55e,0x55e,0x78b,0x1f9b,0x1275, -0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d, -0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a6d,0x1a72,0xd09,0xd10,0xd10,0xd10, -0x1a7a,0x1a7a,0x1a7a,0xd18,0x1e5f,0x1e5f,0x1e5f,0x1e5f,0x1e5f,0x1e5f,0x793,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x797,0x1fcb,0x1fcb,0x12de,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a, -0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0x1c3a,0xe8f,0x1009,0x1011,0x1fd3, -0x1319,0x1321,0xf52,0x1df2,0x1dea,0x1031,0x1039,0x79f,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1f73,0x1f6b,0x11f5, -0x55e,0x55e,0x55e,0x1d30,0x1d30,0xf2a,0x1d28,0xf32,0x55e,0x55e,0x1127,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x7a3,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1d82,0x1d82,0x1d82,0xf76,0xf7b, -0x7ab,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1fe3,0x1341,0x1348,0x1fdb,0x1fdb,0x1fdb,0x7b3, -0x55e,0x184d,0x184d,0x184d,0x184d,0x184d,0x184d,0x184d,0xb35,0x185d,0xb3d,0x185e,0x1855,0x1866,0x186c,0x1874, -0xb45,0x199c,0x199c,0x7bb,0x55e,0x55e,0x55e,0x136c,0x11ed,0x198c,0x198c,0xc3c,0xd20,0x55e,0x55e,0x55e, -0x55e,0x18a5,0x18ac,0xb4d,0x18af,0xb55,0xb5d,0xb65,0x18a9,0xb6d,0xb75,0xb7d,0x18ae,0x18b6,0x18a5,0x18ac, -0x18a8,0x18af,0x18b7,0x18a6,0x18ad,0x18a9,0xb84,0x187c,0x1884,0x188b,0x1892,0x187f,0x1887,0x188e,0x1895,0xb8c, -0x189d,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87,0x1e87, -0x1e87,0x1e77,0x1e7a,0x1e77,0x1e81,0x10e3,0x7c3,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x12fa,0x1302,0x1305,0x1305,0x1305,0x1305,0x1305, -0x1305,0x1117,0x111f,0x1feb,0x1359,0x7cb,0x55e,0x55e,0x55e,0x1f93,0x1237,0x7d3,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x7d7,0x1329,0x1fa3,0x127d,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x7df,0x1389,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x12e6,0x1dc2,0x1dc2,0x1dc2,0x1dc2,0x1dc2,0x1dc2,0xff9,0x55e,0x1ecf,0x1ec7,0x10eb,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x7e7,0x1f63,0x11dd,0x55e,0x55e,0x123f,0x1240,0x7ef,0x55e,0x55e,0x55e,0x55e, -0x55e,0xec7,0xecf,0xed7,0xedf,0xee7,0xeef,0xef6,0xefa,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x7f3,0x1071,0x1e12,0x1077,0x1e12,0x107f,0x1084,0x1089, -0x1089,0x1e97,0x1eb7,0x1ebf,0x1f2b,0x1e9f,0x1f83,0x1ea7,0x1f33,0x1f8b,0x1f8b,0x11a7,0x11af,0x1257,0x125d,0x1265, -0x126d,0x1fab,0x1fab,0x1fab,0x1fab,0x12b1,0x1fab,0x12b7,0x12bb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb, -0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb, -0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fb,0x7fc,0xb94,0x18bf,0x18bf,0x18bf,0x804,0x804,0x804, -0x804,0x1994,0x1994,0x1994,0x1994,0x1994,0x1994,0x1994,0x80c,0x804,0x804,0x804,0x804,0x804,0x804,0x804, -0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804, -0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804, -0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804, -0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0x804,0xbe7,0xbee,0xbf6,0xbfe,0x197c,0x197c,0x197c, -0xc06,0xc0e,0xc11,0x19ac,0x19a4,0xc44,0xd60,0xd64,0xd68,0x55e,0x55e,0x55e,0x55e,0xd70,0x1b28,0xd78, -0xf62,0x1830,0xb27,0xb2d,0x1029,0xc19,0x19f0,0xcaa,0x55e,0x1845,0x1838,0x183d,0x1984,0xc21,0xc29,0x1155, -0x115b,0x1d8a,0xf83,0x1d7a,0xf5a,0x1331,0x1339,0x55e,0x55e,0x1db2,0x1db2,0x1db2,0x1db2,0x1db2,0x1db2,0x1db2, -0x1db2,0x1db2,0xfd1,0xfd9,0xfe1,0x12ee,0x12f2,0x55e,0x55e,0x1b30,0xd88,0x1b38,0x1b38,0xd8c,0xe97,0xe9f, -0xea7,0x1c00,0x1be8,0x1c08,0x1c10,0x1bf8,0xe2f,0xe33,0xe3a,0xe42,0xe46,0xe4e,0xe56,0xe58,0xe58,0xe58, -0xe58,0x1c71,0x1c79,0x1c71,0x1c7f,0x1c87,0x1c52,0x1c8f,0x1c97,0x1c71,0x1c9f,0x1ca7,0x1cae,0x1cb6,0x1c5a,0x1c71, -0x1cbb,0x1c62,0x1c69,0x1cc3,0x1cc9,0x1d6b,0x1d72,0x1d64,0x1cd0,0x1cd8,0x1ce0,0x1ce8,0x1de2,0x1cf0,0x1cf8,0xeaf, -0xeb7,0x1c42,0x1c42,0x1c42,0xebf,0x1d92,0x1d92,0xf8b,0xf93,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1e4a,0x1e4a,0x1e4a,0x1e4a,0x1e4a,0x1e4a,0x1e4a, -0x1e4a,0x1e4a,0x1e4a,0x1e4a,0x1e4a,0x1e4a,0x1e4a,0x1e4f,0x1e4a,0x1e4a,0x1e4a,0x10b1,0x10b3,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1163,0x1c4a,0x1f23,0x1f23,0x1f23,0x1f23,0x1f23,0x1f23, -0x1f23,0x1f43,0x116b,0x1248,0x124f,0x1f4b,0x1f4b,0x1f4b,0x1f4b,0x1f4b,0x1f4b,0x1f4b,0x1f4b,0x1f4b,0x1f4b,0x1f4b, -0x1187,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc, -0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bce,0x1bcc,0x1bd6,0x1bcc,0x1bcc, -0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bd9,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1bcc,0x1be0,0x1213,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef, -0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef,0x1eef, -0x1ef3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x1fc3,0x12a3, -0x12a9,0x12c3,0x12c6,0x12c6,0x12c6,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, -0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7, -0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7, -0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7, -0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18ca, -0x1391,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b, -0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b, -0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x13d5,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb, -0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x1ffb,0x13e5,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x18d2,0x18d2,0x18d2,0x18d2, -0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x13b5,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1392,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x139a,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391, -0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1391,0x1392,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x13bd,0x1d00,0x1d00,0x1d00,0x1d00,0x1d00,0x1d00,0x13c5,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x13cd,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b, -0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb, -0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x13dd, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x174f,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1757,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f,0x175f, -0x175f,0x175f,0x175f,0x175f,0x175f,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7, -0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7, -0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7, -0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x18c7, -0x18c7,0x18c7,0x18c7,0x18c7,0x18c7,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1c18, -0x1c18,0x1c18,0x1c18,0x1c18,0x1c18,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, -0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7, -0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1ee7,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b, -0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b, -0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b, -0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b, -0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1f3b,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb, -0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb, -0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb, -0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb, -0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1fbb,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3, -0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x1ff3,0x53d,0x53d,0x53d,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2, -0x2e2,0x2e5,0x2ee,0x2e8,0x2e8,0x2eb,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2, -0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x828,0x822,0x804,0x7ec,0x7f8,0x7f5,0x7ec,0x807, -0x7f2,0x7fe,0x7ec,0x819,0x80d,0x801,0x825,0x7fb,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9, -0x7e9,0x7e9,0x810,0x80a,0x813,0x813,0x813,0x822,0x7ec,0x834,0x834,0x834,0x834,0x834,0x834,0x82e, -0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e,0x82e, -0x82e,0x82e,0x82e,0x7f2,0x7f8,0x7fe,0x81f,0x7e6,0x81c,0x831,0x831,0x831,0x831,0x831,0x831,0x82b, -0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b, -0x82b,0x82b,0x82b,0x7f2,0x816,0x7ef,0x813,0x2e2,0,0,0,0,0,0,0,0, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, +0xfb5,0xfc5,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, +0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xf35, +0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232, +0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x11f2, +0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232, +0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x1232,0x11f2, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0xbcc,0xbd3,0xbdb,0x53d,0x18e3,0x18e3,0x18e3,0xbe3,0xbeb,0xbee,0x1933,0x1923,0xbf6,0xbfe,0xc02,0xc06, +0x53d,0x53d,0x53d,0x53d,0xc0e,0x1a6d,0xc16,0xc1e,0x182f,0xc26,0xc2c,0xc30,0xc38,0x1977,0xc40,0x53d, +0x1827,0x181a,0x181f,0x18eb,0xc48,0xc50,0xc54,0xc5a,0x1d0e,0xc62,0x1d5e,0xc69,0xc6d,0xc75,0x1f88,0xc7d, +0x1cf6,0x1cf6,0x1cf6,0x1cf6,0x1cf6,0x1cf6,0x1cf6,0x1cf6,0x1cf6,0xc85,0xc8d,0xc95,0xc9d,0xca1,0x53d,0x53d, +0xca9,0xcac,0xcb4,0x1d26,0xcbc,0xcc4,0x53d,0xccc,0xcd4,0xcdc,0x53d,0x53d,0x1c64,0xce4,0xcec,0x1dc5, +0xcf4,0xcfb,0xd03,0x1b44,0x1d1e,0x53d,0x1cfe,0xd0b,0x1b08,0xd13,0xd1b,0xd23,0xd2b,0xd33,0x53d,0x53d, +0x1af0,0x1af0,0xd3b,0x53d,0x1d9e,0xd43,0x1d96,0xd4b,0x1eb7,0xd53,0x1f68,0xd5b,0xd62,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0xd6a,0x1efd,0xd72,0xd7a,0xd7c,0x1ebf,0xd84,0xd8b,0xd92,0xd9a,0xd9e,0xda5,0xdad, +0x1b94,0x1b96,0xdb5,0xdbc,0x1b18,0x1b10,0xdc4,0xdca,0x1c7c,0xdd2,0xdda,0xdde,0x1c8c,0x1c90,0x1c84,0xde6, +0xdee,0x1d46,0xdf6,0x53d,0xdfe,0xe06,0x1d2e,0xe0e,0xe16,0xe1c,0xe24,0xe2c,0xe34,0xe39,0xe41,0xe49, +0x1e2a,0x1e22,0xe51,0xe59,0x1d56,0x1d4e,0xe61,0x53d,0x53d,0x53d,0x53d,0x53d,0x1d7e,0xe69,0xe71,0x53d, +0x1d6e,0x1d66,0xe79,0xe81,0x1c98,0xe89,0xe91,0xe98,0xea0,0xea8,0xeb0,0x53d,0x53d,0x53d,0x53d,0x53d, +0x1e9f,0xeb8,0x53d,0x53d,0x53d,0x1d3e,0x1d36,0xec0,0xec8,0xece,0xed6,0x53d,0x53d,0xede,0xee2,0xeea, +0x1e5e,0x1e56,0xef2,0x1e4e,0x1e46,0xefa,0x1d76,0xf02,0xf0a,0x53d,0x53d,0x53d,0x53d,0x53d,0x1f80,0xf12, +0xf1a,0xf1f,0xf27,0xf2e,0xf33,0xf39,0x53d,0x53d,0xf41,0xf45,0xf4d,0xf55,0xf5b,0xf63,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0xf6b,0xf73,0xf78,0xf80,0x53d,0x53d,0xf87,0x1ed7,0xf8f, +0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4, +0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d4,0x19d9,0xf97,0x53d,0x53d,0x53d, +0x19d4,0x19d4,0x19d4,0xf9f,0x1da6,0x1da6,0x1da6,0x1da6,0x1da6,0x1da6,0xfa7,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0xfab,0x1f25,0x1f25,0xfaf,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8, +0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1aca,0x1ac8,0x1ad2, +0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ad5,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1ac8,0x1adc,0xfb7,0x1f60,0x1f60, +0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60, +0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0xfbf,0x1dcd,0x1dcd, +0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dcd,0x1dd2,0x1dcd,0x1dcd,0x1dcd, +0xfc7,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x1f70,0xfcf, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e, +0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0x1b9e,0xfd7,0xfdf,0xfe7,0x1f2d,0xfeb,0xff3,0xff8,0x1cee,0x1ce6, +0x1000,0x1008,0x1010,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x1f78,0x1018,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x1eaf,0x1ea7,0x1020,0x53d,0x53d,0x53d,0x1c74,0x1c74, +0x1028,0x1c6c,0x1030,0x53d,0x53d,0x1038,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1040,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e36,0x1f15,0x1f15, +0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1f15,0x1048,0x104e,0x1056,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x105a,0x1c54, +0x1e86,0x1e86,0x1e86,0x1e86,0x1e86,0x1e86,0x1e86,0x1e87,0x1062,0x1067,0x106e,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f, +0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1e8f,0x1072,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x1d06, +0x1d06,0x1d06,0x107a,0x107f,0x1087,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1f58,0x108f,0x1f55,0x1f55,0x1f55, +0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1f55,0x1097,0x53d,0x53d,0x1f35,0x109f,0x10a6, +0x1f1d,0x1f1d,0x1f1d,0x10ad,0x53d,0x17b8,0x17b8,0x17b8,0x17b8,0x17b8,0x17b8,0x17b8,0x10b5,0x17b8,0x10bd,0x17b9, +0x17b0,0x17c1,0x17c7,0x17cf,0x10c5,0x192b,0x192b,0x10cd,0x53d,0x53d,0x53d,0x10d5,0x10dd,0x18f3,0x18f3,0x10e5, +0x10ed,0x53d,0x53d,0x53d,0x53d,0x1800,0x1807,0x10f5,0x180a,0x10fd,0x1105,0x110d,0x1804,0x1115,0x111d,0x1125, +0x1809,0x1811,0x1800,0x1807,0x1803,0x180a,0x1812,0x1801,0x1808,0x1804,0x112c,0x17d7,0x17df,0x17e6,0x17ed,0x17da, +0x17e2,0x17e9,0x17f0,0x1134,0x17f8,0x1dae,0x1dae,0x1dae,0x1dae,0x1dae,0x1dae,0x1dae,0x1dae,0x1dae,0x1dae,0x1dae, +0x1dae,0x1dae,0x1dae,0x1dae,0x1dae,0x1dfa,0x1db6,0x1dfa,0x1dbd,0x113c,0x1144,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x114c,0x1154,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x115c,0x1164,0x1f3d,0x116c,0x1171,0x53d,0x53d,0x53d,0x1edf,0x1179,0x1181, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x1185,0x118a,0x1ee7,0x1192,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x119a,0x119f,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x11a6,0x11ab,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x11b3,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x11bb,0x53d,0x1e1a,0x1e12,0x11c3, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x11cb,0x1e97,0x11d0,0x53d,0x53d,0x11d8,0x11d9,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x11e1,0x11e9,0x11f1,0x11f9,0x1201,0x1209,0x53d,0x1210,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x1218,0x1cb7,0x121e,0x1cb7,0x1226,0x122b,0x1233,0x53d,0x1dda,0x1e02,0x1e0a, +0x1e66,0x1de2,0x1ec7,0x1dea,0x1e6e,0x1ecf,0x1ecf,0x12cd,0x12d5,0x12dd,0x1f05,0x12e5,0x12ed,0x1eef,0x1eef,0x1eef, +0x1eef,0x123b,0x1eef,0x1ef5,0x1243,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a, +0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a,0x127a, +0x127a,0x127a,0x127a,0x127a,0x12f4,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d,0x53d, +0x53d,0x53d,0x53d,0x53d,0x124a,0x19e9,0x1252,0x19eb,0x19eb,0x1256,0x125e,0x1266,0x126e,0x1b54,0x1aa8,0x1b5c, +0x1b64,0x1b4c,0x1276,0x127a,0x1281,0x1289,0x128d,0x1295,0x129d,0x127a,0x127a,0x127a,0x127a,0x1bc5,0x1bcd,0x1bc5, +0x1bd3,0x1bdb,0x1ba6,0x1be3,0x1beb,0x1bc5,0x1bf3,0x1bfb,0x1c02,0x1c0a,0x1bae,0x1bc5,0x1c0f,0x1bb6,0x1bbd,0x1c17, +0x1c1d,0x1cbf,0x1cc6,0x1ca8,0x1c24,0x1c2c,0x1c34,0x1c3c,0x1cb0,0x1bc5,0x1c44,0x12a5,0x12ad,0x1b7c,0x1b7c,0x1b7c, +0x12b5,0x1cb7,0x1cb7,0x12bd,0x12c5,0x1304,0x184a,0x184a,0x184a,0x1305,0x1305,0x1305,0x1305,0x18fb,0x18fb,0x18fb, +0x18fb,0x18fb,0x18fb,0x18fb,0x130d,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305, +0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305, +0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305, +0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305, +0x1305,0x1305,0x1305,0x1305,0x1305,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, +0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, +0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, +0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x1842,0x134e,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1356,0x1c4c,0x1c4c,0x1c4c,0x1c4c,0x1c4c,0x1c4c,0x135e,0x1df2,0x1df2, +0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2, +0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2, +0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2, +0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1366,0x1e7e,0x1e7e, +0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e, +0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x136e,0x1f4d,0x1f4d, +0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d,0x1f4d, +0x1372,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837,0x1837, +0x1837,0x137a,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x1382,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d, +0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x138a,0x1f45,0x1f45,0x1f45,0x1f45, +0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45, +0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45, +0x1f45,0x138e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e,0x134e, +0x134e,0x1382,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16da,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2,0x16e2, +0x16e2,0x16e2,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, +0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, +0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, +0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, +0x183f,0x183f,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74,0x1b74, +0x1b74,0x1b74,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2, +0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2, +0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2, +0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2,0x1df2, +0x1df2,0x1df2,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32,0x1e32, +0x1e32,0x1e32,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e, +0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e, +0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e, +0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e,0x1e7e, +0x1e7e,0x1e7e,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d, +0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d, +0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d, +0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d,0x1f0d, +0x1f0d,0x1f0d,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45, +0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45, +0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45, +0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45,0x1f45, +0x1f45,0x1f45,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60, +0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60, +0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60, +0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60,0x1f60, +0x1f60,0x1f60,0x51c,0x51c,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xf3,0xff,0xf9, +0xf9,0xfc,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x43e,0x438,0x41d,0x405,0x411,0x40e,0x405,0x420,0x40b,0x417,0x405,0x42f, +0x423,0x41a,0x43b,0x414,0x402,0x402,0x402,0x402,0x402,0x402,0x402,0x402,0x402,0x402,0x426,0x423, +0x429,0x429,0x429,0x438,0x405,0x44a,0x44a,0x44a,0x44a,0x44a,0x44a,0x444,0x444,0x444,0x444,0x444, +0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x444,0x40b, +0x411,0x417,0x435,0x3ff,0x432,0x447,0x447,0x447,0x447,0x447,0x447,0x441,0x441,0x441,0x441,0x441, +0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x40b, +0x42c,0x408,0x429,0x12,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x300,0x2f1,0x2f1, -0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1, -0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f4,0x690,0x83d,0x840,0x696,0x840,0x83a,0x68a, -0x681,0x2fa,0x69f,0x2fd,0x843,0x678,0x68d,0x837,0x693,0x69c,0x67e,0x67e,0x684,0x2f7,0x68a,0x687, -0x681,0x67e,0x69f,0x2fd,0x67b,0x67b,0x67b,0x690,0x306,0x306,0x306,0x306,0x306,0x306,0x6a8,0x306, -0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x6a8,0x306,0x306,0x306,0x306,0x306,0x306,0x699, -0x6a8,0x306,0x306,0x306,0x306,0x306,0x6a8,0x6a2,0x6a5,0x6a5,0x303,0x303,0x303,0x303,0x6a2,0x303, -0x6a5,0x6a5,0x6a5,0x303,0x6a5,0x6a5,0x303,0x303,0x6a2,0x303,0x6a5,0x6a5,0x303,0x303,0x303,0x699, -0x6a2,0x6a5,0x6a5,0x303,0x6a5,0x303,0x6a2,0x303,0x312,0x6b4,0x312,0x30c,0x312,0x30c,0x312,0x30c, -0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x30f,0x6b1,0x312,0x6b4,0x312,0x30c,0x312,0x30c, -0x312,0x30c,0x312,0x6b4,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x6b7,0x6b1, -0x312,0x30c,0x312,0x6b4,0x312,0x30c,0x312,0x30c,0x312,0x6b1,0x6ae,0x6ab,0x312,0x30c,0x312,0x30c, -0x6b1,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x6ae,0x6ab,0x6b7,0x6b1,0x312,0x6b4,0x312,0x30c,0x312, -0x6b4,0x6ba,0x6b7,0x6b1,0x312,0x6b4,0x312,0x30c,0x312,0x30c,0x6b7,0x6b1,0x312,0x30c,0x312,0x30c, -0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x6b7,0x6b1, -0x312,0x30c,0x312,0x6b4,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x312,0x30c, -0x312,0x312,0x30c,0x312,0x30c,0x312,0x30c,0x309,0x318,0x327,0x327,0x324,0x327,0x324,0x327,0x327, -0x324,0x327,0x327,0x327,0x324,0x31e,0x327,0x333,0x327,0x327,0x324,0x327,0x327,0x324,0x327,0x327, -0x327,0x324,0x324,0x324,0x327,0x327,0x324,0x327,0x336,0x330,0x327,0x324,0x327,0x324,0x327,0x327, -0x324,0x327,0x31e,0x31e,0x327,0x324,0x327,0x336,0x330,0x327,0x327,0x327,0x324,0x327,0x324,0x327, -0x327,0x315,0x31e,0x321,0x327,0x324,0x31e,0x315,0x31b,0x31b,0x31b,0x31b,0x32d,0x32d,0x32a,0x32d, -0x32d,0x32a,0x32d,0x32d,0x32a,0x336,0x6bd,0x336,0x6bd,0x336,0x6bd,0x336,0x6bd,0x336,0x6bd,0x336, -0x6bd,0x336,0x6bd,0x336,0x6bd,0x324,0x336,0x330,0x336,0x330,0x336,0x330,0x327,0x324,0x336,0x330, -0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330,0x330,0x32d,0x32d,0x32a,0x336,0x330,0xa29,0xa29, -0xa35,0xa32,0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330, -0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330,0x336,0x330,0xa35,0xa32,0xa35,0xa32, -0xa29,0xa26,0xa35,0xa32,0xc0c,0xd08,0xa2f,0xa2c,0xa2f,0xa2c,0xa35,0xa32,0xa35,0xa32,0xa35,0xa32, -0xa35,0xa32,0xa35,0xa32,0xa35,0xa32,0xa35,0xa32,0xd05,0xd05,0xd05,0xe01,0xe01,0xe01,0xe04,0xe04, -0xe01,0xe04,0xe04,0xe01,0xe01,0xe04,0xf4e,0xf51,0xf51,0xf51,0xf51,0xf4e,0xf51,0xf4e,0xf51,0xf4e, -0xf51,0xf4e,0xf51,0xf4e,0x339,0x6c0,0x339,0x342,0x342,0x339,0x342,0x342,0x339,0x345,0x339,0x342, -0x339,0x339,0x339,0x339,0x339,0x6c0,0x339,0x342,0x339,0x339,0x339,0x339,0x342,0x342,0x339,0x339, -0x339,0x339,0x339,0x339,0x339,0x339,0x342,0x339,0x339,0x339,0x339,0x33f,0x339,0x339,0x339,0x339, -0x33f,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x342,0x339,0x339, -0x339,0x339,0x339,0x339,0x339,0x339,0x342,0x339,0x33c,0x339,0x339,0x339,0x339,0x339,0x339,0x339, -0x339,0x339,0x33f,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0xa38,0xa38,0xa38, -0xa38,0xa38,0xd0b,0xd0b,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x351,0x351,0x357, -0x357,0x351,0x351,0x351,0x34e,0x34e,0x348,0x348,0x6c3,0x348,0x351,0x6c9,0x354,0x6c9,0x6c9,0x6c9, -0x354,0x6c9,0x351,0x351,0x6cc,0x35a,0x348,0x348,0x348,0x348,0x348,0x348,0x6c6,0x6c6,0x6c6,0x6c6, -0x34b,0x6c6,0x348,0xb82,0x35d,0x35d,0x35d,0x35d,0x35d,0x348,0x348,0x348,0x348,0x348,0xa44,0xa44, -0xa41,0xa3b,0xa3e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e, -0xd0e,0xd0e,0xd0e,0xd0e,0x6db,0x6db,0x6db,0x6db,0x6db,0x6d5,0x6db,0x6db,0x6db,0x6db,0x6db,0x6db, -0x6db,0x6d5,0x6cf,0x6db,0x6db,0x6db,0x6cf,0x6db,0x6db,0x6cf,0x6d5,0x6cf,0x6cf,0x6cf,0x6cf,0x6db, -0x6cf,0x6cf,0x6cf,0x6cf,0x6cf,0x6d5,0x6d5,0x6db,0x6db,0x6db,0x6db,0x6db,0x6db,0x6cf,0x6cf,0x6cf, -0x6cf,0x6db,0x6db,0x6cf,0x6db,0x6db,0x6d5,0x6cf,0x6d5,0x6db,0x6d5,0x6cf,0x6db,0x6db,0x6cf,0x6cf, -0x6cf,0x6cf,0x6cf,0x6cf,0x6d8,0x6d8,0x981,0x6d8,0x6d8,0x984,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85, -0xb85,0xb85,0xb85,0xcbd,0xdcb,0xdcb,0xdcb,0xdcb,0xdcb,0xdcb,0xdcb,0xdcb,0xf15,0xf0f,0xf0f,0xf0f, -0xf12,0xdce,0xdce,0xdce,0x6d2,0x6d2,0xb88,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02, -0xd02,0xd02,0xd02,0xd02,0x100e,0x100b,0x100e,0x100b,0x369,0x375,0x100e,0x100b,9,9,0x378,0xf54, -0xf54,0xf54,0x360,0x158a,9,9,9,9,0x372,0x363,0x38d,0x366,0x38d,0x38d,0x38d,9, -0x38d,9,0x38d,0x38d,0x38a,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1, -0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,9,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x6e1,0x38d,0x38d, -0x38a,0x38a,0x38a,0x38a,0x38a,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de, -0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x387,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x6de,0x38a,0x38a, -0x38a,0x38a,0x38a,0x1011,0x390,0x390,0x393,0x384,0x384,0x390,0x381,0xa4a,0xc15,0xc12,0x37b,0xa47, -0x37b,0xa47,0x37b,0xa47,0x37b,0xa47,0x36f,0x36c,0x36f,0x36c,0x36f,0x36c,0x36f,0x36c,0x36f,0x36c, -0x36f,0x36c,0x36f,0x36c,0x390,0x390,0x381,0x37e,0xbc4,0xbc1,0xc0f,0xd14,0xd11,0xd17,0xd14,0xd11, -0xe07,0xe0a,0xe0a,0xe0a,0xa59,0x6ed,0x3ab,0x3ae,0x3ab,0x3ab,0x3ab,0x3ae,0x3ab,0x3ab,0x3ab,0x3ab, -0x3ae,0xa59,0x3ae,0x3ab,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ed,0x6ea,0x6ea, +0,0,0,0,0x12,0x12,0x12,0x12,0x12,0x102,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x4b,0x30f,0x40e,0x411,0x315,0x411,0x405,0x306,0x2fa,0xa5,0x366,0xcc, +0x429,0x2d6,0x309,0x3fc,0x312,0x33f,0x2e8,0x2e8,0x2fd,0x84,0x306,0x384,0x2fa,0x2e8,0x366,0xcc, +0x2e2,0x2e2,0x2e2,0x30f,0x23d,0x23d,0x23d,0x23d,0x23d,0x23d,0x37b,0x23d,0x23d,0x23d,0x23d,0x23d, +0x23d,0x23d,0x23d,0x23d,0x37b,0x23d,0x23d,0x23d,0x23d,0x23d,0x23d,0x336,0x37b,0x23d,0x23d,0x23d, +0x23d,0x23d,0x37b,0x375,0x378,0x378,0x237,0x237,0x237,0x237,0x375,0x237,0x378,0x378,0x378,0x237, +0x378,0x378,0x237,0x237,0x375,0x237,0x378,0x378,0x237,0x237,0x237,0x336,0x375,0x378,0x378,0x237, +0x378,0x237,0x375,0x237,0x23d,0x378,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x23a,0x375,0x23d,0x378,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x378, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x37b,0x375,0x23d,0x237,0x23d,0x378, +0x23d,0x237,0x23d,0x237,0x23d,0x375,0x372,0x36f,0x23d,0x237,0x23d,0x237,0x375,0x23d,0x237,0x23d, +0x237,0x23d,0x237,0x372,0x36f,0x37b,0x375,0x23d,0x378,0x23d,0x237,0x23d,0x378,0x37e,0x37b,0x375, +0x23d,0x378,0x23d,0x237,0x23d,0x237,0x37b,0x375,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x37b,0x375,0x23d,0x237,0x23d,0x378, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x23d,0x237,0x23d, +0x237,0x23d,0x237,0x22b,0x216,0x225,0x225,0x222,0x225,0x222,0x225,0x225,0x222,0x225,0x225,0x225, +0x222,0x21c,0x225,0x23a,0x225,0x225,0x222,0x225,0x225,0x222,0x225,0x225,0x225,0x222,0x222,0x222, +0x225,0x225,0x222,0x225,0x23d,0x237,0x225,0x222,0x225,0x222,0x225,0x225,0x222,0x225,0x21c,0x21c, +0x225,0x222,0x225,0x23d,0x237,0x225,0x225,0x225,0x222,0x225,0x222,0x225,0x225,0x210,0x21c,0x21f, +0x225,0x222,0x21c,0x210,0x219,0x219,0x219,0x219,0x231,0x231,0x22b,0x231,0x231,0x22b,0x231,0x231, +0x22b,0x23d,0x378,0x23d,0x378,0x23d,0x378,0x23d,0x378,0x23d,0x378,0x23d,0x378,0x23d,0x378,0x23d, +0x378,0x222,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x225,0x222,0x23d,0x237,0x23d,0x237,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x237,0x231,0x231,0x22b,0x23d,0x237,0x738,0x738,0x74a,0x747,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x74a,0x747,0x74a,0x747,0x738,0x735,0x74a,0x747, +0x8eb,0x9b4,0x744,0x741,0x744,0x741,0x74a,0x747,0x74a,0x747,0x74a,0x747,0x74a,0x747,0x74a,0x747, +0x74a,0x747,0x74a,0x747,0x9b1,0x9b1,0x9b1,0xabf,0xabf,0xabf,0xac2,0xac2,0xabf,0xac2,0xac2,0xabf, +0xabf,0xac2,0xbac,0xbaf,0xbaf,0xbaf,0xbaf,0xbac,0xbaf,0xbac,0xbaf,0xbac,0xbaf,0xbac,0xbaf,0xbac, +0x216,0x360,0x216,0x228,0x228,0x216,0x228,0x228,0x216,0x234,0x216,0x228,0x216,0x216,0x216,0x216, +0x216,0x360,0x216,0x228,0x216,0x216,0x216,0x216,0x228,0x228,0x216,0x216,0x216,0x216,0x216,0x216, +0x216,0x216,0x228,0x216,0x216,0x216,0x216,0x21c,0x216,0x216,0x216,0x216,0x21c,0x216,0x216,0x216, +0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x228,0x216,0x216,0x216,0x216,0x216,0x216, +0x216,0x216,0x228,0x216,0x219,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x21c,0x216, +0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x73b,0x73b,0x73b,0x73b,0x73b,0x9b1,0x9b1, +0x240,0x240,0x240,0x240,0x240,0x240,0x240,0x240,0x240,0x96,0x96,0x9c,0x28b,0x96,0x96,0x96, +0x93,0x93,0x6c,0x6c,0x2f7,0x6c,0x96,0x38a,0x99,0x38a,0x38a,0x38a,0x99,0x38d,0x96,0x96, +0x303,0x9f,0x6c,0x6c,0x6c,0x6c,0x6c,0x28e,0x2fa,0x387,0x2fa,0x2fa,0x72,0x2fa,0x6c,0x7d7, +0x240,0x240,0x240,0x240,0x240,0x6c,0x6c,0x6c,0x6c,0x6c,0x6e7,0x6e7,0x6d5,0x6cc,0x6d2,0x963, +0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963, +0x5ee,0x5f1,0x5f4,0x5fa,0x5fd,0x600,0x603,0x606,0x609,0x5f7,0x60c,0x60f,0x612,0x615,0x61b,0x5eb, +0x618,0x61e,0x5df,0x621,0x5eb,0x5df,0x5e5,0x5df,0x5df,0x5df,0x5df,0x5eb,0x5df,0x5df,0x5df,0x5df, +0x624,0x5e5,0x5e5,0x62a,0x62d,0x627,0x5eb,0x5eb,0x5eb,0x5df,0x5df,0x5df,0x5df,0x630,0x627,0x5df, +0x633,0x636,0x5e5,0x5df,0x5e5,0x5eb,0x5e5,0x5df,0x5eb,0x5eb,0x5df,0x5df,0x5df,0x5df,0x5df,0x5df, +0x5e8,0x5e8,0x639,0x5e8,0x5e8,0x63c,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x957, +0xa3b,0xa3b,0xa3b,0xa3b,0xa3b,0xa3b,0xa3b,0xa3b,0xb7c,0xb76,0xb76,0xb76,0xb79,0xa3e,0xa44,0xa3e, +0x5e2,0x5e2,0x849,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d, +0xc8a,0xc87,0xc8a,0xc87,0x291,0x2b2,0xc8a,0xc87,0,0,0x19e,0xb9a,0xb9a,0xb9a,0x4e,0x119d, +0,0,0,0,0x198,0x6f,0x1b6,0x78,0x1b6,0x1b6,0x1b6,0,0x1b6,0,0x1b6,0x1b6, +0x1b3,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d, +0x35d,0x35d,0,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x35d,0x1b6,0x1b6,0x1b3,0x1b3,0x1b3,0x1b3, +0x1b3,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a, +0x35a,0x35a,0x1b0,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x35a,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0xc8d, +0x1b9,0x1b9,0x1bc,0x1ad,0x1ad,0x1b9,0x1aa,0x70e,0x8e8,0x8e5,0x1a1,0x70b,0x1a1,0x70b,0x1a1,0x70b, +0x1a1,0x70b,0x165,0x162,0x165,0x162,0x165,0x162,0x165,0x162,0x165,0x162,0x165,0x162,0x165,0x162, +0x1b9,0x1b9,0x1aa,0x1a4,0x870,0x86d,0x8e2,0x993,0x990,0x999,0x993,0x990,0xab3,0xab6,0xab6,0xab6, +0x6f6,0x354,0x17d,0x180,0x17d,0x17d,0x17d,0x180,0x17d,0x17d,0x17d,0x17d,0x180,0x6f6,0x180,0x17d, +0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x354,0x351,0x351,0x351,0x351,0x351,0x351, +0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351,0x351, +0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34e,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b, +0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x34b,0x6f0,0x34e,0x177,0x17a, +0x177,0x177,0x177,0x17a,0x177,0x177,0x177,0x177,0x17a,0x6f0,0x17a,0x177,0x171,0x16b,0x171,0x16b, +0x171,0x16b,0x171,0x16b,0x171,0x16b,0x171,0x16b,0x171,0x16b,0x171,0x16b,0x171,0x16b,0x171,0x16b, +0x171,0x16b,0x174,0x16e,0x171,0x16b,0x171,0x16b,0x171,0x16b,0x171,0x16b,0x171,0x16b,0x168,0x5d9, +0x5dc,0x5ca,0x5ca,0xdd7,0x7fe,0x7fe,0x8dc,0x8d9,0x6f3,0x6ed,0x6f3,0x6ed,0x17d,0x177,0x17d,0x177, +0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177, +0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177, +0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x177,0x17d,0x180,0x17a,0x17d, +0x177,0x8dc,0x8d9,0x17d,0x177,0x8dc,0x8d9,0x17d,0x177,0x8dc,0x8d9,0xb94,0x180,0x17a,0x180,0x17a, +0x17d,0x177,0x180,0x17a,0x17d,0x177,0x180,0x17a,0x180,0x17a,0x180,0x17a,0x17d,0x177,0x180,0x17a, +0x180,0x17a,0x180,0x17a,0x17d,0x177,0x180,0x17a,0x6f6,0x6f0,0x180,0x17a,0x180,0x17a,0x180,0x17a, +0x180,0x17a,0xa95,0xa92,0x180,0x17a,0xb97,0xb94,0xb97,0xb94,0xb97,0xb94,0x8d6,0x8d3,0x8d6,0x8d3, +0x8d6,0x8d3,0x8d6,0x8d3,0x8d6,0x8d3,0x8d6,0x8d3,0x8d6,0x8d3,0x8d6,0x8d3,0xb97,0xb94,0xb97,0xb94, +0xc7b,0xc78,0xc7b,0xc78,0xc7b,0xc78,0xc7b,0xc78,0xc7b,0xc78,0xc7b,0xc78,0xc7b,0xc78,0xc7b,0xc78, +0xdfe,0xdfb,0xfc0,0xfbd,0x1191,0x118e,0x118b,0x1188,0x118b,0x1188,0x1191,0x118e,0,0x14d,0x14d,0x14d, +0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d, +0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d,0,0,0x150,0x13e,0x13e,0x13e,0x144,0x13e,0x141, +0x1557,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a, +0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a, +0x14a,0x14a,0x14a,0x147,0x1557,0x2b5,0x6e4,0,0,0x1182,0x1182,0x108c,0,0x69f,0x69f,0x69f, +0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0xb58,0x69f, +0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x594,0x594,0x594,0x594, +0x59a,0x594,0x594,0x594,0x594,0x594,0xc09,0x594,0x594,0x594,0x1e0,0x594,0x1d7,0x594,0x594,0x1e3, +0x6a2,0xb5b,0xab9,0xb5e,0,0,0,0,0,0,0,0,0x1f2,0x1f2,0x1f2,0x1f2, +0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2, +0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0,0,0,0,0x1563,0x1f2,0x1f2,0x1f2,0x1dd, +0x1da,0,0,0,0,0,0,0,0,0,0,0,0x97e,0x97e,0x97e,0x97e, +0x1089,0x1179,0xc63,0xc63,0xc63,0xc60,0xc60,0xa6e,0x297,0x978,0x975,0x975,0xa20,0xa20,0xa20,0xa20, +0xa20,0xa20,0xd92,0xd92,0xd92,0xd92,0xd92,0x294,0x114c,0x174c,0xa74,0x29a,0xfb4,0x132,0x135,0x135, +0x135,0x135,0x135,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132, +0x132,0x132,0x132,0x132,0x132,0x132,0x132,0xc66,0xc66,0xc66,0xc66,0xc66,0x29d,0x132,0x132,0x132, +0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x5d0,0x5d0,0x5d0,0x5d0,0x5d0,0x5d0,0x5d0,0x5d0,0x843, +0x843,0x843,0xa20,0xa26,0xa23,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0x104a,0x2b8,0x2b8,0x2b8,0x2b8, +0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x117,0x114,0x111,0x10e,0x8cd,0x8cd,0x5cd,0x132,0x132,0x13b, +0x132,0x123,0x123,0x123,0x123,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132, +0x132,0x132,0x132,0x132,0x132,0x132,0x120,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132, +0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x120,0x132,0x132,0x132,0x132,0x132,0x132, +0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132, +0x6e1,0x6e1,0x132,0x132,0x132,0x132,0x132,0x6e1,0x135,0x132,0x135,0x132,0x132,0x132,0x132,0x132, +0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x6e1,0x132,0x132,0x132,0x135,0x2bb,0x132,0x570,0x570, +0x570,0x570,0x570,0x570,0x570,0x108,0x10e,0x573,0x573,0x570,0x570,0x570,0x570,0x138,0x138,0x570, +0x570,0x10e,0x573,0x573,0x573,0x570,0x97b,0x97b,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a, +0x11a,0x11a,0x6e1,0x6e1,0x6e1,0x6de,0x6de,0x97b,0x7a7,0x7a7,0x7a7,0x7a1,0x7a1,0x7a1,0x7a1,0x7a1, +0x7a1,0x7a1,0x7a1,0x79e,0x7a1,0x79e,0,0x7aa,0x7a4,0x831,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4, +0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x7a4, +0x7a4,0x7a4,0x7a4,0x7a4,0x7a4,0x9c0,0x9c0,0x9c0,0x837,0x837,0x837,0x837,0x837,0x837,0x837,0x837, +0x837,0x837,0x837,0x837,0x837,0x837,0x837,0x837,0x834,0x834,0x834,0x834,0x834,0x834,0x834,0x834, +0x834,0x834,0x834,0,0,0x9c0,0x9c0,0x9c0,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71, +0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71, +0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66, +0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad, +0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad, +0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x7ad,0x83a,0x83a, +0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x8f1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3, +0xbd3,0xbd3,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6, +0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6, +0xbd9,0xbd9,0xbd9,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xbdc,0xbdc,0xbcd,0xbcd, +0xbd0,0xbe2,0xbdf,0,0,0x15f0,0x157b,0x157b,0xf78,0xf78,0xf78,0xf78,0xea9,0xf78,0xf78,0xf78, +0xea9,0xf78,0xf78,0xf78,0xf78,0xf75,0,0,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea3,0xeac, +0xea6,0xeac,0xea6,0xea6,0xea6,0xeac,0xeac,0,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b, +0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b,0x100b, +0x100b,0x1068,0x1068,0x1068,0,0,0x1008,0,0x14c7,0x14c7,0x14c7,0x14c7,0x14c7,0x14c7,0x14c7,0x14c7, +0x14c7,0x14c7,0x14c7,0,0,0,0,0,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746, +0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1740,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0, +0x174f,0x174f,0,0,0,0,0,0x18ea,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1, +0x1185,0x576,0x159,0x159,0,0x15f,0x15f,0x15f,0x15f,0x15f,0x15f,0x15f,0x15f,0,0,0x15f, +0x15f,0,0,0x15f,0x15f,0x546,0x546,0x546,0x546,0x546,0x546,0x546,0x546,0x546,0x546,0x546, +0x546,0,0x546,0x546,0x546,0x546,0x546,0x546,0x546,0,0x546,0,0,0,0x546,0x546, +0x546,0x546,0,0,0x579,0x981,0x576,0x159,0x159,0x576,0x576,0x576,0x576,0,0,0x159, +0x159,0,0,0x15c,0x15c,0x64b,0xa77,0,0,0,0,0,0,0,0,0x576, +0,0,0,0,0x543,0x543,0,0x543,0x15f,0x15f,0x576,0x576,0,0,0x2c1,0x2c1, +0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x546,0x546,0x156,0x156,0x153,0x153,0x153,0x153, +0x153,0x156,0x153,0xdf2,0x14c1,0x14be,0x15e7,0,0,0xa2c,0x588,0x9a8,0,0x1cb,0x1cb,0x1cb, +0x1cb,0x1cb,0x1cb,0,0,0,0,0x1cb,0x1cb,0,0,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb, +0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb, +0x1cb,0,0x1cb,0x1c8,0,0x1cb,0x1c8,0,0x1cb,0x1cb,0,0,0x58b,0,0x1c5,0x1c5, +0x1c5,0x588,0x588,0,0,0,0,0x588,0x588,0,0,0x588,0x588,0x591,0,0, +0,0xd9e,0,0,0,0,0,0,0,0x1c8,0x1c8,0x1c8,0x1cb,0,0x1c8,0, +0,0,0,0,0,0,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4, +0x588,0x58e,0x1cb,0x1cb,0x1cb,0xd9e,0x1560,0,0,0,0,0,0,0,0,0, +0,0x582,0x582,0x1bf,0,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x9a5,0x1c2,0,0x1c2, +0x1c2,0x1c2,0,0x1c2,0x1c2,0x552,0x552,0x552,0x552,0x552,0x552,0x552,0x552,0x552,0x552,0x552, +0x552,0,0x552,0x552,0x552,0x552,0x552,0x552,0x552,0,0x552,0x552,0,0x552,0x552,0x552, +0x552,0x552,0,0,0x585,0x1c2,0x1bf,0x1bf,0x1bf,0x582,0x582,0x582,0x582,0x582,0,0x582, +0x582,0x1bf,0,0x1bf,0x1bf,0x651,0,0,0x1c2,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1c2,0x9a5,0xa29,0xa29,0,0,0x2c7,0x2c7, +0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x109e,0x9a2,0,0,0,0,0,0, +0,0x13d7,0x1518,0x151e,0x1518,0x151b,0x151b,0x151b,0,0x5af,0x255,0x255,0,0x25b,0x25b,0x25b, +0x25b,0x25b,0x25b,0x25b,0x25b,0,0,0x25b,0x25b,0,0,0x25b,0x25b,0x55b,0x55b,0x55b, +0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0,0x55b,0x55b,0x55b,0x55b,0x55b,0x55b, +0x55b,0,0x55b,0x55b,0,0xa1d,0x55b,0x55b,0x55b,0x55b,0,0,0x5b2,0x25b,0x5af,0x5af, +0x255,0x5af,0x5af,0x5af,0xdad,0,0,0x255,0x258,0,0,0x258,0x258,0x657,0,0, +0,0,0,0,0,0x170d,0x5af,0x5af,0,0,0,0,0x558,0x558,0,0x55b, +0x25b,0x25b,0xdad,0xdad,0,0,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252, +0x24f,0xa1d,0xfde,0xfde,0xfde,0xfde,0xfde,0xfde,0,0,0,0,0,0,0,0, +0,0,0x5b5,0x264,0,0x264,0x264,0x264,0x264,0x264,0x264,0,0,0,0x264,0x264, +0x264,0,0x264,0x264,0x267,0x264,0,0,0,0x264,0x264,0,0x264,0,0x264,0x264, +0,0,0,0x264,0x264,0,0,0,0x264,0x264,0x264,0,0,0,0x264,0x264, +0x264,0x264,0x264,0x264,0x264,0x264,0xacb,0x264,0x264,0x264,0,0,0,0,0x5b5,0x25e, +0x5b5,0x25e,0x25e,0,0,0,0x25e,0x25e,0x25e,0,0x261,0x261,0x261,0x5b8,0,0, +0xcd2,0,0,0,0,0,0,0x5b5,0,0,0,0,0,0,0,0, +0,0,0xb19,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2ca,0x2ca,0x2ca,0x9fc, +0x9c3,0x9c3,0x9c3,0x9c3,0x9c3,0x9c6,0x9c3,0,0,0,0,0,0x12f0,0x26d,0x26d,0x26d, +0x15ed,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0,0x270,0x270,0x270,0,0x270,0x270, +0x270,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x12cf,0x55e,0x55e,0x55e,0x55e,0x55e,0,0, +0x17c7,0xcd8,0x5bb,0x5bb,0x5bb,0x26d,0x26d,0x26d,0x26d,0,0x5bb,0x5bb,0x5be,0,0x5bb,0x5bb, +0x5bb,0x65a,0,0,0,0,0,0,0,0x5bb,0x5bb,0,0xd7a,0xd7a,0x13da,0, +0,0x176d,0,0,0x270,0x270,0xdb0,0xdb0,0,0,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a, +0x26a,0x26a,0x26a,0x26a,0,0,0,0,0,0,0,0x1635,0xcd5,0xcd5,0xcd5,0xcd5, +0xcd5,0xcd5,0xcd5,0xcd5,0x1416,0x12e4,0x1f5,0x1f5,0x1566,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb, +0x1fb,0,0x1fb,0x1fb,0x1fb,0,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb, +0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb, +0,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0,0,0xa2f,0x9ab,0x1f5,0x59d,0x5a0,0x1f5,0x59d,0x1f5, +0x1f5,0,0x59d,0x5a0,0x5a0,0,0x5a0,0x5a0,0x59d,0x5a3,0,0,0,0,0,0, +0,0x59d,0x59d,0,0,0,0,0,0,0x1755,0x1f8,0,0x1fb,0x1fb,0xc0c,0xc0c, +0,0,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0,0,0xb9d,0xb9d,0x17ee, +0,0,0,0,0,0,0,0,0,0,0,0,0x1521,0x12e7,0x246,0x246, +0x16c5,0x24c,0x24c,0x24c,0x24c,0x24c,0x24c,0x24c,0x24c,0,0x24c,0x24c,0x24c,0,0x24c,0x24c, +0x24c,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x246,0x5ac,0x5ac,0x5ac, +0xda1,0,0x246,0x246,0x246,0,0x249,0x249,0x249,0x654,0xfdb,0x141c,0,0,0,0, +0x141f,0x141f,0x141f,0x5ac,0x141c,0x141c,0x141c,0x141c,0x141c,0x141c,0x141c,0x1377,0x24c,0x24c,0xda1,0xda1, +0,0,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0xcb4,0xcb4,0xcb4,0xcb4, +0xcb4,0xcb4,0x141c,0x141c,0x141c,0xcb7,0xcba,0xcba,0xcba,0xcba,0xcba,0xcba,0,0x1710,0x792,0x792, +0,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x798,0x798,0x79b,0x79b,0x79b, +0x79b,0x79b,0x79b,0,0,0,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x798,0x79b, +0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0,0x79b,0x79b,0x79b,0x79b,0x79b, +0x79b,0x79b,0x79b,0x79b,0,0x79b,0,0,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0, +0,0,0x82e,0,0,0,0,0x82b,0x792,0x792,0x82b,0x82b,0x82b,0,0x82b,0, +0x792,0x792,0x795,0x792,0x795,0x795,0x795,0x828,0,0,0,0,0,0,0x11c4,0x11c4, +0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0,0,0x792,0x78f,0x78c,0,0,0, +0,0,0,0,0,0,0,0,0,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f, +0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f, +0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x5c1,0x27f,0x27c,0x5c1,0x5c1,0x5c1,0x5c1, +0x5c1,0x5c1,0x5c7,0,0,0,0,0x2a,0x285,0x285,0x285,0x285,0x285,0x27f,0x282,0x5c4, +0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c1,0x5c4,0x273,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279, +0x279,0x279,0x276,0x276,0,0,0,0,0,0x207,0x207,0,0x207,0,0x161d,0x207, +0x207,0x161d,0x207,0,0x161d,0x207,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x207,0x207,0x207,0x207, +0x161d,0x207,0x207,0x207,0x207,0x207,0x207,0x207,0x161d,0x207,0x207,0x207,0,0x207,0,0x207, +0x161d,0x161d,0x207,0x207,0x161d,0x207,0x207,0x207,0x207,0x5a6,0x207,0x201,0x5a6,0x5a6,0x5a6,0x5a6, +0x5a6,0x5a6,0x168f,0x5a6,0x5a6,0x207,0,0,0x20d,0x20d,0x20d,0x20d,0x20d,0,0x20a,0, +0x5a9,0x5a9,0x5a9,0x5a9,0x5a9,0x5a6,0x1833,0,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe, +0x1fe,0x1fe,0,0,0x204,0x204,0x10a1,0x10a1,0x68d,0x68d,0x68d,0x68a,0x68d,0x68d,0x68d,0x68d, +0,0x68d,0x68d,0x68d,0x68d,0x68a,0x68d,0x68d,0x68d,0x68d,0x68a,0x68d,0x68d,0x68d,0x68d,0x68a, +0x68d,0x68d,0x68d,0x68d,0x68a,0x68d,0x68d,0x68d,0x68d,0x68d,0x68d,0x68d,0x68d,0x68d,0x68d,0x68d, +0x68d,0x68a,0x7b6,0xce4,0xce4,0,0,0,0,0x6a8,0x6a8,0x6a5,0x6a8,0x6a5,0x6a5,0x6ba, +0x6a5,0x6ba,0x6a8,0x6a8,0x6a8,0x6a8,0x6a8,0x684,0x6a8,0x6a5,0x6b4,0x6b4,0x6b7,0x666,0x6b1,0x6b1, +0x68d,0x68d,0x68d,0x68d,0xfe4,0x1053,0x1053,0x1053,0x6a8,0x6a8,0x6a8,0x6a5,0x6a8,0x6a8,0x83d,0x6a8, +0,0x6a8,0x6a8,0x6a8,0x6a8,0x6a5,0x6a8,0x6a8,0x6a8,0x6a8,0x6a5,0x6a8,0x6a8,0x6a8,0x6a8,0x6a5, +0x6a8,0x6a8,0x6a8,0x6a8,0x6a5,0x6a8,0x83d,0x83d,0x83d,0x6a8,0x6a8,0x6a8,0x6a8,0x6a8,0x6a8,0x6a8, +0x83d,0x6a5,0x83d,0x83d,0x83d,0,0x7b3,0x7b3,0x7b0,0x7b0,0x7b0,0x7b0,0x7b0,0x7b0,0x840,0x7b0, +0x7b0,0x7b0,0x7b0,0x7b0,0x7b0,0,0xcdb,0x7b0,0xace,0xace,0xcde,0xce1,0xcdb,0xddd,0xddd,0xddd, +0xddd,0xfe1,0xfe1,0,0,0,0,0,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0,0x109b, +0,0,0,0,0,0x109b,0,0,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192, +0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0xa9b, +0x705,0,0x705,0x705,0x705,0x705,0,0,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0, +0x705,0,0x705,0x705,0x705,0x705,0,0,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0xa9b, +0x705,0,0x705,0x705,0x705,0x705,0,0,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0xa9b,0x705,0,0x705,0x705, +0x705,0x705,0,0,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0,0x705,0,0x705,0x705, +0x705,0x705,0,0,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0xa9b,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0xa9b,0x705,0,0x705,0x705,0x705,0x705,0,0,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0xa9b,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0x705,0x705,0x705,0x705,0,0,0x1050,0x1050,0xb52,0xa98,0x6ff,0x708,0x6fc, +0x6fc,0x6fc,0x6fc,0x708,0x708,0x702,0x702,0x702,0x702,0x702,0x702,0x702,0x702,0x702,0x6f9,0x6f9, +0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0,0,0,0xa9b,0xa9b,0xa9b,0xa9b, +0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa98,0xa98,0xa98,0xa98, +0xa98,0xa98,0xa98,0xa98,0xa98,0xa98,0,0,0,0,0,0,0x6ea,0x6ea,0x6ea,0x6ea, 0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea, -0x6ea,0x6ea,0x6ea,0x6ea,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e7,0x6e4,0x6e4, -0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4,0x6e4, -0xa53,0x6e7,0x3a5,0x3a8,0x3a5,0x3a5,0x3a5,0x3a8,0x3a5,0x3a5,0x3a5,0x3a5,0x3a8,0xa53,0x3a8,0x3a5, -0x39f,0x399,0x39f,0x399,0x39f,0x399,0x39f,0x399,0x39f,0x399,0x39f,0x399,0x39f,0x399,0x39f,0x399, -0x39f,0x399,0x39f,0x399,0x39f,0x399,0x3a2,0x39c,0x39f,0x399,0x39f,0x399,0x39f,0x399,0x39f,0x399, -0x39f,0x399,0x396,0x98d,0x990,0x972,0x972,0x11e2,0xa4d,0xa4d,0xc1b,0xc18,0xa56,0xa50,0xa56,0xa50, -0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5, -0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5, -0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5,0x3ab,0x3a5, -0x3ab,0x3ae,0x3a8,0x3ab,0x3a5,0xc1b,0xc18,0x3ab,0x3a5,0xc1b,0xc18,0x3ab,0x3a5,0xc1b,0xc18,0xf57, -0x3ae,0x3a8,0x3ae,0x3a8,0x3ab,0x3a5,0x3ae,0x3a8,0x3ab,0x3a5,0x3ae,0x3a8,0x3ae,0x3a8,0x3ae,0x3a8, -0x3ab,0x3a5,0x3ae,0x3a8,0x3ae,0x3a8,0x3ae,0x3a8,0x3ab,0x3a5,0x3ae,0x3a8,0xa59,0xa53,0x3ae,0x3a8, -0x3ae,0x3a8,0x3ae,0x3a8,0x3ae,0x3a8,0xe10,0xe0d,0x3ae,0x3a8,0xf5a,0xf57,0xf5a,0xf57,0xf5a,0xf57, -0xc81,0xc7e,0xc81,0xc7e,0xc81,0xc7e,0xc81,0xc7e,0xc81,0xc7e,0xc81,0xc7e,0xc81,0xc7e,0xc81,0xc7e, -0xf87,0xf84,0xf87,0xf84,0x1092,0x108f,0x1092,0x108f,0x1092,0x108f,0x1092,0x108f,0x1092,0x108f,0x1092,0x108f, -0x1092,0x108f,0x1092,0x108f,0x121b,0x1218,0x13f8,0x13f5,0x15c6,0x15c3,0x15c0,0x15bd,0x15c0,0x15bd,0x15c6,0x15c3, -0xc,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0, -0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0x3c0,0xc,0xc,0x3c3,0x3b1,0x3b1, -0x3b1,0x3b7,0x3b1,0x3b4,0x19d7,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd, -0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd, -0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3bd,0x3ba,0x19d7,0x3c6,0xa5c,0xc,0xc,0x158d,0x158d,0x14a6, -0xf,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4, -0x9b4,0x9b4,0xe13,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4,0x9b4, -0x3c9,0x3c9,0x3c9,0x3c9,0x3cc,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0xf5d,0x3c9,0x3c9,0x3c9,0x3d8,0x3c9, -0x3cf,0x3c9,0x3c9,0x3db,0x9b7,0xe16,0xe1c,0xe19,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, -0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de, -0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0x3de,0xf,0xf,0xf,0xf,0x19da, -0x3de,0x3de,0x3de,0x3d5,0x3d2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, -0xd2c,0xd2c,0xd2c,0xd2c,0x14a9,0x1590,0x101a,0x101a,0x101a,0x1017,0x1017,0xe22,0x8f7,0xd26,0xd23,0xd23, -0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0x1014,0x1014,0x1014,0x1014,0x1014,0x8f4,0x1587,0x1bfc,0xe25,0x8fa, -0x13bf,0x3ff,0x402,0x402,0x402,0x402,0x402,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff, -0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x101d,0x101d,0x101d,0x101d,0x101d, -0x8fd,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x978,0x978,0x978,0x978,0x978, -0x978,0x978,0x978,0xbbb,0xbbb,0xbbb,0xd1a,0xd20,0xd1d,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0x13bc, -0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x3f3,0x3f0,0x3ed,0x3ea,0xc1e,0xc1e, -0x975,0x3ff,0x3ff,0x408,0x3ff,0x3fc,0x3fc,0x3fc,0x3fc,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff, -0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3f9,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff, -0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3f9,0x3ff,0x3ff, -0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff, -0x3ff,0x3ff,0x3ff,0x3ff,0xa62,0xa62,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0xa62,0x402,0x3ff,0x402,0x3ff, -0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0xa62,0x3ff,0x3ff,0x3ff,0x402, -0x996,0x3ff,0x3e4,0x3e4,0x3e4,0x3e4,0x3e4,0x3e4,0x3e4,0x3e1,0x3ea,0x3e7,0x3e7,0x3e4,0x3e4,0x3e4, -0x3e4,0x405,0x405,0x3e4,0x3e4,0x3ea,0x3e7,0x3e7,0x3e7,0x3e4,0xd29,0xd29,0x3f6,0x3f6,0x3f6,0x3f6, -0x3f6,0x3f6,0x3f6,0x3f6,0x3f6,0x3f6,0xa62,0xa62,0xa62,0xa5f,0xa5f,0xd29,0xa77,0xa77,0xa77,0xa71, -0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa71,0xa6e,0xa71,0xa6e,0x12,0xa7a,0xa74,0xa65,0xa74,0xa74, -0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74, -0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xa74,0xd2f,0xd2f,0xd2f,0xa6b,0xa6b,0xa6b,0xa6b, -0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa6b,0xa68,0xa68,0xa68,0xa68, -0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0x12,0x12,0xd2f,0xd2f,0xd2f,0xe85,0xe85,0xe85,0xe85, -0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85, -0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0xe85,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4, -0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0xa80,0xa80,0xa80,0xa80, -0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80, -0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80,0xa80, -0xa80,0xa80,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xc21,0x15,0x15, -0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0xf9f,0xf9f,0xf9f,0xf9f, -0xf9f,0xf9f,0xf9f,0xf9f,0xf9f,0xf9f,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2, -0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2, -0xfa2,0xfa2,0xfa2,0xfa2,0xfa5,0xfa5,0xfa5,0xf96,0xf96,0xf96,0xf96,0xf96,0xf96,0xf96,0xf96,0xf96, -0xfa8,0xfa8,0xf99,0xf99,0xf9c,0xfae,0xfab,0xff,0xff,0x19fe,0x1a01,0x1a01,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb94,0xb94,0xb97,0xb97, -0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0x1d40,0x1d40,0x1d3d,0x1d3d,0x1dd,0x1dd,0x1dd,0x1dd, -0x1dd,0x1dd,0x1dd,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1e9,0x1e9,0x1e9,0x1e9, -0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x173d,0x173d,0x173d,0x173d,0x173d,0x173d,0x173d,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1311,0x1311,0x1311,0x1311, -0x1311,0x1311,0x1311,0x1311,0x1311,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1cda,0x1cd7,0x1bf,0x1bf, -0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1563,0x1563,0x1563,0x1563, -0x1563,0x1563,0x1563,0x1563,0x1563,0x1563,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1c59,0x1c59,0x1c59,0x1c59, -0x1c59,0x1c59,0x1c59,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x246,0x246,0x246,0x246, -0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1a4f,0x1a4f,0x1a4f,0x1a4f, -0x1a4f,0x1a4f,0x1a4f,0x1a4f,0x1a4f,0x1a4f,0x24c,0x24c,0x24c,0x24c,0x24c,0x24c,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1bc0,0x288,0x288,0x288, -0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x183f,0x183f,0x183f,0x183f, -0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1c6b,0x1c6b,0x1c6b,0x1c6b, -0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x172b,0x172b,0x172b,0x172b, -0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1cc2,0x1cc2,0x1cc2,0x1cc2, -0x29d,0x1cc2,0x1cc2,0x1cc2,0x1cc2,0x1cc2,0x1cc2,0x1cc2,0x29d,0x1cc2,0x1cc2,0x29d,0x17a3,0x17a3,0x17a3,0x17a3, -0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1c9e,0x1c9e,0x1c9e,0x1c9e, -0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xe7c,0xe7c,0xe79,0xe79, -0xe79,0xe7c,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x210,0x1857,0x1857,0x1857, -0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x2b8,0x2b8,0x2b8,0x2b8, -0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x1cf5,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1b0c,0x1b0c,0x1b0c,0x1b0c, -0x1b0c,0x1b0c,0x1b0c,0x1b0c,0x1b0c,0x1b0c,0x26d,0x26d,0x26d,0x26d,0x1b0f,0x1b09,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1c92,0x1c92,0x1c92,0x1c92, -0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1d25,0x1d25,0x1d25,0x1d25, -0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x252,0x1a64,0x1a64,0x1a64, -0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x270,0x270,0x270,0x270, -0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0,0,0,0, +0x6ea,0x1365,0,0,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0,0,0x783,0x786,0x786,0x786, +0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786, +0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x780,0x77d,0,0,0,0x789,0x789,0x789,0x789, +0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x7c5,0x7c5,0x7c5,0x789,0x789,0x789,0x11be,0x11be,0x11be, +0x11be,0x11be,0x11be,0x11be,0x11be,0,0,0,0,0,0,0,0x8f4,0x8f4,0x8f4,0x8f4, +0x8f4,0x8f4,0x8f4,0x8f4,0x8f4,0x8f4,0x8f4,0x8f4,0x8f4,0x1773,0x8f4,0x8f4,0x8f4,0x8f4,0x945,0x945, +0x948,0x17ca,0,0,0,0,0,0,0,0,0,0x1773,0x8f7,0x8f7,0x8f7,0x8f7, +0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x8f7,0x94b,0x94b, +0x94e,0x900,0x900,0,0,0,0,0,0,0,0,0,0x8fa,0x8fa,0x8fa,0x8fa, +0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x8fa,0x951,0x951, +0,0,0,0,0,0,0,0,0,0,0,0,0x8fd,0x8fd,0x8fd,0x8fd, +0x8fd,0x8fd,0x8fd,0x8fd,0x8fd,0x8fd,0x8fd,0x8fd,0x8fd,0,0x8fd,0x8fd,0x8fd,0,0x954,0x954, +0,0,0,0,0,0,0,0,0,0,0,0,0x726,0x726,0x726,0x726, +0x726,0x726,0x801,0x726,0x726,0x80d,0x80d,0x80d,0x80d,0x80d,0x807,0x807,0x80d,0x80a,0x810,0x804, +0x732,0x732,0x720,0x72c,0x71a,0x714,0x71d,0x717,0x72c,0xa32,0,0,0x723,0x723,0x723,0x723, +0x723,0x723,0x723,0x723,0x723,0x723,0,0,0,0,0,0,0x9ae,0x9ae,0x9ae,0x9ae, +0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0,0,0,0,0,0,0x750,0x750,0x7cb,0x7ce, +0x756,0x7c8,0x753,0x750,0x759,0x768,0x75c,0x81c,0x81c,0x81c,0x74d,0x17c4,0x75f,0x75f,0x75f,0x75f, +0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0,0,0,0,0,0,0x762,0x762,0x762,0x762, +0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762, +0x762,0x762,0x762,0x762,0x1572,0,0,0,0,0,0,0,0x762,0x762,0x762,0x762, +0x762,0x762,0x762,0x762,0x762,0x816,0xcbd,0,0,0,0,0,0xe25,0xe25,0xe25,0xe25, +0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25, +0xe25,0xe25,0,0,0,0,0,0,0,0,0,0,0x9d5,0x9d5,0x9d5,0x9d5, +0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5, +0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0x11c7,0x11c7,0,0xa35,0xa35,0xa35,0x9d2, +0x9d2,0x9d2,0x9d2,0xa35,0xa35,0x9d2,0x9d2,0x9d2,0,0,0,0,0x9d2,0x9d2,0xa35,0x9d2, +0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0xa38,0xa38,0xa38,0,0,0,0,0x9cc,0,0,0, +0x9d8,0x9d8,0x9cf,0x9cf,0x9cf,0x9cf,0x9cf,0x9cf,0x9cf,0x9cf,0x9cf,0x9cf,0x9e7,0x9e7,0x9e7,0x9e7, +0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0,0, +0x9e7,0x9e7,0x9e7,0x9e7,0x9e7,0,0,0,0,0,0,0,0,0,0,0, +0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xe2b,0xe2b,0,0,0,0, +0xafb,0xafb,0xafb,0xafb,0xafb,0xafe,0xafe,0xafe,0xafb,0xafb,0xafe,0xafb,0xafb,0xafb,0xafb,0xafb, +0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0,0,0,0,0,0,0xaf8,0xaf8,0xaf8,0xaf8, +0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xe28,0,0,0,0xaf5,0xaf5,0xad7,0xad7,0xad7,0xad7, +0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7,0xad7, +0xad7,0xad7,0xad7,0xb61,0xb61,0xad4,0xad4,0xb61,0,0,0xad1,0xad1,0xe5b,0xe5b,0xe5b,0xe5b, +0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, +0xe5b,0xe58,0xf5a,0xe58,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0,0xf63,0xe55,0xf5a,0xe55, +0xe55,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xf5a, +0xf5a,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0,0,0xf5d,0xe52,0xe52,0xe52,0xe52, +0xe52,0xe52,0xe52,0xe52,0xe52,0xe52,0,0,0,0,0,0,0xe52,0xe52,0xe52,0xe52, +0xe52,0xe52,0xe52,0xe52,0xe52,0xe52,0,0,0,0,0,0,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe5e,0xe61,0xe61,0xe61,0xe61,0xe4f,0xe4f,0,0,0x12d8,0x12d8,0x12d8,0x12d8, +0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d2,0x170a,0x170a,0x17be,0x17be,0x17be, +0x17be,0x17be,0x17be,0x17be,0x17be,0x17be,0x17be,0x17be,0x17b8,0x17b8,0x17b8,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xbc1,0xbc1,0xc0f,0xc12, +0xc1b,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0x177c,0,0x1872,0x1872,0xbbb,0xbbb,0xbbb,0xbbb, +0xbbb,0xbbb,0xbbb,0xbbb,0xbbb,0xbbb,0xbca,0xbca,0xbb5,0xbb8,0xbca,0xbca,0xff0,0xff0,0xff0,0xff0, +0xff0,0xff0,0x105c,0xfed,0x1059,0x1059,0xfed,0xfed,0xfed,0x1059,0xfed,0x1059,0x1059,0x1059,0x105f,0x105f, +0,0,0,0,0,0,0,0,0xfea,0xfea,0xfea,0xfea,0xd0b,0xd0b,0xd0b,0xd0b, +0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc, +0xd08,0xd08,0xdc2,0xdbf,0,0,0,0xd0e,0xd0e,0xd02,0xd02,0xd02,0xd05,0xd05,0xd05,0xd05, +0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0,0,0,0xd0b,0xd0b,0xd0b,0xd32,0xd32,0xd32,0xd32, +0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0x1410,0x1410,0x1410,0x1410, +0x1410,0x1410,0x1410,0x1410,0x1410,0x1866,0x1863,0,0,0,0,0,0x155d,0x155d,0x155d,0x155d, +0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d, +0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0,0,0x155d,0x155d,0x155d,0x10bc,0x10bc,0x10bc,0x10bc, +0x10bc,0x10bc,0x10bc,0x10bc,0,0,0,0,0,0,0,0,0xf8a,0xf87,0xf8a,0xedf, +0xf87,0xf8d,0xf8d,0xf90,0xf8d,0xf90,0xf93,0xf87,0xf90,0xf90,0xf87,0xf87,0xf90,0xee2,0xf87,0xf87, +0xf87,0xf87,0xf87,0xf87,0xf87,0xee8,0xee5,0xedc,0xedc,0xf8d,0xedc,0xedc,0xedc,0xedc,0xeeb,0x1107, +0x1143,0x1104,0x1104,0x14fd,0x1344,0x1344,0x1674,0,0,0,0,0,0x1b3,0x1b3,0x1b3,0x1b3, +0x1b3,0x1b3,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b3,0x1b3,0x1b3,0x1b3, +0x1b3,0x1b3,0,0,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0,0,0x1b3,0x1b3,0x1b3,0x1b3, +0x1b3,0x1b3,0x1b3,0x1b3,0,0x1b6,0,0x1b6,0,0x1b6,0,0x1b6,0x1b3,0x1b3,0x1b3,0x1b3, +0x1b3,0x1b3,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b3,0x1a7,0x1b3,0x1a7, +0x1b3,0x1a7,0x1b3,0x1a7,0x1b3,0x1a7,0x1b3,0x1a7,0x1b3,0x1a7,0,0,0x1b3,0x1b3,0x1b3,0x1b3, +0x1b3,0x1b3,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b3,0x1b3,0x1b3,0x1b3, +0x1b3,0,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1ad,0x1b6,0x198,0x1a7,0x198,0x198,0x195,0x1b3,0x1b3, +0x1b3,0,0x1b3,0x1b3,0x1b6,0x1ad,0x1b6,0x1ad,0x1b6,0x195,0x195,0x195,0x1b3,0x1b3,0x1b3,0x1a7, +0,0,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1ad,0,0x195,0x195,0x195,0x1b3,0x1b3,0x1b3,0x1a7, +0x1b3,0x1b3,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1ad,0x1b6,0x195,0x195,0x195,0,0,0x1b3,0x1b3, +0x1b3,0,0x1b3,0x1b3,0x1b6,0x1ad,0x1b6,0x1ad,0x1b6,0x19b,0x198,0,0x88e,0x891,0x891,0x891, +0xc21,9,0x1149,0x1149,0x1149,0x1149,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3f,0x8ee,0,0, +0x2e8,0x3f,0x3f,0x3f,0x3f,0x3f,0x57,0x69,0x57,0x63,0x5d,0x366,0x3c,0x2e5,0x2e5,0x2e5, +0x2e5,0x3c,0x3c,0x3c,0x3c,0x3c,0x54,0x66,0x54,0x60,0x5a,0,0xac5,0xac5,0xac5,0xac5, +0xac5,0xfd5,0xfd5,0xfd5,0xfd5,0xfd5,0xfd5,0xfd5,0xfd5,0,0,0,0x561,0x564,0x7fb,0x7fb, +0x93c,0x942,0x942,0x93f,0x93f,0x93f,0x93f,0xb4c,0xc03,0xc03,0xc03,0xc03,0xdd4,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x21f,0x21f,0x21f,0x73e, +0xba0,0xc93,0xc93,0xc93,0xc93,0xf0c,0x1353,0x1353,0,0,0,0,0x336,0x336,0x336,0x336, +0x336,0x336,0x336,0x336,0x336,0x336,0xd2,0xd2,0xcf,0xcf,0xcf,0xcf,0xa86,0xa83,0xa86,0xa83, +0xa83,0xa7a,0xa7a,0xa7a,0xa7a,0xa7a,0xa7a,0xdf8,0xdf5,0xdf8,0xdf5,0xf42,0xf45,0xf45,0x1092,0x108f, +0,0,0,0,0,0xa8c,0xa89,0xa89,0xa7d,0xa7a,0xa80,0xa7d,0xa9e,0xa9e,0xa9e,0xa9e, +0xa9e,0xa9e,0,0x1095,0,0,0,0,0,0x1095,0,0,0xb01,0xb01,0xb01,0xb01, +0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0x10ad,0x10ad, +0,0,0,0,0,0,0,0xb04,0xfe7,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x1056,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b, +0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0, +0,0,0,0,0,0,0,0,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0, +0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0, +0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd, +0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd, +0x7dd,0x7dd,0,0x7dd,0x7dd,0x7dd,0x7dd,0x7e0,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd, +0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7e0,0,0,0,0, +0,0,0,0,0,0,0,0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0, +0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x7f2,0x7f2,0x7f5,0x7f5,0x7f2,0x7f2,0x7f2,0x7f2,0x7f2,0x7f2,0x7f2,0x7f2,0x1851,0x1851,0x184e,0x184e, +0,0x4d1,0x4cb,0x4d1,0x4cb,0x4d1,0x4cb,0x4d1,0x4cb,0x4d1,0x4cb,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb, +0x4ce,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb, +0x4cb,0x4cb,0x4cb,0x4d1,0x4cb,0x4d1,0x4cb,0x4d1,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4d1,0x4cb, +0x4cb,0x4cb,0x4cb,0x4cb,0x4ce,0x924,0x924,0,0,0x645,0x645,0x519,0x519,0x4d4,0x4d7,0x921, +0,0,0,0,0,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7, +0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7,0x4a7, +0x4a7,0xd71,0x1506,0x15db,0,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2, +0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0,0x525,0x525,0x531,0x531,0x531,0x531,0x531,0x531, +0x531,0x531,0x531,0x531,0x531,0x531,0x531,0x531,0xd77,0xd77,0xd77,0xd77,0x18e7,0x18e7,0,0, +0,0,0,0,0,0,0,0x1851,0x927,0x927,0x927,0x927,0x927,0x927,0x927,0x927, +0x927,0x927,0x927,0x927,0x927,0x927,0x927,0x927,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9, +0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9, +0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0xa17,0xa17,0,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec, +0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0,0,0,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9, +0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x92d,0x7e9,0x7e9,0x7e9,0x92d,0x7e9,0, +0,0,0,0,0,0,0,0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0, +0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xd14,0xd14,0xd14,0xd14,0xd14,0xd14,0xd14,0xd14, +0xd14,0xd14,0xd1a,0xd1a,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7, +0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xf84,0xf84,0xec1,0xeca,0xec4,0xec4,0xec4,0xeca, +0,0,0,0,0,0,0,0,0x1761,0x175b,0x1629,0x1626,0x1629,0x1629,0x1629,0x16bf, +0x16bc,0x16bf,0x16bc,0x186c,0x186c,0x1869,0,0,0x1761,0x175b,0,0x175b,0,0x175b,0x1761,0x175b, +0x1761,0x175b,0x186c,0x1869,0x186c,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x1758,0x1758,0x1758,0x16b6,0x16b3,0x11a3, +0x10aa,0x10aa,0xfd2,0xc93,0xc93,0xc93,0xc93,0xc93,0xaf2,0xaf2,0xaf2,0xaef,0xaef,0xb6d,0xb6d,0xaef, +0xaec,0xaec,0xaec,0xaec,0x1713,0,0,0,0xef1,0xef1,0xef1,0xef4,0xef4,0xef4,0xef7,0xef7, +0xefa,0xef7,0,0,0,0,0,0,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8, +0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe5,0xbe5,0xbeb,0xbeb, +0,0,0,0,0,0,0,0,0xd4d,0xd4d,0xd4d,0xd4d,0xdcb,0x148e,0,0, +0,0,0,0,0,0,0xd53,0xd53,0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xd4a, +0xd4a,0xd4a,0,0,0,0,0,0,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xdc5, +0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xd44,0xdc8,0,0,0,0, +0,0,0,0,0,0,0,0xd41,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33, +0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33,0xf33, +0xf33,0xf33,0xf33,0xf33,0xf33,0,0,0,0xf57,0xe37,0xe37,0xe37,0xe37,0xe37,0xe37,0xe3a, +0xe46,0xe46,0xe37,0xe37,0xe37,0xe37,0,0xefd,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d, +0xe3d,0xe3d,0,0,0,0,0xe37,0xe37,0x11b2,0x11b2,0x11b2,0x11b2,0x11b2,0x12ea,0x11b8,0x11b5, +0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac, +0x11ac,0x11ac,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3, +0xcf3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xced,0xced,0xdb3,0xdb3,0xced,0xced,0xdb3,0xdb3,0, +0,0,0,0,0,0,0,0,0xcf0,0xcf0,0xcf0,0xdb3,0xcf0,0xcf0,0xcf0,0xcf0, +0xcf0,0xcf0,0xcf0,0xcf0,0xdb3,0xced,0,0,0xcea,0xcea,0xcea,0xcea,0xcea,0xcea,0xcea,0xcea, +0xcea,0xcea,0,0,0xce7,0xcf6,0xcf6,0xcf6,0xeb8,0xf81,0xeb8,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xeb5,0xeb5,0xebb,0xeaf,0xeb2,0x10c5,0x10c5,0x10c5,0x10c5,0x10c5,0x10c5,0x10c5,0x10c5, +0x10c5,0x10c5,0x10c5,0x10c2,0x1125,0x1125,0x10c2,0x10c2,0x10cb,0x10cb,0x10c5,0x10c8,0x10c8,0x10c2,0x1128,0, +0,0,0,0,0,0,0,0,0,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0, +0,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0,0,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0, +0,0,0,0,0,0,0,0,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0, +0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0xfc9,0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0, +0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x136e,0x136e,0x136e,0x136e,0x11a0,0x119a,0x1626,0x1626, +0x16b9,0x16c2,0x16a7,0x16a7,0,0,0,0,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362, +0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0xe6d,0xe6d,0xe6d,0xe67,0xe67,0xf66,0xe67,0xe67, +0xf66,0xe67,0xe67,0xe70,0xe6a,0xf69,0,0,0xe64,0xe64,0xe64,0xe64,0xe64,0xe64,0xe64,0xe64, +0xe64,0xe64,0,0,0,0,0,0,0x69c,0x69c,0x69c,0x69c,0,0,0,0, +0,0,0,0,0,0,0,0,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d, +0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0,0,0,0,0xe0a, +0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a, +0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0,0,0,0, +0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0,0,0,0,0,0,0,0,0, +0,0,0,0x147,0x147,0x147,0x147,0x147,0,0,0,0,0,0x711,0x597,0x1e9, +0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1e6,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9, +0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0,0x1e9,0, +0x1e9,0x1e9,0,0x1e9,0x1e9,0,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1ec, +0x12c,0x126,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126, +0xfb1,0xfb1,0x1743,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x12c,0x12c,0x126, +0x126,0x126,0x126,0x129,0x126,0x126,0x129,0x126,0x129,0x129,0x129,0x126,0x129,0x129,0x129,0x129, +0,0,0x129,0x129,0x129,0x129,0x126,0x126,0x129,0x126,0x126,0x126,0x126,0x129,0x126,0x126, +0x126,0x126,0x126,0x129,0x129,0x129,0x126,0x126,0,0,0,0,0,0,0,0x1743, +0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879, +0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a,0x95a, +0xb1f,0xb1f,0xb2e,0xb28,0xb25,0xb31,0xb31,0xb2b,0xb1c,0xb22,0,0,0,0,0,0, +0x456,0x47a,0x477,0x47a,0x477,0x930,0x930,0xa0e,0xa08,0x459,0x459,0x459,0x459,0x48f,0x48f,0x48f, +0x47d,0x480,0x495,0,0x486,0x483,0x498,0x498,0x471,0x465,0x453,0x465,0x453,0x465,0x453,0x45c, +0x45c,0x489,0x489,0x48c,0x489,0x489,0x489,0,0x489,0x46e,0x46b,0x45c,0,0,0,0, +0x11d,0x12f,0x11d,0x8d0,0x11d,0,0x11d,0x12f,0x11d,0x12f,0x11d,0x12f,0x11d,0x12f,0x11d,0x12f, +0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c, +0x126,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126,0,0,0x1b, +0,0x3ed,0x3cc,0x3ba,0x3c3,0x3c0,0x3ba,0x3cf,0x3bd,0x3b7,0x3ba,0x3db,0x3d2,0x3c9,0x3ea,0x3ba, +0x3e7,0x3e7,0x3e7,0x3e7,0x3e7,0x3e7,0x3e7,0x3e7,0x3e7,0x3e7,0x3d5,0x3d8,0x3db,0x3db,0x3db,0x3ed, +0x39c,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399, +0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0x399,0, +0,0,0x399,0x399,0x399,0x399,0x399,0x399,0,0,0x399,0x399,0x399,0x399,0x399,0x399, +0,0,0x399,0x399,0x399,0x399,0x399,0x399,0,0,0x399,0x399,0x399,0,0,0, +0x3c0,0x3c3,0x3db,0x3de,0x3ba,0x3c3,0x3c3,0,0x393,0x396,0x396,0x396,0x396,0x393,0x393,0, +9,9,9,9,9,9,9,9,9,0x6c3,0x6c3,0x6c3,0x6bd,0x2d9,0x288,0x288, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0,0x9db,0x9db,0,0x9db,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0,0,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0,0,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0,0,0,0,0,0x9f3,0x9f3,0x9f9,0, +0,0,0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0, +0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0,0,0,0x9f6, +0x9f6,0x9f6,0x9f6,0x9f6,0x9f6,0x9f6,0x9f6,0x9f6,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7, +0xaa7,0xaa7,0xaa7,0x1197,0x1197,0x1413,0x1413,0,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24, +0xc24,0xc24,0xc24,0xc24,0x16a4,0,0,0,0x1197,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a, +0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a, +0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xd7d,0,0,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29, +0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29, +0xd29,0xd29,0xd29,0xd29,0xd29,0,0,0,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26, +0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1347,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd, +0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd,0x12bd, +0x12bd,0x12bd,0x12bd,0x12bd,0,0,0,0,0x873,0x873,0x873,0x873,0,0,0,0, +0,0,0,0,0,0x14c4,0x14c4,0x14c4,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a, +0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0x86a,0,0,0,0,0, +0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df, +0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0,0,0,0,0, +0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed, +0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0x9ed,0,0x9ea, +0xb0a,0xb0a,0xb0a,0xb0a,0,0,0,0,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a, +0xb07,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0,0,0,0,0,0,0,0,0,0, +0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1, +0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0x9e1,0,0, +0x9de,0x9de,0x9de,0x9de,0x9de,0x9de,0x9de,0x9de,0x9de,0x9de,0,0,0,0,0,0, +0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a,0x146a, +0x146a,0x146a,0x146a,0x146a,0,0,0,0,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467, +0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467, +0x1467,0x1467,0x1467,0x1467,0,0,0,0,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c, +0,0,0,0,0,0,0,0,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281, +0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0,0,0,0,0,0,0,0, +0,0,0,0x127e,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0, +0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0x17a3,0,0x17a3,0x17a3,0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0, +0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0, +0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0,0x17a0, +0x17a0,0,0,0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c3,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0, +0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0,0,0,0,0,0,0,0, +0,0,0,0,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc, +0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0,0,0,0,0, +0,0,0,0,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc, +0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0,0,0,0,0,0, +0,0,0,0,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1764,0x176a,0x176a,0x1767,0x1767,0x1767,0,0x1767,0x1767,0x1767,0x1767,0x1767, +0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, +0x1767,0x1767,0x1767,0x1767,0x1767,0,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0, +0,0,0,0,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0,0,0x9c9,0,0x9c9,0x9c9, +0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9, +0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0x9c9,0,0x9c9,0x9c9,0,0,0,0x9c9,0,0,0x9c9, +0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79, +0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0,0xe76,0xe73,0xe73,0xe73,0xe73,0xe73,0xe73,0xe73,0xe73, +0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230, +0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0, +0,0,0,0,0,0,0,0x122d,0x122d,0x122d,0x122d,0x122d,0x122d,0x122d,0x122d,0x122d, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0,0x13bf,0x13bf,0,0,0,0,0,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc, +0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4, +0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbf4,0xbee,0xbee,0xbee,0xbee,0xe4c,0xe4c,0,0,0,0xbf1, +0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, +0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0,0,0,0,0,0xd2c, +0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd, +0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0,0,0,0,0x1392,0x1392,0x10dd,0x10dd, +0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392, +0,0,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392, +0xae6,0xb64,0xb64,0xb64,0,0xb64,0xb64,0,0,0,0,0,0xb64,0xb64,0xb64,0xb64, +0xae6,0xae6,0xae6,0xae6,0,0xae6,0xae6,0xae6,0,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6, +0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6,0xae6, +0x1578,0x1578,0,0,0xb67,0xb67,0xb67,0,0,0,0,0xb6a,0xae0,0xae0,0xae0,0xae0, +0xae0,0xae0,0xae0,0xae0,0x1575,0,0,0,0,0,0,0,0xae3,0xae3,0xae3,0xae3, +0xae3,0xae3,0xae9,0xae9,0xae0,0,0,0,0,0,0,0,0x11f1,0x11f1,0x11f1,0x11f1, +0x11f1,0x12fc,0x12fc,0,0,0,0,0x11e8,0x11e8,0x11e8,0x11e8,0x11e8,0x11ee,0x11ee,0x12c0,0x11ee, +0x11ee,0x11ee,0x11eb,0,0,0,0,0,0,0,0,0,0xe82,0xe82,0xe82,0xe82, +0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82, +0xe82,0xe82,0,0,0,0xe7c,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xea0,0xea0,0xea0,0xea0, +0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0,0xea0, +0xea0,0xea0,0,0,0xe9d,0xe9d,0xe9d,0xe9d,0xe9d,0xe9d,0xe9d,0xe9d,0xe9a,0xe9a,0xe9a,0xe9a, +0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0xe9a,0, +0,0,0,0,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0x11fa,0x11fa,0x11fa,0x11fa, +0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0x11fa,0,0, +0,0,0,0,0,0x11f7,0x11f7,0x11f7,0x11f7,0,0,0,0,0,0,0, +0,0,0,0,0,0x11f4,0x11f4,0x11f4,0x11f4,0x11f4,0x11f4,0x11f4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe49,0xe49,0xe49,0xe49, +0xe49,0xe49,0xe49,0xe49,0xe49,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1380,0x1380,0x1380,0x1380, +0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x137d,0x137d,0x137d,0x137d, +0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0, +0,0,0,0,0,0,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x15bd,0x15bd,0x15c0,0x15c0, +0x1608,0x1608,0x1608,0x1608,0,0,0,0,0,0,0,0,0x15ba,0x15ba,0x15ba,0x15ba, +0x15ba,0x15ba,0x15ba,0x15ba,0x15ba,0x15ba,0,0,0,0,0,0,0x1887,0x1887,0x1887,0x1887, +0x1887,0x1887,0,0,0,0x18f3,0x18f6,0x18f0,0x18f0,0x18f0,0x1878,0x188a,0x1881,0x1881,0x1881,0x1881, +0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0,0, +0,0,0,0,0,0,0x187b,0x187b,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef, +0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef, +0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5, +0x16f5,0x16f5,0,0x1725,0x1725,0x16f2,0,0,0x16f5,0x16f5,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x1860,0x1860,0x1860,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x18ea,0x182d,0x182d,0x182d, +0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cf,0,0,0,0,0,0,0,0, +0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6, +0x15c6,0x15c6,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x15c3,0x15c3,0x15c3, +0x15c3,0x15c9,0x15c9,0x15c9,0x15c9,0x15c9,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1791,0x1791,0x1791,0x1791,0x1791,0x1791,0x1791,0x1791, +0x1791,0x1791,0x1791,0x1791,0x1791,0x1791,0x1791,0x1791,0x1791,0x1791,0x17d6,0x17d6,0x17d6,0x17d6,0x1794,0x1794, +0x1794,0x1794,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x16da,0x16da,0x16da,0x16da,0x16da,0x16da,0x16da,0x16da, +0x16da,0x16da,0x16da,0x16da,0x16da,0x16da,0x16da,0x16da,0x16da,0x16d7,0x16d7,0x16d7,0x16d7,0x16d7,0x16d7,0x16d7, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653, +0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0,0,0,0,0, +0,0,0,0,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1065,0x1005,0x1005,0xff6,0xff6,0xff6, +0xff6,0xff6,0,0,0,0,0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff3, +0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9, +0x17d0,0x1782,0x1782,0x17cd,0x17cd,0x1782,0,0,0,0,0,0,0,0,0,0x12f3, +0xe91,0xe91,0x17d3,0,0,0,0,0,0,0,0,0,0,0x1584,0,0, +0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8, +0x10f8,0,0,0,0,0,0,0,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5, +0x10f5,0x10f5,0,0,0,0,0,0,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x112b, +0x112b,0x112b,0x112b,0x112b,0x10d4,0x112b,0x112e,0x112e,0x112b,0x112b,0x112b,0x1131,0x1131,0,0x10d1,0x10d1, +0x10d1,0x10d1,0x10d1,0x10d1,0x10d1,0x10d1,0x10d1,0x10d1,0x10ce,0x10da,0x10da,0x10da,0x1581,0x157e,0x157e,0x16c8, +0,0,0,0,0,0,0,0,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a, +0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x1332,0x1284,0x1287,0x128a,0, +0,0,0,0,0,0,0,0,0,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1, +0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0,0,0, +0,0,0,0,0,0,0,0,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0,0x1269,0x1269,0x1269,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1803,0x183c,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0, +0x13c2,0,0x13c2,0x13c2,0x13c2,0x13c2,0,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2, +0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2, +0x13c2,0x13c5,0,0,0,0,0,0,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f, +0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123c,0x123c,0x123c,0x1314,0x1314,0x1314,0x1314,0x1314, +0x1314,0x1317,0x131a,0,0,0,0,0,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239, +0x1239,0x1239,0,0,0,0,0,0,0x13ec,0x134a,0x120f,0x12c3,0,0x1218,0x1218,0x1218, +0x1218,0x1218,0x1218,0x1218,0x1218,0,0,0x1218,0x1218,0,0,0x1218,0x1218,0x1218,0x1218,0x1218, +0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218, +0x1218,0,0x1218,0x1218,0,0x1218,0x1218,0x1218,0x1218,0x1218,0,0x160e,0x134d,0x1215,0x1308,0x120f, +0x1308,0x120f,0x120f,0x120f,0x120f,0,0,0x120f,0x120f,0,0,0x1212,0x1212,0x130e,0,0, +0x138f,0,0,0,0,0,0,0x1308,0,0,0,0,0,0x121e,0x121b,0x121b, +0x1218,0x1218,0x120f,0x120f,0,0,0x130b,0x130b,0x130b,0x130b,0x130b,0x130b,0x130b,0,0,0, +0x130b,0x130b,0x130b,0x130b,0x130b,0,0,0,0,0,0,0,0,0,0,0, +0x18d5,0x18d5,0x18d5,0x18d8,0x18d5,0x18d8,0x18d5,0x18d5,0x18d5,0x18d5,0,0x18d5,0,0,0x18d8,0, +0x18d5,0x18d8,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf, +0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0x18cf,0,0x18cc,0x1908,0x18c9,0x18c9,0x1908, +0x1908,0x1908,0x1908,0x1908,0x1908,0,0x1908,0,0,0x190b,0,0x190b,0x190b,0x1908,0x18c9,0, +0x18c9,0x18c9,0x1914,0x1914,0x1917,0x18d2,0x1911,0x18db,0x18de,0x18de,0,0x18c6,0x18c6,0,0,0, +0,0,0,0,0,0x190e,0x190e,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x145e,0x145e,0x14ac,0x14a6,0x14a6,0x145e,0x14a9,0x1461,0x1461,0x1461,0x1461,0x1464, +0x1464,0x1458,0x1455,0x1452,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x16d1,0x1458, +0,0x1452,0x15f3,0x164d,0x16d4,0x16d4,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x9b1,0x9b1,3,3,3,3, +0,0,0,0,0x1329,0x1275,0x132f,0x132c,0x127b,0x127b,0x126f,0x127b,0,0,0,0, +0,0,0,0,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0x1272,0,0, +0,0,0,0,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae, +0x12ae,0x12ae,0x12ae,0x133b,0x12a8,0x12a8,0x133b,0x133b,0x133b,0x133b,0,0,0x12a8,0x12a8,0x12ab,0x12ab, +0x133b,0x133b,0x12a8,0x1341,0x133e,0x129f,0x12b1,0x12b1,0x12a2,0x12a2,0x12a5,0x12a5,0x12a5,0x12b1,0x13cb,0x13cb, +0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13c8,0x13c8,0x13c8,0x13c8, +0x13fb,0x13fb,0,0,0x1335,0x1299,0x1299,0x128d,0x1296,0,0,0,0,0,0,0, +0,0,0,0,0x1290,0x1290,0x1290,0x1290,0x1290,0x1290,0x1290,0x1290,0x1290,0x1290,0,0, +0,0,0,0,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422, +0x1422,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x113a, +0x10fe,0x113a,0x10fe,0x10fe,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x1140,0x113d,0x1647,0x1785,0,0, +0,0,0,0,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0,0, +0,0,0,0,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f, +0x186f,0x186f,0x186f,0x186f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, +0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x1587,0,0,0x13f5,0x13b3,0x13f5, +0x13b0,0x13b0,0x13f5,0x13f5,0x13f5,0x13f5,0x13b3,0x13f5,0x13f5,0x13f5,0x13f5,0x13f8,0,0,0,0, +0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13aa,0x13aa,0x13b9,0x13b9,0x13b9,0x13aa, +0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1590,0x1590,0x1590,0x15f6, +0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x1590,0x15fc,0x15f9,0x158d,0,0,0,0, +0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242, +0x1242,0x1242,0x1242,0,0,0,0,0,0,0,0,0,0,0,0,0x124b, +0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0,0,0x16e9,0,0,0x16e9,0x16e9,0x16e9,0x16e9, +0x16e9,0x16e9,0x16e9,0x16e9,0,0x16e9,0x16e9,0,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9, +0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x16e9,0x1719,0x16e3,0x16e3,0x16e3,0x16e3,0x16e3,0,0x16e3, +0x16e6,0,0,0x1719,0x1719,0x171f,0x1722,0x16ec,0x16e3,0x16ec,0x16e3,0x171c,0x16ef,0x16dd,0x16ef,0, +0,0,0,0,0,0,0,0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0, +0x16e0,0x16e0,0,0,0,0,0,0,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668, +0,0,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668, +0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1668,0x1665,0x1665,0x1665,0x1698,0x1698,0x1698,0x1698, +0,0,0x1698,0x1698,0x1665,0x1665,0x1665,0x1665,0x169b,0x1668,0x1662,0x1668,0x1665,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x14e8,0x14eb,0x14fa,0x14fa,0x14eb,0x14ee,0x14e8,0x153f, +0,0,0,0,0,0,0,0,0x14df,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x14dc, +0x14dc,0x1530,0x1530,0x1530,0x14df,0x14df,0x14df,0x14df,0x14d6,0x14d9,0x14d9,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1770,0x1770,0x1770,0x1770,0x1770,0x1770,0x1770,0x1770, +0x1770,0x1770,0x1770,0x1770,0x1770,0x1770,0x1770,0x1770,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c, +0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c, +0x129c,0,0,0,0,0,0,0,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb, +0x17eb,0x17eb,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x18bd,0x18b7,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba, +0x18ba,0x18ba,0,0,0,0,0,0,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440, +0x1440,0,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440, +0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x143d,0x149d,0x149d,0x149d,0x149d, +0x149d,0x149d,0x149d,0,0x149d,0x149d,0x149d,0x149d,0x149d,0x149d,0x143d,0x14a0,0x1440,0x1443,0x1443,0x1437, +0x1434,0x1434,0,0,0,0,0,0,0,0,0,0,0x143a,0x143a,0x143a,0x143a, +0x143a,0x143a,0x143a,0x143a,0x143a,0x143a,0x1431,0x1431,0x1431,0x1431,0x1431,0x1431,0x1431,0x1431,0x1431,0x1431, +0x1431,0x1431,0x1431,0x1431,0x1431,0,0,0,0x1446,0x1449,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f, +0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0,0,0x14a3,0x14a3, +0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0,0x144c,0x14a3,0x14a3, +0x14a3,0x14a3,0x14a3,0x14a3,0x14a3,0x144c,0x14a3,0x14a3,0x144c,0x14a3,0x14a3,0,0,0,0,0, +0,0,0,0,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0,0x14cd,0x14cd,0,0x14cd, +0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x14cd, +0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0,0,0,0x1527,0, +0x1527,0x1527,0,0x1527,0x1527,0x1527,0x152a,0x1527,0x152d,0x152d,0x14d0,0x1527,0,0,0,0, +0,0,0,0,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0,0, +0,0,0,0,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0,0x159c,0x159c,0,0x159c,0x159c, +0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x159c, +0x159c,0x159c,0x159c,0x159c,0x159c,0x159c,0x1599,0x1599,0x1599,0x1599,0x1599,0,0x15ff,0x15ff,0,0x1599, +0x1599,0x15ff,0x1599,0x1602,0x159c,0,0,0,0,0,0,0,0x1596,0x1596,0x1596,0x1596, +0x1596,0x1596,0x1596,0x1596,0x1596,0x1596,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x15a5,0x15a5,0x15a5,0x15a5, +0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a2,0x1605, +0x1605,0x159f,0x159f,0x15a8,0x15a8,0,0,0,0,0,0,0,0x183f,0x183f,0x1812,0x180c, +0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0,0x180f,0x180f, +0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f, +0x180f,0x180f,0x180f,0x180f,0x180c,0x180c,0x183f,0x183f,0x183f,0x183f,0x183f,0,0,0,0x180c,0x180c, +0x183f,0x1842,0x1845,0x1815,0x1815,0x1806,0x1806,0x1806,0x1806,0x1806,0x1806,0x1806,0x1806,0x1806,0x1806,0x1806, +0x1809,0x1809,0x1809,0x1809,0x1809,0x1809,0x1809,0x1809,0x1809,0x1809,0x18ed,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x16cb,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1632,0x162c,0x162c,0x162c, +0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x162f,0x11e5,0x11e5,0x11e5,0x11e5, +0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5, +0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x1383,0,0,0,0,0,0,0xbfa,0xbfa,0xbfa,0x11e5, +0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0,0xbf7,0xbf7,0xbf7,0xbf7, +0x11e2,0,0,0,0,0,0,0,0,0,0,0,0x1383,0x1383,0x1383,0x1383, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x178e,0x178e,0x178e,0x178e, +0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178b,0x178b,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1836,0x17fd,0x17fd,0x17fd, +0x17fd,0x17fd,0x17fd,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839, +0x1839,0x1839,0,0,0,0,0,0,0,0,0,0,0x1875,0x1875,0x1875,0x1875, +0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875, +0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0,0,0,0,0,0x13a1,0x13a1,0x13a1,0x13a1, +0x13a1,0x13a1,0x13a1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x18f9,0x18fc,0x18fc,0x18fc, +0x18fc,0x18fc,0x18fc,0x18fc,0x18fc,0x18f9,0x1893,0x1893,0x1893,0x18f9,0x18f9,0x18ff,0x1890,0x1890,0x1890,0x1890, +0x1890,0x1890,0x1890,0x1890,0x1890,0x1890,0,0,0,0,0,0,0x100e,0x100e,0x100e,0x100e, +0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e, +0x100e,0x100e,0x100e,0x100e,0x100e,0,0,0,0,0,0,0,0x1254,0x1254,0x1254,0x1254, +0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254, +0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0x1254,0,0x1251,0x1251,0x1251,0x1251, +0x1251,0x1251,0x1251,0x1251,0x1251,0x1251,0,0,0,0,0x1257,0x1257,0x179a,0x179a,0x179a,0x179a, +0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, +0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0,0x1797,0x1797,0x1797,0x1797, +0x1797,0x1797,0x1797,0x1797,0x1797,0x1797,0,0,0,0,0,0,0x11fd,0x11fd,0x11fd,0x11fd, +0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0,0, +0x12ff,0x12ff,0x12ff,0x12ff,0x12ff,0x1200,0,0,0,0,0,0,0,0,0,0, +0x11d3,0x11d3,0x11d6,0x11d6,0x11d9,0x11ca,0,0,0,0,0,0,0,0,0,0, +0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0,0x11ca,0x11ca,0x11ca,0x11ca,0x11ca, +0x11ca,0x11ca,0,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3, +0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0,0,0,0,0,0x11d3,0x11d3,0x11d3, +0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x189f,0x189f,0x189f,0x18a2,0x189f,0x189f,0x189f,0x18a2,0x18a5,0x18a5,0x18a5,0x18a8,0x18a8,0x1899,0x18ab,0x18ab, +0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0,0,0,0,0,0, +0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab, +0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ab,0x15ae,0x15b7,0x15ab,0x15ab,0,0,0,0,0, +0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x1644,0x1644,0x1644,0x1644,0x1644,0x1644,0,0,0,0,0x1692, +0x10b6,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3, +0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0,0,0,0,0,0,0,0x111c, +0x111c,0x111c,0x111c,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9, +0x147f,0x1512,0x1680,0x1683,0x172b,0,0,0,0,0,0,0,0,0,0,0, +0x1728,0x1728,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x15e1,0x15e1,0x15e1, +0x15e1,0x15e1,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0,0,0,0,0,0,0,0, +0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, +0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x18e4,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704, +0x1704,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x17b5,0x17b5,0x17b5,0x17b5,0,0x17b5,0x17b5,0x17b5, +0x17b5,0x17b5,0x17b5,0x17b5,0,0x17b5,0x17b5,0,0x17b2,0x17b2,0x17b2,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x1827,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1686,0x1686,0x1686,0, +0,0x182a,0,0,0,0,0,0,0,0,0,0,0x1689,0x1689,0x1689,0x1689, +0,0,0,0,0,0,0,0,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f, +0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f, +0x150f,0x150f,0x150f,0x150f,0,0,0,0,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206, +0x1206,0x1206,0x1206,0,0,0,0,0,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206, +0x1206,0x1206,0x1206,0x1206,0x1206,0,0,0,0,0,0,0,0x1206,0x1206,0x1206,0x1206, +0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0,0,0x1203,0x1302,0x1305,0x1209,0x12b4,0x12b4,0x12b4,0x12b4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1857,0x1857,0x1857,0x1857, +0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x185a,0x185a,0x185a,0x185a, +0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0,0,0,0,0,0,0x1854,0x1854,0x1854,0x1854, +0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854, +0,0,0,0,0,0,0,0,0,0,0,0,0x17bb,0x17bb,0x17bb,0x17bb, +0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0,0,0x17bb,0x17bb,0x17bb,0x17bb, +0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0, +0,0,0,0,0,0,0,0,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731, +0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0,0,0,0,0,0, +0,0,0,0,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0,0,0xc2d,0x852,0x852, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, +0x852,0x852,0x852,0x852,0x1359,0x1359,0x1359,0x1359,0x1359,0x1359,0x1359,0x1359,0x1359,0x1731,0x1731,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xaaa,0xaaa,0xb55,0xb55,0xb55,0xaaa,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df, +0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0,0,0,0,0,0,0,0, +0,0,0,0,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0,0,0,0,0,0,0,0, +0,0,0,0,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05, +0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0,0,0,0,0, +0,0,0,0,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, +0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x1545,0x1545,0,0,0, +0,0,0,0,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0x861,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x861,0x861,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x861,0,0x861,0x861,0,0,0x861,0,0,0x861,0x861,0,0,0x861,0x861,0x861, +0x861,0,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x85e,0x85e,0x85e,0x85e,0,0x85e, +0,0x85e,0x85e,0x85e,0x85e,0x969,0x85e,0x85e,0,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0x861,0x861,0x861,0x85e,0x85e,0x85e,0x85e,0x861,0x861,0,0x861,0x861,0x861,0x861,0, +0,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x861,0x861,0,0x861, +0x861,0x861,0x861,0,0x861,0x861,0x861,0x861,0x861,0,0x861,0,0,0,0x861,0x861, +0x861,0x861,0x861,0x861,0x861,0,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0xa50,0xa50,0,0,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x85e,0x85e,0x85e,0x858,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0xb88,0xb85,0,0,0x85b,0x85b, +0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b, +0x1386,0x1386,0x1386,0x1386,0x13e9,0x1386,0x1386,0x1389,0x138c,0x1389,0x1389,0x1386,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9, +0,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175e,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0, +0,0,0,0,0,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b, +0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0,0,0x148b,0x148b,0x148b,0x148b,0x148b, +0x148b,0x148b,0,0x148b,0x148b,0,0x148b,0x148b,0x148b,0x148b,0x148b,0,0,0,0,0, +0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8, +0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e8,0x17e8,0x17e8,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x1830,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c, +0x165c,0,0,0,0x1695,0x1695,0x1695,0x1695,0x1695,0x1695,0x1695,0x165c,0x165c,0x165c,0x165c,0x165c, +0x165f,0x165f,0,0,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0,0, +0,0,0x165c,0x1656,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x179d,0x179d,0x179d,0x179d,0x179d,0x179d,0x179d,0x179d,0x179d,0x179d,0x179d,0x179d, +0x179d,0x179d,0x179d,0x179d,0x179d,0x179d,0x17d9,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671, +0x1671,0x1671,0x1671,0x1671,0x169e,0x169e,0x169e,0x169e,0x166e,0x166e,0x166e,0x166e,0x166e,0x166e,0x166e,0x166e, +0x166e,0x166e,0,0,0,0,0,0x166b,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b, +0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x1848,0x1848,0x1848,0x1848,0x1818,0x1818,0x1818,0x1818, +0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4, +0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x1902,0x1905,0x18b4,0x18b1,0x18b1,0x18b1, +0x18b1,0x18b1,0x18b1,0x18b1,0x18b1,0x18b1,0x18b1,0,0,0,0,0x18ae,0x1752,0x1752,0x1752,0x1752, +0x1752,0x1752,0x1752,0,0x1752,0x1752,0x1752,0x1752,0,0x1752,0x1752,0,0x1752,0x1752,0x1752,0x1752, +0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0,0x1224,0x1224,0x1224,0x1224, +0x1224,0,0,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1311,0x1311,0x1311,0x1311, +0x1311,0x1311,0x1311,0,0,0,0,0,0,0,0,0,0x142b,0x142b,0x142b,0x142b, +0x149a,0x149a,0x149a,0x1494,0x1497,0x1497,0x1497,0x164a,0,0,0,0,0x1428,0x1428,0x1428,0x1428, +0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0,0,0,0,0x1425,0x1425,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x154b,0x1545,0x1545,0x1545, +0x154b,0x1545,0x1545,0x1545,0x1545,0,0,0,0,0,0,0,0,0,0,0, +0,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611, +0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611, +0x1611,0x1611,0,0,0x1086,0x1086,0x1086,0x1086,0,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086, +0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086, +0x1086,0x1086,0x1086,0x1086,0,0x1086,0x1086,0,0x1086,0,0,0x1086,0,0x1086,0x1086,0x1086, +0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0,0x1086,0x1086,0x1086,0x1086,0,0x1086,0,0x1086, +0,0,0,0,0,0,0x1086,0,0,0,0,0x1086,0,0x1086,0,0x1086, +0,0x1086,0x1086,0x1086,0,0x1086,0x1086,0,0x1086,0,0,0x1086,0,0x1086,0,0x1086, +0,0x1086,0,0x1086,0,0x1086,0x1086,0,0x1086,0,0,0x1086,0x1086,0x1086,0x1086,0, +0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0,0x1086,0x1086,0x1086,0x1086,0,0x1086,0x1086,0x1086, +0x1086,0,0x1086,0,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0,0x1086, +0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086, +0,0,0,0,0,0x1086,0x1086,0x1086,0,0x1086,0x1086,0x1086,0x1086,0x1086,0,0x1086, +0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086,0x1086, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1080,0x1080,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0,0,0,0, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0,0,0,0,0,0,0,0,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0x1152,0x1152,0,0,0,0,0,0,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0,0,0,0,0,0,0,0,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0,0,0x16a4,0x16a4,0x1854,0x1854, +0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0,0,0,0,0x1854,0x1854,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x16a4,0x16a4,0x16a4,0x16a4, +0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0, +0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x1854,0x1854,0x1854,0x1854, +0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x16aa,0x16aa,0x16aa,0x16aa, +0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x693,0x693,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27, +0xc27,0xc27,0xc27,0xc27,3,3,3,3,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27, +0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,3,3,3,3, +3,3,3,3,3,3,3,3,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c, +0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,3,3,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c, +0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0x1155,3,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c, +0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0x1023,3,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c, +0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0xf9c,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,3,3, +3,3,3,3,3,3,3,3,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470, +0x1470,0x1470,0x1470,0x1470,0x1470,0x16a4,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,0x9b1,0x9b1, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -0x1596,0x426,0x435,0x435,0x18,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x18,0x18,0x43e, -0x43e,0x18,0x18,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e, -0x43e,0x18,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x43e,0x18,0x43e,0x18,0x18,0x18,0x43e,0x43e, -0x43e,0x43e,0x18,0x18,0x429,0xd35,0x426,0x435,0x435,0x426,0x426,0x426,0x426,0x18,0x18,0x435, -0x435,0x18,0x18,0x438,0x438,0x42c,0xe2b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x426, -0x18,0x18,0x18,0x18,0x43b,0x43b,0x18,0x43b,0x43e,0x43e,0x426,0x426,0x18,0x18,0x99c,0x99c, -0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x43e,0x43e,0x432,0x432,0x42f,0x42f,0x42f,0x42f, -0x42f,0x432,0x42f,0x11f1,0x1938,0x1935,0x19dd,0x18,0x1b,0xd38,0x441,0xd3b,0x1b,0x450,0x450,0x450, -0x450,0x450,0x450,0x1b,0x1b,0x1b,0x1b,0x450,0x450,0x1b,0x1b,0x450,0x450,0x450,0x450,0x450, -0x450,0x450,0x450,0x450,0x450,0x450,0x450,0x450,0x450,0x1b,0x450,0x450,0x450,0x450,0x450,0x450, -0x450,0x1b,0x450,0x44d,0x1b,0x450,0x44d,0x1b,0x450,0x450,0x1b,0x1b,0x444,0x1b,0x44a,0x44a, -0x44a,0x441,0x441,0x1b,0x1b,0x1b,0x1b,0x441,0x441,0x1b,0x1b,0x441,0x441,0x447,0x1b,0x1b, -0x1b,0x1026,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x44d,0x44d,0x44d,0x450,0x1b,0x44d,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x99f,0x99f,0x99f,0x99f,0x99f,0x99f,0x99f,0x99f,0x99f,0x99f, -0x441,0x441,0x450,0x450,0x450,0x1026,0x19e0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1e,0x453,0x453,0x45c,0x1e,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0xd44,0x45f,0x1e,0x45f, -0x45f,0x45f,0x1e,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f, -0x45f,0x1e,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x1e,0x45f,0x45f,0x1e,0x45f,0x45f,0x45f, -0x45f,0x45f,0x1e,0x1e,0x456,0x45f,0x45c,0x45c,0x45c,0x453,0x453,0x453,0x453,0x453,0x1e,0x453, -0x453,0x45c,0x1e,0x45c,0x45c,0x459,0x1e,0x1e,0x45f,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, -0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x45f,0xd44,0xd3e,0xd3e,0x1e,0x1e,0x9a2,0x9a2, -0x9a2,0x9a2,0x9a2,0x9a2,0x9a2,0x9a2,0x9a2,0x9a2,0x14ac,0xd41,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, -0x1e,0x17b8,0x193b,0x193b,0x193b,0x193e,0x193e,0x193e,0x21,0x462,0x471,0x471,0x21,0x47a,0x47a,0x47a, -0x47a,0x47a,0x47a,0x47a,0x47a,0x21,0x21,0x47a,0x47a,0x21,0x21,0x47a,0x47a,0x47a,0x47a,0x47a, -0x47a,0x47a,0x47a,0x47a,0x47a,0x47a,0x47a,0x47a,0x47a,0x21,0x47a,0x47a,0x47a,0x47a,0x47a,0x47a, -0x47a,0x21,0x47a,0x47a,0x21,0xd47,0x47a,0x47a,0x47a,0x47a,0x21,0x21,0x465,0x47a,0x462,0x462, -0x471,0x462,0x462,0x462,0x1029,0x21,0x21,0x471,0x474,0x21,0x21,0x474,0x474,0x468,0x21,0x21, -0x21,0x21,0x21,0x21,0x21,0x1b54,0x462,0x462,0x21,0x21,0x21,0x21,0x477,0x477,0x21,0x47a, -0x47a,0x47a,0x1029,0x1029,0x21,0x21,0x46e,0x46e,0x46e,0x46e,0x46e,0x46e,0x46e,0x46e,0x46e,0x46e, -0x46b,0xd47,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, -0x24,0x24,0x47d,0x489,0x24,0x489,0x489,0x489,0x489,0x489,0x489,0x24,0x24,0x24,0x489,0x489, -0x489,0x24,0x489,0x489,0x48c,0x489,0x24,0x24,0x24,0x489,0x489,0x24,0x489,0x24,0x489,0x489, -0x24,0x24,0x24,0x489,0x489,0x24,0x24,0x24,0x489,0x489,0x489,0x24,0x24,0x24,0x489,0x489, -0x489,0x489,0x489,0x489,0x489,0x489,0xe2e,0x489,0x489,0x489,0x24,0x24,0x24,0x24,0x47d,0x483, -0x47d,0x483,0x483,0x24,0x24,0x24,0x483,0x483,0x483,0x24,0x486,0x486,0x486,0x480,0x24,0x24, -0x102c,0x24,0x24,0x24,0x24,0x24,0x24,0x47d,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, -0x24,0x24,0xf4b,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a5,0x9a5,0x9a5,0xdfb, -0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xd4d,0xd4a,0x24,0x24,0x24,0x24,0x24,0x1599,0x49b,0x49b,0x49b, -0x19e3,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x27,0x49e,0x49e,0x49e,0x27,0x49e,0x49e, -0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x27,0x49e,0x49e, -0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x159c,0x49e,0x49e,0x49e,0x49e,0x49e,0x27,0x27, -0x1bff,0x1038,0x48f,0x48f,0x48f,0x49b,0x49b,0x49b,0x49b,0x27,0x48f,0x48f,0x492,0x27,0x48f,0x48f, -0x48f,0x495,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x48f,0x48f,0x27,0x1035,0x1035,0x17bb,0x27, -0x27,0x1c02,0x27,0x27,0x49e,0x49e,0x102f,0x102f,0x27,0x27,0x498,0x498,0x498,0x498,0x498,0x498, -0x498,0x498,0x498,0x498,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x1ab2,0x1032,0x1032,0x1032,0x1032, -0x1032,0x1032,0x1032,0x1032,0x187b,0x159f,0x4a7,0x4a7,0x19e6,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0, -0x4b0,0x2a,0x4b0,0x4b0,0x4b0,0x2a,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0, -0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x2a,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0, -0x2a,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x2a,0x2a,0xd50,0xd53,0x4a7,0x4a1,0x4aa,0x4a7,0x4a1,0x4a7, -0x4a7,0x2a,0x4a1,0x4aa,0x4aa,0x2a,0x4aa,0x4aa,0x4a1,0x4a4,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, -0x2a,0x4a1,0x4a1,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x1c05,0x4ad,0x2a,0x4b0,0x4b0,0xf63,0xf63, -0x2a,0x2a,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x2a,0xf66,0xf66,0x1cc8, -0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x1941,0x15a2,0x4bc,0x4bc, -0x1b57,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x2d,0x4c2,0x4c2,0x4c2,0x2d,0x4c2,0x4c2, -0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4bc,0x4b3,0x4b3,0x4b3, -0x103b,0x2d,0x4bc,0x4bc,0x4bc,0x2d,0x4bf,0x4bf,0x4bf,0x4b6,0x13d1,0x187e,0x2d,0x2d,0x2d,0x2d, -0x1881,0x1881,0x1881,0x4b3,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x17be,0x4c2,0x4c2,0x103b,0x103b, -0x2d,0x2d,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x103e,0x103e,0x103e,0x103e, -0x103e,0x103e,0x187e,0x187e,0x187e,0x1041,0x1044,0x1044,0x1044,0x1044,0x1044,0x1044,0x30,0x1b5a,0xa92,0xa92, -0x30,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa98,0xa98,0xa9b,0xa9b,0xa9b, -0xa9b,0xa9b,0xa9b,0x30,0x30,0x30,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa98,0xa9b, -0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0x30,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b, -0xa9b,0xa9b,0xa9b,0xa9b,0x30,0xa9b,0x30,0x30,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0xa9b,0x30, -0x30,0x30,0xa89,0x30,0x30,0x30,0x30,0xa86,0xa92,0xa92,0xa86,0xa86,0xa86,0x30,0xa86,0x30, -0xa92,0xa92,0xa95,0xa92,0xa95,0xa95,0xa95,0xa83,0x30,0x30,0x30,0x30,0x30,0x30,0x15a5,0x15a5, -0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x15a5,0x30,0x30,0xa92,0xa8f,0xa8c,0x30,0x30,0x30, -0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x33,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd, -0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd, -0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4c8,0x4dd,0x4da,0x4c8,0x4c8,0x4c8,0x4c8, -0x4c8,0x4c8,0x4ce,0x33,0x33,0x33,0x33,0x4c5,0x4e3,0x4e3,0x4e3,0x4e3,0x4e3,0x4dd,0x4e0,0x4cb, -0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4c8,0x4cb,0x4d1,0x4d7,0x4d7,0x4d7,0x4d7,0x4d7,0x4d7,0x4d7,0x4d7, -0x4d7,0x4d7,0x4d4,0x4d4,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, -0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, -0x33,0x33,0x33,0x33,0x36,0x4f5,0x4f5,0x36,0x4f5,0x36,0x1ab8,0x4f5,0x4f5,0x1ab8,0x4f5,0x36, -0x1ab8,0x4f5,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x4f5,0x4f5,0x4f5,0x4f5,0x1ab8,0x4f5,0x4f5,0x4f5, -0x4f5,0x4f5,0x4f5,0x4f5,0x1ab8,0x4f5,0x4f5,0x4f5,0x36,0x4f5,0x36,0x4f5,0x1ab8,0x1ab8,0x4f5,0x4f5, -0x1ab8,0x4f5,0x4f5,0x4f5,0x4f5,0x4e6,0x4f5,0x4ef,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x1ab5,0x4e6, -0x4e6,0x4f5,0x36,0x36,0x4fb,0x4fb,0x4fb,0x4fb,0x4fb,0x36,0x4f8,0x36,0x4e9,0x4e9,0x4e9,0x4e9, -0x4e9,0x4e6,0x1ccb,0x36,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0x36,0x36, -0x4f2,0x4f2,0x14af,0x14af,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, -0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, -0x36,0x36,0x36,0x36,0x9fc,0x9fc,0x9fc,0x9f9,0x9fc,0x9fc,0x9fc,0x9fc,0x39,0x9fc,0x9fc,0x9fc, -0x9fc,0x9f9,0x9fc,0x9fc,0x9fc,0x9fc,0x9f9,0x9fc,0x9fc,0x9fc,0x9fc,0x9f9,0x9fc,0x9fc,0x9fc,0x9fc, -0x9f9,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9fc,0x9f9,0xaaa,0x1050, -0x1050,0x39,0x39,0x39,0x39,0x9bd,0x9bd,0x9ba,0x9bd,0x9ba,0x9ba,0x9cf,0x9ba,0x9cf,0x9bd,0x9bd, -0x9bd,0x9bd,0x9bd,0x9f3,0x9bd,0x9ba,0x9c9,0x9c9,0x9cc,0x9d5,0x9c6,0x9c6,0x9fc,0x9fc,0x9fc,0x9fc, -0x13da,0x13d4,0x13d4,0x13d4,0x9bd,0x9bd,0x9bd,0x9ba,0x9bd,0x9bd,0xa9e,0x9bd,0x39,0x9bd,0x9bd,0x9bd, -0x9bd,0x9ba,0x9bd,0x9bd,0x9bd,0x9bd,0x9ba,0x9bd,0x9bd,0x9bd,0x9bd,0x9ba,0x9bd,0x9bd,0x9bd,0x9bd, -0x9ba,0x9bd,0xa9e,0xa9e,0xa9e,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0xa9e,0x9ba,0xa9e,0xa9e, -0xa9e,0x39,0xaa7,0xaa7,0xaa4,0xaa4,0xaa4,0xaa4,0xaa4,0xaa4,0xaa1,0xaa4,0xaa4,0xaa4,0xaa4,0xaa4, -0xaa4,0x39,0x1047,0xaa4,0xe31,0xe31,0x104a,0x104d,0x1047,0x11f4,0x11f4,0x11f4,0x11f4,0x13d7,0x13d7,0x39, -0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, -0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, -0x501,0x501,0x501,0x501,0x501,0x501,0x3c,0x14b5,0x3c,0x3c,0x3c,0x3c,0x3c,0x14b5,0x3c,0x3c, -0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xe40,0xad4,0x3f,0xad4,0xad4,0xad4,0xad4,0x3f,0x3f, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0x3f,0xad4,0x3f,0xad4,0xad4,0xad4,0xad4,0x3f,0x3f, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xe40,0xad4,0x3f,0xad4,0xad4,0xad4,0xad4,0x3f,0x3f, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4, -0xad4,0xad4,0xad4,0xe40,0xad4,0x3f,0xad4,0xad4,0xad4,0xad4,0x3f,0x3f,0xad4,0xad4,0xad4,0xad4, -0xad4,0xad4,0xad4,0x3f,0xad4,0x3f,0xad4,0xad4,0xad4,0xad4,0x3f,0x3f,0xad4,0xad4,0xad4,0xad4, -0xad4,0xad4,0xad4,0xe40,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0x3f,0xad4,0xad4,0xad4,0xad4, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xe40,0xad4,0x3f,0xad4,0xad4, -0xad4,0xad4,0x3f,0x3f,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xe40,0xad4,0xad4,0xad4,0xad4, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0x3f, -0x3f,0x13dd,0x13dd,0xe3a,0xe3d,0xace,0xad7,0xacb,0xacb,0xacb,0xacb,0xad7,0xad7,0xad1,0xad1,0xad1, -0xad1,0xad1,0xad1,0xad1,0xad1,0xad1,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8, -0xac8,0x3f,0x3f,0x3f,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada, -0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0x17c4,0x42,0x42,0x17c1,0x17c1,0x17c1,0x17c1, -0x17c1,0x17c1,0x42,0x42,0xaec,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef, -0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xae9, -0xae6,0x45,0x45,0x45,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf2, -0xaf2,0xaf2,0xaf5,0xaf5,0xaf5,0x15a8,0x15a8,0x15a8,0x15a8,0x15a8,0x15a8,0x15a8,0x15a8,0x48,0x48,0x48, -0x48,0x48,0x48,0x48,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xaf8,0xb1f,0xb1f,0xb04,0xb04,0xb04, -0xb04,0xb04,0xafe,0xafe,0xb04,0xb01,0xb07,0xafb,0xb2b,0xb2b,0xb19,0xb25,0xb13,0xb0d,0xb16,0xb10, -0xb25,0xd56,0x4b,0x4b,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0x4b,0x4b, -0x4b,0x4b,0x4b,0x4b,0xd59,0xd59,0xd59,0xd59,0xd59,0xd59,0xd59,0xd59,0xd59,0xd59,0x4b,0x4b, -0x4b,0x4b,0x4b,0x4b,0xb37,0xb37,0xbaf,0xbb2,0xb3d,0xbac,0xb3a,0xb37,0xb40,0xb4f,0xb43,0xb52, -0xb52,0xb52,0xb2e,0x1c08,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0x4e,0x4e, -0x4e,0x4e,0x4e,0x4e,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49, -0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0x19e9,0x4e,0x4e,0x4e, -0x4e,0x4e,0x4e,0x4e,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb31,0x106e,0x4e, -0x4e,0x4e,0x4e,0x4e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e, -0x124e,0x124e,0x124e,0x124e,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x52b,0x52b,0x52b,0x52b, -0x52b,0x52b,0x52b,0x52b,0x528,0x528,0x528,0x528,0x528,0x528,0x51,0x51,0x52b,0x52b,0x52b,0x52b, -0x52b,0x52b,0x51,0x51,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x51,0x52b,0x51,0x52b, -0x51,0x52b,0x51,0x52b,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x52b,0x52b,0x52b,0x52b, -0x52b,0x52b,0x52b,0x52b,0x528,0x522,0x528,0x522,0x528,0x522,0x528,0x522,0x528,0x522,0x528,0x522, -0x528,0x522,0x51,0x51,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x52b,0x52b,0x52b,0x52b, -0x52b,0x52b,0x52b,0x52b,0x528,0x528,0x528,0x528,0x528,0x51,0x528,0x528,0x52b,0x52b,0x52b,0x525, -0x52b,0x51c,0x522,0x51c,0x51c,0x519,0x528,0x528,0x528,0x51,0x528,0x528,0x52b,0x525,0x52b,0x525, -0x52b,0x519,0x519,0x519,0x528,0x528,0x528,0x522,0x51,0x51,0x528,0x528,0x52b,0x52b,0x52b,0x525, -0x51,0x519,0x519,0x519,0x528,0x528,0x528,0x522,0x528,0x528,0x528,0x528,0x52b,0x52b,0x52b,0x525, -0x52b,0x519,0x519,0x519,0x51,0x51,0x528,0x528,0x528,0x51,0x528,0x528,0x52b,0x525,0x52b,0x525, -0x52b,0x51f,0x51c,0x51,0xc27,0xc2a,0xc2a,0xc2a,0x107a,0x54,0x1584,0x1584,0x1584,0x1584,0x534,0x534, -0x534,0x534,0x534,0x534,0x57f,0xc3c,0x57,0x57,0x726,0x57f,0x57f,0x57f,0x57f,0x57f,0x585,0x597, -0x585,0x591,0x58b,0x729,0x57c,0x723,0x723,0x723,0x723,0x57c,0x57c,0x57c,0x57c,0x57c,0x582,0x594, -0x582,0x58e,0x588,0x57,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0x13e0,0x13e0,0x13e0,0x13e0,0x13e0,0x13e0,0x13e0, -0x13e0,0x57,0x57,0x57,0x1c0b,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, -0x5a,0x5a,0x5a,0x5a,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6,0x5a6, -0x5a6,0x5a3,0x5a3,0x5a3,0x5a3,0x5a6,0xb5e,0xb5e,0xc42,0xc48,0xc48,0xc45,0xc45,0xc45,0xc45,0xe52, -0xf69,0xf69,0xf69,0xf69,0x11df,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, -0x5d,0x5d,0x5d,0x5d,0x5d6,0x5d6,0x5d6,0xb67,0xf72,0x1080,0x1080,0x1080,0x1080,0x133e,0x17ca,0x17ca, -0x60,0x60,0x60,0x60,0x750,0x750,0x750,0x750,0x750,0x750,0x750,0x750,0x750,0x750,0x5e5,0x5e5, -0x5e2,0x5e2,0x5e2,0x5e2,0x606,0x606,0x606,0x606,0x606,0xb70,0xb70,0x63,0x63,0x63,0x63,0x63, -0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, -0x63,0x63,0x63,0x63,0x609,0x609,0x609,0x609,0x609,0x609,0x609,0x609,0x609,0x609,0x609,0x66, -0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, -0x66,0x66,0x66,0x66,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b, -0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0x69,0xb8b, -0xb8b,0xb8b,0xb8b,0xb8e,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b, -0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8e,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69, -0x69,0x69,0x69,0x69,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91, -0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c, -0x6c,0x6c,0x6c,0x6c,0x6f,0x873,0x86d,0x873,0x86d,0x873,0x86d,0x873,0x86d,0x873,0x86d,0x86d, -0x870,0x86d,0x870,0x86d,0x870,0x86d,0x870,0x86d,0x870,0x86d,0x870,0x86d,0x870,0x86d,0x870,0x86d, -0x870,0x86d,0x870,0x86d,0x86d,0x86d,0x86d,0x873,0x86d,0x873,0x86d,0x873,0x86d,0x86d,0x86d,0x86d, -0x86d,0x86d,0x873,0x86d,0x86d,0x86d,0x86d,0x86d,0x870,0xce1,0xce1,0x6f,0x6f,0x98a,0x98a,0x951, -0x951,0x876,0x879,0xcde,0x72,0x72,0x72,0x72,0x72,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b, -0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b, -0x88b,0x88b,0x88b,0x88b,0x88b,0x11cd,0x19b0,0x1a9d,0x75,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e, -0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x75,0x95a,0x95a,0x95d,0x95d, -0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x95d,0x897,0x897,0x897,0x897, -0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897, -0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0x897,0xde0,0xde0,0x78,0xba3,0xba3,0xba3,0xba3, -0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0x7b,0x7b,0x7b,0xba9,0xba9,0xba9,0xba9, -0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xcea,0xba9,0xba9, -0xba9,0xcea,0xba9,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x1275,0x1275,0x1275,0x1275, -0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0xa1d,0xa1d,0xa1d,0xa1d, -0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x12ea,0x12ea,0x12ea,0x12ea, -0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x64e,0x64e,0x64e,0x64e, -0x64e,0x64e,0x64e,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x63c, -0x63c,0x63c,0x63c,0x63c,0x84,0x84,0x84,0x84,0x84,0xb7c,0x63f,0x645,0x64b,0x64b,0x64b,0x64b, -0x64b,0x64b,0x64b,0x64b,0x64b,0x642,0x645,0x645,0x645,0x645,0x645,0x645,0x645,0x645,0x645,0x645, -0x645,0x645,0x645,0x84,0x645,0x645,0x645,0x645,0x645,0x84,0x645,0x84,0x645,0x645,0x84,0x645, -0x645,0x84,0x645,0x645,0x645,0x645,0x645,0x645,0x645,0x645,0x645,0x648,0x65a,0x654,0x65a,0x654, -0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x13f2,0x13f2,0x1c0e,0x87, -0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x65a, -0x654,0x657,0x65d,0x65a,0x654,0x65a,0x654,0x65a,0x654,0x65a,0x65a,0x654,0x654,0x654,0x654,0x657, -0x654,0x654,0x657,0x654,0x657,0x657,0x657,0x654,0x657,0x657,0x657,0x657,0x87,0x87,0x657,0x657, -0x657,0x657,0x654,0x654,0x657,0x654,0x654,0x654,0x654,0x657,0x654,0x654,0x654,0x654,0x654,0x657, -0x657,0x657,0x654,0x654,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x1c0e,0xbc7,0xbc7,0xbc7,0xbc7, -0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0x8af,0x8c1,0x8be,0x8c1, -0x8be,0xcff,0xcff,0xdec,0xde9,0x8b2,0x8b2,0x8b2,0x8b2,0x8c4,0x8c4,0x8c4,0x8dc,0x8df,0x8ee,0x8a, -0x8e2,0x8e5,0x8f1,0x8f1,0x8d9,0x8d0,0x8ca,0x8d0,0x8ca,0x8d0,0x8ca,0x8cd,0x8cd,0x8e8,0x8e8,0x8eb, -0x8e8,0x8e8,0x8e8,0x8a,0x8e8,0x8d6,0x8d3,0x8cd,0x8a,0x8a,0x8a,0x8a,0x666,0x672,0x666,0xc7b, -0x666,0x8d,0x666,0x672,0x666,0x672,0x666,0x672,0x666,0x672,0x666,0x672,0x672,0x66f,0x669,0x66c, -0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66f,0x669,0x66f,0x669,0x66c, -0x672,0x66f,0x669,0x66f,0x669,0x66f,0x669,0x66f,0x669,0x8d,0x8d,0x663,0x7ad,0x7b0,0x7c5,0x7c8, -0x7a7,0x7b0,0x7b0,0x93,0x78f,0x792,0x792,0x792,0x792,0x78f,0x78f,0x93,0x90,0x90,0x90,0x90, -0x90,0x90,0x90,0x90,0x90,0xb7f,0xb7f,0xb7f,0xa20,0x789,0x675,0x675,0x93,0x7d7,0x7b6,0x7a7, -0x7b0,0x7ad,0x7a7,0x7b9,0x7aa,0x7a4,0x7a7,0x7c5,0x7bc,0x7b3,0x7d4,0x7a7,0x7d1,0x7d1,0x7d1,0x7d1, -0x7d1,0x7d1,0x7d1,0x7d1,0x7d1,0x7d1,0x7c2,0x7bf,0x7c5,0x7c5,0x7c5,0x7d7,0x798,0x795,0x795,0x795, -0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795, -0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x795,0x93,0x93,0x93,0x795,0x795, -0x795,0x795,0x795,0x795,0x93,0x93,0x795,0x795,0x795,0x795,0x795,0x795,0x93,0x93,0x795,0x795, -0x795,0x795,0x795,0x795,0x93,0x93,0x795,0x795,0x795,0x93,0x93,0x93,0xbca,0xbca,0xbca,0xbca, -0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x194d,0x194d,0x194d,0xbd0,0xbd0,0xbd0,0xbd0, -0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0xbd0,0x99, -0x99,0x99,0x99,0x99,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713, -0x1713,0x1713,0x1713,0x1713,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9, -0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c, -0x9c,0x9c,0x9c,0x9c,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0x9f,0x9f,0x108c,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x1c11,0x1c11,0x9f, -0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f, -0x9f,0x9f,0x9f,0x9f,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xa2,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfd,0xbfd,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfd,0xa2,0xbfd,0xbfd,0xa2,0xa2,0xbfd,0xa2,0xa2,0xbfd,0xbfd,0xa2,0xa2,0xbfd,0xbfd,0xbfd, -0xbfd,0xa2,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfa,0xbfa,0xbfa,0xbfa,0xa2,0xbfa, -0xa2,0xbfa,0xbfa,0xbfa,0xbfa,0xd74,0xbfa,0xbfa,0xa2,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfd,0xbfd,0xbfa,0xbfa,0xbfa,0xbfa,0xbfd,0xbfd,0xa2,0xbfd,0xbfd,0xbfd,0xbfd,0xa2, -0xa2,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xa2,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xa2,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfd,0xbfd,0xa2,0xbfd, -0xbfd,0xbfd,0xbfd,0xa2,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xa2,0xbfd,0xa2,0xa2,0xa2,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xa2,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xe64,0xe64,0xa2,0xa2,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfa,0xbfa,0xbfa,0xbf4,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xf81,0xf7e,0xa2,0xa2,0xbf7,0xbf7, -0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7, -0xa5,0xc03,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, +3,3,3,3,3,3,3,3,3,3,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2, +0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2,0xfa2, +0xfa2,0xfa2,0xfa2,0xfa2,0xf36,0x1029,0x1029,3,3,3,3,3,3,3,3,3, +3,3,3,3,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24, +0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0x1029,0x1029,0x1029,0x1029,0x1029,0x1029,0x1029,0x1029,0x1029,0x1479, +3,3,3,3,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,3,3,3, +3,3,3,3,0x1041,0x1041,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,0x1026,0x1023,0x1023,0x1023,0x1023,0x1023,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155, +0x12c9,0x1155,0x1155,0x1155,0x13ce,0x1473,0x1473,0x14b2,0x14b2,0x167a,0x16f8,0x16f8,3,3,3,3, +0x181e,0x17a6,0x17a6,0x17a6,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x12c6, +0x12c6,3,3,3,0x1155,0x1155,0x1155,0x1155,0x1473,0x1473,0x1473,0x1500,0x1500,0x15d5,0x167a,0x16f8, +0x16f8,3,3,3,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99, +0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0x17e2,0x17e2,0x17e2,3,3,3,3,0x17e2, +0x17e2,0x17e2,0x17e2,0x17e2,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1548,0x1548,0x1548,0x1548,0x17e2,3,3, +3,3,3,3,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a, +3,3,3,3,0x17a6,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611, +0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,3,3,3,3,3,3,3,3, +3,3,3,3,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548, +0x1548,0x1548,3,3,0x167a,0x167a,0x167a,0x167a,0x16f8,0x181e,0x181e,0x181e,0x167a,0x167a,0x167a,0x17a6, +0x17a6,3,3,3,0x167a,0x167a,0x167a,0x16f8,0x16f8,0x16f8,0x16f8,0x181e,0x181e,0x18e1,3,3, +3,3,3,0x18e1,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8, +0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x17a9,0x17a9,0x17a9,0x18e1,3,3,3,3,3, +3,3,0x181e,0x181e,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x17a6,0x17a6,0x17a6,0x181e,0x181e, +0x18e1,3,3,0x18e1,0x17a6,0x17a6,0x17a6,0x17a6,0x17a6,0x17a6,0x17a6,0x17a6,0x181e,0x18e1,3,3, +3,3,3,3,0x17a9,0x17a9,0x17a9,0x17a9,0x17a9,0x17a9,0x17a9,0x1821,0x1821,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,0x693,0x693, +0x172e,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x561,0x561,0x561, +9,0x84f,9,9,9,9,9,9,9,9,9,9,9,9,9,9, +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, +9,9,9,9,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41, +0xa41,0xa41,0xa41,0xa41,9,9,9,9,9,9,9,9,9,9,9,9, +9,9,9,9,0xa5,0xa5,0xa5,0xa5,0xa5,0x6d8,0x6d8,0x185d,0x185d,0x185d,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a, +0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0xc,0xc,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a, +0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a, +0x116a,0x116a,0xc,0x16ad,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x1173,0x12ba,0x1176,0x146d, +0x1407,0x14bb,0x14bb,0x14bb,0x14bb,0x14bb,0x1551,0x154e,0x1554,0x154e,0x1554,0x161a,0x16ad,0x16ad,0x16ad,0x173d, +0x173d,0x1734,0x1737,0x1734,0x1737,0x1734,0x1737,0x1734,0x1737,0x173a,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x91e,0x91e,0x91e,0x91e, +0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0xf2d,0xf2d,0xf2d,0xf,0xf,0xb3a,0xb3a,0xb3a,0xb3a, +0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a, +0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30, +0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0x17ac,0x17ac,0x17ac, +0x17ac,0x1824,0xf,0xf,0xf,0xf,0xf,0xf,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038, +0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038, +0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0xf,0xf,0x13d4,0x13d4,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509, +0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b, +0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b, +0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0xf,0xf,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c, +0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c, +0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0x693,0x693,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701, +0x1701,0x1701,0x1701,0xf,0xf,0xf,0xf,0xf,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824, +0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x306,0x306,0x309,0xa5,0x348,0x31b,0x31b,0x31e, +0xf6,0xf6,0x15,0x15,0x15,0x15,0x15,0x7d1,0x312,0xb4,0x33c,0x345,0xe7,0x312,0xc0,0xc0, +0xa5,0xcc,0xcc,0x306,0xf0,0xed,0x318,0x75,0x45,0x45,0x48,0x48,0x48,0x48,0x48,0x4b, +0x48,0x48,0x48,0x18,0x10b,0x56d,0x105,0x105,0x32a,0xc6,0xc3,0x327,0x324,0x321,0x336,0xbd, +0x330,0x333,0xc9,0xcc,0x32d,0x32d,0xc9,0xcc,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, +0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0xa5,0x102c,0x102c,0x102c, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x36,0x36,0x90,0x2eb,0x24,0x2dc,0x36,0x8d, +0x24,0x2eb,0x87,0x90,0x90,0x90,0x87,0x87,0x90,0x90,0x90,0x300,0x24,0x90,0x2ee,0x24, +0x81,0x90,0x90,0x90,0x90,0x90,0x24,0x24,0x3f,0x2dc,0x2e8,0x24,0x90,0x24,0x357,0x2d, +0x90,0x51,0x22e,0x369,0x90,0x90,0x7e,0x87,0x90,0x90,0x213,0x90,0x87,0x8a,0x8a,0x8a, +0x8a,0x6cf,0x6c6,0x960,0xa50,0x8a3,0x8a6,0x8a6,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x27, +0x42,0x390,0x2a,0x65d,0x6c0,0x6c9,0x6c9,0x6c9,0x897,0x897,0xa4a,0xa4a,0xa4a,0xa4a,0xde0,0xde3, +0xde3,0xf9f,0x1146,0x115b,0x115e,0x115e,0x1350,0x14b5,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1, +0x2f1,0x2f1,0x30,0x906,0x906,0x906,0x906,0x906,0x906,0x906,0x906,0x906,0x906,0x906,0x906,0x906, +0x906,0x906,0x906,0x906,0x906,0x906,0x906,0xa02,0x8a0,0x89d,0x89d,0x89d,0x89d,0x8a6,0x8a3,0x8a3, +0x8a3,0x8a3,0x894,0x89d,0xa47,0xb7f,0xba0,0xc2a,0xde6,0xde6,0xde6,0x2e2,0x2e2,0x33,0x33,0x33, +0x33,0x33,0x33,0x2e2,0x2e2,0x2e2,0x2e2,0x39,0x7b,0xa5,0xa5,0xa5,0xdb,0xb1,0xa8,0x8c7, +0x6db,0x6db,0x6d8,0x6d8,0x6d8,0x6d8,0x8ac,0x903,0x8ac,0x8ac,0x8b8,0x96f,0x966,0xa53,0xa5f,0x8b5, +0xa5f,0xa5f,0xb0d,0xa5f,0xa5c,0xb10,0xa5f,0x89a,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306, +0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0xa2,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0xa5,0xcf,0xcf,0xcf,0xcf,0xcf,0xd2,0xa5,0xcf,0xcf,0xa5,0xa5,0xa5,0xa5,0xcf,0xcf, +0x309,0x309,0xa5,0xa5,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0xcf,0xd2,0xd2,0xd2,0xcf,0xcf,0x336,0xcf,0x336,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0xa5,0xcf,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xcf,0xcf,0xa5,0x309,0xa5,0xa5,0xa5,0x6d8, +0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0xa5,0x6d8,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xde,0xd5,0xde,0xd5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x306,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x49e,0x49e, +0xa5,0xa5,0xa5,0xa5,0xcf,0xcf,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x4a4,0x4a1,0xa5, 0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, -0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0x1c17,0xc8a,0xc8a, -0xc8a,0xc8a,0xc84,0xc84,0xc87,0x1c14,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x1c17, -0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93,0xc93, -0xc93,0xc93,0xc8d,0xc8d,0xc90,0xcf3,0xcf3,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab, -0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99,0xc99, -0xc99,0xc99,0xc96,0xc96,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae, -0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xc9f,0xb1,0xc9f,0xc9f, -0xc9f,0xb1,0xc9c,0xc9c,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86, -0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0x15c9,0x15c9,0xb4, -0xd77,0xd77,0xd77,0xd83,0xd83,0xd83,0xd83,0xd77,0xd77,0xd83,0xd83,0xd83,0xb4,0xb4,0xb4,0xb4, -0xd83,0xd83,0xd77,0xd83,0xd83,0xd83,0xd83,0xd83,0xd83,0xd7a,0xd7a,0xd7a,0xb4,0xb4,0xb4,0xb4, -0xd7d,0xb4,0xb4,0xb4,0xd89,0xd89,0xd80,0xd80,0xd80,0xd80,0xd80,0xd80,0xd80,0xd80,0xd80,0xd80, -0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c, -0xd8c,0xd8c,0xb7,0xb7,0xd8c,0xd8c,0xd8c,0xd8c,0xd8c,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7, -0xb7,0xb7,0xb7,0xb7,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc, -0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0xba,0xba,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc, -0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc, -0x15cc,0x15cc,0xba,0x1b5d,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0xdb0,0xdb0,0xdb0,0xdb0, -0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xbd,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0, -0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xbd, -0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0, -0xdb0,0xdb0,0xdb0,0xbd,0xdb0,0xdb0,0xbd,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0, -0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xbd,0xbd,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0, -0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xdb0,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, -0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, -0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3, -0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3, -0xdb3,0xdb3,0xdb3,0xc0,0xc0,0xc0,0xc0,0xc0,0xdf2,0xdf2,0xdf8,0xc3,0xc3,0xc3,0xc3,0xdef, -0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef, -0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xdef,0xc3,0xc3,0xc3,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5, -0xdf5,0xdf5,0xdf5,0xdf5,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9, -0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9,0xdb9, -0xdb9,0xdb9,0xc6,0xdb6,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2, -0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2,0xdc2, -0xdc2,0xdc2,0xc9,0xc9,0xdbf,0xdbf,0xdbf,0xdbf,0xdbf,0xdbf,0xdbf,0xdbf,0xdbf,0xdbf,0xc9,0xc9, -0xc9,0xc9,0xc9,0xc9,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911, -0x1911,0x1911,0x1911,0x1911,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xcc,0xcc,0xdc5,0xcc,0xdc5,0xdc5, -0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5, -0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0xcc,0xdc5,0xdc5,0xcc,0xcc,0xcc,0xdc5,0xcc,0xcc,0xdc5, -0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8, -0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, -0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0x15cf,0x15cf,0x1887,0x1887,0xd5, -0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x1b72,0x126,0x126,0x126, -0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91, -0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe88,0xe88,0xe8e,0xe8e,0xe88,0xd8,0xd8,0xe8b,0xe8b, -0x11d9,0x11d9,0x11d9,0x11d9,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0x1d43, -0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0,0xcf0, -0xea3,0xea0,0xea3,0xea0,0xea0,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0x122a,0x1227,0x122a,0x1227,0x1221, -0x1224,0x1224,0x14be,0x14bb,0xde,0xde,0xde,0xde,0xde,0xe9d,0xe9a,0xe9a,0xe9a,0xe97,0xe9d,0xe9a, -0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6, -0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, -0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xe1,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xe1, -0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xe1,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xea6,0xe1, -0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac,0xeac, -0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4, -0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xe7,0x14c1,0xe7,0xe7,0xe7,0xe7,0xe7,0x14c1,0xe7,0xe7, -0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09, -0xec7,0xebb,0xebb,0xebb,0xea,0xebb,0xebb,0xea,0xea,0xea,0xea,0xea,0xebb,0xebb,0xebb,0xebb, -0xec7,0xec7,0xec7,0xec7,0xea,0xec7,0xec7,0xec7,0xea,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7, -0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7, -0x19f2,0x19f2,0xea,0xea,0xeb8,0xeb8,0xeb8,0xea,0xea,0xea,0xea,0xebe,0xec1,0xec1,0xec1,0xec1, -0xec1,0xec1,0xec1,0xec1,0x19ef,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xec4,0xec4,0xec4,0xec4, -0xec4,0xec4,0xeca,0xeca,0xec1,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xed6,0xed6,0xed6,0xed6, -0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0x1230,0x1230,0xed,0xed,0xed,0xed,0xed6,0xed6,0xed6,0xed6, -0xed6,0xed9,0xed9,0xed9,0xed6,0xed6,0xed9,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6, -0xed6,0xed6,0xed,0xed,0xed,0xed,0xed,0xed,0xed3,0xed3,0xed3,0xed3,0xed3,0xed3,0xed3,0xed3, -0xed3,0xed3,0x122d,0xed,0xed,0xed,0xed0,0xed0,0xedf,0xedf,0xedf,0xedf,0xf0,0xf0,0xf0,0xf0, -0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedc,0xedf,0xedf,0xedf,0xedf,0xedf,0xf0,0xf0, -0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x15de,0x15e4,0x15e1,0x1932,0x188d,0x1956,0x1956,0x1956, -0x1956,0x1956,0x19f8,0x19f5,0x19fb,0x19f5,0x19fb,0x1abe,0x1b60,0x1b60,0x1b60,0x1c29,0x1c29,0x1c23,0x1c20,0x1c23, -0x1c20,0x1c23,0x1c20,0x1c23,0x1c20,0x1c26,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, -0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, -0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf06,0xf06,0xf06,0xf03,0xf03,0xefa,0xefa,0xf03, -0xf00,0xf00,0xf00,0xf00,0x1b63,0xf6,0xf6,0xf6,0x1395,0x1395,0x1395,0x1398,0x1398,0x1398,0x139b,0x139b, -0x139e,0x139b,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0x14d0,0x14d0, -0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf0c,0x1404,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9, -0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0x1401,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3, -0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xf3c,0xf2d,0xf27,0xf39,0xf36,0xf30,0xf30,0xf3f, -0xf2a,0xf33,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc9,0xfc9,0xfb1,0xfc9,0xfcc,0xfcf,0xfcf,0xfcf, -0xfcf,0xfcf,0xfcf,0xfcf,0x1c2c,0x102,0x102,0x102,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3, -0xfc3,0xfc3,0xfd5,0xfd5,0xfbd,0xfc0,0xfd5,0xfd5,0xfba,0xfbd,0xfbd,0xfbd,0xfbd,0xfbd,0xfbd,0xfbd, -0xfbd,0xfbd,0xfbd,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfbd,0xfbd,0xfbd,0xfbd, -0xfbd,0xfbd,0xfbd,0xfbd,0xfbd,0x1c2f,0x1c2f,0x102,0x1c38,0x1c35,0x1aca,0x1ac7,0x1aca,0x1aca,0x1aca,0x1b6f, -0x1b6c,0x1b6f,0x1b6c,0x105,0x105,0x105,0x105,0x105,0x1c38,0x1c35,0x105,0x1c35,0x105,0x1c35,0x1c38,0x1c35, -0x1c38,0x1c35,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105, -0x105,0x105,0x105,0x105,0x105,0x105,0x1c32,0x1c32,0x1c32,0x1b69,0x1b66,0x15ed,0x14d9,0x14d9,0x140d,0x10ef, -0x10ef,0x10ef,0x10ef,0x10ef,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0, -0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xfed,0xfed,0xff3,0xff3,0x108,0x108,0x108,0x108, -0x108,0x108,0x108,0x108,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc, -0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xff6,0xff6,0xff6,0xff6,0x1239,0x1239, -0x10b,0x10b,0x10b,0xff9,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3, -0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x17df,0x10e,0x10e, -0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e, -0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e, -0x1005,0x1005,0x1005,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x111, -0x1002,0x1002,0x1002,0x1002,0x15f6,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111, -0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008,0x1008, -0x1008,0x1008,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x114,0x114,0x114,0x114,0x114,0x114,0x114, -0x1125,0x1125,0x1125,0x1125,0x1122,0x1122,0x1122,0x1122,0x1122,0x1122,0x1122,0x1122,0x1113,0x1113,0x1113,0x1113, -0x1113,0x1113,0x1113,0x1113,0x1122,0x1122,0x1119,0x1116,0x117,0x117,0x117,0x1128,0x1128,0x111c,0x111c,0x111c, -0x111f,0x111f,0x111f,0x111f,0x111f,0x111f,0x111f,0x111f,0x111f,0x111f,0x117,0x117,0x117,0x1125,0x1125,0x1125, -0x112b,0x112b,0x112b,0x112b,0x112b,0x112b,0x112b,0x112b,0x112b,0x112b,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e, -0x1140,0x1140,0x1140,0x1140,0x1140,0x1140,0x1140,0x1140,0x1140,0x1140,0x1146,0x1146,0x11a,0x11a,0x11a,0x11a, -0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a, -0x1170,0x1170,0x1170,0x1170,0x116a,0x1893,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x1176,0x1176, -0x116d,0x116d,0x116d,0x116d,0x116d,0x116d,0x116d,0x116d,0x116d,0x116d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d, -0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188, -0x1188,0x1188,0x118e,0x1191,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x118b, -0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x1197,0x1197,0x1197,0x1197,0x1197,0x1197,0x11a0, -0x11a0,0x1197,0x1197,0x11a0,0x11a0,0x1197,0x1197,0x123,0x123,0x123,0x123,0x123,0x123,0x123,0x123,0x123, -0x11a3,0x11a3,0x11a3,0x1197,0x11a3,0x11a3,0x11a3,0x11a3,0x11a3,0x11a3,0x11a3,0x11a3,0x1197,0x11a0,0x123,0x123, -0x119d,0x119d,0x119d,0x119d,0x119d,0x119d,0x119d,0x119d,0x119d,0x119d,0x123,0x123,0x119a,0x11a9,0x11a9,0x11a9, -0x1605,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0x6d8,0x8b8,0x6d8,0x6d8,0x6d8,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306, +0x306,0x306,0x306,0x306,0xa5,0xa5,0xa5,0xa5,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306, +0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0xa5,0xa5,0x306,0x306,0x306,0x306,0x8ac,0x8ac, +0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x336,0x336,0xa5,0x306,0x306,0x306,0x306,0x306, +0x306,0x306,0xa5,0xa5,0xa5,0xa5,0xcf,0xcf,0xcf,0xcf,0x336,0x336,0xcf,0xcf,0x336,0x336, +0xa5,0xa5,0xa5,0xa5,0x336,0x336,0xcf,0xcf,0x336,0x336,0xa5,0xa5,0xa5,0xa5,0x336,0x336, +0x306,0xa5,0xcf,0x336,0xa5,0xa5,0x306,0x336,0x336,0x336,0xcf,0xcf,0xa5,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x336,0x306,0x336,0x306,0xa5,0xcf, +0xcf,0xcf,0xcf,0xcf,0xcf,0xa5,0xa5,0x306,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x918,0x918,0x8b8,0xae,0xae,0xae,0xae,0xa5,0x336,0x336,0xa5, +0xa5,0x306,0xa5,0xa5,0xa5,0xa5,0x306,0x306,0xa5,0xa5,0xa5,0xa5,0xa14,0xa14,0x8a9,0x8a9, +0xa56,0x6d8,0xae,0xae,0x30c,0xba,0x30c,0xae,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b, +0xa5,0xae,0xae,0xae,0xa5,0xa5,0xa5,0xa5,0x336,0xa5,0x336,0xa5,0xa5,0xa5,0xa5,0xa5, +0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0xa5,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x336,0x336,0xcf,0x336,0x306,0x306,0xa5,0x306, +0x30c,0x306,0x306,0xa5,0x306,0x336,0xcf,0x336,0x6d8,0x6d8,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac, +0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0xa53,0xb37,0x1170,0xae,0xae,0xae,0xae,0x102c,0xa5,0xa5, +0xae,0xae,0x1032,0x1032,0xba,0xba,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x102c,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x309,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x102c,0xa5,0x102c,0xa5, +0xa5,0xa5,0xa5,0x102c,0x102c,0x102c,0xa5,0xf27,0xa5,0xa5,0xa5,0xb7,0xb7,0xb7,0xb7,0xfab, +0xfab,0xa5,0xab,0xab,0xae,0xa5,0xa5,0xa5,0x8b2,0x8af,0x8b2,0x8af,0x8b2,0x8af,0x8b2,0x8af, +0x8b2,0x8af,0x8b2,0x8af,0x8b2,0x8af,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, +0x102c,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0x102c, +0x336,0xcf,0x336,0x336,0xd2,0xcf,0xcf,0x336,0x336,0xd2,0xcf,0x336,0xd2,0xcf,0xcf,0x336, +0xcf,0x336,0xea,0xe1,0xcf,0x336,0xcf,0xcf,0xcf,0xcf,0x336,0xcf,0xcf,0x336,0x336,0x336, +0x336,0xcf,0xcf,0x336,0xd2,0x336,0xd2,0x336,0x336,0x336,0x336,0x336,0x342,0xe4,0x336,0xe4, +0xe4,0xcf,0xcf,0xcf,0x336,0x336,0x336,0x336,0xcf,0xcf,0xcf,0xcf,0x336,0x336,0xcf,0xcf, +0xcf,0xd2,0xcf,0xcf,0xd2,0xcf,0xcf,0xd2,0x336,0xd2,0xcf,0xcf,0x336,0xcf,0xcf,0xcf, +0xcf,0xcf,0x336,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0x339,0x336,0xd2,0xcf,0x336,0x336,0x336,0x336,0xcf,0xcf,0x336,0x336,0xcf,0xd2,0x339,0x339, +0xd2,0xd2,0xcf,0xcf,0xd2,0xd2,0xcf,0xcf,0xd2,0xd2,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0xd2,0xd2,0x336,0x336,0xd2,0xd2,0x336,0x336,0xd2,0xd2,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0xcf,0xcf,0xcf,0xcf,0xcf,0x336,0xcf,0xcf,0xcf,0x336,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0xcf,0x336,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xd2,0xd2,0xd2,0xd2,0xcf,0xcf,0xcf,0xcf, +0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0x336,0xcf,0xcf,0xcf,0xcf, +0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, +0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xd2,0xd2,0xd2,0xd2, +0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xd2,0xd2,0xd2,0xd2,0xcf,0xd8,0xcf,0xcf,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x12c,0x12c,0x12c,0x12c, +0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c, +0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d, 0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126, -0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af, -0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11af,0x11b2,0x129,0x129, -0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5, -0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x12c,0x12c,0x12c, -0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8, -0x11b8,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f, -0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be, -0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x11be,0x132,0x132,0x132,0x132,0x132,0x11bb, -0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x135,0x135,0x135,0x135, -0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4, -0x11c4,0x11c4,0x11c4,0x11c4,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138, -0x123f,0x123f,0x123f,0x123f,0x1248,0x123f,0x123f,0x123f,0x1248,0x123f,0x123f,0x123f,0x123f,0x123c,0x13b,0x13b, -0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x124b,0x1245,0x124b,0x1245,0x1245,0x1245,0x124b,0x124b,0x13b, -0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e, -0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e, -0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269, -0x1269,0x1269,0x1269,0x1269,0x1269,0x1266,0x1251,0x1266,0x1251,0x1251,0x1251,0x1251,0x1251,0x1251,0x1251,0x141, -0x125a,0x1263,0x1251,0x1263,0x1263,0x1251,0x1251,0x1251,0x1251,0x1251,0x1251,0x1251,0x1251,0x1266,0x1266,0x1266, -0x1266,0x1266,0x1266,0x1251,0x1251,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x141,0x141,0x1254, -0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x141,0x141,0x141,0x141,0x141,0x141, -0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x1260,0x141,0x141,0x141,0x141,0x141,0x141, -0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x126c,0x126f,0x126f,0x126f,0x126f,0x125d,0x125d,0x141,0x141, -0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1644,0x1b84, -0x13b0,0x1389,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x138f,0x138c,0x1383,0x1383,0x13ad,0x1383,0x1383, -0x1383,0x1383,0x1392,0x1578,0x157e,0x157b,0x157b,0x19d1,0x17a6,0x17a6,0x1b4b,0x144,0x144,0x144,0x144,0x144, -0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284, -0x127b,0x127b,0x127e,0x1287,0x1281,0x1281,0x1281,0x1287,0x147,0x147,0x147,0x147,0x147,0x147,0x147,0x147, -0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374, -0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x1374,0x14d,0x14d,0x14d, -0x12a5,0x1299,0x1299,0x1299,0x1299,0x1299,0x1299,0x129c,0x12ab,0x12ab,0x1299,0x1299,0x1299,0x1299,0x150,0x13a4, -0x129f,0x129f,0x129f,0x129f,0x129f,0x129f,0x129f,0x129f,0x129f,0x129f,0x150,0x150,0x150,0x150,0x1299,0x1299, -0x12c9,0x12bd,0x12c9,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153, -0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x12c6,0x12c6,0x12cc,0x12c0,0x12c3, -0x12e1,0x12e1,0x12e1,0x12db,0x12db,0x12d2,0x12db,0x12db,0x12d2,0x12db,0x12db,0x12e4,0x12de,0x12d5,0x156,0x156, -0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x156,0x156,0x156,0x156,0x156,0x156, -0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x12ea,0x159,0x159,0x159,0x159,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7, -0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7, -0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x12e7,0x159,0x159,0x159,0x159,0x12f3,0x12f3,0x12f3,0x12f3, -0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3,0x12f3, -0x12f3,0x12f3,0x15c,0x12f0,0x12ed,0x12ed,0x12ed,0x12ed,0x12ed,0x12ed,0x12ed,0x12ed,0x1302,0x1302,0x1302,0x1302, -0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302, -0x1302,0x1302,0x15f,0x15f,0x15f,0x12fc,0x12ff,0x12ff,0x12ff,0x12ff,0x12ff,0x12ff,0x1308,0x1308,0x1308,0x1308, -0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308,0x1308, -0x1308,0x1308,0x162,0x162,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x1305,0x130e,0x130e,0x130e,0x130e, -0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x130e,0x165, -0x165,0x165,0x165,0x165,0x130b,0x130b,0x130b,0x130b,0x130b,0x130b,0x130b,0x130b,0x1314,0x1314,0x1314,0x1314, -0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314, -0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x1314,0x16b,0x132c,0x132c,0x1c3b,0x16e, -0x16e,0x16e,0x16e,0x16e,0x16e,0x16e,0x16e,0x16e,0x16e,0x1a16,0x16e,0x16e,0x1557,0x1557,0x1557,0x1557, -0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1914,0x1914,0x1914,0x1914, -0x1914,0x1914,0x1914,0x1914,0x1914,0x1914,0x1914,0x1914,0x1914,0x1b75,0x171,0x171,0x171,0x171,0x171,0x171, -0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171, -0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x1419,0x1419, -0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419, -0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x137d,0x147f,0x147f,0x174,0x174,0x174,0x174,0x174, -0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a, -0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x137a,0x147f,0x147f,0x147f,0x147f,0x147f,0x147f, -0x147f,0x147f,0x147f,0x1917,0x174,0x174,0x174,0x174,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377, -0x1377,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x14a3,0x14a3,0x174,0x174,0x174,0x174,0x174,0x174, -0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x174,0x174, -0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174, -0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174, -0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422, -0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x141c,0x141c,0x141c,0x177,0x177,0x141f,0x177, -0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1425,0x142e,0x1428,0x1428,0x142e,0x142e,0x142e,0x1428,0x142e,0x1428, -0x1428,0x1428,0x1431,0x1431,0x17a,0x17a,0x17a,0x17a,0x17a,0x17a,0x17a,0x17a,0x142b,0x142b,0x142b,0x142b, -0x17d,0x1437,0x1437,0x1437,0x1437,0x1437,0x1437,0x17d,0x17d,0x1437,0x1437,0x1437,0x1437,0x1437,0x1437,0x17d, -0x17d,0x1437,0x1437,0x1437,0x1437,0x1437,0x1437,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d, -0x1437,0x1437,0x1437,0x1437,0x1437,0x1437,0x1437,0x17d,0x1437,0x1437,0x1437,0x1437,0x1437,0x1437,0x1437,0x17d, -0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa, -0x143a,0x143a,0x143a,0x143a,0x143a,0x143a,0x143d,0x1452,0x1452,0x1443,0x1443,0x1443,0x1443,0x1443,0x180,0x180, -0x180,0x180,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440,0x1440, -0x1440,0x1440,0x1446,0x1446,0x1446,0x1446,0x1446,0x1446,0x1446,0x1446,0x1446,0x1446,0x1c41,0x1c44,0x1c44,0x1c3e, -0x1c3e,0x1c44,0x180,0x180,0x180,0x180,0x180,0x180,0x180,0x180,0x180,0x1614,0x1455,0x1455,0x1455,0x1455, -0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455, -0x1455,0x1455,0x1455,0x1455,0x1455,0x183,0x183,0x183,0x183,0x183,0x183,0x183,0x1458,0x1458,0x1458,0x1458, -0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x186,0x186,0x1458,0x1458,0x1458, -0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1617,0x186,0x1458,0x1458,0x1458, -0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1488,0x186,0x1458,0x1458,0x1458, -0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1617,0x1617,0x1617,0x1617, -0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617,0x1617, -0x1617,0x1617,0x186,0x186,0x186,0x186,0x186,0x186,0x186,0x186,0x186,0x186,0x149d,0x149a,0x149a,0x149a, -0x149a,0x149a,0x1623,0x1623,0x1623,0x1623,0x1623,0x1623,0x179d,0x1623,0x1623,0x1623,0x186f,0x1920,0x1920,0x1959, -0x1959,0x1b2d,0x1bde,0x1bde,0x189,0x189,0x189,0x189,0x1d2b,0x1cad,0x1cad,0x1cad,0x1623,0x1623,0x1623,0x1623, -0x1623,0x1623,0x1623,0x1623,0x1623,0x1623,0x1623,0x179a,0x179a,0x189,0x189,0x189,0x1623,0x1623,0x1623,0x1623, -0x1920,0x1920,0x1920,0x19bc,0x19bc,0x1aa3,0x1b2d,0x1bde,0x1bde,0x189,0x189,0x189,0x145b,0x145b,0x145b,0x145b, -0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b, -0x1cd1,0x1cd1,0x1cd1,0x18c,0x18c,0x18c,0x18c,0x1cd1,0x1cd1,0x1cd1,0x1cd1,0x1cd1,0x14fa,0x14fa,0x14fa,0x14fa, -0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa, -0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x14fa,0x18f, -0x14fa,0x18f,0x18f,0x14fa,0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x18f, -0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x14fa,0x18f, -0x18f,0x18f,0x18f,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x14fa,0x18f, -0x14fa,0x18f,0x18f,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x14fa,0x18f, -0x14fa,0x18f,0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x18f, -0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x18f,0x14fa,0x14fa,0x14fa,0x14fa, -0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa, -0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x18f,0x18f,0x18f,0x18f,0x14fa,0x14fa,0x14fa, -0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa, -0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f, +0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x879,0x879,0x879,0x879, +0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x879,0x12c,0x12c,0x2d3,0x12c, +0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x11d,0x11d,0x8ca,0x9ff,0x1743,0x1743,0x129,0x12f,0x12c,0x126, +0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126, +0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c,0x126,0x12c,0x126, +0x12c,0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126, +0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c,0x126, +0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c,0x126,0xfb1,0xfb1,0xfb1,0xfb1,0xfb1,0xfb1, +0xfb1,0xfb1,0xfb1,0xfb1,0xfb1,0xfb1,0xfb1,0xfb1,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x129,0x12f, +0x129,0x12f,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126, +0x129,0x12c,0x126,0x129,0x12c,0x126,0x129,0x12f,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126, +0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x129, +0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c, +0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x126,0x126,0x126,0x126,0x126,0x126,0x126, +0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x129,0x129,0x129,0x129,0x129,0x129,0x129, +0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x126,0x12c,0x2ac,0x2af,0x1743,0x1743,0x1743,0x1743, +0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x129,0x126,0x129,0x129, +0x129,0x129,0x129,0x129,0x126,0x129,0x126,0x126,0x129,0x129,0x126,0x126,0x129,0x129,0x126,0x129, +0x126,0x129,0x126,0x126,0x129,0x126,0x126,0x129,0x126,0x129,0x126,0x126,0x129,0x126,0x129,0x129, +0x126,0x126,0x126,0x129,0x126,0x126,0x126,0x126,0x126,0x129,0x126,0x126,0x126,0x126,0x126,0x126, +0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126, +0x129,0x129,0x126,0x126,0x129,0x126,0x129,0x126,0x126,0x126,0x126,0x126,0x12c,0x12c,0x126,0x12c, +0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c,0x126,0x129,0x12f,0x12c, +0x126,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x12c, +0x126,0x12c,0x126,0x12c,0x126,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129, +0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129, +0x12f,0x12c,0x126,0x129,0x12f,0x12c,0x126,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129, +0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129, +0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x12f,0x12c,0x12c,0x12c,0x12c, +0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c, +0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12f,0x12f,0x12f,0x12f, +0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f, +0x12f,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x12c,0x189,0x189,0x57c,0x57c, +0x2a0,0x2a3,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x183,0xc84,0xc81,0xfc6, +0xfc6,0xfc6,0xfc6,0xfc6,0x12cc,0xf3c,0xf3c,0xc00,0xc00,0xb46,0xc00,0xc00,0xf48,0x57c,0x57c,0x186, +0x98d,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189,0x189, +0x189,0x54c,0x54c,0x54c,0x54c,0x54c,0x54c,0x54c,0x54c,0x54c,0x54c,0x54c,0x54c,0x54f,0x54c,0x54c, +0x54c,0x54c,0x54c,0x54c,0x54c,0x54f,0x54c,0x54c,0x54f,0x54c,0x54c,0x54c,0x54c,0x54c,0x104d,0xfc3, +0x57f,0x189,0x186,0x186,0x186,0x57c,0x57c,0x57c,0x57c,0x57c,0x57c,0x57c,0x57c,0x186,0x186,0x186, +0x186,0x64e,0xe04,0xfc3,0x189,0x5d3,0x5d6,0x567,0x567,0xf48,0x104d,0x104d,0x549,0x549,0x549,0x549, +0x549,0x549,0x549,0x549,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192, +0x192,0x192,0x192,0x192,0x192,0x18c,0x18c,0x18c,0x18c,0x18c,0x18c,0x8df,0x8df,0xaa4,0xaa4,0x2a6, +0xaa1,0x1098,0x1098,0x1098,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f, 0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f, -0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x14f7,0x14f7,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f, -0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x14fd, -0x14fd,0x14fd,0x14fd,0x14fd,0x150c,0x14fd,0x1500,0x1500,0x14fd,0x14fd,0x14fd,0x1503,0x1503,0x192,0x1509,0x1509, -0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1506,0x1512,0x1512,0x1512,0x1a22,0x1a1f,0x1a1f,0x1b7b, -0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc, -0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x151e,0x151e,0x151e,0x151e,0x151e,0x151e,0x151e,0x151e, -0x151e,0x151e,0x151e,0x151b,0x1515,0x1515,0x151b,0x151b,0x1524,0x1524,0x151e,0x1521,0x1521,0x151b,0x1518,0x195, -0x195,0x195,0x195,0x195,0x195,0x195,0x195,0x195,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527, -0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527,0x1527, -0x198,0x198,0x198,0x198,0x17f4,0x17f4,0x1527,0x1527,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4, -0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x198,0x198,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4, -0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x1533,0x1533,0x1533,0x1533,0x1533,0x1ad6,0x1ad6,0x1ad6, -0x1ad6,0x1ad6,0x1ad6,0x19b,0x19b,0x19b,0x19b,0x1ad0,0x1533,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530, -0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1ad3,0x1ad3,0x1ad3,0x1ad3,0x1ad3,0x1ad3,0x1ad3,0x1ad3, -0x19b,0x19b,0x19b,0x19b,0x19b,0x19b,0x19b,0x152d,0x152d,0x152d,0x152d,0x1536,0x1536,0x1536,0x1536,0x1536, -0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557,0x1557, -0x1557,0x19e,0x19e,0x19e,0x19e,0x19e,0x19e,0x19e,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554, -0x1554,0x1554,0x19e,0x19e,0x19e,0x19e,0x19e,0x19e,0x155a,0x155a,0x155a,0x155a,0x155a,0x155a,0x155a,0x155a, -0x1a1,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1,0x13aa,0x13a7,0x13aa,0x1386,0x13a7,0x13ad,0x13ad,0x13b0, -0x13ad,0x13b0,0x13b3,0x13a7,0x13b0,0x13b0,0x13a7,0x13a7,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c, -0x156c,0x156c,0x156c,0x155d,0x1566,0x155d,0x1566,0x1566,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x1569,0x1560, -0x1ad9,0x1c50,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638, -0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1a7,0x1a7,0x1635,0x1635,0x1635,0x1635,0x1635,0x163b,0x1a7,0x1a7, -0x1a7,0x1a7,0x1a7,0x1a7,0x1a7,0x1a7,0x1a7,0x1a7,0x1641,0x1641,0x1641,0x1641,0x1aa,0x1aa,0x1aa,0x1aa, -0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x163e,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b, -0x1c9b,0x1c9b,0x1c9b,0x2af,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x17a9,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0, -0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0, -0x17a0,0x17a0,0x17a0,0x17a0,0x1ad,0x1ad,0x1ad,0x1ad,0x1b84,0x1c56,0x1c56,0x1c56,0x1c56,0x1c56,0x1c56,0x1c56, -0x1c56,0x1c56,0x1c56,0x1c56,0x1c53,0x1c53,0x1c53,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0, -0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0, -0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653, -0x1653,0x1653,0x1653,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653, -0x1653,0x1653,0x1653,0x1653,0x1653,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1653,0x1653,0x1653,0x1653, -0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1b3,0x1b3,0x1650,0x164a,0x164d,0x1656,0x1659,0x1659,0x1659,0x1659, -0x1659,0x1659,0x1659,0x1659,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1641,0x1641,0x1641,0x1641, -0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x165c,0x165c,0x165c,0x165c, -0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c, -0x165c,0x1a25,0x1a25,0x1a25,0x1a25,0x1cd4,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b30,0x1b30,0x1b30,0x1b30, -0x1b30,0x1b30,0x1b30,0x1b30,0x1b30,0x1b30,0x1b30,0x1b30,0x1b9,0x1b9,0x1b9,0x1b9,0x1cb0,0x1b9,0x1b9,0x1b9, -0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1809,0x17ac,0x1665,0x17b2, -0x1bc,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1bc,0x1bc,0x1671,0x1671,0x1bc,0x1bc,0x1671, -0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1bc,0x1671,0x1671, -0x1671,0x1671,0x1671,0x1671,0x1671,0x1bc,0x1671,0x1671,0x1bc,0x1671,0x1671,0x1671,0x1671,0x1671,0x1bc,0x1aaf, -0x17af,0x166e,0x165f,0x1665,0x165f,0x1665,0x1665,0x1665,0x1665,0x1bc,0x1bc,0x1665,0x1665,0x1bc,0x1bc,0x1668, -0x1668,0x166b,0x1bc,0x1bc,0x180c,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x165f,0x1bc,0x1bc,0x1bc,0x1bc, -0x1bc,0x1677,0x1674,0x1674,0x1671,0x1671,0x1665,0x1665,0x1bc,0x1bc,0x1662,0x1662,0x1662,0x1662,0x1662,0x1662, -0x1662,0x1bc,0x1bc,0x1bc,0x1662,0x1662,0x1662,0x1662,0x1662,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc, -0x1bc,0x1bc,0x1bc,0x1bc,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c, -0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x1bf,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c, -0x168c,0x168c,0x168c,0x168c,0x169e,0x169e,0x169e,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1695,0x1698,0x1c2, -0x1c2,0x1c2,0x1c2,0x1c2,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x1c2,0x1c2, -0x1c2,0x1c2,0x1c2,0x1c2,0x180f,0x180f,0x180f,0x180f,0x16aa,0x16a7,0x1adc,0x1adc,0x1b8a,0x1b8d,0x1b87,0x1b87, -0x1c5,0x1c5,0x1c5,0x1c5,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c, -0x183c,0x183c,0x183c,0x183c,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0, -0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, -0x1c8,0x1c8,0x1c8,0x1c8,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0, -0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, -0x1c8,0x1c8,0x1c8,0x1c8,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x1c8,0x1c8,0x1c8,0x1c8, -0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, -0x1c8,0x1c8,0x1c8,0x1c8,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc, -0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16bc,0x16b3,0x16b6,0x16b9,0x16bc,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb, -0x1cb,0x1cb,0x1cb,0x1cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16bf,0x16bf,0x1ce,0x1ce,0x1ce,0x1ce,0x16c2, -0x16c2,0x16c2,0x16c2,0x16c2,0x16c8,0x16c8,0x17b5,0x16c8,0x16c8,0x16c8,0x16c5,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce, -0x1ce,0x1ce,0x1ce,0x1ce,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x1d1,0x1d1,0x16d1,0x16d1,0x16d1,0x16d1,0x16d1, -0x16d1,0x16d1,0x16d1,0x16d1,0x16ce,0x16ce,0x16ce,0x16ce,0x16ce,0x16ce,0x16ce,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1, -0x1d1,0x1d1,0x1d1,0x1d1,0x16d7,0x16e9,0x16e9,0x16dd,0x16e6,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4, -0x1d4,0x1d4,0x1d4,0x1d4,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x16e0,0x1d4,0x1d4, -0x1d4,0x1d4,0x1d4,0x1d4,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef, -0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef,0x16ef, -0x16ef,0x16ef,0x16ef,0x1d7,0x16ec,0x16ec,0x16ec,0x16ec,0x16ec,0x16ec,0x16ec,0x16ec,0x16ec,0x16ec,0x1d7,0x1d7, -0x1d7,0x1d7,0x16f2,0x16f2,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c, -0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x16fb,0x16fb,0x16fb,0x16fb,0x16fb,0x16f5,0x1701,0x16fe,0x16fe,0x16fe,0x16fe,0x16fe, -0x16fe,0x16fe,0x16fe,0x16fe,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16fe,0x16fe, -0x16fe,0x16fe,0x16fe,0x1da,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, -0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, -0x1707,0x1707,0x1707,0x1dd,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713, -0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1713,0x1710,0x1710,0x1710,0x1710,0x1710,0x1e0, -0x1e0,0x1e0,0x1e0,0x1e0,0x172b,0x172b,0x172e,0x172e,0x1731,0x1722,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3, -0x1e3,0x1e3,0x1e3,0x1e3,0x1728,0x1728,0x1728,0x1728,0x1728,0x1728,0x1728,0x1728,0x1728,0x1728,0x1e3,0x1722, -0x1722,0x1722,0x1722,0x1722,0x1722,0x1722,0x1e3,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b, -0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x1e3,0x1e3,0x1e3,0x1e3, -0x1e3,0x172b,0x172b,0x172b,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a, -0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x1e6,0x1e6,0x1e6, -0x1e6,0x1e6,0x1e6,0x1e6,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743, -0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1740,0x1740,0x1740, -0x1740,0x1e9,0x1e9,0x1e9,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e, -0x175e,0x175e,0x175e,0x1746,0x1758,0x1758,0x1746,0x1746,0x1746,0x1746,0x1ef,0x1ef,0x1758,0x1758,0x175b,0x175b, -0x1746,0x1746,0x1758,0x174c,0x1749,0x174f,0x1761,0x1761,0x1752,0x1752,0x1755,0x1755,0x1755,0x1761,0x1818,0x1818, -0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0x1818,0x1815,0x1815,0x1815,0x1815, -0x1812,0x1812,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef, -0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef, -0x1ef,0x1ef,0x1ef,0x1ef,0x1f2,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764, -0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2, -0x1f2,0x1f2,0x1f2,0x1f2,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1f5,0x1f5,0x1f5,0x1f5,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1f5,0x1f5, -0x1b90,0x1b90,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5, -0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5, -0x1f5,0x1f5,0x1f5,0x1f5,0x176a,0x1779,0x1770,0x176d,0x177f,0x177f,0x1773,0x177f,0x1f8,0x1f8,0x1f8,0x1f8, -0x1f8,0x1f8,0x1f8,0x1f8,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1f8,0x1f8, -0x1f8,0x1f8,0x1f8,0x1f8,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1782,0x1782, -0x1782,0x1782,0x1782,0x1782,0x1782,0x1782,0x1782,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb, -0x1fb,0x1fb,0x1fb,0x178b,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d, -0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x182d,0x1a28,0x1fe, -0x1fe,0x181b,0x181b,0x181b,0x1827,0x1827,0x181b,0x181b,0x181b,0x181b,0x182a,0x181b,0x181b,0x181b,0x181b,0x181e, -0x1fe,0x1fe,0x1fe,0x1fe,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1821,0x1821, -0x1830,0x1830,0x1830,0x1821,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x201,0x201,0x201,0x201,0x201, -0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201, -0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x1845,0x1845,0x1845,0x1845, -0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x207, -0x1845,0x1845,0x207,0x207,0x207,0x207,0x207,0x1842,0x1842,0x1842,0x1842,0x1842,0x1848,0x1848,0x1848,0x1848, -0x1848,0x1848,0x1848,0x20a,0x1848,0x20a,0x1848,0x1848,0x1848,0x1848,0x20a,0x1848,0x1848,0x1848,0x1848,0x1848, -0x1848,0x1848,0x1848,0x1848,0x1848,0x1848,0x1848,0x1848,0x1848,0x1848,0x20a,0x1848,0x1848,0x1848,0x1848,0x1848, -0x1848,0x1848,0x1848,0x1848,0x1848,0x184b,0x20a,0x20a,0x20a,0x20a,0x20a,0x20a,0x16a1,0x16a1,0x16a1,0x16a1, -0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x1854,0x1854,0x1854,0x1854, -0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x20d, -0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x1851,0x1851,0x1851,0x1851, -0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x20d, -0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x185a,0x185a,0x185a,0x185a, -0x1857,0x185a,0x185a,0x185d,0x1860,0x185d,0x185d,0x185a,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210, -0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x1857,0x1857,0x1857,0x1857,0x1857,0x18b7,0x18b7,0x18b7,0x18b7, -0x18ae,0x18ae,0x18ae,0x18a8,0x18ab,0x18ab,0x18ab,0x1adf,0x213,0x213,0x213,0x213,0x18b4,0x18b4,0x18b4,0x18b4, -0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x18b4,0x213,0x213,0x213,0x213,0x18b1,0x18b1,0x18d2,0x18d2,0x18d2,0x18d2, -0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x216,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2, -0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18cf, -0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x216,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18cf,0x18c0, -0x18d2,0x18d5,0x18d5,0x18c9,0x18c6,0x18c6,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216, -0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, -0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x216,0x216,0x216,0x18e1,0x18e4,0x18ea,0x18ea, -0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18d8,0x18d8,0x18d8,0x18d8, -0x18d8,0x18d8,0x18d8,0x18d8,0x18d8,0x219,0x219,0x219,0x219,0x219,0x219,0x219,0x1a46,0x1a46,0x1a46,0x1a46, -0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x18db,0x18db,0x18db,0x18db, -0x18db,0x18db,0x18db,0x21c,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db, -0x18db,0x18db,0x18db,0x18db,0x18db,0x21c,0x21c,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x21c,0x18db, -0x18db,0x21c,0x18db,0x18db,0x18db,0x18db,0x18db,0x21c,0x21c,0x21c,0x21c,0x21c,0x1cfb,0x1cfb,0x1cfb,0x1cfb, -0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1929,0x19c5,0x1b39,0x1b3c, -0x1bea,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x1be7,0x1be7,0x21f,0x21f, -0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x18ea,0x18ea,0x18ea,0x18ea, -0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x222,0x222,0x18de,0x18de, -0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x222,0x18e7,0x18de,0x18de, -0x18de,0x18de,0x18de,0x18de,0x18de,0x18e7,0x18de,0x18de,0x18e7,0x18de,0x18de,0x222,0x222,0x222,0x222,0x222, -0x222,0x222,0x222,0x222,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed, -0x18ed,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225, -0x225,0x225,0x225,0x225,0x1905,0x1905,0x18f6,0x18f0,0x18f0,0x1905,0x18f3,0x1908,0x1908,0x1908,0x1908,0x190b, -0x190b,0x18ff,0x18fc,0x18f9,0x1902,0x1902,0x1902,0x1902,0x1902,0x1902,0x1902,0x1902,0x1902,0x1902,0x1b93,0x18ff, -0x228,0x18f9,0x1a2b,0x1ae2,0x1b96,0x1b96,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228, -0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228, -0x228,0x228,0x228,0x228,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911, -0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x1911,0x22b,0x22b,0x22b,0x22b,0x190e,0x190e,0x190e,0x190e, -0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e, -0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x22b,0x22b,0x22b,0x22b,0x192c,0x192c,0x192c,0x192c, -0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1b3f,0x1b3f, -0x1b3f,0x1b3f,0x1b3f,0x1b3f,0x22e,0x22e,0x22e,0x22e,0x22e,0x22e,0x22e,0x22e,0x1cb9,0x1cb9,0x1cb9,0x231, -0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x273,0x273,0x1d2e,0x273, -0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x196b,0x196b,0x196b,0x196b, -0x196b,0x196b,0x196b,0x234,0x196b,0x196b,0x234,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b, -0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x195f,0x195f,0x195f, -0x195f,0x195f,0x195f,0x234,0x234,0x234,0x195f,0x234,0x195f,0x195f,0x234,0x195f,0x195f,0x195f,0x1962,0x195f, -0x1965,0x1965,0x196e,0x195f,0x234,0x234,0x234,0x234,0x234,0x234,0x234,0x234,0x1968,0x1968,0x1968,0x1968, -0x1968,0x1968,0x1968,0x1968,0x1968,0x1968,0x234,0x234,0x234,0x234,0x234,0x234,0x19ce,0x19ce,0x19ce,0x19ce, -0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce, -0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x237,0x237,0x237,0x237,0x197d,0x1980,0x1980,0x23a, -0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x1c95,0x1c95,0x1c95,0x1c95, -0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x1c95,0x198f,0x198f,0x198f,0x198f, -0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x23d,0x23d,0x23d,0x23d,0x23d,0x1c62,0x1c62,0x1c62,0x1c62, -0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x199b,0x199e,0x19ad,0x19ad, -0x199e,0x19a1,0x199b,0x1998,0x240,0x240,0x240,0x240,0x240,0x240,0x240,0x240,0x1986,0x1971,0x1971,0x1971, -0x1971,0x1971,0x1971,0x1983,0x1983,0x1971,0x1971,0x1971,0x1986,0x1986,0x1986,0x1986,0x1ae8,0x1ae8,0x1ae8,0x1ae8, -0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8, -0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x1a31,0x1a31,0x1a31,0x1a31, -0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x243,0x243,0x1b48,0x1b48,0x1b48,0x1b48, -0x1bf0,0x1d34,0x1d34,0x1d34,0x1b48,0x1b48,0x1b48,0x1cbc,0x1cbc,0x276,0x276,0x276,0x1a43,0x1a43,0x1a43,0x1a43, -0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a40,0x1a40,0x1a40,0x1a34,0x1a34,0x1a34,0x1a34,0x1a34, -0x1a34,0x1a34,0x1a34,0x1a34,0x1a40,0x1a3a,0x1a37,0x1a3d,0x246,0x246,0x246,0x246,0x1a46,0x1a46,0x1a46,0x1a46, -0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46, -0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x249,0x249,0x1a46,0x1a46,0x1a46,0x1a55,0x1a55,0x1a55,0x1a55, -0x1a55,0x1a55,0x24c,0x1a55,0x1a55,0x24c,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55, -0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a55,0x1a52,0x1a52, -0x1a52,0x1a52,0x1a52,0x24c,0x1a49,0x1a49,0x24c,0x1a52,0x1a52,0x1a49,0x1a52,0x1a4c,0x1a55,0x24c,0x24c,0x24c, -0x24c,0x24c,0x24c,0x24c,0x1a5e,0x1a5e,0x1a61,0x1a61,0x1a58,0x1a58,0x1a58,0x1a58,0x24f,0x24f,0x24f,0x24f, -0x24f,0x24f,0x24f,0x24f,0x1a5b,0x1a5b,0x1a5b,0x1a5b,0x1a5b,0x1a5b,0x1a5b,0x1a5b,0x1a5b,0x1a5b,0x24f,0x24f, -0x24f,0x24f,0x24f,0x24f,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64, -0x1a67,0x1a64,0x1a64,0x1a64,0x1a67,0x1a64,0x1a64,0x1a64,0x1a64,0x252,0x252,0x252,0x252,0x252,0x252,0x252, -0x252,0x252,0x252,0x252,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73, -0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a73,0x1a70,0x1a6a,0x1a6a,0x1a6d,0x1a6d,0x1a76,0x1a76,0x255,0x255,0x255, -0x255,0x255,0x255,0x255,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79, -0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x258,0x258,0x258,0x258,0x258,0x258,0x258,0x258, -0x258,0x258,0x258,0x258,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c, -0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7c,0x1a7f,0x1a88,0x1a7c,0x1a7c,0x25b, -0x25b,0x25b,0x25b,0x25b,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8e,0x25e,0x25e,0x25e,0x25e, -0x25e,0x25e,0x25e,0x25e,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97, -0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a97,0x1a91,0x1a91,0x1a91,0x1a91,0x1a91,0x1a91,0x1a91,0x1a91,0x1a91,0x1a91, -0x1a91,0x1a94,0x1a94,0x1a94,0x1a94,0x1a9a,0x1a9a,0x1a9a,0x1a9a,0x1a9a,0x261,0x261,0x261,0x261,0x261,0x261, -0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x1c83,0x1c83,0x1c83,0x1c83, -0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1c83,0x1ce6,0x1cec,0x1cec,0x1cec, -0x1cec,0x1cec,0x1cec,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9,0x1ce9, -0x1ce9,0x1ce9,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x1af4,0x1af4,0x1af4,0x1af4, -0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4, -0x1af4,0x1af4,0x1af4,0x267,0x267,0x267,0x267,0x267,0x267,0x267,0x267,0x267,0x1b03,0x1b03,0x1b03,0x1b03, -0x1b03,0x1b03,0x1b03,0x1b03,0x26a,0x26a,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03, -0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b00,0x1b00,0x1b00, -0x1af7,0x1af7,0x1af7,0x1af7,0x26a,0x26a,0x1af7,0x1af7,0x1b00,0x1b00,0x1b00,0x1b00,0x1afa,0x1b03,0x1afd,0x1b03, -0x1b00,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a, -0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x1b0f,0x1b0f,0x1b0f,0x1b0f, -0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x26d,0x26d,0x26d,0x1b06,0x1b06,0x1b06,0x1b06, -0x1b06,0x1b06,0x1b06,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b12,0x1b12,0x26d,0x26d,0x270,0x1b15,0x1b15,0x1b15, -0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15, -0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x1b15,0x270,0x270, -0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273, -0x1b42,0x1b42,0x1b42,0x273,0x273,0x1d31,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273, -0x1b45,0x1b45,0x1b45,0x1b45,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x19ce,0x19ce,0x19ce,0x19ce, -0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x1b48,0x1b48,0x1b48,0x1bf0, -0x1bf0,0x1bf0,0x1bf0,0x1d34,0x1d34,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x1b48,0x1b48,0x1b48,0x1b48, -0x1b48,0x1b48,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1cbc,0x1cbc,0x1cbc, -0x1cbc,0x1d34,0x1d34,0x1d34,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1cbc,0x1cbc,0x1cbc,0x1cbc,0x1d34, -0x1d34,0x1d34,0x276,0x1d34,0x1bf0,0x1bf0,0x1bf0,0x1cbf,0x1cbf,0x1cbf,0x276,0x276,0x276,0x276,0x276,0x276, -0x276,0x276,0x1d34,0x1d34,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1cbc,0x1cbc,0x1cbc,0x1d34,0x1d34, -0x276,0x276,0x276,0x276,0x1cbc,0x1cbc,0x1cbc,0x1cbc,0x1cbc,0x1cbc,0x1cbc,0x1cbc,0x1d34,0x276,0x276,0x276, -0x276,0x276,0x276,0x276,0x1cbf,0x1cbf,0x1cbf,0x1cbf,0x1cbf,0x1cbf,0x1cbf,0x1d37,0x1d37,0x276,0x276,0x276, -0x276,0x276,0x276,0x276,0x1b1e,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18, -0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279, -0x279,0x279,0x279,0x1b1b,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a, -0x1b21,0x1b21,0x1b21,0x1b21,0x1b27,0x1b27,0x1b27,0x1b27,0x1b27,0x1b27,0x1b27,0x1b27,0x1b27,0x1b27,0x27c,0x27c, -0x27c,0x27c,0x27c,0x1b24,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99, -0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f, -0x27f,0x27f,0x27f,0x27f,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x282,0x282,0x1bb7,0x282,0x282, -0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x282,0x1bb7,0x1bb7,0x282,0x1bb7,0x1bb7,0x1bb7,0x1bb7, -0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1bb7,0x1b9f,0x1bae,0x1bae,0x1bae, -0x1bae,0x1bae,0x282,0x1bae,0x1bb1,0x282,0x282,0x1b9f,0x1b9f,0x1bb4,0x1ba5,0x1bba,0x1bae,0x1bba,0x1bae,0x1ba2, -0x1bbd,0x1ba8,0x1bbd,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x1bab,0x1bab,0x1bab,0x1bab, -0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x282,0x282,0x282,0x282,0x282,0x282,0x1bf6,0x1bf6,0x1bf6,0x1bf6, -0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6, -0x1bf6,0x1bf6,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285, -0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285, -0x285,0x285,0x285,0x285,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3, -0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x28b,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3, -0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b, -0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x1bc6,0x1bc6,0x1bc6,0x1bc6, -0x1bc6,0x1bc6,0x1bc6,0x1bc6,0x1bc6,0x1bc6,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x1bf9,0x1bf9,0x1bf9,0x1bf9, -0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e, -0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e, -0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf, -0x1bcf,0x1bcf,0x291,0x1bc9,0x1bc9,0x1bcc,0x291,0x291,0x1bcf,0x1bcf,0x291,0x291,0x291,0x291,0x291,0x291, -0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62, -0x1c5f,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x1c62,0x294,0x1c65,0x1c65,0x294,0x294,0x294,0x294,0x294,0x294, -0x1c5c,0x1c5c,0x1c5c,0x1c5c,0x1c5c,0x1c5c,0x1c5c,0x1c5c,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b, -0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c68,0x1c68,0x297,0x297,0x297,0x297,0x297, -0x297,0x297,0x297,0x297,0x297,0x297,0x297,0x297,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x29a, -0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x29a,0x1c6e,0x1c6e,0x29a,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e, -0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x1c6e,0x29a,0x1c71,0x1c77,0x1c77,0x1c74,0x1c74,0x1c74,0x2a0,0x1c74, -0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74, -0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x2a0,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74,0x1c74, -0x1c74,0x1c74,0x1c74,0x2a0,0x2a0,0x2a0,0x2a0,0x2a0,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a, -0x1c7a,0x1c7a,0x1c7d,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a, -0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x1c7a,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x1cef,0x1cef,0x1cef, -0x1cef,0x1cef,0x1cef,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3, -0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3, -0x2a3,0x2a3,0x2a3,0x2a3,0x1c83,0x1c83,0x1c80,0x1c80,0x1c80,0x1c80,0x1c86,0x1c86,0x1c86,0x1c86,0x2a6,0x2a6, -0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6, -0x2a6,0x2a6,0x2a6,0x2a6,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c, -0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c, -0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c, -0x1c8c,0x1c8c,0x1c8c,0x2a9,0x1c89,0x1c89,0x1c89,0x1c89,0x1c89,0x1c89,0x1c89,0x1c89,0x1c89,0x1c89,0x2a9,0x2a9, -0x2a9,0x2a9,0x2a9,0x2a9,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638, -0x1638,0x1638,0x1638,0x1638,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92,0x1c92, -0x1c92,0x1c92,0x1c8f,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac, -0x2ac,0x2ac,0x2ac,0x2ac,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x2af, -0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x1c9b,0x2af,0x1c9b,0x1c9b,0x2af,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98, -0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x2af,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98, -0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x2af,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x1c98,0x2af,0x1c98, -0x1c98,0x2af,0x2af,0x2af,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1, -0x1ca1,0x1ca1,0x2b2,0x2b2,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1, -0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2, -0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e, -0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5, -0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5, -0x2b5,0x1cf2,0x1cf2,0x1cf2,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cfb, -0x1cfb,0x1cfb,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8, -0x2b8,0x2b8,0x2b8,0x2b8,0x1cfe,0x1cfe,0x1cfe,0x1cfe,0x1cfe,0x1cfe,0x1cfe,0x1cfe,0x1cfe,0x1cfe,0x2bb,0x2bb, -0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb, -0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb, -0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01,0x1d01, -0x1d01,0x1d01,0x1d01,0x1d01,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be, -0x1d04,0x1d04,0x1d19,0x1d10,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16, -0x1d16,0x2c1,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16, -0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d16,0x1d10,0x1d10,0x1d04,0x1d04,0x1d04,0x1d04,0x1d04,0x2c1, -0x2c1,0x2c1,0x1d10,0x1d10,0x1d04,0x1d13,0x1d07,0x1d1c,0x1d1c,0x1d0a,0x1d0a,0x1d0a,0x1d0a,0x1d0a,0x1d0a,0x1d0a, -0x1d0a,0x1d0a,0x1d0a,0x1d0a,0x1d0d,0x1d0d,0x1d0d,0x1d0d,0x1d0d,0x1d0d,0x1d0d,0x1d0d,0x1d0d,0x1d0d,0x2c1,0x2c1, -0x2c1,0x2c1,0x2c1,0x2c1,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25,0x1d25, -0x1d1f,0x1d1f,0x1d1f,0x1d1f,0x1d22,0x1d22,0x1d22,0x1d22,0x1d22,0x1d22,0x1d22,0x1d22,0x1d22,0x1d22,0x2c4,0x2c4, -0x2c4,0x2c4,0x2c4,0x2c4,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x9b1,0x9b1,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a, -0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced, -0xced,0xced,0xced,0x136e,0x136e,0x136e,0x2ca,0x2ca,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24, -0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24, -0xf24,0xf24,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca, -0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca, -0x2ca,0x2ca,0x2ca,0x2ca,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09, -0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09, -0xc09,0xc09,0x2cd,0x2cd,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, -0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1caa,0x1caa,0x1caa,0x1caa,0x1d28,0x2d0,0x2d0, -0x2d0,0x2d0,0x2d0,0x2d0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0, -0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0, -0x14a0,0x14a0,0x2d3,0x2d3,0x1872,0x1872,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6, -0x2d6,0x2d6,0x2d6,0x2d6,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8, -0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9, -0x2d9,0x2d9,0x2d9,0x2d9,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46, -0x1d46,0x1d46,0x1d46,0x1d46,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x2dc, -0x2dc,0x2dc,0x2dc,0x2dc,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a, -0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46, -0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46, -0x1d46,0x1d46,0x2df,0x2df,0x41a,0x40e,0x40e,0x40e,0x40e,0x40e,0x40e,0x40e,0x40e,0x41a,0x41a,0x41a, -0x41a,0x414,0x11eb,0x13c5,0x420,0x97b,0x97e,0x40b,0x40b,0x11e8,0x13c2,0x13c2,0x41d,0x41d,0x41d,0x41d, -0x41d,0x41d,0x41d,0x41d,0x11e8,0x40e,0x40e,0x41a,0xd32,0x420,0x420,0x420,0x420,0x420,0x420,0x420, -0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420, -0x420,0x420,0x420,0x420,0x420,0x420,0x40e,0x40e,0x900,0x903,0x999,0x999,0x999,0x999,0x999,0x999, -0x999,0x999,0x999,0x999,0x417,0x1023,0x1020,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x1593,0x11ee,0x11ee,0xf60, -0xf60,0xe28,0xf60,0xf60,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x420,0x423,0x420,0x420, -0x420,0x420,0x420,0x420,0x420,0x423,0x420,0x420,0x423,0x420,0x420,0x420,0x420,0x420,0x13c2,0x13c5, -0x411,0x420,0x41a,0x41a,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x13ce,0x4c2,0x4c2, -0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x13ce,0x1944, -0x1944,0x1044,0x4b3,0x4bc,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504,0x504, -0x504,0x504,0x504,0x504,0x504,0x4fe,0x4fe,0x4fe,0x4fe,0x4fe,0x4fe,0xc24,0xc24,0xe37,0xe37,0x906, -0xe34,0x14b2,0x14b2,0x14b2,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501, -0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501,0x501, -0x501,0x501,0x501,0x501,0x50a,0x50a,0x50a,0x1203,0x1203,0x1203,0x1203,0x1203,0x507,0x507,0x507,0x507, -0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507, -0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x507,0x1200,0x1200, -0x1200,0x1200,0x1200,0x1200,0x50d,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a, -0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a, -0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x50a,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513, -0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x513,0x513, -0x513,0x513,0x510,0x9ff,0x1071,0x1071,0x1077,0x1071,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513, -0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513, -0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x516,0x513,0x1074,0x1071,0x1074,0x1071,0x1074,0x1071, -0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b, -0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b, -0x6f0,0x6f0,0x6f3,0x546,0x6ff,0x6fc,0x6fc,0x702,0x570,0x570,0x52e,0x52e,0x52e,0x52e,0x52e,0xbb5, -0x6f6,0x54f,0x71d,0x720,0x567,0x6f6,0x555,0x555,0x546,0x561,0x561,0x6f0,0x56d,0x56a,0x6f9,0x540, -0x537,0x537,0x53a,0x53a,0x53a,0x53a,0x53a,0x53d,0x53a,0x53a,0x53a,0x531,0x579,0x576,0x573,0x573, -0x70e,0x55b,0x558,0x70b,0x708,0x705,0x71a,0x552,0x714,0x717,0x55e,0x561,0x711,0x711,0x55e,0x561, -0x543,0x546,0x546,0x546,0x564,0x54c,0x549,0xc39,0xb58,0xb58,0xb55,0xb55,0xb55,0xb55,0xc30,0xc30, -0xc30,0xc30,0xc36,0xd5f,0xd5c,0xe43,0xe49,0xc33,0xe49,0xe49,0xe49,0xe49,0xe46,0xe49,0xe49,0xc2d, -0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59a,0x5a0,0x78c,0x59d,0xa02,0xa23,0xb5b,0xb5b,0xb5b, -0xc3f,0xc3f,0xe4f,0xe4f,0xe4f,0xe4f,0x120c,0x120f,0x120f,0x13e3,0x1581,0x15ab,0x15ae,0x15ae,0x17c7,0x1947, -0x5af,0x5af,0x5c7,0x732,0x5a9,0x72c,0x5af,0x5c4,0x5a9,0x732,0x5be,0x5c7,0x5c7,0x5c7,0x5be,0x5be, -0x5c7,0x5c7,0x5c7,0x738,0x5a9,0x5c7,0x735,0x5a9,0x5bb,0x5c7,0x5c7,0x5c7,0x5c7,0x5c7,0x5a9,0x5a9, -0x5b2,0x72c,0x72f,0x5a9,0x5c7,0x5a9,0x73b,0x5ac,0x5c7,0x5b5,0x5cd,0x73e,0x5c7,0x5c7,0x5b8,0x5be, -0x5c7,0x5c7,0x5ca,0x5c7,0x5be,0x5c1,0x5c1,0x5c1,0x5c1,0xb64,0xb61,0xd62,0xe58,0xc54,0xc57,0xc57, -0xc51,0xc4e,0xc4e,0xc4e,0xc4e,0xc57,0xc54,0xc54,0xc54,0xc54,0xc4b,0xc4e,0xe55,0xf6c,0xf6f,0x107d, -0x1212,0x1212,0x1212,0x744,0x741,0x5d0,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x741,0x744,0x744,0x741,0x5d3, -0x74a,0x74a,0x74a,0x74a,0x74a,0x74a,0x74a,0x74a,0x74a,0x74a,0x74a,0x74a,0x5dc,0x5dc,0x5dc,0x5dc, -0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9, -0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5df,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e5,0x5df, -0x5e2,0x5e2,0x5df,0x5df,0x5df,0x5df,0x5e2,0x5e2,0x74d,0x74d,0x5df,0x5df,0x5e2,0x5e2,0x5e2,0x5e2, -0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e5,0x5e5,0x5e5,0x5e2,0x5e2,0x750,0x5e2, -0x750,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5e2,0x5df,0x5e2,0x5df,0x5df,0x5df,0x5df,0x5df,0x5df, -0x5e2,0x5e2,0x5df,0x74d,0x5df,0x5df,0x5df,0xb6a,0xb6a,0xb6a,0xb6a,0xb6a,0xb6a,0xb6a,0xb6a,0xb6a, -0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0xc5a,0x753,0x5e8,0x753,0x753, -0x5eb,0x5e8,0x5e8,0x753,0x753,0x5eb,0x5e8,0x753,0x5eb,0x5e8,0x5e8,0x753,0x5e8,0x753,0x5f7,0x5f1, -0x5e8,0x753,0x5e8,0x5e8,0x5e8,0x5e8,0x753,0x5e8,0x5e8,0x753,0x753,0x753,0x753,0x5e8,0x5e8,0x753, -0x5eb,0x753,0x5eb,0x753,0x753,0x753,0x753,0x753,0x759,0x5f4,0x753,0x5f4,0x5f4,0x5e8,0x5e8,0x5e8, -0x753,0x753,0x753,0x753,0x5e8,0x5e8,0x5e8,0x5e8,0x753,0x753,0x5e8,0x5e8,0x5e8,0x5eb,0x5e8,0x5e8, -0x5eb,0x5e8,0x5e8,0x5eb,0x753,0x5eb,0x5e8,0x5e8,0x753,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x753,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x756,0x753,0x5eb,0x5e8, -0x753,0x753,0x753,0x753,0x5e8,0x5e8,0x753,0x753,0x5e8,0x5eb,0x756,0x756,0x5eb,0x5eb,0x5e8,0x5e8, -0x5eb,0x5eb,0x5e8,0x5e8,0x5eb,0x5eb,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5eb,0x5eb,0x753,0x753, -0x5eb,0x5eb,0x753,0x753,0x5eb,0x5eb,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x753,0x5e8,0x5e8,0x5e8,0x753,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x753,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5eb,0x5eb,0x5eb,0x5eb,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x753,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5eb,0x5eb,0x5eb,0x5eb,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5eb,0x5eb,0x5eb,0x5eb,0x5e8,0x5ee,0x5e8,0x5e8,0xc5d,0xc5d,0xc5d,0xc5d,0xc5d,0xc5d, -0xc5d,0xc5d,0xc5d,0xc5d,0xc5d,0xc5d,0xc5d,0xc5d,0x5fa,0xb6d,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa, -0x603,0x600,0x603,0x600,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x75c,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa, -0x5fa,0x5fa,0x84c,0x84c,0x5fa,0x5fa,0x5fa,0x5fa,0x5fd,0x5fd,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa, -0x5fa,0x852,0x84f,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa, -0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa, -0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0x5fa,0xb6d,0xc63,0xb6d,0xb6d,0xb6d,0x606,0x606,0x606,0x606, -0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606, -0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x765,0x765,0x765,0x765, -0x765,0x765,0x765,0x765,0x765,0x765,0x60c,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0, -0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xcc0,0xdd1,0x76b,0x76b,0x76b,0x76b, -0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b, -0x60f,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x76b,0x76b,0x76b,0x76b, -0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x612,0x612,0x612,0x612,0x76b,0x76b,0x76b,0x76b, -0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76e,0x76e,0x76e,0x76e, -0x76e,0x76e,0x76e,0x76e,0x76e,0x76e,0x76e,0x76e,0x76e,0x76e,0x76e,0x76e,0x615,0x615,0x76e,0x76e, -0x76e,0x76e,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0x774,0x774,0x618,0x771, -0x771,0x771,0x771,0x771,0x771,0x771,0x618,0x618,0x618,0x618,0x61b,0x61b,0x61b,0x61b,0x774,0x774, -0x61b,0x61b,0x774,0x774,0x618,0x618,0x618,0x618,0x774,0x774,0x61b,0x61b,0x774,0x774,0x618,0x618, -0x618,0x618,0x774,0x774,0x771,0x618,0x61b,0x774,0x618,0x618,0x771,0x774,0x774,0x774,0x61b,0x61b, -0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x774,0x771, -0x774,0x771,0x618,0x61b,0x61b,0x61b,0x61b,0x61b,0x61b,0x618,0x618,0x771,0xb73,0xb73,0xb73,0xb73, -0xb73,0xb73,0xb73,0xb73,0xc69,0xc69,0xc69,0xc69,0xc69,0xcd8,0xcd8,0xc69,0x621,0x621,0x621,0x621, -0x61e,0x77d,0x77d,0x61e,0x61e,0x777,0x61e,0x61e,0x61e,0x61e,0x777,0x777,0x61e,0x61e,0x61e,0x61e, -0xdda,0xdda,0xc6c,0xc6c,0xe61,0xb76,0x621,0x621,0x77a,0x624,0x77a,0x621,0x61e,0x61e,0x61e,0x61e, -0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e, -0x61e,0x61e,0x61e,0x61e,0x61e,0x621,0x621,0x621,0x61e,0x61e,0x61e,0x61e,0x77d,0x61e,0x77d,0x61e, -0x61e,0x61e,0x61e,0x61e,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855, -0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x61e,0x77d,0x77d,0x627,0x77d, -0x777,0x777,0x61e,0x777,0x77a,0x777,0x777,0x61e,0x777,0x77d,0x627,0x77d,0xb76,0xb76,0xc6f,0xc6f, -0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xe5e,0xf1b,0x62a,0x62a,0x62a,0x62a, -0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a,0x62a, -0x62d,0x1473,0x1473,0x1473,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x15b4,0x633,0x633,0x633, -0x633,0x1473,0x62d,0x62d,0x633,0x633,0x1476,0x1476,0x639,0x639,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d, -0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x1473,0x62d,0x62d,0x62d, -0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d, -0x62d,0x783,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d, -0x1473,0x62d,0x1473,0x62d,0x62d,0x62d,0x62d,0x1473,0x1473,0x1473,0x62d,0x1368,0x62d,0x62d,0x62d,0x636, -0x636,0x636,0x636,0x13ef,0x13ef,0x62d,0x630,0x630,0x633,0x62d,0x62d,0x62d,0xc75,0xc72,0xc75,0xc72, -0xc75,0xc72,0xc75,0xc72,0xc75,0xc72,0xc75,0xc72,0xc75,0xc72,0x780,0x780,0x780,0x780,0x780,0x780, -0x780,0x780,0x780,0x780,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d, -0x62d,0x62d,0x62d,0x62d,0x1473,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d,0x62d, -0x62d,0x62d,0x62d,0x1473,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a, -0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a, -0x65a,0x65a,0x651,0x651,0x651,0x651,0x651,0x651,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654, -0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654, -0x654,0x654,0x654,0x654,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7,0xbc7, -0xbc7,0xbc7,0xbc7,0xbc7,0x65a,0x65a,0x9ae,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x651,0x651, -0xc78,0xdfe,0x1c0e,0x1c0e,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654, -0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654, -0x657,0x65d,0x65a,0x654,0x65a,0x654,0x65a,0x654,0x65a,0x654,0x65a,0x654,0x65a,0x654,0x65a,0x654, -0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654, -0x65a,0x654,0x657,0x65d,0x65a,0x654,0x65a,0x654,0x657,0x65d,0x65a,0x654,0x657,0x65d,0x65a,0x654, -0x65a,0x654,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2,0x13f2, -0x65a,0x654,0x65a,0x654,0x65a,0x654,0x657,0x65d,0x657,0x65d,0x65a,0x654,0x65a,0x654,0x65a,0x654, -0x65a,0x654,0x65a,0x654,0x65a,0x654,0x65a,0x654,0x657,0x65a,0x654,0x657,0x65a,0x654,0x657,0x65d, -0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654, -0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657, -0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a, -0x65a,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654, -0x654,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d, -0x654,0x65a,0x96c,0x96f,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e, -0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x657,0x654,0x657,0x657,0x657,0x657,0x657,0x657,0x654,0x657,0x654,0x654, -0x657,0x657,0x654,0x654,0x657,0x657,0x654,0x657,0x654,0x657,0x654,0x654,0x657,0x654,0x654,0x657, -0x654,0x657,0x654,0x654,0x657,0x654,0x657,0x657,0x654,0x654,0x654,0x657,0x654,0x654,0x654,0x654, -0x654,0x657,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654, -0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x657,0x657,0x654,0x654,0x657,0x654,0x657,0x654, -0x654,0x654,0x654,0x654,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657, -0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x657, -0x657,0x657,0x657,0x657,0x657,0x657,0x657,0x65d,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a, -0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a, -0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d, -0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65d,0x65a,0x65a,0x65a, -0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x660,0x660,0x660,0x660,0x1089,0x1089,0x1089,0x15b7, -0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x17cd,0x17cd,0x8b5,0x8bb,0x8bb,0x8c7,0x8c7,0x8b8,0x8af,0x8b8, -0x8af,0x8b8,0x8af,0x8b8,0x8af,0x8b8,0x8af,0x8b8,0x66f,0x66f,0x669,0x66f,0x669,0x66f,0x669,0x66f, -0x669,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66f,0x669,0x66c, -0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66f,0x669,0x66f,0x669,0x66f, -0x669,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c, -0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c,0x672,0x66f,0x669,0x66c, -0x672,0x66f,0x669,0x66c,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762, -0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f, -0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f, -0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x75f,0x768,0x768,0x768,0x768,0x768,0x768, -0x768,0x768,0x768,0x768,0x768,0x768,0x768,0x768,0x768,0x768,0x768,0x768,0x765,0x765,0x765,0x765, -0x765,0x765,0x765,0x765,0x765,0x765,0x765,0x765,0x765,0x765,0x765,0x765,0x76b,0x76b,0x76b,0x76b, -0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b, -0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x76b,0x786,0x786,0x786,0x786, -0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786, -0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0x786,0xcc6,0x918,0x90f,0x90c, -0x912,0x915,0x79b,0x79e,0x79e,0x79e,0x79e,0x79e,0x79e,0x79e,0x79e,0x79e,0x91e,0x79b,0x79b,0x79b, -0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b, -0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x91b,0x91b, -0x7a1,0x92d,0x930,0x936,0x858,0x867,0x94e,0x864,0x924,0x921,0x924,0x921,0x92a,0x927,0x92a,0x927, -0x924,0x921,0x85e,0x936,0x924,0x921,0x924,0x921,0x924,0x921,0x924,0x921,0x93c,0x942,0x945,0x93f, -0x7a7,0x7e3,0x7e3,0x7e3,0x7e3,0x7e3,0x7e3,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd, -0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7aa,0x7c5,0x7a4,0x7cb,0x7ce, -0x7c8,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da, -0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7aa,0x7c5,0x7a4,0x7c5,0xcc9, -0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846, -0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846, -0x846,0x846,0x1362,0x1362,0x1362,0x1362,0x1362,0x849,0x85e,0x861,0x861,0x861,0x861,0x861,0x861,0x861, -0x861,0x861,0x987,0x987,0x987,0x987,0x86a,0x86a,0x939,0x94b,0x94b,0x94b,0x94b,0x948,0x85b,0x933, -0xb9a,0xb9a,0xb9a,0xcdb,0xcf9,0xcf6,0xbb8,0x909,0x870,0x86d,0x870,0x873,0x86d,0x870,0x86d,0x870, -0x86d,0x870,0x86d,0x86d,0x86d,0x86d,0x86d,0x86d,0x870,0x870,0x86d,0x870,0x870,0x86d,0x870,0x870, -0x86d,0x870,0x870,0x86d,0x870,0x870,0x86d,0x86d,0xcfc,0x882,0x87c,0x882,0x87c,0x882,0x87c,0x882, -0x87c,0x882,0x87c,0x87c,0x87f,0x87c,0x87f,0x87c,0x87f,0x87c,0x87f,0x87c,0x87f,0x87c,0x87f,0x87c, -0x87f,0x87c,0x87f,0x87c,0x87f,0x87c,0x87f,0x87c,0x87f,0x87c,0x87f,0x882,0x87c,0x87f,0x87c,0x87f, -0x87c,0x87f,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87f,0x87f,0x87c,0x87f,0x87f,0x87c,0x87f,0x87f, -0x87c,0x87f,0x87f,0x87c,0x87f,0x87f,0x87c,0x87c,0x87c,0x87c,0x87c,0x882,0x87c,0x882,0x87c,0x882, -0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x882,0x87c,0x87c,0x87c,0x87c,0x87c,0x87f,0x882,0x882,0x87f, -0x87f,0x87f,0x87f,0x954,0x957,0x885,0x888,0xce4,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e, -0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e, -0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x891,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e, -0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e,0x88e, -0x88e,0x88e,0x88e,0x88e,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a, -0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a,0x89a, -0xde3,0xde3,0xf1e,0x894,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960, -0xddd,0xddd,0xddd,0xddd,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d, -0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d,0x89d, -0x89d,0x89d,0x89d,0x1b51,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966, -0x966,0x966,0x966,0x966,0x966,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0xde6,0xde6,0xde6,0xde6,0x969, -0x969,0x969,0x969,0x969,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0, -0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0, -0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0x8a0,0xde6,0xde6,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3, -0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3, -0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x8a3,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966, -0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6, -0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6, -0x8a6,0x8a6,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21, -0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0x11d0,0x11d0,0x11d0,0x11d0,0x8a9,0x8a9,0x8a9,0x8a9, -0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9, -0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8ac,0x8ac, -0x8a9,0x8ac,0x8a9,0x8ac,0x8ac,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8a9,0x8ac, -0x8a9,0x8ac,0x8a9,0x8ac,0x8ac,0x8a9,0x8a9,0x8ac,0x8ac,0x8ac,0x8a9,0x8a9,0x8a9,0x8a9,0x1572,0x1572, -0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced, -0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960, -0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960, -0x13a1,0x13a1,0x13a1,0x13a1,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0xddd,0xce7,0xce7,0xce7, -0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0x963,0x963,0x963,0x963, -0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963, -0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0x963,0xce7,0xce7,0xce7, -0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0x966,0x966,0x966,0x966, -0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966, -0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0xde6,0x9fc,0x9d8,0x9d8,0x9d8, -0x9d8,0x9d2,0x9d8,0x9d8,0x9ed,0x9d8,0x9d8,0x9e7,0x9e4,0x9ea,0x9ea,0x9ea,0x9ea,0x9ea,0x9ed,0x9d2, -0x9de,0x9d2,0x9d2,0x9d2,0x9c0,0x9c0,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0x9f0,0x9f0,0x9f0,0x9f0, -0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9f0,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2,0x9d2, -0x9d5,0x9c6,0x9d2,0x9c6,0x9d2,0x9c3,0x9e1,0x9db,0x9e1,0x9db,0x9f6,0x9f6,0xa05,0xa05,0xa05,0xa05, +0x18f,0x18f,0x18f,0x18f,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1b6, +0x1b6,0x1b6,0x1b6,0x1b6,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b6,0x1b6,0x1b6,0x1b6, +0x1b6,0x1b6,0x1b6,0x1b6,0x1d1,0x1d1,0x1d1,0xe0d,0xe0d,0xe0d,0xe0d,0xe0d,0x1ce,0x1ce,0x1ce,0x1ce, +0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce, +0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0xe0a,0xe0a, +0xe0a,0xe0a,0xe0a,0xe0a,0x1d4,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1, +0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1, +0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x237,0x237, +0x237,0x237,0x22b,0x660,0xc99,0xc99,0xcb1,0xc99,0x36c,0x36c,0x36c,0x36c,0x36c,0x36c,0x36c,0x36c, +0x36c,0x36c,0x36c,0x36c,0x231,0x231,0x231,0x231,0x363,0x363,0x363,0x363,0x363,0x363,0x363,0x363, +0x363,0x363,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237, +0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0x23d,0x237,0xc9c,0xc99,0xc9c,0xc99,0xc9c,0xc99, +0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x1044,0x555,0x555,0x555,0x555,0x555,0x555, +0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x555,0x1044,0x1524,0x1524,0xcba,0x5ac,0x246, +0x49e,0x4aa,0x4aa,0x4aa,0x4aa,0x4aa,0x4aa,0x4aa,0x4aa,0x4aa,0x648,0x648,0x648,0x648,0x642,0x642, +0x50a,0x51f,0x51f,0x51f,0x51f,0x51c,0x459,0x504,0x7e3,0x7e3,0x7e3,0x91b,0x939,0x936,0x7f8,0x2a9, +0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df,0x2df, +0x2df,0x2df,0x2df,0x2df,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc, +0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc, +0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4, +0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f4,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1, +0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306, +0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306, +0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381, +0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381, +0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x381,0x909,0x3b1,0x3a8,0x3a5,0x3ab,0x3ae,0x39f,0x3a2, +0x3a2,0x3a2,0x3a2,0x3a2,0x3a2,0x3a2,0x3a2,0x3a2,0x3b4,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f, +0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f, +0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x39f,0x63f,0x63f,0x3ba,0x3f9,0x3f9,0x3f9, +0x3f9,0x3f9,0x3f9,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3, +0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3f3,0x3bd,0x3db,0x3b7,0x3e1,0x3e4,0x3de,0x3f6,0x3f6,0x3f6, +0x3f6,0x3f6,0x3f6,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0, +0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3f0,0x3bd,0x3db,0x3b7,0x3db,0x90c,0x3c6,0x4fe,0x501,0x507, +0x44d,0x4b3,0x534,0x4b0,0x53a,0x537,0x540,0x53d,0x4fb,0x4f8,0x4fb,0x4f8,0x4f5,0x4f2,0x49e,0x507, +0x4f5,0x4f2,0x4f5,0x4f2,0x4f5,0x4f2,0x4f5,0x4f2,0x50d,0x513,0x516,0x510,0x4bc,0x4bc,0x4bc,0x4bc, +0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc, +0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0x4bc,0xa1a,0xa1a,0xb40,0x450,0x56a,0x567,0x56a,0x567, +0xd8c,0xd89,0xd8c,0x12de,0x12db,0x12de,0x12db,0x12de,0x12db,0x12de,0x13e6,0x13e3,0x462,0x474,0x474,0x492, +0x492,0x468,0x456,0x468,0x456,0x468,0x456,0x468,0x456,0x468,0x456,0x468,0x528,0x528,0x528,0x528, +0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x45f,0x45f,0x45f, +0x45f,0x45f,0x45f,0xa0b,0xa0b,0xa0b,0xa0b,0x52e,0x52e,0x52e,0x52e,0x52e,0x45f,0x45f,0x45f,0x45f, +0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f, +0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0x45f,0xa0b,0xa0b, +0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad, +0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad, +0x4ad,0x4ad,0x4b6,0x4b6,0x4ad,0x4b6,0x4ad,0x4b6,0x4b6,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad, +0x4ad,0x4ad,0x4ad,0x4b6,0x4ad,0x4b6,0x4ad,0x4b6,0x4b6,0x4ad,0x4ad,0x4b6,0x4b6,0x4b6,0x4ad,0x4ad, +0x4ad,0x4ad,0x110d,0x110d,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e, +0x91e,0x91e,0x91e,0x91e,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6, +0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6, +0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0x4b6,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d, +0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xd74,0xd74,0xd74,0xd74, +0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, +0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, +0x4bf,0x4bf,0xf33,0xf33,0xf33,0xf33,0xf33,0x4c8,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2, +0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2, +0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c5,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2, +0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x4c2, +0x4c2,0x4c2,0x4c2,0x4c2,0x4ce,0x4cb,0x4ce,0x4d1,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb,0x4ce,0x4cb,0x4cb, +0x4cb,0x4cb,0x4cb,0x4cb,0x4ce,0x4ce,0x4cb,0x4ce,0x4ce,0x4cb,0x4ce,0x4ce,0x4cb,0x4ce,0x4ce,0x4cb, +0x4ce,0x4ce,0x4cb,0x4cb,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528, +0xa0b,0xa0b,0xa0b,0xa0b,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da, +0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da,0x4da, +0x4da,0x4da,0x4da,0x16a1,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd, +0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd,0x4dd, +0x4dd,0x4dd,0x4dd,0x4dd,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x933,0x4e6,0x4e0,0x4e6, +0x4e0,0x4e6,0x4e0,0x4e6,0x4e0,0x4e6,0x4e0,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0, +0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e6, +0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e3,0x4e0,0x4e0,0x4e0,0x4e0,0x4e0,0x4e0,0x4e3,0x4e3,0x4e0,0x4e3, +0x4e3,0x4e0,0x4e3,0x4e3,0x4e0,0x4e3,0x4e3,0x4e0,0x4e3,0x4e3,0x4e0,0x4e0,0x4e0,0x4e0,0x4e0,0x4e6, +0x4e0,0x4e6,0x4e0,0x4e6,0x4e0,0x4e0,0x4e0,0x4e0,0x4e0,0x4e0,0x4e6,0x4e0,0x4e0,0x4e0,0x4e0,0x4e0, +0x4e3,0x4e6,0x4e6,0x4e3,0x4e3,0x4e3,0x4e3,0x4ef,0x522,0x4e9,0x4ec,0x92a,0x528,0x528,0x528,0x528, +0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528, +0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0xf39,0xf39,0xf39,0xf39, +0xf03,0xf03,0xf03,0xf03,0xf03,0xf03,0xf03,0xf03,0xa0b,0x915,0x915,0x915,0x915,0x915,0x915,0x915, +0x915,0x915,0x915,0x915,0x915,0x915,0x915,0x915,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528, +0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528,0x528, +0x528,0x528,0x528,0x528,0x528,0x528,0x528,0xa0b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b, +0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b, +0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x52b,0x915,0x915,0x915,0x915,0x915,0x915,0x915, +0x915,0x915,0x915,0x915,0x915,0x915,0x915,0x915,0x68d,0x669,0x669,0x669,0x669,0x663,0x669,0x669, +0x67e,0x669,0x669,0x678,0x675,0x67b,0x67b,0x67b,0x67b,0x67b,0x67e,0x663,0x66f,0x663,0x663,0x663, +0x6ab,0x6ab,0x663,0x663,0x663,0x663,0x663,0x663,0x681,0x681,0x681,0x681,0x681,0x681,0x681,0x681, +0x681,0x681,0x663,0x663,0x663,0x663,0x663,0x663,0x663,0x663,0x663,0x663,0x666,0x6b1,0x663,0x6b1, +0x663,0x6ae,0x672,0x66c,0x672,0x66c,0x687,0x687,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690, +0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690, +0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x690,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696, +0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696, +0x696,0x696,0x696,0x696,0x696,0x696,0x693,0x693,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696, +0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696, +0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x699,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c, +0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c, +0x69c,0x69c,0x69c,0x69c,0x699,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c, +0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c,0x69c, +0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8, +0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x6d8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea, +0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea,0x6ea, +0x705,0x705,0x705,0x705,0x705,0x705,0x705,0xa9b,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0xa9b,0x705,0x705,0x705,0x705, +0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x705,0x72c,0x72c,0x72c,0x72f, +0x72f,0x72c,0x72c,0x72c,0x729,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c, +0x813,0x813,0x726,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x726,0x726,0x72c,0x72c,0x72c,0x72c, +0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c, +0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x72c,0x762,0x762,0x762,0x762, +0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762, +0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x765, +0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762, +0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x819,0x819,0x762, +0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762, +0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x762,0x7d4,0x7d4,0x7d4,0x7d4,0x7d4,0x7d4,0x7d4,0x7d4, +0x7d4,0x7d4,0x77a,0x77a,0x76b,0x76b,0x76b,0x76b,0x774,0x774,0x774,0x774,0x774,0x774,0x771,0x771, +0x81f,0x81f,0xccf,0xccf,0xccf,0xccf,0xda4,0xda4,0x774,0x774,0xccf,0x774,0x774,0x774,0x777,0x774, +0xccf,0x774,0x774,0xcc6,0x76e,0x81f,0x81f,0x81f,0x81f,0x771,0x81f,0xda4,0xda4,0xda4,0x81f,0x822, +0x76e,0x825,0xdaa,0xcc9,0xcc9,0xda4,0xda4,0xccf,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774, +0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774, +0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x774,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789, +0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789, +0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x789,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc, +0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7b9,0x7bf,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0xe25, +0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe22,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc, +0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc, +0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7bc,0x7c2,0x7c2,0x7c2,0x7c2, +0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2, +0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7c2,0x7da,0x7da,0x7da,0x7da, +0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da,0x7da, +0x7da,0x7da,0x7da,0x7da,0x1035,0x1035,0x1035,0x16fe,0x16fe,0x16fe,0x16fe,0x16fe,0x7dd,0x7dd,0x7dd,0x7dd, +0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd, +0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7e0,0x7e0,0x7e0,0x7e0, +0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0, +0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e6,0x7e6,0x7e6,0x7e6, +0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6, +0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x1701,0x1701, +0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x7e9,0x7e9,0x92d,0x92d,0x7e9,0x7e9,0x7e9,0x7e9, +0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x92d,0x7e9,0x7e9,0x7e9, +0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7e9,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec, +0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ef,0x7ec,0x7ec, +0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec, +0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec,0x7ec, +0x855,0x855,0x855,0x855,0x855,0x885,0x885,0x88b,0x88b,0x88b,0x852,0x852,0x852,0x888,0x888,0x888, +0x888,0x888,0x888,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x88b,0x88b,0x88b,0x88b,0x88b, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, +0x852,0x852,0x855,0x855,0x88b,0x88b,0x88b,0x852,0x852,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b,0x88b, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, +0x852,0x852,0x852,0x852,0x852,0x852,0x88b,0x88b,0x88b,0x88b,0x852,0x852,0x852,0x852,0x852,0x852, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x855,0x855,0x855,0x855,0x855,0x855,0x852,0x852,0x852, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x1359,0x1359,0x861,0x858,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x858,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x861,0x861, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x858,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x858,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x858,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b, +0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b,0x85b, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861, +0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x861,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e,0x85e, +0x85e,0x85e,0x85e,0x85e,0x861,0x861,0x861,0x861,0x867,0x867,0x867,0x867,0x867,0x867,0x98a,0x98a, +0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864, +0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x864,0x987,0x987,0x9e4,0x9e4,0x9e4,0x9e4, +0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x867,0x867,0x867,0x867, +0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867, +0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x867,0x876,0x876,0x876,0x876, +0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876, +0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x876,0x11bb,0x87c,0x87c,0x87c,0x87c, +0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c, +0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87c,0x87f,0x87f,0x87f,0x87f, +0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f, +0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x87f,0x1701, +0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x17ac,0x17ac,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882, +0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882, +0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x882,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8ac,0x8b8, +0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x96c, +0x972,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xb91,0xb91,0xb91,0xb91, +0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0x8ac,0xa11,0xa11,0xa11,0xa11,0xa11,0xa11, +0x96c,0x96c,0xa53,0xb34,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xc36,0xf18,0xf18, +0xa65,0xa65,0xa65,0xa65,0xa65,0xa6b,0xa68,0xb91,0xb91,0xb91,0xb91,0x107d,0xc51,0x107d,0xfae,0xfae, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x912,0x90f,0x912,0x90f,0x912,0x90f,0xd68,0xd65,0xc57,0xc54,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8be, +0x8bb,0x912,0x90f,0x8be,0x8bb,0x8be,0x8bb,0x8be,0x8bb,0x8be,0x8bb,0x8be,0x8bb,0x8be,0x8bb,0x8be, +0x8bb,0x8be,0x8bb,0x8be,0x8bb,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8be,0x8bb,0x8be,0x8bb,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8be,0x8bb,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8c4,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8c4,0x8c4,0x8c4,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8, +0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8b8,0x8c1,0x8b8,0x8b8,0x8b8,0x91e,0x91e,0x91e,0x91e, +0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e, +0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x91e,0x96c,0xa11,0xa53,0xa53, +0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xb34,0xb34,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53,0xb8e,0xc36, +0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xf2a,0xf2a,0xf1b,0x96c,0x96c,0x96c,0x96c, +0x96c,0x96c,0x96c,0x96c,0x96c,0x96c,0x96c,0x96c,0x96c,0x96c,0xa53,0xa53,0xa53,0xa53,0xa53,0xa53, +0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xd6e,0xd6e,0xc36,0xc36,0xc36,0x9b1,0x9b1,0x9b1,0x9b1, +0x9b1,0x9b1,0x996,0x996,0x996,0x996,0x996,0x984,0x9bd,0x9bd,0x9bd,0x9b7,0x9bd,0x9bd,0x9bd,0x9bd, +0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9b7,0x9bd,0x9bd,0x9bd,0x9bd,0x99f,0x99f,0x9ba,0x9ba, +0x9ba,0x9ba,0x99c,0x99c,0x99c,0x99c,0x99c,0x9b1,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc, +0xabc,0xabc,0xabc,0xabc,0xa8f,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0x9bd,0x9bd,0x9bd,0x9bd, +0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9b7,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd, +0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x9bd,0x99f,0x99f,0x99f,0x9ae,0x9ae,0x9ae,0x9ae, +0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae, +0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9b1,0x9b1,0x9b1,0x9b1, +0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1, +0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9b1,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db, +0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9db,0x9e4,0x9e4,0x9e4,0x9e4, +0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4, +0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0x9e4,0xa05,0xa05,0xa05,0xa05, 0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05, -0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa08,0xa08,0xa08,0xa08, -0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08, -0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa0b,0xa0b,0xa0b,0xa0b, -0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b, -0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa14,0xa14,0xa14,0xa14, -0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14, -0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa0e,0xa0e,0xa17,0xa17,0xa17,0xa17, -0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17, -0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa11,0xa11,0xa14,0xa14,0xa14,0xa14, -0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14, -0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa17,0xa17,0xa17,0xa17, -0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17, -0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa1a,0xa1d,0xa1d,0xa1d, -0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d, -0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1a,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d, -0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d,0xa1d, -0xa1d,0xa1d,0xa1d,0xa1d,0xabf,0xabf,0x106b,0xabf,0xabf,0xabf,0xac2,0xabf,0x106b,0xabf,0xabf,0x1062, -0xab9,0xaad,0xaad,0xaad,0xaad,0xabc,0xaad,0x1053,0x1053,0x1053,0xaad,0xab0,0xab9,0xab3,0x1059,0x1065, -0x1065,0x1053,0x1053,0x106b,0xbbe,0xbbe,0xbbe,0xbbe,0xbbe,0xbbe,0xbbe,0xbbe,0xbbe,0xbbe,0xac5,0xac5, -0xab6,0xab6,0xab6,0xab6,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabc,0xabc,0xaad,0xaad,0x106b,0x106b, -0x106b,0x106b,0x1053,0x1053,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf, -0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf,0xabf, -0xabf,0xabf,0xabf,0xabf,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xe40,0xad4,0xad4,0xad4,0xad4, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xe40, -0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4,0xad4, -0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada, +0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa05,0xa41,0xa41,0xa41,0xa41, +0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41, +0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xa41,0xb16,0xb16,0xb16,0xb16, +0xb16,0xb16,0xb16,0xb16,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d, +0xa4d,0xa4d,0xa4d,0xb8b,0xb8b,0xb8b,0xb8b,0xc33,0xc33,0xc33,0xc33,0xc33,0xa62,0xa62,0xa62,0xa62, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f, +0xa5f,0xa5f,0xa5c,0xb13,0xc42,0xc39,0xc4e,0xc36,0xa59,0xa59,0xc36,0xc36,0xa86,0xa83,0xa86,0xa83, +0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83, +0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa86,0xa83,0xa9e,0xa9e,0xa9e,0xa9e, +0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e, +0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xa9e,0xaad,0xaad,0xaad,0xaad, +0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad, +0xaad,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaaa,0xaaa,0xaaa,0xaaa, +0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa, +0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaaa,0xaad,0xaad,0xaad,0xaad, +0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad, +0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xaad,0xac8,0xac8,0xac8,0xac8, +0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8, +0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xab0,0xabc,0xabc,0xabc,0xabc, +0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc, +0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xabc,0xac8,0xac8,0xac8,0xac8,0xac8,0xadd,0xadd,0xadd,0xadd, +0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0x1779,0xada,0xada,0xada,0xada, 0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada, -0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xadd,0xae3,0xae0, -0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0x1209,0x1209,0x1209,0x1209,0x1209,0x1209,0x1209,0x1209,0x1209, -0x1206,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0, -0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0,0xae0, -0xae0,0xae0,0xae0,0xae0,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5, -0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5,0xaf5, -0xaf5,0xaf5,0xaf5,0xaf5,0xb25,0xb25,0xb25,0xb28,0xb28,0xb25,0xb25,0xb25,0xb22,0xb25,0xb25,0xb25, -0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb0a,0xb0a,0xb1f,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8, -0xaf8,0xaf8,0xb1f,0xb1f,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25, -0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25, -0xb25,0xb25,0xb25,0xb25,0xb49,0xb49,0xb49,0xb49,0xb49,0xb34,0xb34,0xb49,0xb49,0xb49,0xb49,0xb49, -0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49, -0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb4c, -0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49, -0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb6d,0xb6d,0xb6d,0xb6d, -0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d, -0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xb6d,0xc63,0xc63,0xc63,0xc63,0xc63,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb8b,0xb8b,0xb8b,0xb8b, -0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b, -0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb91,0xb91,0xb91,0xb91, -0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91, -0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb91,0xb9d,0xb9d,0xb9d,0xb9d, -0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d,0xb9d, -0xb9d,0xb9d,0xb9d,0xb9d,0x1479,0x1479,0x1479,0x1bd2,0x1bd2,0x1bd2,0x1bd2,0x1bd2,0xba0,0xba0,0xba0,0xba0, -0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0, -0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0xba0,0x1bd5,0x1bd5, -0x1bd5,0x1bd5,0x1bd5,0x1bd5,0x1bd5,0x1bd5,0x1bd5,0x1bd5,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3, -0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba6,0xba3,0xba3, -0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3, -0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3,0xba3, -0xba9,0xba9,0xcea,0xcea,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9, -0xba9,0xba9,0xba9,0xba9,0xcea,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9,0xba9, -0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd, -0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0xbcd,0x15ba, -0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xd71,0xd71,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3, -0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3,0xbd3, -0xbd3,0xbd3,0xd6e,0xd6e,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc, -0xdbc,0xdbc,0xdbc,0xdbc,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6, -0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6,0xbd6, -0xbd6,0xbd6,0xbd6,0xbd6,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9, -0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9, -0xbd9,0xbd9,0xbd9,0xbd9,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbdf,0xbeb,0xbf1,0xbf1,0xbf1,0xbe5,0xbe5, -0xbe5,0xbee,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbf1, -0xbf1,0xbf1,0xbf1,0xbf1,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe8,0xbe8,0xbf1,0xbf1,0xbf1,0xbe5,0xbe5,0xbf1,0xbf1,0xbf1, -0xbf1,0xbf1,0xbf1,0xbf1,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbf1,0xbf1,0xbf1,0xbf1,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8, -0xbe8,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0x17d0,0x17d0, -0xbfd,0xbf4,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbf4,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbf4,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbf4,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbf4,0xbfa,0xbfa, +0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0xada,0x1776,0xadd,0xadd,0xadd,0xadd, +0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd, +0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xadd,0xaf2,0xaf2,0xb6d,0xaf2, +0xaf2,0xaf2,0xb70,0xaf2,0xaf2,0xaf2,0xaf2,0xb6d,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2, +0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xafb,0xafb,0xafb,0xafb, +0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb, +0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xb01,0xb01,0xb01,0xb01, +0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01, +0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb01,0xb0a,0xb0a,0xb0a,0xb0a, +0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a, +0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb3a,0xb3a,0xb3a,0xb3a, +0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a, +0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb3a,0xb43,0xb43,0xb43,0xb43, +0xb43,0xb43,0xb43,0xb43,0xb43,0xb43,0xb43,0xb43,0xb43,0xb43,0xb43,0xb43,0xd77,0xd77,0xd77,0xd77, +0xd77,0xd77,0xd77,0xd77,0xd77,0xd77,0xd77,0xd77,0xd77,0xd77,0xd77,0xd77,0xb73,0xb73,0xb49,0xb49, +0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xd89,0xd89,0xd8c,0xd8f,0xd89,0xd80,0xd83,0xd83,0xd86, +0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xb82,0xb82,0xca2,0xc9f, +0xca2,0xc9f,0xca2,0xc9f,0xca2,0xc9f,0xca2,0xc9f,0xca2,0xc9f,0xca2,0xc9f,0xc90,0xc90,0xc96,0xc90, +0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xb91,0xb91,0xb91,0xb8e, +0xb8e,0xb8e,0xb8e,0xb8e,0xdec,0x102c,0x102c,0x102c,0x102c,0xfa5,0xfa5,0xfa5,0x102f,0xfa8,0xfa8,0x102f, +0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x1404,0x1404,0x1404,0x1404,0x14b8,0xb8e,0xb8e,0xb8e,0xb8e, +0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc51,0xc51,0xc51,0xc51, +0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0xba9,0xba6,0xba9,0xba9, +0xba9,0xba6,0xba6,0xba9,0xbac,0xbaf,0xbac,0xbaf,0xbac,0xc96,0xc96,0xc96,0xe10,0xc90,0xc96,0xc90, +0xba0,0xba3,0xba0,0xba6,0xc99,0xc99,0xc99,0xc99,0xcab,0xcae,0xe10,0xe10,0xbb2,0xbb5,0xbb5,0xbb5, +0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18, +0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0xbb5,0x177f,0x177f,0x1872,0xc0f,0xc0f,0xc0f,0xc0f, +0xbbe,0xbc4,0xbc7,0xbc4,0xbc7,0xbc4,0xbc7,0xbc4,0xbc7,0xbc4,0xbc7,0xbc4,0xbc4,0xbc4,0xbc7,0xbc4, +0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4,0xbc4, +0xbc4,0xbc4,0xbc4,0xbc4,0xc15,0xc0f,0xc0f,0xc0f,0xc0f,0xc0f,0xc0f,0xc12,0xc0f,0xc12,0xbbe,0xbbe, +0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8, +0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8, 0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7, -0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7,0xbf7, -0xbf7,0xbf7,0xbf7,0xbf7,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfa,0xbfa, 0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd, -0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfd,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa, -0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfa,0xbfd,0xbfd,0xbfd,0xbfd,0xc00,0xc00,0xc00,0xc00, -0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00, -0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc00,0xc06,0xc06,0xc06,0xc06, -0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06, -0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0xc06,0x1bdb, -0x1bdb,0x1bdb,0x1bdb,0x1bdb,0x1bdb,0x1bdb,0x1ca7,0x1ca7,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09, -0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09, -0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63, -0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc63,0xc60,0xc63, -0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xc60,0xd65, -0xd68,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xf78,0xf78,0xf78,0xf78, -0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b, -0xd6b,0xd6b,0xe5e,0xf18,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0x1083,0x1341,0x1341, -0xe67,0xe67,0xe67,0xe67,0xe67,0xe6d,0xe6a,0xf8a,0xf8a,0xf8a,0xf8a,0x14b8,0x1095,0x14b8,0x13fb,0x13fb, -0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2,0xca2, -0xca2,0xca2,0xccf,0xccc,0xccf,0xccc,0xccf,0xccc,0x11ca,0x11c7,0x109b,0x1098,0xca5,0xca5,0xca5,0xca5, -0xca5,0xca5,0xca5,0xca5,0xca5,0xca5,0xca5,0xca5,0xca5,0xca5,0xca5,0xca5,0xca8,0xca8,0xca8,0xca8, -0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8, -0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xca8,0xcab,0xcab,0xcab,0xcb1, -0xcae,0xcd5,0xcd2,0xcb1,0xcae,0xcb1,0xcae,0xcb1,0xcae,0xcb1,0xcae,0xcb1,0xcae,0xcb1,0xcae,0xcb1, -0xcae,0xcb1,0xcae,0xcb1,0xcae,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab, -0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab, -0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcb1,0xcae,0xcb1,0xcae,0xcab,0xcab,0xcab,0xcab, -0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab, -0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcab,0xcb1,0xcae,0xcab,0xcab,0xcb4,0xcb4,0xcb4,0xcb4, -0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcba,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4, -0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4, -0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcba,0xcba,0xcba,0xcb4, -0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4, -0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb4,0xcb7,0xcb4,0xcb4,0xcb4, -0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced, -0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced,0xced, -0xd6b,0xdd7,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xf18,0xf18,0xe5e,0xe5e,0xe5e,0xe5e, -0xe5e,0xe5e,0xf7b,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1365,0x1365,0x1344, -0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f, -0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f,0xd8f, -0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd95,0xd95,0xd95,0xd95,0xd95,0xd92,0xda7,0xda7,0xda7,0xda1, -0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda1,0xda7,0xda7,0xda7,0xda7, -0xd9b,0xd9b,0xda4,0xda4,0xda4,0xda4,0xd98,0xd98,0xd98,0xd98,0xd98,0xd9e,0xe73,0xe73,0xe73,0xe73, -0xe73,0xe73,0xe73,0xe73,0xe73,0xe73,0xe73,0xe73,0xe70,0xe73,0xe73,0xe73,0xe73,0xe73,0xe73,0xe73, -0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda1,0xda7, -0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xda7,0xd9b,0xd9b,0xd9b, -0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e, -0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e,0xd9e, -0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xdaa,0xe76,0xe76, -0xe76,0xe76,0xe76,0xe76,0xf8d,0xf8d,0xf8d,0xf8d,0xf8d,0xf8d,0xf8d,0x11d3,0x11d3,0x109e,0x109e,0x109e, -0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad, -0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad,0xdad, -0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3, -0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3,0xdb3, -0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc, -0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc,0xdbc, -0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8, -0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8,0xdc8, -0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4, -0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4, -0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c, -0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c, -0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82, -0xe82,0xe82,0xe82,0xe82,0xe82,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f, +0xbfa,0xbfa,0xbfa,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5, +0x11e5,0x11e5,0x11e5,0x11e5,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0xd86,0x12d5,0x12d5,0x12d5,0x12d5,0x12d5, +0x12d5,0x12d5,0x12d5,0x12d5,0x12d5,0x12d5,0x12d5,0x12d5,0x12d5,0x12db,0x1515,0x1515,0x1542,0x1515,0x17dc,0x1482, +0x1047,0xf3f,0xc06,0xc06,0xc27,0xc27,0xc27,0xc27,0xd6b,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27, +0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27, +0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc96,0xc90,0xc96,0xc90, +0xc96,0xc90,0xc96,0xc90,0xc33,0xc30,0xc30,0xca8,0xca5,0xfd8,0xfd2,0x1371,0xfcf,0xfcc,0x10a7,0x10a4, +0x11a0,0x11a0,0x11a6,0x11a0,0x11a6,0x11a0,0x11a6,0x11a0,0x11a6,0x11a0,0x11a6,0x11a0,0xc51,0xc51,0xc51,0xc51, +0xc51,0xc36,0xc36,0xc51,0xc51,0xc51,0xc51,0xc51,0xc51,0x116a,0x116a,0x116a,0xd6e,0xc36,0xc36,0xc36, +0xc36,0xf27,0xf18,0xf18,0xf18,0xf18,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0xc48,0xc48,0xc45,0xc3c, +0xc45,0xc3c,0xc45,0xc3c,0xc45,0xc3c,0xc4b,0xc4b,0xc4b,0xc4b,0xc5d,0xc5a,0xd5f,0xeee,0x1077,0x1074, +0x1074,0x1077,0x1071,0x1071,0x1071,0x1077,0x107a,0x107a,0x12b7,0x116d,0x116d,0x116a,0xc3f,0xc3f,0xc3f,0xc3f, +0xf2a,0xf2a,0xf1b,0xf1b,0xf1b,0xf18,0xf18,0xf18,0xf18,0xf1b,0x102c,0xf1b,0xf1b,0xf1b,0xf18,0xf1b, +0xf2a,0xf18,0xf18,0xf18,0xf1b,0xf1b,0xf18,0xf18,0xf1b,0xf18,0xf18,0xf1b,0xfba,0xfb7,0xc75,0xc6f, +0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc72,0xdda,0xd95,0xd95,0xd95,0xc6c, +0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0xd9b,0xd9b,0xc69,0xc7e,0xc75,0xc6f,0xc75,0xc6f, +0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f, +0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0xc75,0xc6f,0x118b,0x1188,0x118b,0x1188, +0x1194,0x1194,0x13e0,0x1119,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90, +0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90,0xc96,0xc90, +0xc96,0xc90,0xc96,0xc90,0xcae,0xc90,0xc90,0xc90,0xc90,0xc90,0xc90,0xc90,0xc90,0xc96,0xc90,0xc96, +0xc90,0xc96,0xc96,0xc90,0xccf,0xccf,0xda4,0xcc6,0xcc9,0xda4,0xda4,0xccc,0xccc,0xccc,0xccc,0xccc, +0xccc,0xda7,0xccf,0xccc,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xcc3,0xe19,0xe19, +0xe16,0xf4e,0xcc0,0xcc0,0xda4,0xccf,0xcc6,0xccc,0xccc,0xccf,0xccf,0xcc6,0xcc6,0xccc,0xccc,0xccc, +0xccc,0xccc,0xccf,0xccf,0xccf,0xda4,0xda4,0xda4,0xda4,0xccf,0xccf,0xccf,0xccf,0xccf,0xccf,0xccf, +0xccf,0xccf,0xccf,0xccf,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3, +0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3,0xcf3, +0xcf3,0xcf3,0xcf3,0xcf3,0xcf9,0xcf9,0xcf9,0xcf9,0xcf9,0xcf9,0xcf9,0xcf9,0xcf9,0xcf9,0xcfc,0xcfc, +0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc, +0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xdb6,0xdb6,0xdb6,0xdb6,0xdb6,0xdb9,0xdb9,0xdb9,0xd62,0xcff, +0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47, +0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b, +0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b, +0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd1d,0xd11,0xd23,0xd20, +0xd1a,0xd1a,0xd1a,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17, +0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17,0xd17, +0xd17,0xd17,0xd17,0xd17,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26, +0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26, +0xd26,0xd26,0xd26,0xd26,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35, +0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd38,0xd38,0xd38,0xd3b, +0xd38,0xd38,0xd3e,0xd3e,0xd4d,0xd4d,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50, +0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50, +0xd50,0xd50,0xd50,0xd50,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d,0xd4d, +0xd5c,0xd59,0xdce,0xdce,0xdce,0xdce,0xd59,0xd59,0xdce,0xdce,0xdd1,0x1122,0x111f,0x111f,0xd5c,0xd5c, +0xd56,0xd56,0xd56,0xd56,0xd56,0xd56,0xd56,0xd56,0xd56,0xd56,0x10bf,0x10bf,0x10bf,0x10bf,0x10bf,0x10bf, +0xdce,0xdce,0xd59,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c, +0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c,0xd5c, +0xd74,0xd74,0xd74,0xd74,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0x1110,0x13d4,0x13d4,0x13d4, +0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509, +0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98, +0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98, +0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf09,0xf09,0xf09,0xde9,0x1545, +0x101a,0xf15,0x101a,0x101a,0x101a,0x101a,0x101a,0x101a,0x101a,0x101a,0x101a,0x101a,0x101a,0xf15,0x101a,0xf15, +0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b,0xf4b, +0xf4b,0xf96,0xe07,0xf00,0xe07,0xe07,0xe07,0xe07,0xe01,0xe01,0xe01,0xe07,0x1368,0x136b,0x155a,0x15ea, +0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c, +0xe1f,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe13,0xe13,0xe13,0xe1c,0xe19,0x12ed,0x11af,0x11b5,0x11b5, +0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25, +0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25, +0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e, +0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e, +0xe34,0xe34,0xe34,0xe31,0xe31,0xe31,0xe2e,0xe2e,0xe2e,0xe2e,0xe31,0xe2e,0xe2e,0xe2e,0xe34,0xe31, +0xe34,0xe31,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e, +0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe34,0xe31,0xe31, +0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0x1800, +0x163b,0x163b,0x163b,0x163b,0x163b,0x163b,0x163b,0x163e,0x1638,0x17f7,0x17f7,0x17f7,0x17fa,0x17f4,0x17fa,0x17f4, +0xf51,0xf51,0xf51,0xe40,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43, +0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43, +0xe43,0xe43,0xe43,0xf54,0xe40,0xe40,0xf51,0xf51,0xf51,0xf51,0xe40,0xe40,0xf51,0xf51,0xe40,0xe40, +0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49, +0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49, +0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, +0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, +0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d, +0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d,0xe6d, 0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82, 0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82,0xe82, -0xf48,0xf48,0xe94,0xe94,0xf90,0xf90,0xf90,0xf90,0xf90,0xf90,0xf90,0x10ad,0x10ad,0x10b0,0x10b3,0x10ad, -0x10a7,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa, -0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0, -0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0,0xea3,0xea0, -0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf, -0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf,0xeaf, -0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0x1c1d, -0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2, -0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0x1c1a, +0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8e,0xe8b,0xe8b,0xe8b,0xe8b, +0xe88,0xe88,0xe88,0xf6c,0xf6c,0xf6c,0xf6c,0xe88,0xe88,0xf72,0xf6f,0xe85,0xe85,0xe94,0xe91,0xe91, +0xf6c,0xf6c,0xe88,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b, +0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8b,0xe8e,0xe8b,0xe8e,0xe8b,0xe8b,0xe8b, +0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xea9, +0xea9,0xea9,0xea9,0xea9,0xea9,0xea9,0xf78,0xf78,0xf7b,0xf7b,0xea9,0xf78,0xf78,0xf78,0xf78,0xf78, 0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5, 0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5, -0xf42,0xf42,0xf42,0xf42,0xf42,0xf42,0xf42,0xf42,0xecd,0xecd,0xecd,0xecd,0xecd,0xecd,0xecd,0xecd, -0xecd,0xecd,0xecd,0xecd,0xecd,0xecd,0xecd,0xf93,0xf93,0xf93,0xf93,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6, -0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6, -0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6,0xed6, -0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf, -0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf,0xedf, -0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8, -0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee8,0xee2, -0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5, -0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee5,0xee8,0xee8,0xee8,0xee8,0xee8, -0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef4,0xef1,0xef1, -0xef1,0xef1,0xef1,0xef1,0xef1,0xef1,0xeee,0xef7,0x10c2,0x10bc,0x10ce,0x10b9,0xeeb,0xeeb,0x10b9,0x10b9, -0xf06,0xf06,0xefa,0xf06,0xf06,0xf06,0xefd,0xf06,0xf06,0xf06,0xf06,0xefa,0xf06,0xf06,0xf06,0xf06, +0xf7e,0xeb5,0xf7e,0xf7e,0xf7e,0xebe,0xebe,0xf7e,0xf7e,0xebe,0xeb5,0xebe,0xebe,0xeb5,0xf7e,0xf81, +0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7, +0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7,0xec7, +0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0, +0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xed0,0xecd,0xed3, +0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9, +0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed9,0xed6,0xed6,0xed6, +0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0xf03,0xf03,0xf03,0xf03,0x101d,0x1011, +0xf0f,0x101d,0x101d,0x101d,0x101d,0x101d,0x101d,0x101d,0x101d,0x101d,0x101d,0x1470,0x1470,0x1470,0x1470,0x1470, +0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0x114f,0x114f,0x16a4,0x16a4,0x16a4, 0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06, -0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09, -0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09, -0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24, -0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24, -0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45,0xf45, -0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9, -0xf78,0xf78,0xf78,0xf75,0xf75,0xf75,0xf75,0xf75,0x1215,0x146a,0x146a,0x146a,0x146a,0x13e6,0x13e6,0x13e6, -0x146d,0x13e9,0x13e9,0x146d,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x1884,0x1884,0x1884,0x1884,0x194a, -0xf8d,0xf8d,0xf8d,0xf8d,0x109e,0x109e,0x109e,0x109e,0x109e,0x109e,0x109e,0x109e,0x109e,0x109e,0x109e,0x109e, -0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1, -0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2, -0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d5,0x1953,0x1953,0x19d4,0x1953,0x1cc5,0x188a,0x13fe,0x121e,0xf90,0xf90, -0xfb1,0xfb1,0xfb1,0xfb1,0xfc6,0xfcf,0xfd2,0xfcf,0xfd2,0xfcf,0xfd2,0xfcf,0xfd2,0xfcf,0xfd2,0xfcf, -0xfcf,0xfcf,0xfd2,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf, -0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfcf,0xfb4,0xfb1,0xfb1,0xfb1,0xfb1,0xfb1,0xfb1,0xfc9, -0xfb1,0xfc9,0xfc6,0xfc6,0xfe1,0xfde,0xfe1,0xfe1,0xfe1,0xfde,0xfde,0xfe1,0xfe4,0xfe7,0xfe4,0xfe7, -0xfe4,0x10da,0x10da,0x10da,0x1236,0x10d7,0x10da,0x10d7,0xfd8,0xfdb,0xfd8,0xfde,0x10dd,0x10dd,0x10dd,0x10dd, -0x10e0,0x10e3,0x1236,0x1236,0xfea,0xfea,0x10f8,0x10f5,0x10f8,0x10f5,0x10f8,0x10f5,0x10f8,0x10f5,0x10f8,0x10f5, -0x10f8,0x10f5,0x10f8,0x10f5,0x10ec,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec, -0x10f2,0x10ec,0x10f2,0x10ec,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0, +0x101a,0x101a,0xf15,0x101a,0x101a,0x101a,0xf15,0x101a,0x101a,0x101a,0xf0f,0xf0f,0xf0f,0xf0f,0xf0f,0x1014, +0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0xf12,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0xf12, +0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x106e,0x106e,0x1614,0x16a4,0x16a4,0x16a4, +0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0x1017,0xf12,0x1017,0xf12,0xf12,0x1017,0x1017,0xf12, +0xf1b,0xf1b,0xfa5,0xf18,0xfa5,0xfa5,0xfa5,0xfa5,0xf18,0xf18,0xf2a,0xf18,0xf18,0xf18,0xf18,0xf18, +0xf18,0xf1b,0xf2a,0xf2a,0xf1b,0xf2a,0xf18,0xf1b,0xf1b,0xf1e,0xf2a,0xf18,0xf18,0xf2a,0xf1b,0xf1b, +0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30, +0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30, +0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99, +0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99, +0xfcf,0xfcc,0xfcf,0xfcc,0xfcf,0xfcc,0xfcf,0xfcc,0xfcf,0xfcc,0x10a7,0x11a6,0x11a6,0x11a6,0x1419,0x1569, +0x11a6,0x11a6,0x1374,0x1374,0x1374,0x136e,0x1374,0x136e,0x156f,0x156c,0x1623,0x1620,0x1623,0x1620,0x1623,0x1620, 0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0, -0xff0,0xff0,0xff0,0xff0,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff, +0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0,0xff0, +0xffc,0x1062,0xffc,0x1002,0x1002,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff, 0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff, -0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3, -0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005, -0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005, -0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1005,0x1053,0x106b,0x1062,0x1068,0x1068,0x106b,0x106b,0x1062, -0x1062,0x1068,0x1068,0x1068,0x1068,0x1068,0x106b,0x106b,0x106b,0x1053,0x1053,0x1053,0x1053,0x106b,0x106b,0x106b, -0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x1053,0x1062,0x1065,0x1053,0x1053,0x1068, -0x1068,0x1068,0x1068,0x1068,0x1068,0x1056,0x106b,0x1068,0x105f,0x105f,0x105f,0x105f,0x105f,0x105f,0x105f,0x105f, -0x105f,0x105f,0x11fd,0x11fd,0x11fa,0x11f7,0x105c,0x105c,0x1086,0x1086,0x1086,0x1086,0x1365,0x1365,0x1344,0x1344, -0x1344,0x1341,0x1341,0x1341,0x1341,0x1344,0x1470,0x1344,0x1344,0x1344,0x1341,0x1344,0x1365,0x1341,0x1341,0x1341, -0x1344,0x1344,0x1341,0x1341,0x1344,0x1341,0x1341,0x1344,0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x109e,0x109e,0x10a1, -0x10a1,0x10a1,0x10a1,0x10a1,0x10a1,0x15cc,0x15cc,0x15cc,0x11d3,0x109e,0x109e,0x109e,0x109e,0x1371,0x134d,0x134d, -0x134d,0x134d,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x10c8,0x10c8,0x10c5,0x10bf,0x10c5,0x10bf,0x10c5,0x10bf, -0x10c5,0x10bf,0x10cb,0x10cb,0x10cb,0x10cb,0x10d4,0x10d1,0x10cb,0x1233,0x14ca,0x14c7,0x14c7,0x14ca,0x14c4,0x14c4, -0x14c4,0x14ca,0x14cd,0x14cd,0x15e7,0x15db,0x15db,0x15d8,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec, -0x10e9,0x10e6,0x10e6,0x10fe,0x10fb,0x1410,0x140d,0x17d9,0x140a,0x1407,0x14d6,0x14d3,0x15ea,0x15ea,0x15f0,0x15ea, -0x15f0,0x15ea,0x15f0,0x15ea,0x15f0,0x15ea,0x15f0,0x15ea,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec, -0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec, -0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x1101,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec, -0x10ec,0x10f2,0x10ec,0x10f2,0x10ec,0x10f2,0x10f2,0x10ec,0x1104,0x1104,0x110a,0x1110,0x1110,0x1110,0x1110,0x1110, -0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110, -0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x110a,0x1104,0x1104,0x1104,0x1104,0x110a,0x110a, -0x1104,0x1104,0x110d,0x14df,0x14dc,0x14dc,0x1110,0x1110,0x1107,0x1107,0x1107,0x1107,0x1107,0x1107,0x1107,0x1107, -0x1107,0x1107,0x14e2,0x14e2,0x14e2,0x14e2,0x14e2,0x14e2,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125, -0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125, -0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x1125,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e, -0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e,0x112e, -0x1131,0x1131,0x1131,0x1134,0x1131,0x1131,0x1137,0x1137,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a, -0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a, -0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143, -0x1143,0x1143,0x1143,0x1143,0x1149,0x113d,0x114f,0x114c,0x1146,0x1146,0x1146,0x1143,0x1143,0x1143,0x1143,0x1143, -0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143, -0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1416,0x1413,0x1164,0x115e, -0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1161,0x11e5,0x1152,0x1152,0x1152,0x115b, -0x14e5,0x14e5,0x14e5,0x14e5,0x14e5,0x14e5,0x14e5,0x14e5,0x1155,0x1155,0x1158,0x1167,0x1164,0x115e,0x1164,0x115e, -0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e, -0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x1164,0x115e,0x15ff,0x15fc,0x15ff,0x15fc, -0x1602,0x1602,0x17e2,0x14e5,0x1170,0x1170,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173, -0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173,0x1173, -0x1173,0x1173,0x1173,0x1173,0x1170,0x1170,0x1170,0x1170,0x1170,0x1170,0x1170,0x1170,0x1170,0x1170,0x1170,0x1170, -0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1179,0x1179,0x1179,0x1179,0x1179,0x117c,0x117c,0x117c,0x11dc,0x1185, -0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194,0x1194, -0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182, -0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182, -0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6, -0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6, -0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8, -0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8,0x11b8, -0x11c1,0x11c1,0x11c1,0x11c1,0x11d6,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1, -0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1, -0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4, -0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4,0x11c4, -0x11d0,0x11d0,0x11d0,0x11d0,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x156f,0x1863,0x1863,0x1863, -0x1863,0x1863,0x1863,0x1863,0x1863,0x1863,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3, +0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e, +0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e, +0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x100e,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1020,0x1020,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1020,0x1023,0x1023,0x1023,0x1020,0x1023,0x1020,0x1023,0x1020,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1026,0x1023,0x1023,0x1023,0x1023,0x1020,0x1023,0x1020,0x1020,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1020, +0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020,0x1020, +0x1020,0x1020,0x1152,0x1152,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155, +0x1155,0x13ce,0x13ce,0x13ce,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1155,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1155,0x13ce,0x13ce,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1026,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1152,0x1152,0x1155,0x1155,0x1023,0x1023,0x1026,0x1026, +0x1026,0x12c6,0x1023,0x1026,0x1023,0x1023,0x1026,0x1164,0x1164,0x1155,0x1155,0x13ce,0x13ce,0x13ce,0x13ce,0x13ce, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1155,0x1155,0x1155, +0x12c6,0x1155,0x1155,0x1155,0x13ce,0x13ce,0x13ce,0x13fe,0x13fe,0x13fe,0x13fe,0x13fe,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1155,0x1023,0x1155,0x1026,0x1026, +0x1023,0x1023,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1026,0x1026, +0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026,0x1026, +0x1026,0x1023,0x1023,0x1023,0x1026,0x1023,0x1023,0x1023,0x1023,0x1026,0x1026,0x1026,0x1023,0x1026,0x1026,0x1026, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1026,0x1023,0x1026,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x12c6,0x1023,0x1023,0x1023,0x1023,0x1155,0x1155,0x13ce,0x106b,0x106b,0x106b,0x106b, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1155,0x13ce,0x13ce,0x13ce,0x13ce,0x1356,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1155,0x1155,0x1155,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1164,0x1164,0x1155,0x1155,0x1155,0x1155,0x1476,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1155,0x1023,0x1023,0x1023,0x1023,0x1023, +0x110a,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x110a,0x1023,0x1023,0x1023,0x110a,0x1023,0x110a,0x1023,0x110a,0x1023,0x110a,0x1023,0x1023,0x1023,0x110a, +0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x110a,0x110a,0x1023,0x1023,0x1023,0x1023,0x110a,0x1023,0x110a,0x110a, +0x1023,0x1023,0x1023,0x1023,0x110a,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x12c6,0x12c6,0x13ce,0x13ce,0x1026,0x1026,0x1026,0x1023,0x1023,0x1023,0x1026,0x1026,0x1026,0x1026,0x1026, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0x1023,0x1023,0x1023,0x1026,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1023,0x1023,0x1023,0x1023,0x1026,0x1026,0x1026,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023,0x1023, +0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038, +0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038, +0x103e,0x103b,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c, +0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c, +0x1083,0x117f,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x117c,0x117c,0x117c, +0x117c,0x117c,0x117f,0x135f,0x135f,0x1746,0x140d,0x140d,0x140d,0x140d,0x140d,0x140d,0x140d,0x140d,0x16b0,0x16b0, +0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0, +0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0, +0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3, +0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x1641, +0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6, +0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6, +0x112b,0x112b,0x112b,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7, +0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7, +0x1137,0x10ec,0x10ef,0x10ef,0x10ec,0x10f2,0x10f2,0x10e0,0x10e3,0x13ef,0x13f2,0x13f2,0x13f2,0x125d,0x16ce,0x1716, +0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x125a,0x1398,0x139b,0x1395,0x139e,0x139e, +0x1134,0x1134,0x10e9,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec, +0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec, +0x10ec,0x10ec,0x10ec,0x10e9,0x10e9,0x10e9,0x1134,0x1134,0x1134,0x1134,0x1134,0x1134,0x1134,0x1134,0x1134,0x10e9, +0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101, +0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101,0x1101, +0x1485,0x1485,0x140a,0x13dd,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113, +0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x1116,0x12e1, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1155,0x1155,0x1155,0x1155, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1161,0x1161,0x1161,0x1158,0x1158,0x1158,0x1152,0x1152,0x1152,0x1152, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152, +0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1152,0x1155,0x1155,0x1155,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1164,0x1155,0x1155,0x1155, +0x1155,0x12c9,0x12c9,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1473,0x1155,0x1155,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155, +0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x1155,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0, +0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0, +0x11a0,0x11a0,0x11a0,0x1167,0x11a9,0x11a9,0x11a9,0x11a9,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a, +0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a, +0x116a,0x116a,0x154e,0x154e,0x154e,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a, +0x116a,0x1617,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x116a,0x14b8,0x154e,0x154e,0x154e,0x154e,0x154e, +0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3, +0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x12f6,0x12f6,0x12f6,0x12f6,0x12f6,0x12f6,0x12f6,0x11d9, +0x11d9,0x11cd,0x11ca,0x11ca,0x11ca,0x11ca,0x11ca,0x11ca,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3, +0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3, +0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11d3,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc, +0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc, +0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11dc,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1, +0x11e8,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1, +0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x11f1,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206, +0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206, +0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x1206,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c, +0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c, +0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x120c,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224, +0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224, +0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a, +0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a, +0x122a,0x122a,0x122a,0x122a,0x122a,0x1227,0x1227,0x1227,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236, +0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x1233, +0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f, +0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f, +0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x1314,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248, 0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248, -0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x123f,0x123f,0x1242,0x1242,0x1248,0x123f,0x123f,0x123f,0x123f,0x123f, -0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e, +0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e, 0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e, -0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269, -0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269, -0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275, -0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1275,0x1272,0x1278, -0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284, -0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284, -0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a, -0x128a,0x13b6,0x1290,0x13b9,0x1290,0x1290,0x1290,0x1290,0x128d,0x128d,0x128d,0x1290,0x17e5,0x17e8,0x1a13,0x1a10, -0x1293,0x1293,0x1293,0x12a2,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8, -0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8, -0x12a8,0x12a8,0x12a8,0x1296,0x12a2,0x12a2,0x1293,0x1293,0x1293,0x1293,0x12a2,0x12a2,0x1293,0x1293,0x12a2,0x12a2, -0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4, -0x12b7,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12b4,0x12ae,0x12ae,0x12ae,0x12b4,0x12b1,0x1608,0x160b,0x160e,0x160e, -0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6, -0x12ba,0x12c6,0x12ba,0x12ba,0x12ba,0x12cf,0x12cf,0x12ba,0x12ba,0x12cf,0x12c6,0x12cf,0x12cf,0x12c6,0x12ba,0x12bd, -0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6, -0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6,0x12c6, -0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1, -0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1,0x12e1, -0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9, -0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9,0x12f6,0x12f6,0x12f6, -0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302, -0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302,0x1302, -0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311, -0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311, -0x1317,0x1317,0x1323,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326, -0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1329,0x1326,0x1329,0x1326,0x1326,0x1326, -0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1326,0x1329,0x1326,0x1326,0x1326,0x1326, -0x1323,0x1323,0x1323,0x1317,0x1317,0x1317,0x1317,0x1323,0x1323,0x131d,0x131a,0x1320,0x1320,0x132f,0x132c,0x132c, -0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332, -0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332, -0x1338,0x1338,0x1338,0x1335,0x1335,0x1335,0x1332,0x1332,0x1332,0x1332,0x1335,0x1332,0x1332,0x1332,0x1338,0x1335, -0x1338,0x1335,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332, -0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1338,0x1335,0x1335, -0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1332,0x1cce, -0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1af1,0x1aeb,0x1ce0,0x1ce0,0x1ce0,0x1ce3,0x1cdd,0x1ce3,0x1cdd, -0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1356,0x1356,0x1356,0x133b,0x1a19, -0x1467,0x135f,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x135f,0x1467,0x135f, -0x1344,0x1344,0x13ec,0x1341,0x13ec,0x13ec,0x13ec,0x13ec,0x1341,0x1341,0x1365,0x1341,0x1341,0x1341,0x1341,0x1341, -0x1341,0x1344,0x1365,0x1365,0x1344,0x1365,0x1341,0x1344,0x1344,0x1347,0x1365,0x1341,0x1341,0x1365,0x1344,0x1344, -0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1350,0x1350,0x1350,0x1350,0x147c,0x145e, -0x1359,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x1914,0x1914,0x1914,0x1914,0x1914, -0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1611,0x1611,0x1b75,0x1b75,0x1b75, -0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353, -0x1467,0x1467,0x135f,0x1467,0x1467,0x1467,0x135f,0x1467,0x1467,0x1467,0x1359,0x1359,0x1359,0x1359,0x1359,0x1461, -0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x135c,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x135c, -0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x14e8,0x14e8,0x1acd,0x1b75,0x1b75,0x1b75, -0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x135c,0x1464,0x135c,0x135c,0x1464,0x1464,0x135c, -0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, +0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x124e,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1266,0x1266,0x1266,0x131d,0x131d,0x131d,0x1266,0x1266,0x131d,0x1326,0x1320,0x1323, +0x126c,0x126c,0x1263,0x126c,0x126c,0x1260,0x1491,0x1803,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b, +0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x1329,0x1275,0x1275,0x1329,0x1329,0x1329,0x1329,0x1329, +0x1329,0x1275,0x1329,0x1278,0x1278,0x1329,0x1278,0x1329,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b, +0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b, +0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x127b,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281, +0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281, +0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296, +0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1293,0x1293,0x1293,0x1335,0x1335,0x1335,0x1335,0x1335, +0x1335,0x1335,0x1335,0x1293,0x1293,0x1335,0x1293,0x1338,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296, +0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296, +0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x1296,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c, +0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c, +0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae, +0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae, +0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e, +0x154e,0x154e,0x154e,0x154e,0x135c,0x135c,0x135c,0x135c,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e, +0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x154e,0x1617,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362, +0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362, +0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d, +0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d, +0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, 0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, -0x140a,0x1407,0x140a,0x1407,0x140a,0x1407,0x140a,0x1407,0x140a,0x1407,0x14d6,0x15f0,0x15f0,0x15f0,0x1890,0x1a04, -0x15f0,0x15f0,0x17dc,0x17dc,0x17dc,0x17d6,0x17dc,0x17d6,0x1a0a,0x1a07,0x1ac4,0x1ac1,0x1ac4,0x1ac1,0x1ac4,0x1ac1, -0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434, -0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434, -0x1449,0x143a,0x1449,0x144f,0x144f,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c, -0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c, -0x143a,0x143a,0x143a,0x143a,0x143a,0x143a,0x143a,0x143a,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455, -0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455, -0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b, -0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b, -0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x1485,0x1482,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9, -0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9, -0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148b,0x148b,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148b,0x148e,0x148e,0x148e,0x148b,0x148e,0x148b,0x148e,0x148b,0x148e,0x148e,0x148e, -0x148e,0x148e,0x1491,0x148e,0x148e,0x148e,0x148e,0x148b,0x148e,0x148b,0x148b,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148b, -0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b, -0x148b,0x148b,0x161a,0x161a,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d, -0x161d,0x1866,0x1866,0x1866,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x161d,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x161d,0x1866,0x1866,0x148e,0x148e,0x148e,0x148e, -0x148e,0x1491,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161a,0x161a,0x161d,0x161d,0x148e,0x148e,0x1491,0x1491, -0x1491,0x1791,0x148e,0x1491,0x148e,0x148e,0x1491,0x1620,0x1620,0x161d,0x161d,0x1866,0x1866,0x1866,0x1866,0x1866, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x161d,0x161d,0x161d, -0x1791,0x161d,0x161d,0x161d,0x1866,0x1866,0x1866,0x1869,0x1869,0x1869,0x1869,0x1869,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x161d,0x148e,0x161d,0x1491,0x1491, -0x148e,0x148e,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x1491,0x1491, -0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491, -0x1491,0x148e,0x148e,0x148e,0x1491,0x148e,0x148e,0x148e,0x148e,0x1491,0x1491,0x1491,0x148e,0x1491,0x1491,0x1491, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x1491,0x148e,0x1491,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x1791,0x148e,0x148e,0x148e,0x148e,0x161d,0x161d,0x1866,0x14eb,0x14eb,0x14eb,0x14eb, -0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161d,0x1866,0x1866,0x1866,0x1866,0x17eb,0x148e,0x148e,0x148e,0x148e, -0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x148e,0x161d,0x161d,0x161d,0x161d, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x1620,0x1620,0x161d,0x161d,0x161d,0x161d,0x191d,0x161d, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d, -0x161d,0x161d,0x161d,0x161d,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161d,0x148e,0x148e,0x148e,0x148e,0x148e, -0x1575,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494, -0x1494,0x1575,0x1494,0x1494,0x1494,0x1575,0x1494,0x1575,0x1494,0x1575,0x1494,0x1575,0x1494,0x1494,0x1494,0x1575, -0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1575,0x1575,0x1494,0x1494,0x1494,0x1494,0x1575,0x1494,0x1575,0x1575, -0x1494,0x1494,0x1494,0x1494,0x1575,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494,0x1494, -0x1494,0x1797,0x1797,0x186c,0x186c,0x1497,0x1497,0x1497,0x1494,0x1494,0x1494,0x1497,0x1497,0x1497,0x1497,0x1497, -0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716, -0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a, -0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a, -0x149a,0x149a,0x149a,0x149d,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a, -0x149a,0x149a,0x149a,0x149a,0x149d,0x149d,0x149d,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a, -0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0, -0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0,0x14a0, -0x1899,0x1899,0x1896,0x17ee,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14ee,0x14ee,0x14ee,0x14ee,0x14ee,0x14ee, -0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x1626, -0x14f4,0x162c,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x1629,0x1629,0x1629, -0x1629,0x1629,0x162c,0x17f1,0x17f1,0x1c4a,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x1b78,0x1b78, -0x14fd,0x14fd,0x14fd,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f, +0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383, +0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383, +0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386, +0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386, +0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9, +0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x1386, +0x1386,0x1386,0x1386,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9, +0x13e9,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x13e9,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386, +0x1386,0x1386,0x1386,0x1386,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392, +0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392,0x1392, +0x1392,0x1392,0x1392,0x1392,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1, +0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1, +0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a7,0x13a4,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1, +0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x13a1,0x14af,0x14af,0x14af,0x14af,0x14af,0x14af,0x14af,0x14af, +0x14af,0x14af,0x14af,0x14af,0x16fb,0x167a,0x167a,0x167d,0x13ce,0x13ce,0x13ce,0x13ce,0x13ce,0x13ce,0x13ce,0x13ce, +0x13d1,0x1476,0x1476,0x1476,0x1476,0x1476,0x1476,0x1503,0x13ce,0x13ce,0x13ce,0x13ce,0x13ce,0x1473,0x1473,0x1473, +0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x13ce,0x15d5,0x15d5,0x167a,0x167a,0x167a,0x167a,0x167a, +0x167a,0x167a,0x167a,0x16f8,0x17a6,0x167d,0x167d,0x167d,0x1500,0x1503,0x1503,0x1503,0x1503,0x1503,0x1503,0x1503, +0x1503,0x1503,0x1503,0x1503,0x1503,0x1503,0x1500,0x1500,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4, +0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4, +0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13d4,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9, +0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9, +0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x13e9,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1476,0x1473, +0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,0x1476,0x1503,0x1503,0x1476,0x1476,0x1476,0x1476,0x1476, +0x1476,0x1476,0x1473,0x1401,0x1476,0x1476,0x1476,0x167a,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1401,0x1473, +0x1473,0x1473,0x1473,0x1473,0x1500,0x15d5,0x15d5,0x15d5,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473, +0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1473,0x1500,0x142e,0x142e,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b, +0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b, +0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142b,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e, +0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e, +0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461, +0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x145e,0x145e,0x145e, +0x14a6,0x14a6,0x14a6,0x14a6,0x14a6,0x14a6,0x14a6,0x14a6,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461, +0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461, +0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c, +0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c, +0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x1704,0x1704,0x1704,0x1704,0x1704, +0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x1704,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0, +0x1746,0x1749,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x15e4,0x1488,0x1488,0x1488,0x1488, +0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x14df,0x14df,0x14df,0x14df,0x1650,0x1650,0x14e2,0x14e2, +0x14e2,0x14e2,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x14dc, +0x1533,0x1536,0x14d3,0x14e5,0x14e5,0x158a,0x14d6,0x14d6,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df, +0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df, +0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x1539,0x153f,0x153c,0x153c,0x153c, +0x153c,0x14f1,0x14f7,0x153c,0x153c,0x153c,0x153c,0x14ee,0x14f4,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, +0x153c,0x153c,0x153c,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500, +0x1500,0x1500,0x1500,0x1500,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x167a,0x16f8,0x15d5,0x15d5,0x15d5,0x15d5,0x16fb, +0x16f8,0x17a6,0x15d5,0x167a,0x15d5,0x15d5,0x15d5,0x15d5,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,0x1500,0x15d5, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509, +0x1509,0x1509,0x1509,0x15de,0x15de,0x15de,0x15de,0x15de,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701, +0x1701,0x1701,0x1701,0x1701,0x1701,0x17ac,0x17ac,0x17ac,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509, +0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509, +0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x1509,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c, +0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c, +0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x150c,0x17af,0x150f,0x150f,0x150f,0x150f, 0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f, -0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a, -0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a,0x152a, -0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530, -0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1530,0x1ad3, -0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533, -0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533,0x1533, -0x1539,0x1539,0x1545,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b, -0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b, -0x154b,0x154b,0x154b,0x1545,0x1545,0x1545,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x1545, -0x1548,0x154b,0x154e,0x154e,0x154b,0x1551,0x1551,0x153c,0x153f,0x17f7,0x17fa,0x17fa,0x17fa,0x1632,0x1b81,0x1b7e, -0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x162f,0x1800,0x1803,0x17fd,0x1806,0x1806, -0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c, -0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c, -0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc, -0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x19ec,0x19ec,0x19ec,0x15cc,0x15cc,0x15cc, -0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x1abb,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc,0x15cc, -0x15cc,0x15cc,0x1950,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d, -0x161d,0x161d,0x161d,0x161d,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161d,0x161d,0x161d,0x161d, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x1620,0x161d,0x161d,0x161d, -0x161d,0x1794,0x1794,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x191a,0x161d,0x161d,0x161d, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d, -0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, -0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641, -0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653, -0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653, -0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1653,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659, -0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659, -0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c, +0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x150f,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1593,0x1593,0x1593,0x1593, +0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593, +0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x1593,0x15b1,0x15b1,0x15b1,0x15b1, +0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1, +0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b4,0x15b4,0x15b4,0x15b4, +0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4, +0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15b4,0x15bd,0x15bd,0x15bd,0x15bd, +0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd, +0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15bd,0x15cf,0x15cf,0x15cf,0x15cf, +0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf, +0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cc,0x15cc,0x15cc,0x15d5,0x15d5,0x15d5,0x16f8, +0x16f8,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x16f8,0x16f8,0x16f8,0x167a,0x167a,0x15d5,0x15d5,0x15d5,0x15d5, +0x15d5,0x15d8,0x15d8,0x15d5,0x15d8,0x15d8,0x167a,0x167d,0x167a,0x167a,0x167a,0x167a,0x1611,0x1611,0x1611,0x1611, +0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611, +0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x162c,0x162c,0x162c,0x162c, +0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x1677,0x1677,0x162c,0x1677, +0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x162c,0x1632,0x1632,0x1632,0x165c,0x165c,0x165c,0x165c, 0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c, -0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c, -0x168c,0x168c,0x168c,0x168c,0x1686,0x1686,0x1686,0x167a,0x167a,0x167a,0x1686,0x1686,0x167a,0x1689,0x167d,0x167a, -0x168f,0x168f,0x1683,0x168f,0x168f,0x1680,0x18a2,0x1cda,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1, -0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1, -0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x1692,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa, -0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa, -0x16aa,0x16aa,0x16aa,0x16a4,0x16ad,0x16ad,0x16ad,0x16ad,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0, -0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0, -0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb, -0x16c2,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb, -0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16cb,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4, -0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4, -0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6, -0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e3,0x16e3,0x16e3,0x16d7,0x16d7,0x16d7,0x16d7,0x16d7, -0x16d7,0x16d7,0x16d7,0x16e3,0x16e3,0x16d7,0x16e3,0x16da,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6, -0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6, -0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x16e6,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d, -0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d,0x170d, -0x170d,0x170d,0x170d,0x170d,0x170d,0x170a,0x170a,0x170a,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716, -0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x171c,0x171c, -0x171c,0x1719,0x1719,0x1719,0x1716,0x1716,0x1716,0x1716,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b, -0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x171f,0x171f,0x171f,0x171f,0x171f,0x171f,0x171f,0x1731, -0x1731,0x1725,0x1722,0x1722,0x1722,0x1722,0x1722,0x1722,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b, -0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b, -0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737, -0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1734, -0x1734,0x1734,0x1734,0x1734,0x1734,0x1734,0x1734,0x1734,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a, -0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a, -0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e, -0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e, -0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f, -0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x176a,0x1779,0x1779,0x176a,0x176a,0x176a,0x176a,0x176a, -0x176a,0x1779,0x176a,0x177c,0x177c,0x176a,0x177c,0x176a,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f, -0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f, -0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x177f,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788, -0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788, -0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e, +0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x1671,0x1671,0x1671,0x1671, +0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671, +0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x16a4,0x16a4,0x16a4,0x16a4, +0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4, +0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x1854, +0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854, +0x1854,0x1854,0x1854,0x1854,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5, +0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5,0x16f5, +0x16f5,0x16f5,0x16f5,0x16f5,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x17a6,0x17a6,0x17a6, +0x17a6,0x181e,0x181e,0x181e,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x16f8,0x17a6,0x17a6,0x17a6,0x17a6,0x181e, +0x181e,0x181e,0x18e1,0x181e,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701, +0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701,0x1701, +0x1701,0x1701,0x1701,0x1701,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, +0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, +0x1707,0x1707,0x1707,0x1707,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731, +0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731,0x1731, +0x1731,0x1731,0x1731,0x1731,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e, 0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e, -0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x178e,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec, -0x19ec,0x19ec,0x19ec,0x19ec,0x17d3,0x17d3,0x17d3,0x17d3,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec, -0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x1abb,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4, -0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4, -0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833, -0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833, -0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1839,0x1836,0x1833,0x1833,0x1833,0x1833, -0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x183c,0x183c,0x183c,0x183c, -0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c, -0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183c,0x183f,0x183f,0x183f,0x183f, -0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, -0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x1851,0x1851,0x1851,0x1851, -0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851, -0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1854,0x1854,0x1854,0x1854, +0x178e,0x178e,0x178e,0x178e,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, +0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, +0x179a,0x179a,0x179a,0x179a,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb, +0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb,0x17bb, +0x17bb,0x17bb,0x17bb,0x17bb,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e8, +0x17e8,0x17e8,0x17e8,0x17e8,0x17e8,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5, +0x17e5,0x17e5,0x17e5,0x17e5,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824, +0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824, +0x1824,0x1824,0x1824,0x1824,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b, +0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b,0x184b, +0x184b,0x184b,0x184b,0x184b,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854, 0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854, -0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1857,0x1857,0x1857,0x1857, -0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857, -0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x185a, -0x185a,0x185a,0x185a,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857, -0x1857,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x1857,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a, -0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a, -0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x185a,0x1872,0x1872,0x1872,0x1872, -0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872, -0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x195c,0x195c,0x195c,0x195c, -0x195c,0x195c,0x195c,0x195c,0x195c,0x195c,0x195c,0x195c,0x1be4,0x1b33,0x1b33,0x1b36,0x1875,0x1875,0x1875,0x1875, -0x1875,0x1875,0x1875,0x1875,0x1878,0x1926,0x1926,0x1926,0x1926,0x1926,0x1926,0x19c2,0x1875,0x1875,0x1875,0x1875, -0x1875,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x19bf,0x19bf, -0x19bf,0x19bf,0x19bf,0x19bf,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1875,0x1aa6,0x1aa6,0x1b33, -0x1b33,0x1b33,0x1b33,0x1b33,0x1b33,0x1b33,0x1b33,0x1be1,0x1cb3,0x1b36,0x1b36,0x1b36,0x19bf,0x19c2,0x19c2,0x19c2, -0x19c2,0x19c2,0x19c2,0x19c2,0x19c2,0x19c2,0x19c2,0x19c2,0x19c2,0x19c2,0x19bf,0x19bf,0x1b78,0x1b78,0x1b78,0x1b78, -0x1b78,0x1b78,0x1b78,0x1b78,0x1c4a,0x1c4d,0x1c47,0x1c47,0x1c47,0x1c47,0x1c47,0x1c47,0x1c47,0x1c47,0x1c47,0x1a1c, -0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x189c,0x1923,0x1923,0x1923,0x1923, -0x1923,0x1923,0x1926,0x1923,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x1926,0x19c2,0x19c2,0x1926, -0x1926,0x1926,0x1926,0x1926,0x1926,0x1926,0x1923,0x18a5,0x1926,0x1926,0x1926,0x1b33,0x1923,0x1923,0x1923,0x1923, -0x1923,0x1923,0x18a5,0x1923,0x1923,0x1923,0x1923,0x1923,0x19bf,0x1aa6,0x1aa6,0x1aa6,0x1923,0x1923,0x1923,0x1923, -0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x1923,0x19bf,0x18ba,0x18ba,0x18b7,0x18b7, -0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7, -0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18ba,0x18ba,0x18ba,0x18ba, -0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba, -0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x1908,0x1908,0x1908,0x1908, -0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908, -0x1908,0x1905,0x1905,0x1905,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x1908,0x1908,0x1908,0x1908, -0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908, -0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x1908,0x192c,0x192c,0x192c,0x192c, -0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c, -0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192c,0x192f,0x192f,0x192f,0x192f, -0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f, -0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x192f,0x1bed, -0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1986,0x1986,0x1986,0x1986, -0x1ae5,0x1ae5,0x1989,0x1989,0x1989,0x1989,0x1971,0x1971,0x1971,0x1971,0x1971,0x1971,0x1971,0x1971,0x1971,0x1971, -0x1971,0x1971,0x1971,0x1983,0x1974,0x1977,0x197a,0x198c,0x198c,0x1a2e,0x197d,0x197d,0x1986,0x1986,0x1986,0x1986, -0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986, -0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x19a7,0x19a7,0x19a7,0x19a7, -0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x1992, -0x1998,0x1995,0x1995,0x1995,0x1995,0x19a4,0x19aa,0x1995,0x1995,0x1995,0x1995,0x19a1,0x19a7,0x1995,0x1995,0x1995, -0x1995,0x1995,0x1995,0x1995,0x1995,0x1995,0x1995,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7, -0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19a7,0x19b3,0x19b3,0x19b3,0x19b3, -0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x1aa0,0x1aa0,0x1aa0,0x1aa0,0x1aa0,0x1bd8,0x1bd8,0x1bd8,0x1bd8, -0x1bd8,0x1bd8,0x1bd8,0x1bd8,0x1bd8,0x1bd8,0x1bd8,0x1bd8,0x1bd8,0x1ca4,0x1ca4,0x1ca4,0x19b9,0x19b9,0x19b9,0x19b9, -0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9, -0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x19bf,0x19bf,0x19bf,0x19bf, -0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1b33,0x1be1,0x1aa6, -0x1aa6,0x1aa6,0x1aa6,0x1be4,0x1be1,0x1cb3,0x1aa6,0x1b33,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x19bf,0x19bf,0x19bf,0x19bf, -0x19bf,0x19bf,0x19bf,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6, -0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x1aa6,0x19c8,0x19c8,0x19c8,0x19c8, -0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8, -0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19c8,0x19cb,0x19cb,0x19cb,0x19cb, -0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb, -0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x1cb6,0x19ce,0x19ce,0x19ce,0x19ce, -0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce, -0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x19ce,0x1a43,0x1a43,0x1a43,0x1a43, -0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43, -0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a5e,0x1a5e,0x1a5e,0x1a5e, -0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e, -0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a5e,0x1a64,0x1a64,0x1a64,0x1a64, -0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64, -0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a64,0x1a82,0x1a82,0x1a82,0x1a82, -0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82, -0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a82,0x1a85,0x1a85,0x1a85,0x1a85, -0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85, -0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a85,0x1a8e,0x1a8e,0x1a8e,0x1a8e, -0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e, -0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8e,0x1a8b,0x1a8b,0x1a8b,0x1aa6,0x1aa6,0x1aa6,0x1be1, -0x1be1,0x1b33,0x1b33,0x1b33,0x1b33,0x1b33,0x1b33,0x1be1,0x1be1,0x1be1,0x1b33,0x1b33,0x1aa6,0x1aa6,0x1aa6,0x1aa6, -0x1aa6,0x1aa9,0x1aa9,0x1aa6,0x1aa9,0x1aa9,0x1b33,0x1b36,0x1b33,0x1b33,0x1b33,0x1b33,0x1ae8,0x1ae8,0x1ae8,0x1ae8, -0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8, -0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1b0f,0x1b0f,0x1b0f,0x1b0f, -0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f, -0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b18,0x1b18,0x1b18,0x1b18, -0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b4e,0x1b4e,0x1b18,0x1b4e, -0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b18,0x1b1e,0x1b1e,0x1b1e,0x1b2a,0x1b2a,0x1b2a,0x1b2a, -0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a, -0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1b2a,0x1bc3,0x1bc3,0x1bc3,0x1bc3, -0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3, -0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bcf,0x1bcf,0x1bcf,0x1bcf, -0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf, -0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bf3,0x1bf3,0x1bf3,0x1bf3, -0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3, -0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf3,0x1bf6,0x1bf6,0x1bf6,0x1bf6, -0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6, -0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1bf6,0x1c6b,0x1c6b,0x1c6b,0x1c6b, -0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b, -0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c6b,0x1c8c,0x1c8c,0x1c8c,0x1c8c, -0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c, -0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c8c,0x1c9e,0x1c9e,0x1c9e,0x1c9e, -0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e, -0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1c9e,0x1ca1,0x1ca1,0x1ca1,0x1ca1, -0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1, -0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1ca1,0x1cfb,0x1cfb,0x1cfb,0x1cfb, -0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cf8,0x1cf8,0x1cf8, -0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1cf8,0x1d3a,0x1d3a,0x1d3a,0x1d3a, -0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a, -0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d3a,0x1d46,0x1d46,0x1d46,0x1d46, -0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46, -0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0x1d46,0,0,0,0 +0x1854,0x1854,0x1854,0x1854,0x1854,0x1854,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857,0x1857, +0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875, +0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875,0x1875, +0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x1884,0x1884,0x1884,0x1884,0x188d,0x1884, +0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887,0x1887, +0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896, +0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x1896,0x18f9,0x18f9, +0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f, +0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f,0x189f, +0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd, +0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd,0x18bd, +0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c3,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0, +0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0,0x18c0, +0,0,0,0 }; static const UTrie2 propsVectorsTrie={ propsVectorsTrie_index, - propsVectorsTrie_index+5368, + propsVectorsTrie_index+5236, nullptr, - 5368, - 27416, + 5236, + 27088, 0xa40, - 0x1578, + 0x14f4, 0x0, 0x0, 0x110000, - 0x800c, + 0x7e40, nullptr, 0, false, false, 0, nullptr }; -static const uint32_t propsVectors[7497]={ -0x67,0,0,0x67,0,0xe00000,0x67,0x80000,0x20,0x867,0,0,0xa67,0,0,0xb67, -0,0,0xd67,0,0,0xe67,0,0,0x1067,0,0,0x1167,0,0,0x1267,0, -0,0x1367,0,0,0x1467,0,0,0x1567,0,0,0x1667,0,0,0x1767,0,0, -0x1867,0,0,0x1967,0,0,0x1a67,0,0,0x1b67,0,0,0x1d67,0,0,0x1f67, -0,0,0x2067,0,0,0x2267,0,0,0x2367,0,0,0x2467,0,0,0x2567,0, -0,0x2767,0,0,0x2867,0x80000,0x20,0x2967,0,0,0x2a67,0,0x1600000,0x2b67,0,0, -0x2d67,0,0,0x3167,0x20000000,0,0x3267,0x20000000,0,0x3a67,0,0,0x3b67,0,0,0x3e67, -0,0,0x4067,0,0,0x4167,0,0,0x4467,0,0,0x4867,0,0,0x4967,0, -0,0x4a67,0,0,0x5067,0,0,0x5167,0,0,0x5467,0,0,0x5567,0,0, -0x5667,0x80000,0x20,0x5767,0,0,0x5867,0,0,0x5967,0,0,0x5b67,0,0,0x5c67, -0,0,0x5d67,0,0,0x6067,0x80000,0x20,0x6267,0,0,0x6367,0,0,0x6467,0, -0,0x6567,0,0,0x6f67,0,0,0x7067,0,0,0x7367,0x20000000,0,0x7567,0,0, -0x7667,0,0,0x7767,0,0,0x7867,0,0,0x7a67,0,0,0x7b67,0,0,0x7c67, -0,0,0x7e67,0,0,0x7f67,0,0,0x8167,0,0,0x8267,0,0,0x8467,0, -0,0x8567,0,0,0x8667,0,0,0x8767,0,0,0x8967,0,0,0x8b67,0,0, -0x8c67,0,0,0x8e67,0x20000000,0,0x8f67,0,0,0x9067,0,0,0x9167,0,0,0x9267, -0,0,0x9367,0,0,0x9567,0,0,0x9667,0,0,0x9767,0,0,0x9867,0, -0,0x9967,0,0,0x9a67,0,0,0x9c67,0,0,0x9f67,0,0,0xa167,0,0, -0xa367,0,0,0xa467,0,0,0xa567,0,0,0xa667,0,0,0xa767,0,0,0xa867, -0,0,0xa967,0,0,0xaa67,0,0xe00000,0xab67,0,0xe00000,0xac67,0,0,0xad67,0, -0,0xae67,0,0,0xaf67,0,0,0xb167,0,0,0xb267,0,0,0xb467,0,0, -0xb567,0,0,0xb767,0,0,0xb867,0,0,0xb967,0,0,0xba67,0,0,0xbc67, -0,0,0xbd67,0,0,0xbe67,0,0,0xbf67,0,0,0xc067,0,0,0xc167,0, -0,0xc367,0,0xe00000,0xc467,0,0xe00000,0xc667,0,0,0xc767,0,0,0xc867,0,0, -0xc967,0,0,0xca67,0,0,0xcc67,0,0xe00000,0xcf67,0,0xe00000,0xd067,0,0xe00000,0xd367, -0,0,0xd467,0,0,0xd567,0,0,0xd667,0,0,0xd867,0,0,0xda67,0, -0,0xdb67,0,0,0xdc67,0,0,0xdd67,0,0,0xde67,0,0,0xdf67,0,0, -0xe067,0,0,0xe167,0,0,0xe267,0,0,0xe367,0,0xe00000,0xe467,0,0,0xe567, -0,0,0xe667,0,0,0xe767,0,0,0xe867,0,0,0xe967,0,0,0xea67,0, -0,0xeb67,0,0,0xec67,0,0,0xed67,0,0,0xee67,0,0,0xef67,0,0, -0xf167,0,0,0xf367,0,0,0xf567,0,0,0xf667,0,0,0xf767,0,0,0xf867, -0,0,0xf967,0,0,0xfa67,0,0xe00000,0xfb67,0,0,0xfc67,0,0,0xfd67,0, -0,0xfe67,0,0,0x10167,0,0,0x10267,0,0,0x10367,0,0,0x10467,0,0, -0x10667,0,0,0x10767,0,0,0x10867,0,0,0x10967,0,0,0x10a67,0,0,0x10b67, -0,0,0x10c67,0,0,0x10d67,0,0,0x10e67,0,0,0x10f67,0,0,0x11067,0, -0,0x11367,0,0,0x11467,0,0,0x11567,0,0,0x11667,0,0,0x11767,0,0, -0x11867,0,0,0x11967,0,0xe00000,0x11a67,0,0,0x11b67,0,0,0x11c67,0,0,0x11d67, -0,0,0x11e67,0,0,0x11f67,0,0,0x12067,0,0,0x12167,0,0,0x12267,0, -0,0x12367,0,0,0x12467,0,0,0x12567,0,0,0x12667,0,0,0x12767,0,0, -0x12867,0,0,0x12967,0,0,0x12a67,0,0xe00000,0x12b67,0,0,0x12c67,0,0,0x12d67, -0,0,0x12f67,0,0,0x13067,0,0,0x13167,0,0,0x13267,0,0,0x13367,0, -0,0x13467,0,0,0x13567,0,0,0x13667,0,0,0x13767,0,0,0x13867,0,0, -0x13967,0,0,0x13a67,0,0,0x13b67,0,0,0x13c67,0,0,0x13d67,0,0,0x13f67, -0,0,0x14067,0,0,0x14167,0,0,0x14367,0,0,0x14467,0,0,0x14567,0, -0,0x14667,0,0,0x14767,0,0,0xa0067,0,0xe00000,0xa4f67,0,0xe00000,0xa5f67,0,0xe00000, -0xac567,0,0xe00000,0xad167,0,0xe00000,0xb0067,0,0xe00000,0xb1267,0,0xe00000,0xb2e67,0,0xe00000,0xb4867, -0,0xe00000,0x11000100,0,0x900020,0x11000100,0x40000001,0x4440020,0x11000100,0x40000001,0x4643020,0x11000100,0x40000001,0x4a5a040,0x11000100,0x40000001, -0x516a8a0,0x11000200,0,0x900020,0x11000200,0x4000001,0xc8c4000b,0x11000200,0x7c00100,0xc8220402,0x11000200,0x24000000,0x4200000,0x11000200,0x24000008,0x5710000, -0x11000200,0x40000001,0x5d3b020,0x11000219,0x7c00100,0xfc220401,0x11000219,0x7c00100,0xfc250401,0x11000319,0x7c00100,0xc8220402,0x11000319,0x7c00100,0xfc220401,0x11000319, -0x7c00100,0xfc250400,0x11000319,0x7c00100,0xfc250401,0x11000419,0x7c00100,0x8220400,0x11000419,0x7c00100,0x10220400,0x11000419,0x7c00100,0x10230400,0x11000419,0x7c00100, -0x18220400,0x11000419,0x7c00100,0x18230400,0x11000419,0x7c00100,0x20220400,0x11000419,0x7c00100,0x20250400,0x11000419,0x7c00100,0xc8220402,0x11000419,0x7c00100,0xc8250402, -0x11000419,0x7c00100,0xfc220401,0x11000419,0x7c00100,0xfc250400,0x11000419,0x7c00100,0xfc250401,0x11000519,0x7c00100,0x10220400,0x11000519,0x7c00100,0x10230400,0x11000519, -0x7c00100,0x18220400,0x11000519,0x7c00100,0x30220400,0x11000519,0x7c00100,0xfc220400,0x11000600,0x4000400,0x4200400,0x11000600,0x4000400,0xc8200002,0x11000600,0x7c00500, -0x10220400,0x11000600,0x7c00500,0x10230400,0x11000600,0x7c00500,0x10530400,0x11000600,0x7c00500,0xfc230400,0x11000600,0x7c00d00,0x10230400,0x11000619,0x7c00500,0xc822040f, -0x11000800,0x4000010,0xc9001401,0x11000800,0x4000400,0xc8200001,0x11000800,0x6800010,0xc8201001,0x11000800,0x7c00500,0xc8230401,0x11000807,0x7c00100,0x80220400,0x11000807, -0x7c00100,0x80250400,0x1100080e,0x4000400,0xc8200002,0x1100080e,0x4000400,0xf8200000,0x1100080e,0x7000500,0xc8220402,0x1100080e,0x7c00100,0x8250400,0x1100080e,0x7c00100, -0x18220400,0x1100080e,0x7c00100,0xc8220402,0x1100080e,0x7c00100,0xc8250401,0x1100080e,0x7c00100,0xfc220400,0x1100080e,0x7c00100,0xfc220401,0x1100080e,0x7c00100,0xfc250401, -0x1100080e,0x7c00120,0xc8220402,0x1100080e,0x7c00120,0xc8250402,0x11000908,0x4000000,0xc200000,0x11000908,0x7c00100,0x8220400,0x11000908,0x7c00100,0x8220401,0x11000908, -0x7c00100,0x8250400,0x11000908,0x7c00100,0x8250401,0x11000908,0x7c00100,0xfc220400,0x11000908,0x7c00100,0xfc220401,0x11000908,0x7c00100,0xfc250400,0x11000908,0x7c00100, -0xfc250401,0x11000a03,0x4000000,0x4200400,0x11000a03,0x4000000,0x4201000,0x11000a03,0x4000000,0x4270000,0x11000a03,0x7c00100,0xc8220402,0x11000a03,0x7c00100,0xfc220400, -0x11000a03,0x7c00100,0xfc250400,0x11000a03,0x7c00500,0xfc230400,0x11000a03,0xc000010,0x5049400,0x11000b13,0x2802500,0x20962460,0x11000b13,0x2802500,0xfc962460,0x11000b13, -0x4000000,0x4200000,0x11000b13,0x4000000,0xf8201000,0x11000b13,0x4000000,0xf8230400,0x11000b13,0x4000002,0x4400000,0x11000b13,0x4000010,0x4200000,0x11000b13,0x7c00100, -0xfe633800,0x11000c00,0x80000000,0x5329960,0x11000c02,0x2802100,0x20962460,0x11000c02,0x2802400,0x20962460,0x11000c02,0x4000000,0x4200000,0x11000c02,0x4000000,0x5329400, -0x11000c02,0x4000000,0x5329800,0x11000c02,0x4000000,0x5500000,0x11000c02,0x6800000,0xfd329800,0x11000c02,0x7c00100,0x8230400,0x11000c02,0x7c00100,0xc8230402,0x11000c02, -0x7c00100,0xfc230400,0x11000c02,0x7c00100,0xfc230401,0x11000c02,0x7c00500,0xfc230400,0x11000c02,0x7d00100,0xc0230400,0x11000f01,0x2802400,0x10962460,0x11000f0a,0x2802100, -0xfc962460,0x11000f0a,0x2802400,0xfc962460,0x11000f0a,0x2806400,0xfc962460,0x11000f0a,0x4000000,0x4200000,0x11000f0a,0x6800100,0xfc962540,0x11000f0a,0x7c00100,0xc8230401, -0x11000f0a,0x7c00100,0xfc230400,0x11000f0a,0x7c00100,0xfc230401,0x11001004,0x2802100,0xfc962460,0x11001004,0x2802400,0xfc962460,0x11001004,0x2806400,0xfc962460,0x11001004, -0x4000000,0x4200000,0x11001004,0x4000000,0x5500000,0x11001004,0x6800100,0xfc962540,0x11001004,0x6800100,0xfc962541,0x11001004,0x7c00100,0xc8230401,0x11001004,0x7c00100, -0xfc230400,0x11001110,0x2802100,0xfc962460,0x11001110,0x2802400,0xfc962460,0x11001110,0x2806400,0xfc962460,0x11001110,0x6800100,0xfc962540,0x11001110,0x7c00100,0xc8230401, -0x11001110,0x7c00100,0xfc230400,0x1100120f,0x2802100,0xfc962460,0x1100120f,0x2802400,0xfc962460,0x1100120f,0x2806400,0xfc962460,0x1100120f,0x6800100,0xfc962540,0x1100120f, -0x7c00100,0xfc230400,0x1100131f,0x2802100,0xfc962460,0x1100131f,0x2802400,0xfc962460,0x1100131f,0x2806400,0xfc962460,0x1100131f,0x4000000,0x4200000,0x1100131f,0x6800000, -0xfd329800,0x1100131f,0x6800100,0xfc962540,0x1100131f,0x6800100,0xfc962541,0x1100131f,0x7c00100,0xc8230401,0x1100131f,0x7c00100,0xfc230400,0x11001423,0x2802100,0xfc962460, -0x11001423,0x2806400,0xfc962460,0x11001423,0x6800100,0xfc962540,0x11001423,0x6800100,0xfc962541,0x11001423,0x7c00100,0xfc230400,0x11001423,0x7c00100,0xfc230401,0x11001524, -0x2802100,0xfc962460,0x11001524,0x2802100,0xfc962461,0x11001524,0x2806400,0xfc962460,0x11001524,0x6800000,0xfd329800,0x11001524,0x6800100,0xfc962540,0x11001524,0x7c00100, -0xfc230400,0x11001615,0x2802100,0xfc962460,0x11001615,0x2806400,0xfc962460,0x11001615,0x6800100,0xfc962540,0x11001615,0x6800100,0xfc962541,0x11001615,0x7c00100,0x8230400, -0x11001615,0x7c00100,0xfc230400,0x1100171a,0x2802100,0xfc962460,0x1100171a,0x2806400,0xfc962460,0x1100171a,0x6800000,0xfd329800,0x1100171a,0x6800100,0xfc962540,0x1100171a, -0x6800100,0xfc962541,0x1100171a,0x7c00100,0xfc230400,0x11001900,0x4000000,0x5600000,0x11001926,0x2802100,0xfd862460,0x11001926,0x2802400,0xfd862460,0x11001926,0x2806100, -0xfd862460,0x11001926,0x4000000,0x4200000,0x11001926,0x4000010,0x4400000,0x11001926,0x6800000,0xfd329800,0x11001926,0x7800100,0xc9830142,0x11001926,0x7c00100,0xfd830000, -0x11001926,0x7c00900,0xfd830000,0x11001926,0x7e00100,0xfd830000,0x11001a18,0x2802100,0xfd862460,0x11001a18,0x2802400,0xfd862460,0x11001a18,0x6800000,0xfd329800,0x11001a18, -0x7800100,0xc9830142,0x11001a18,0x7c00100,0xc9830002,0x11001a18,0x7c00100,0xfd830000,0x11001a18,0x7c00900,0xfd830000,0x11001a18,0x7e00100,0xfd830000,0x11001d0c,0x7c00100, -0x8230400,0x11001d0c,0x7c00100,0x8250400,0x11001d0c,0x7c00100,0xfc230400,0x11001e12,0x7c00100,0xa230500,0x11001e12,0x7c00100,0xa330520,0x11001e12,0x7c80100,0xc6330520, -0x11002619,0x7c00100,0xc8220402,0x11002619,0x7c00100,0xfc220401,0x11002619,0x7c00100,0xfc250401,0x1100270e,0x4000400,0xc8200001,0x1100270e,0x4000400,0xc8200002,0x1100270e, -0x4000400,0xc8500001,0x1100270e,0x7c00100,0xc8220401,0x1100270e,0x7c00100,0xc8250401,0x1100270e,0x7c00100,0xfc220401,0x1100270e,0x7c00100,0xfc250401,0x11002800,0x80000, -0xc4918820,0x11002800,0x80000,0xc5c18020,0x11002800,0x180000,0xc0918820,0x11002800,0x4000001,0xc8445801,0x11002800,0x4000001,0xc8445802,0x11002800,0x4000001,0xc8c4000b, -0x11002800,0x6800000,0x10201c00,0x11002800,0x6800020,0x10201c00,0x11002800,0x24000000,0x4200000,0x11002800,0x24000000,0x4810000,0x11002800,0x24000000,0x5410000,0x11002800, -0x24000000,0x5500000,0x11002800,0x24000000,0xc8200002,0x11002800,0x24000000,0xc9500002,0x11002800,0x24000002,0x4400000,0x11002800,0x24000006,0xc8c0000b,0x11002800,0x24000008, -0x5410000,0x11002800,0x24000008,0x5710000,0x11002800,0x24000020,0x5001400,0x11002800,0x24000020,0xc9500002,0x11002800,0x2c000010,0x5248000,0x11002800,0x2c000010,0xc9248002, -0x11002800,0x40000001,0x463b020,0x11002800,0x40080000,0xc4918820,0x11002801,0x2880000,0xc6a65620,0x11002801,0x2882000,0xc4962460,0x11002900,0x4000000,0xc820000e,0x11002900, -0x4000000,0xc820000f,0x11002900,0x4000020,0xc820000e,0x11002900,0x4000020,0xc820000f,0x11002900,0x4000020,0xc881000e,0x11002900,0x4000020,0xc881000f,0x11002900,0x4000020, -0xc941000e,0x11002900,0x4000020,0xc941000f,0x11002900,0x4000022,0xc820000e,0x11002900,0x4000022,0xc820000f,0x11002a00,0x4000000,0x5500000,0x11002a00,0x4000000,0x5600000, -0x11002a00,0x4000000,0xc9600002,0x11002b01,0x2000,0x14962460,0x11002b01,0x2802020,0x10962460,0x11002c00,0x4000000,0x4200000,0x11002c00,0x4000000,0xc200000,0x11002c00, -0x4000000,0xc8200002,0x11002c00,0x4000000,0xc820000f,0x11002c00,0x4000020,0x4200000,0x11002c00,0x7c00000,0x10200000,0x11002c00,0x7c00020,0x10200000,0x11002c00,0x7c00120, -0xc8220405,0x11002c00,0x7c00120,0xc8230402,0x11002c00,0x7c00120,0xc8250402,0x11002c00,0x7c00120,0xc8250405,0x11002c19,0x7c00100,0x8250400,0x11002c19,0x7c00100,0xc8250401, -0x11002d00,0x4000000,0xc8100006,0x11002d00,0x4000000,0xc8200006,0x11002d19,0x7c00100,0x18230400,0x11002d19,0x7c00100,0xc8220402,0x11002d19,0x7c00100,0xc8250402,0x11002e00, -0x24000000,0x4200000,0x11002e00,0x24000020,0x4200000,0x11002e00,0x24000020,0x4200001,0x11002f00,0x24000020,0x4200000,0x11002f00,0x24000020,0x4200001,0x11002f00,0x24000020, -0x4f00000,0x11002f00,0x24000020,0x5600000,0x11002f00,0x24000020,0xc8200002,0x11002f00,0x24000022,0x5600000,0x11003000,0x24000000,0x4200000,0x11003000,0x24000020,0x4200000, -0x11003000,0x24000020,0x4810000,0x11003000,0x24000020,0x5410000,0x11003100,0x24000000,0x4200000,0x11003200,0x24000000,0x4200000,0x11003300,0x4000000,0xc8100003,0x11003400, -0x24000000,0x4100000,0x11003400,0x24000000,0x4200000,0x11003500,0x24000000,0x4200000,0x11003600,0x24000000,0x4200000,0x11003600,0x24000020,0x4200000,0x11003700,0x24000000, -0x4200000,0x11003700,0x24000000,0x4e00000,0x11003700,0x24000000,0x6800000,0x11003700,0x24000020,0x4200000,0x11003800,0x4000000,0x4100000,0x11003800,0x24000000,0x4200000, -0x11003800,0x24000000,0x4b00000,0x11003800,0x24000000,0x4e00000,0x11003800,0x24000000,0x5710000,0x11003800,0x24000000,0x6800000,0x11005003,0x7c00100,0xc8220402,0x11005013, -0x2802500,0x30962460,0x11005013,0x4000020,0xc8200005,0x11005013,0x7c00100,0xca633801,0x11005013,0x7c00100,0xca633802,0x11005013,0x7c00100,0xca633805,0x11005019,0x7c00100, -0xc8220402,0x11005102,0x7000100,0xc8230408,0x11005102,0x7c00100,0xc8230404,0x11005102,0x7c00100,0xc8230407,0x11005102,0x7c00100,0xc8230408,0x11005102,0x7c00100,0xc8230409, -0x11005201,0x2802400,0x10962460,0x11005500,0x80000,0xc5e18820,0x11005502,0x7000100,0xc8230408,0x11005502,0x7c00100,0xc8230404,0x11005502,0x7c00100,0xc8230407,0x11005502, -0x7c00100,0xc8230408,0x11005502,0x7c00100,0xc8230409,0x11005667,0x1000,0,0x11020200,0x80004,0xc4418820,0x11020200,0x4000000,0xc8100006,0x11020200,0x4000000, -0xc810000f,0x11020200,0x4000400,0xc8100002,0x11020200,0x4000400,0xc8500002,0x11020200,0x6800c00,0xf8101000,0x11020200,0x24000000,0x4100000,0x11020200,0x24000000,0x4200000, -0x11020200,0x24000000,0x5400000,0x11020200,0x24000000,0x5500000,0x11020200,0x24000000,0x5600000,0x11020200,0x24000020,0x4100000,0x11020200,0x24000020,0x5600000,0x11020219, -0x7c00100,0xc812040f,0x11020219,0x7c00100,0xfc220400,0x11020219,0x7c00100,0xfc220401,0x11020219,0x7c00100,0xfc250400,0x11020319,0x7c00100,0xc8220402,0x11020319,0x7c00100, -0xc8250402,0x11020319,0x7c00100,0xfc220400,0x11020319,0x7c00100,0xfc220401,0x11020319,0x7c00100,0xfc250400,0x11020319,0x7d00100,0xc0220402,0x11020419,0x7c00100,0xfc220401, -0x11020519,0x7c00100,0x10220400,0x11020600,0x4000400,0x4200400,0x11020600,0x4000400,0xc8100002,0x11020600,0x7c00500,0x10130400,0x11020600,0x7c00d00,0x10130400,0x11020701, -0x2802400,0x10962460,0x11020701,0x2802400,0x10c62460,0x11020701,0x2802400,0x20962460,0x11020701,0x2802400,0xc8962461,0x11020701,0x2802400,0xfc962460,0x1102080e,0x7c00100, -0xfc220400,0x1102080e,0x7c00100,0xfc250400,0x11020908,0x7c00100,0xfc220400,0x11020908,0x7c00100,0xfc220401,0x11020908,0x7c00100,0xfc250400,0x11020908,0x7c00100,0xfc250401, -0x11022800,0x24000000,0x4100000,0x11022800,0x24000000,0x4200000,0x11022800,0x24000000,0x5500000,0x11022800,0x24000000,0xc8200002,0x11022800,0x24000000,0xc8f00002,0x11022800, -0x24000000,0xc8f0ac02,0x11022800,0x24000000,0xf8401000,0x11022800,0x24000002,0x4100000,0x11022800,0x24000002,0x4370000,0x11022800,0x24000002,0x4470000,0x11022800,0x24000006, -0xf8400000,0x11022800,0x24000008,0x5710000,0x11022800,0x24000008,0x5712c00,0x11022800,0x24000008,0xf9712c00,0x11022800,0x24000020,0x4100000,0x11022800,0x24000020,0x5500000, -0x11022800,0x24000020,0xc9500002,0x11022900,0x4000000,0xc810000e,0x11022900,0x4000000,0xc810000f,0x11022919,0x7c00100,0xc812040f,0x11022c00,0x4000000,0xc8100002,0x11022c00, -0x4000000,0xc810000f,0x11022c00,0x4000000,0xc9500002,0x11022c00,0x4000000,0xc9600002,0x11022c00,0x7c00120,0xc8120405,0x11022c0e,0x7c00100,0xc8250401,0x11022c19,0x7c00100, -0xc8150401,0x11022d00,0x4000000,0xc8100006,0x11022d00,0x4000000,0xc8200006,0x11022d19,0x7c00100,0xc8120402,0x11022d19,0x7c00100,0xc8150402,0x11022e00,0x24000000,0x4200000, -0x11022e00,0x24000020,0x4100000,0x11022f00,0x24000020,0x4100000,0x11022f00,0x24000020,0x4100001,0x11022f00,0x24000020,0xc8100002,0x11023000,0x24000000,0x4100000,0x11023300, -0x4000000,0xc8100002,0x11023300,0x4000000,0xc8100003,0x11023300,0x4000100,0xc8120403,0x11023300,0x4000100,0xc8150403,0x11023400,0x24000000,0x4100000,0x11023500,0x24000000, -0x4100000,0x11023600,0x24000000,0x4100000,0x11023600,0x24000020,0x4100000,0x11023700,0x24000000,0x4100000,0x11023700,0x24000000,0x4e00000,0x11023700,0x24000020,0x4100000, -0x11023800,0x4000000,0x4100000,0x11023800,0x24000000,0x4200000,0x11024e67,0,0,0x11025600,0x4000000,0x4100000,0x11042a00,0x4000000,0x5600000,0x11045700, -0x4000000,0xc820000a,0x11045700,0x4000020,0xc820000a,0x11045712,0x7c00100,0xc8e3040a,0x11045712,0x7c80100,0xc4e3040a,0x11045716,0x7c00100,0xc8e30c0a,0x11045716,0x7c00100, -0xca530c0a,0x11063d00,0x4000001,0xc8445811,0x11065700,0x4000000,0xc8810011,0x11065700,0x4000000,0xc8e00011,0x11065700,0x4000000,0xc9410011,0x11065700,0x4000000,0xc9500011, -0x11065700,0x4000000,0xc9600011,0x11065700,0x4000006,0xc8e70011,0x11065700,0x4000008,0xc8e00011,0x11065700,0x4000008,0xc8e02c11,0x11065700,0x4000010,0xc8871411,0x11065700, -0x4000010,0xc9201411,0x11065700,0x4000010,0xc9271011,0x11065700,0x4000020,0xc8e00011,0x11065700,0x4000400,0xc8e00011,0x11065700,0x4000420,0xc8e00011,0x11065700,0x6800000, -0xc8e01c11,0x11065700,0x6800040,0xc8e29811,0x11065700,0xc000010,0xc880ac11,0x11065700,0xc000010,0xc8b48011,0x11065719,0x7c00100,0xc8e20411,0x11065719,0x7c00100,0xc8e50411, -0x11065719,0x7c00140,0xc8e20411,0x11065719,0x7c00140,0xc8e50411,0x11080100,0x6800000,0xfc201c00,0x11080100,0x68000c0,0xfd329800,0x11080100,0x24000000,0x4200000,0x11080100, -0x24000000,0x4810000,0x11080100,0x24000000,0x5410000,0x11080100,0x24000000,0x5500000,0x11080100,0x24000000,0x5600000,0x11080100,0x24000000,0x5b00000,0x11080100,0x24000000, -0x6410000,0x11080100,0x24000006,0xf8d70000,0x11080100,0x24000008,0x5714000,0x11080100,0x24000008,0xf9713c00,0x11080100,0x24000010,0x5001400,0x11080100,0x24000010,0x5071400, -0x11080100,0x24000010,0xf9071000,0x11080100,0x24000020,0x4200000,0x11080100,0x24000020,0x4400000,0x11080100,0x24000020,0x5600000,0x11080100,0x24000400,0x4200000,0x11080100, -0x24000420,0x4200000,0x11080100,0x2c000010,0x4b48000,0x11080100,0x2c000010,0xf900ac00,0x11080100,0x44000001,0x5a45800,0x11080119,0x7c00100,0xfc220400,0x11080119,0x7c00100, -0xfc250400,0x11080119,0x7c001c0,0xfc220400,0x11080119,0x7c001c0,0xfc250400,0x11080200,0x4000400,0xc8200002,0x11080200,0x24000000,0x4200000,0x11080200,0x24000000,0x5500000, -0x11080200,0x24000000,0x5600000,0x11080200,0x24000020,0x4200000,0x110a1e12,0x7c00100,0xa130480,0x110a1e12,0x7c80100,0xc6130480,0x110a3000,0x24000000,0x4e00000,0x110a3000, -0x24100000,0xc0810001,0x110a3000,0x24100000,0xc1410001,0x110a3700,0x24000000,0x4200000,0x110a3d00,0x4000000,0x4e00000,0x110a3d00,0x4000000,0xc8e00002,0x110a3d00,0x24000000, -0x4e00000,0x110a3d11,0x7c00300,0x10e30000,0x110a3d11,0x7c00300,0xfce30000,0x110a3d11,0x7c00900,0xfd230400,0x110a3d12,0x2802400,0x18962460,0x110a3e14,0x7c00100,0xfce30000, -0x110a3e14,0x7c00100,0xfce30001,0x110a3e14,0x7c00100,0xfe530000,0x110a3e14,0x7c00900,0xfd230000,0x110a3e14,0x7c00900,0xfd230001,0x110a3f16,0x7c00100,0xfce30c00,0x110a3f16, -0x7c00100,0xfce30c01,0x110a3f16,0x7c00100,0xfe530c00,0x110a3f16,0x7c00900,0xfd230c00,0x110a3f16,0x7c00900,0xfd230c01,0x110a4005,0x7c00100,0xfce30400,0x110a4112,0x7c00100, -0xc8e30402,0x110a4112,0x7c80100,0xc4e30402,0x110a4400,0x4000000,0x14e00000,0x110a4412,0x4000000,0xc8e00002,0x110a4412,0x4000000,0xc8e00003,0x110a4416,0x4000000,0xc8e00c03, -0x110a4500,0x4000000,0xc8e0000d,0x110a4516,0x4000000,0xc8e00c0d,0x110a4711,0x7c40300,0xfce30000,0x110a4f11,0x7c00300,0xc8e30001,0x110a4f11,0x7c40300,0xfce30000,0x110a5300, -0x4000000,0xc8810010,0x110a5300,0x4000000,0xc8e00002,0x110a5300,0x4000000,0xc8e00010,0x110a5300,0x4000000,0xc9410010,0x110a5300,0x4000002,0xc8e70010,0x110a5300,0x4000008, -0xc8810010,0x110a5300,0x4000008,0xc9410010,0x110a5300,0x6800000,0xc8e01c02,0x110a5300,0x6800000,0xc8e01c10,0x110a5400,0x4000000,0xc881000c,0x110a5400,0x4000000,0xc8e0000c, -0x110a5400,0x4000000,0xc941000c,0x110a5400,0x4000000,0xc950000c,0x110a5400,0x4000000,0xc960000c,0x110a5400,0x4000002,0xc8e7000c,0x110a5400,0x4000010,0xc887140c,0x110a5400, -0x4000010,0xc8e7000c,0x110a5400,0x4000010,0xc920140c,0x110a5400,0x4000010,0xc927100c,0x110a5400,0x4000020,0xc8e0000c,0x110a5400,0x4000026,0xc8e7000c,0x110a5400,0xc000010, -0xc880ac0c,0x110a5400,0xc000010,0xc8b4800c,0x11400c0c,0x4000010,0x4b00000,0x11400c0c,0x4000010,0x5071400,0x11400c17,0xc000010,0x4b48000,0x11400c1e,0x7c00900,0x8230400, -0x11400f4b,0xc000010,0x4448000,0x11400f5f,0xc000010,0x4448000,0x11401d94,0x4000000,0x4200000,0x11403dcc,0x4000000,0x4e00000,0x114457c1,0x4000008,0xc881000a,0x114457c1, -0x4000008,0xc941000a,0x114457c1,0x4000010,0xc887000a,0x114457c1,0x6800004,0xc920000a,0x114457c1,0xc000010,0xc884800a,0x114457ca,0x3802500,0xc926246a,0x114457ca,0x7c00d00, -0xca530c0a,0x114a3dc1,0x24000000,0x4810000,0x114a3dc1,0x24000000,0x5410000,0x114a3dc1,0x24000008,0x4810000,0x114a3dc1,0x24000008,0x5410000,0x114a3dc1,0x24000010,0x4870000, -0x114a3dc1,0x2c000010,0x4848000,0x114a3dc7,0x4000000,0x4e00000,0x114a3dc7,0x24000000,0x4e00000,0x114a3dc7,0x24000002,0x4e00000,0x114a3dc7,0x24000002,0x5200000,0x114a3dc7, -0x24000008,0x4810000,0x114a3dc7,0x24000008,0x5410000,0x114a3dc7,0x24000008,0xc810000,0x114a3dca,0x7c00900,0x10930c00,0x114a3dca,0x7c00900,0x10e30c00,0x114a3dcc,0x7c00300, -0xfce30000,0x114a3eca,0x7000400,0xc9200c02,0x114a3fc1,0x6800004,0xf9200000,0x114a3fca,0x7c00d00,0xfe530c00,0x114a42cc,0x4000000,0x4e00000,0x114a42cc,0x4000000,0xc8e0000f, -0x114a44cc,0x4000000,0xc8e00002,0x114a44cc,0x4000000,0xc8e00003,0x114a45cc,0x4000000,0xc8e00002,0x114a45cc,0x4000000,0xc8e0000d,0x11505113,0x24000000,0x14810000,0x11505113, -0x24000000,0x15410000,0x1180090a,0x2802400,0x18962460,0x11800c27,0x2802100,0xfc962460,0x11800c27,0x2802500,0xfc962460,0x11800f32,0x2802400,0x8962460,0x11800f3f,0x2802400, -0x8962460,0x11820700,0x2802400,0xfc962460,0x11820700,0x2802500,0xfc962460,0x118a3dcd,0x2802400,0x10962460,0x118a3eca,0x2802400,0xfc962460,0x11c00904,0x2802400,0x8962460, -0x11c00908,0x2802400,0x18962460,0x11c00c2c,0x6800000,0xfd329800,0x11c00c30,0xc000010,0x4b48000,0x11c00f78,0x6800000,0xfd329800,0x11c0107d,0x6800000,0xfd329800,0x11c01181, -0x6800000,0xfd329800,0x11c01285,0x6800000,0xfd329800,0x11c01489,0x4000000,0x4200000,0x11c01489,0x6800000,0xfd329800,0x11c0168d,0x6800000,0xfd329800,0x11d05117,0x7c00100, -0xc8230408,0x20000067,0x1000,0,0x20000b13,0x2802400,0x20962460,0x20000b13,0x2802500,0x20962460,0x20001b27,0x2802100,0xc8962461,0x20001b27,0x2802100,0xfc962460, -0x20001b27,0x2802400,0x10962460,0x20001b27,0x2802400,0x20962460,0x20001b27,0x2802400,0xfc962460,0x20001b27,0x2802500,0xfc962460,0x20001b27,0x2806400,0xfc962460,0x20001b27, -0x2902100,0xc0962462,0x20001b27,0x4000000,0x4200000,0x20001b27,0x4000000,0x4400000,0x20001b27,0x4000000,0x4500000,0x20001b27,0x4000000,0x4810000,0x20001b27,0x4000000, -0x4b00000,0x20001b27,0x4000000,0x5410000,0x20001b27,0x4000000,0xc8c0000b,0x20001b27,0x4000000,0xf8400000,0x20001b27,0x4000010,0x4b00000,0x20001b27,0x4000010,0x4c00000, -0x20001b27,0x6800000,0xfd329800,0x20001b27,0x6800100,0xfc462540,0x20001b27,0x6800400,0xfc962540,0x20001b27,0x7c00100,0xc8230401,0x20001b27,0x7c00100,0xfc230400,0x20002619, -0x7c00100,0xc8220401,0x20002a00,0x4000000,0x5600000,0x20004b67,0,0x1900000,0x20004c67,0,0x1900000,0x20004d67,0,0x1900000,0x20006d67,0x1000, -0,0x20006e67,0x1000,0,0x20026d67,0,0,0x20026e67,0,0,0x200a4a12,0x7c00100,0xfdf304c1,0x200a4a12,0x7c00100,0xfe0304e1, -0x21005600,0x4000000,0x4700000,0x21022a00,0x4000000,0x5600000,0x30000419,0x7c00100,0x8220400,0x30000419,0x7c00100,0x8250400,0x30000419,0x7c00100,0x20220400,0x30000419, -0x7c00100,0x20250400,0x30000419,0x7c00100,0xfc220401,0x30000419,0x7c00100,0xfc250401,0x30000519,0x7c00100,0x10220400,0x30000600,0x4000400,0x4200400,0x30000600,0x7c00500, -0x10230400,0x30000600,0x7c00500,0xfc230400,0x30000605,0x4000400,0x4200400,0x3000080e,0x7c00100,0x8220400,0x3000080e,0x7c00100,0x10220400,0x30000908,0x2000,0xc962460, -0x30000908,0x7c00100,0xfc220400,0x30000908,0x7c00100,0xfc220401,0x30000908,0x7c00100,0xfc250400,0x30000908,0x7c00100,0xfc250401,0x30000a03,0x4000006,0xf8400400,0x30000c02, -0x4000000,0xf8200000,0x30000c02,0x7c00100,0xfc230400,0x30000d22,0x2802100,0x40962460,0x30000d22,0x2802400,0x50962460,0x30000d22,0x2802500,0x40962460,0x30000d22,0x4000000, -0x44200000,0x30000d22,0x4000010,0x44200000,0x30000d22,0x7c00100,0x40230400,0x30000d22,0xc000010,0x44248000,0x30000d22,0x80000000,0x44218560,0x30000e25,0x2802500,0xfc962460, -0x30000e25,0x7c00100,0xfc230400,0x30001821,0x2802100,0x30962460,0x30001821,0x2802100,0xfc962460,0x30001821,0x2806400,0xfc962460,0x30001821,0x4000000,0x4200000,0x30001821, -0x6800100,0x30962540,0x30001821,0x6800100,0xfc962540,0x30001821,0x6800100,0xfc962541,0x30001821,0x7c00100,0x30230400,0x30001821,0x7c00100,0xfc230400,0x30001b27,0x2802100, -0xfc962460,0x30001b27,0x2802400,0xfc962460,0x30001b27,0x4000000,0x4200000,0x30001b27,0x4000000,0x4400000,0x30001b27,0x7c00100,0xfc230400,0x30001c1c,0x2802100,0xfd862460, -0x30001c1c,0x2802400,0xfd862460,0x30001c1c,0x2806400,0xfd862460,0x30001c1c,0x4000000,0x4200000,0x30001c1c,0x6800100,0xfd862400,0x30001c1c,0x6800100,0xfd862540,0x30001c1c, -0x7c00100,0xfd830000,0x30001c1c,0x7c00100,0xfd830001,0x30001c1c,0xc000010,0x4448000,0x30001f0b,0x4000000,0x4200000,0x30001f0b,0x4000010,0x4200000,0x30001f0b,0x4000010, -0x4400000,0x30001f0b,0x6800000,0x8200000,0x30001f0b,0x7c00100,0xfc230400,0x30001f0b,0xc000010,0x4248000,0x30002006,0x7c00100,0x40250400,0x30002128,0x4000000,0x44200000, -0x30002128,0x7c00100,0x40230400,0x30002128,0xc000010,0x44248000,0x3000221d,0x4000000,0x84810000,0x3000221d,0x4000000,0x85410000,0x3000221d,0x4000001,0x84445800,0x3000221d, -0x7c00100,0x80230400,0x30002300,0x4000010,0x4400000,0x30002320,0x7c00100,0x80230400,0x30002417,0x2802100,0xfd862460,0x30002417,0x2802400,0x9862460,0x30002417,0x2802400, -0x11862460,0x30002417,0x2802400,0x19862460,0x30002417,0x2802400,0xfd862460,0x30002417,0x2806400,0xfd862460,0x30002417,0x2882000,0xc5862460,0x30002417,0x4000000,0x4200000, -0x30002417,0x4000000,0x5600000,0x30002417,0x4000000,0xc400000,0x30002417,0x4000010,0x4400000,0x30002417,0x4000010,0x5200000,0x30002417,0x6800000,0xfd329800,0x30002417, -0x6800100,0xfd862540,0x30002417,0x7c00100,0x9830000,0x30002417,0x7c00100,0xfd830000,0x30002417,0x7d00100,0xc1830000,0x30002417,0xc000010,0x4448000,0x3000251b,0x80000, -0xc4c18820,0x3000251b,0x2802100,0xa0962460,0x3000251b,0x3c02100,0x80962460,0x3000251b,0x4000000,0x84200000,0x3000251b,0x4000006,0x84500000,0x3000251b,0x4000010,0x84400000, -0x3000251b,0x4000010,0x84b70000,0x3000251b,0x4000800,0x84200000,0x3000251b,0x6800000,0x81329800,0x3000251b,0x7c00100,0x80230400,0x3000251b,0x7c00900,0x80230400,0x3000251b, -0xc000010,0x84b48000,0x3000251b,0x12882000,0xc4962460,0x30002800,0x24000000,0x4200000,0x30002800,0x2c000010,0xc9248002,0x30002a00,0x4000000,0x5600000,0x30002b01,0x2000, -0x14962460,0x30002c00,0x4000000,0x4200000,0x30002c00,0x7c00100,0xc8220405,0x30002d19,0x7c00100,0x18250400,0x30002e00,0x24000000,0x4200000,0x30003000,0x24000000,0x4200000, -0x30003100,0x24000000,0x4200000,0x30003600,0x24000000,0x4200000,0x30003700,0x24000000,0x4200000,0x3000392e,0x24000000,0x14200000,0x30005013,0x7c00100,0xca633801,0x30005600, -0,0x4918820,0x30020600,0x4000400,0x4500400,0x30020701,0x2802400,0x10962460,0x30020701,0x2802400,0x10c62460,0x300a3a11,0x4020000,0x4e00000,0x300a3a11,0x4020000, -0xc8e00002,0x300a3b11,0x4020000,0xc8e00002,0x300a3c00,0x4008000,0x4e00000,0x300a3c00,0x4010000,0x4e00000,0x300a3d11,0x7c00300,0xc8e30002,0x300a4305,0x7c00100,0xfce30400, -0x300a4611,0x7c40300,0xfce30000,0x300a4829,0x7c00100,0x40e30400,0x300a4829,0x7c00900,0x41230400,0x300a4929,0x4000000,0x44e00000,0x3040259a,0x4000010,0x84400000,0x3040259a, -0x4000010,0x84b70000,0x3040259a,0xc000010,0x84b48000,0x304028bc,0x4000001,0xc8c41c0b,0x304a3dcc,0x4000000,0x4e00000,0x30800c27,0x2802100,0xfc962460,0x30c01c92,0x6800000, -0xfd329800,0x3100080e,0x7c00120,0xc8220402,0x3100080e,0x7c00120,0xc8250402,0x31005167,0x1000,0,0x3100581e,0x4000000,0x84200000,0x3100581e,0x7c00100,0x80230400, -0x3100590d,0x7c00100,0x80230400,0x31005a09,0x7c00100,0x80220400,0x31005a09,0x7c00100,0x80250400,0x31005b00,0x4000000,0x14200000,0x31005c00,0x80000,0xc4918820,0x31005c00, -0x2802000,0x10962460,0x31005c00,0x2802400,0x10962460,0x31005c00,0x4000000,0x14200000,0x31005c00,0x4000000,0xc8200001,0x31005c00,0x6800000,0x10962540,0x31005c00,0x6800400, -0x10962540,0x31005c01,0x2802400,0x10962460,0x31005d00,0x4000020,0xc8200005,0x31005d00,0x6800020,0xc9329805,0x31005d00,0x7c00120,0xc8220405,0x31005d00,0x7c00120,0xc8250405, -0x31006000,0x82000,0xc4962460,0x31006000,0x180000,0xc0918820,0x310a5e11,0x7c40300,0xfce30000,0x310a5f11,0x7c00300,0xc8e30001,0x32000419,0x7c00100,0x20250400,0x3200080e, -0x4000020,0x4200000,0x3200080e,0x7c00100,0x8220400,0x3200080e,0x7c00100,0x8250400,0x32000908,0x7c00100,0xfc220400,0x32000908,0x7c00100,0xfc250400,0x32000c02,0x7c00100, -0x8230400,0x32000e25,0x7c00100,0xfc230400,0x32001d0c,0x7c00100,0xfc230400,0x32002800,0x80000,0xc5e18820,0x32002800,0x80020,0xc4218820,0x32002800,0x4000001,0xc8445802, -0x32002800,0x24000000,0x4200000,0x32002800,0x24000000,0xc9500002,0x32002800,0x24000020,0x4200000,0x32002800,0x2c000010,0xc9248002,0x32002919,0x7c00100,0xc822040f,0x32002a00, -0x4000000,0x5600000,0x32002b01,0x2000,0x14962460,0x32002b01,0x2802000,0x10962460,0x32002b01,0x2802020,0x10962460,0x32002c00,0x4000000,0x4200000,0x32002c00,0x4000020, -0x4200000,0x32002c00,0x4000020,0xc8200005,0x32002c00,0x7c00120,0xc8220405,0x32002c00,0x7c00120,0xc8250405,0x32002e00,0x24000020,0x4200000,0x32002f00,0x24000020,0x4200000, -0x32003000,0x24000000,0x4200000,0x32003000,0x24000020,0x4200000,0x32003500,0x24000000,0x4200000,0x32003600,0x24000020,0x4200000,0x32003700,0x24000000,0x4100000,0x32003700, -0x24000000,0x4200000,0x32003800,0x24000000,0x4810000,0x32003800,0x24000000,0x5410000,0x32005102,0x4000000,0xc9500008,0x32005502,0x7c00100,0x10230400,0x32006108,0x7c00100, -0x8220400,0x32006108,0x7c00100,0x8250400,0x3200622a,0x2802100,0x80962460,0x3200622a,0x2806400,0x80962460,0x3200622a,0x7c00100,0x80230400,0x3200632b,0x2802100,0x80962460, -0x3200632b,0x6804000,0x80962540,0x3200632b,0x7c00100,0x80230400,0x3200642c,0x2802100,0x80962460,0x3200642c,0x7c00100,0x80230400,0x3200652d,0x2802100,0x80962460,0x3200652d, -0x7c00100,0x80230400,0x32006600,0x24000020,0x4200000,0x32006700,0x24000020,0x4200000,0x32006800,0x24000020,0x4200000,0x32006900,0x24000020,0x4200000,0x32006900,0x24000020, -0x4810000,0x32006900,0x24000020,0x5410000,0x32006a00,0x24000020,0x4200000,0x32006a00,0x24000020,0xc8200001,0x32006a00,0x24000020,0xc8200002,0x32020701,0x2882000,0xc4c62460, -0x32023300,0x4000000,0x14100000,0x32026c01,0x12882000,0xc4962460,0x32065700,0x4000000,0xc8810011,0x32065700,0x4000000,0xc9410011,0x32086600,0x24000020,0x4810000,0x32086600, -0x24000020,0x5410000,0x32086900,0x24000020,0x4810000,0x32086900,0x24000020,0x5410000,0x320a3600,0x24000020,0x4200000,0x320a3d11,0x7c00100,0x11230400,0x320a3e14,0x7c00100, -0xc8e30010,0x320a3e14,0x7c00100,0xfe530000,0x320a3f16,0x7c00100,0xc8e30c10,0x320a4400,0x4000000,0xc8e00003,0x320a4929,0x4000000,0x44e00000,0x320a4f11,0x7c00300,0xc8e30001, -0x320a6b16,0x7c00100,0xa530c00,0x32406396,0xc000010,0x84448000,0x324a3dcf,0x4000000,0x4e00000,0x324a3dcf,0x7c00100,0x11230400,0x324a3fca,0x4000002,0xf9200c00,0x324a53c7, -0x24000000,0x14e00000,0x32820701,0x2802000,0x8962460,0x40000419,0x7c00100,0x10220400,0x40000419,0x7c00100,0x20220400,0x40000519,0x7c00100,0x10220400,0x40000600,0x4000400, -0x4200400,0x4000080e,0x7c00100,0x8220400,0x4000080e,0x7c00100,0x8250400,0x4000080e,0x7c00100,0xc8250402,0x40000c02,0x2802100,0x20962460,0x40000c02,0x2802400,0x20962460, -0x40000c02,0x2802500,0x20962460,0x40000c02,0x4000000,0x4200000,0x40000c02,0x4000000,0x5071400,0x40000c02,0x7c00100,0xfc230400,0x40000c02,0x80000000,0x5329960,0x40000d22, -0x7c00100,0x40230400,0x40000f0a,0x7c00100,0xfc230400,0x40001004,0x7c00100,0xfc230400,0x40001110,0x2802100,0xfc962460,0x40001110,0x6800100,0xfc962540,0x4000120f,0x2802100, -0xfc962460,0x4000120f,0x4000000,0x5600000,0x4000120f,0x7c00100,0xfc230400,0x4000131f,0x7c00100,0xfc230400,0x40001423,0x4000000,0x4200000,0x40001423,0x4000000,0x5600000, -0x40001615,0x2802400,0xfc962460,0x40001615,0x7c00100,0xfc230400,0x40002417,0x2802400,0x19862460,0x40002417,0x4000000,0x4200000,0x40002800,0x6800000,0x20201c00,0x40002800, -0x24000002,0x4200000,0x40002c00,0x4000000,0xc8200002,0x40003000,0x24000000,0x4200000,0x40003000,0x24000020,0x4200000,0x40003700,0x24000000,0x4200000,0x40005a09,0x7c00100, -0x80220400,0x40005a09,0x7c00100,0x80250400,0x40005d00,0x7c00120,0xc8220405,0x40006f30,0x2802100,0x40962460,0x40006f30,0x2802400,0x40962460,0x40006f30,0x4000000,0x44200000, -0x40006f30,0x6800000,0x41329800,0x40006f30,0x6800100,0x40962540,0x40006f30,0x7c00100,0x40230400,0x40006f30,0xc000010,0x44b48000,0x40007034,0x7c00100,0x41830000,0x40007117, -0x4000000,0x4200000,0x40007208,0x7c00100,0x10220400,0x4000720e,0x7c00100,0x10220400,0x4000720e,0x7c00500,0xc822040e,0x4000720e,0x7c00500,0xc822040f,0x40007219,0x7c00100, -0x10220400,0x40007219,0x7c00500,0x10220400,0x40007219,0x7c00500,0xc822040e,0x40007219,0x7c00500,0xc822040f,0x40007300,0x24000000,0x4200000,0x40007400,0x4000000,0x14200000, -0x40007531,0x7c00100,0x80230400,0x40007631,0x7c00100,0x80230400,0x40007835,0x4000010,0x84400000,0x40007835,0x7c00100,0x80230400,0x40007933,0x7c00100,0x80230400,0x40007a32, -0x6800000,0x81329800,0x40007a32,0x7c00100,0x80230400,0x40007b2f,0x7c00100,0x80230400,0x40007c00,0x4000000,0x14200000,0x40020701,0x2802400,0x10962460,0x40020701,0x2802400, -0x10c62460,0x40023300,0x4000000,0x14200000,0x40027d01,0x12882000,0xc4962460,0x400a3700,0x24000000,0x4200000,0x400a3700,0x24000000,0x4e00000,0x400a4400,0x4000000,0xc8e0000d, -0x400a4412,0x4000000,0xc8e00002,0x400a4412,0x4000000,0xc8e00003,0x400a4500,0x4000000,0xc8e0000d,0x400a5300,0x4000000,0xc8810010,0x400a5300,0x4000000,0xc9410010,0x40507719, -0x4000000,0x84200000,0x4050771c,0x4000000,0x84400000,0x4050771f,0x4000000,0x84200000,0x4050771f,0x4000000,0x84400000,0x40c01489,0x4000000,0x4200000,0x40d05117,0x4000000, -0x14200000,0x41000419,0x7c00100,0x20220400,0x41000419,0x7c00100,0x20250400,0x4100080e,0x7c00100,0xfc220400,0x4100080e,0x7c00100,0xfc250400,0x41000908,0x7c00100,0xfc220400, -0x41000908,0x7c00100,0xfc250400,0x41000b13,0x2802000,0x28962460,0x41000b13,0x2802100,0x28962460,0x41000b13,0x2802100,0x30962460,0x41000b13,0x4000000,0xcb00000,0x41000c02, -0x2802100,0x20962460,0x41000c02,0x4000000,0x5500000,0x41000c02,0xc000010,0x4b48000,0x41000f0a,0x7c00100,0xfc230400,0x41001004,0x7c00100,0xfc230400,0x41001423,0x7c00100, -0xfc230400,0x41001b27,0x4000000,0x4500000,0x41001d0c,0x7c00100,0xc822040f,0x41001d0c,0x7c00100,0xfc230400,0x41001f0b,0x2802400,0xfc962460,0x41001f0b,0x4000000,0x4200000, -0x41001f0b,0x7c00100,0xfc230400,0x41002800,0x24000000,0x4200000,0x41002800,0x24000000,0xc200000,0x41002800,0x24000000,0xc400000,0x41002919,0x7c00100,0xc822040e,0x41002a00, -0x4000000,0x5600000,0x41002b01,0x2802020,0x10962460,0x41002c00,0x4000000,0x4200000,0x41002c00,0x7c00120,0xc8220405,0x41003000,0x24000000,0x4200000,0x41003700,0x24000000, -0x4200000,0x41003700,0x24000000,0x4e00000,0x41005d00,0x7c00120,0xc8220405,0x41006600,0x24000020,0x4200000,0x41006600,0x24000020,0x4810000,0x41006600,0x24000020,0x5410000, -0x41007208,0x7c00100,0xc822040f,0x41007219,0x7c00100,0x10220400,0x41007300,0x24000000,0x4200000,0x41007e0e,0x2802000,0x18962460,0x41007e0e,0x4000000,0xc200000,0x41007f0e, -0x4000000,0x4200000,0x41007f0e,0x7c00100,0x8230400,0x41008002,0x7c00100,0xfc230400,0x41008137,0x2802100,0x80962460,0x41008137,0x4000000,0x84200000,0x41008137,0x6800100, -0x80962540,0x41008137,0x7c00100,0x80230400,0x41008301,0x2802000,0x18962460,0x41008407,0x4000000,0x84200000,0x41008407,0x4000000,0x84400000,0x41008407,0x4000000,0x84b00000, -0x41008407,0x7c00100,0x80220400,0x41008407,0x7c00100,0x80250400,0x4100850b,0x7c00100,0xfc230400,0x4100860b,0x4000000,0x4200000,0x4100860b,0x7c00100,0xfc230400,0x4100870c, -0x7c00100,0x8220400,0x41008838,0x7c00100,0x80220400,0x41008838,0x7c00100,0x80250400,0x41008939,0x2802000,0x80962460,0x41008939,0x2802100,0x80962460,0x41008939,0x2806000, -0x80962460,0x41008939,0x4000000,0x84200000,0x41008939,0x4000000,0x84400000,0x41008939,0x7c00100,0x80230400,0x41008939,0xc000010,0x84448000,0x41008a00,0x4000400,0x14200400, -0x41008b3b,0x4000000,0x45800000,0x41008b3b,0x6800000,0x41329800,0x41008b3b,0x7c00100,0x41830000,0x41008b3b,0x7e00100,0x41830000,0x41008c3d,0x4000010,0x84400000,0x41008c3d, -0x7c00100,0x80230400,0x41008d0e,0x7c00100,0xc822040f,0x41008d19,0x7c00100,0x10220400,0x41008d19,0x7c00100,0xc822040f,0x41008e00,0x24000000,0x5710000,0x41008e00,0x24000000, -0xc200000,0x41008e00,0x24000000,0xc400000,0x41008e00,0x24000000,0x1d710000,0x41008e00,0x24000006,0x4400000,0x41008f3a,0x2802100,0x40962460,0x41008f3a,0x2806000,0x40962460, -0x41008f3a,0x4000000,0x44200000,0x41008f3a,0x6800100,0x40962540,0x41008f3a,0x7c00100,0x40230400,0x4100903c,0x7c00100,0x40230400,0x4100903c,0x7c00100,0xc823040f,0x41020701, -0x2802000,0x10962460,0x41020701,0x2802000,0x10c62460,0x41020701,0x2802000,0x20962460,0x410a3700,0x24000000,0x4200000,0x410a3700,0x24000000,0x4e00000,0x410a4412,0x4000000, -0xc8e00003,0x410a4711,0x7c40300,0xfce30000,0x410a4f11,0x7c00300,0xc8e30001,0x410a9100,0x4000000,0xc8800010,0x410a9100,0x4000000,0xc8810010,0x410a9100,0x4000000,0xc8870010, -0x410a9100,0x4000000,0xc8b00010,0x410a9100,0x4000000,0xc8f00010,0x410a9100,0x4000000,0xc9001410,0x410a9100,0x4000000,0xc9071010,0x410a9100,0x4000000,0xc9071410,0x410a9100, -0x4000000,0xc9410010,0x41408ad2,0x4000400,0xc200000,0x414a82cc,0x4000000,0x4e00000,0x41808300,0x2802000,0x18962460,0x41c01489,0x6800000,0xfd329800,0x50000419,0x7c00100, -0x20220400,0x50000419,0x7c00100,0x20250400,0x5000080e,0x7c00100,0xfc220400,0x50000908,0x7c00100,0xfc220400,0x50000908,0x7c00100,0xfc250400,0x50000b13,0x2802500,0x20962460, -0x50000f0a,0x7c00100,0xfc230400,0x50001615,0x2802100,0xfc962460,0x50001615,0x7c00100,0xfc230400,0x50002b01,0x2802020,0x10962460,0x50002c00,0x4000000,0x4200000,0x50002c19, -0x7c00100,0x8220400,0x50002d19,0x7c00100,0x8220400,0x50003000,0x24000000,0x4200000,0x50003000,0x24000020,0x4200000,0x50003700,0x24000000,0x4200000,0x50005d00,0x7c00120, -0xc8220405,0x50005d00,0x7c00120,0xc8250405,0x50006108,0x7c00100,0xfc220400,0x50006108,0x7c00100,0xfc250400,0x50006600,0x24000020,0x4200000,0x50007300,0x24000000,0x4200000, -0x50008301,0x2802400,0x10962460,0x50008a00,0x7c00500,0xfc230400,0x50009257,0x2802400,0x40962460,0x50009257,0x4000000,0x44200000,0x50009257,0x4000010,0x45071400,0x50009257, -0x6800000,0x41329800,0x50009257,0x7c00100,0x40230400,0x50009257,0x7c00100,0x48230400,0x50009257,0x7c00500,0x40230400,0x50009257,0x7c00900,0x48230400,0x50009257,0xc000010, -0x44b48000,0x5000933e,0x2802100,0x40962460,0x5000933e,0x2802400,0x40962460,0x5000933e,0x2802400,0x50962460,0x5000933e,0x4000000,0x44400000,0x5000933e,0x4000000,0x44e00000, -0x5000933e,0x4000010,0x44400000,0x5000933e,0x6800000,0x40e29800,0x5000933e,0x6800100,0x40962540,0x5000933e,0x6800100,0x40962541,0x5000933e,0x6804400,0x42f62540,0x5000933e, -0x7c00100,0x42b30400,0x5000933e,0x7c00100,0x42b30401,0x5000933e,0xc000010,0x44448000,0x50009419,0x7c00100,0x8220400,0x50009419,0x7c00100,0x8250400,0x50009419,0x7c00100, -0x10220400,0x50009419,0x7c00100,0x10250400,0x50009419,0x7c00100,0x20220400,0x50009419,0x7c00100,0x20250400,0x50009500,0x4000400,0x4200400,0x5000965a,0x4000000,0x84500000, -0x5000965a,0x7c00100,0x80230400,0x5000965a,0xc000010,0x84b48000,0x5000975b,0x4000000,0x84200000,0x5000975b,0x4000010,0x84400000,0x5000975b,0x7c00100,0x80230400,0x50009865, -0x7c00100,0x80230400,0x50009965,0x4000010,0x84400000,0x50009965,0x7c00100,0x80230400,0x50409acc,0x4000000,0x4200000,0x5100080e,0x7c00100,0x8220400,0x5100080e,0x7c00100, -0x8250400,0x5100080e,0x7c00100,0x10250400,0x51000c02,0x2802100,0x20962460,0x51000c02,0x4000000,0x5500000,0x51000c02,0x4000020,0x4200000,0x51000c02,0x7c00100,0xfc230400, -0x51000f0a,0x7c00100,0xfc230400,0x51000f0a,0x7c00500,0xfc230400,0x51001110,0x2802100,0x20962460,0x5100131f,0x2802100,0x20962460,0x51001423,0x7c00100,0xfc230400,0x51001524, -0x2802100,0x20962460,0x51001524,0x4000000,0x4200000,0x51001524,0x7c00100,0x8230400,0x51001524,0x7c00100,0xfc230400,0x5100171a,0x2802100,0x20962460,0x5100171a,0x4000000, -0x4200000,0x5100171a,0x4000000,0x5500000,0x5100171a,0x7c00100,0xfc230400,0x51001b27,0x4000000,0x4200000,0x51001b27,0x4000000,0x4400000,0x51001b27,0x4000000,0x4500000, -0x51001b27,0x7c00100,0xfc230400,0x51001c1c,0x2802100,0xfd862460,0x51001c1c,0x2802500,0xfd862460,0x51001c1c,0x2806400,0xfd862460,0x51001c1c,0x4000000,0x5800000,0x51001c1c, -0x6800000,0xfd329800,0x51001c1c,0x6800100,0xfd862400,0x51001c1c,0x6800100,0xfd862540,0x51001c1c,0x6800500,0xfd862400,0x51001c1c,0x7c00100,0xfd830000,0x5100251b,0x7c00100, -0x80230400,0x51002619,0x7c00100,0x10220400,0x51002619,0x7c00100,0x10250400,0x51002619,0x7c00100,0xfc250400,0x51002800,0x80020,0xc4218820,0x51002c00,0x4000000,0xc200000, -0x51002d19,0x7c00100,0x8230400,0x51003700,0x24000000,0x4200000,0x51003700,0x24000000,0x4e00000,0x51005201,0x2802400,0x10962460,0x51005c00,0x4000000,0x14200000,0x51006108, -0x7c00100,0xfc220400,0x51006108,0x7c00100,0xfc250400,0x51006600,0x24000020,0x4200000,0x51006600,0x24000020,0x4810000,0x51006600,0x24000020,0x5410000,0x51007300,0x24000000, -0x4200000,0x51007300,0x24000020,0x4200000,0x51008002,0x7c00100,0xfc230400,0x51008301,0x2802000,0x10962460,0x51008301,0x2802000,0x18962460,0x51008301,0x2802400,0x10962460, -0x51008301,0x2802400,0x10c62460,0x51008301,0x2802400,0x18962460,0x51008a00,0x7c00500,0xfc230400,0x51008e00,0x24000000,0x4200000,0x51008e00,0x24000000,0x4400000,0x51008e00, -0x24000000,0x4810000,0x51008e00,0x24000000,0x5400000,0x51008e00,0x24000000,0x5410000,0x51008e00,0x24000000,0x5710000,0x51008e00,0x24000000,0xc400000,0x51008e00,0x24000002, -0x4200000,0x51008e00,0x24000500,0xc230400,0x51008e00,0x2c000010,0xcb48000,0x51009419,0x7c00100,0x8220400,0x51009419,0x7c00100,0x8250400,0x51009419,0x7c00100,0x10220400, -0x51009419,0x7c00100,0xc822040e,0x51009419,0x7c00100,0xc822040f,0x51009500,0x4000400,0x4200400,0x51009500,0x7c00500,0xfc230400,0x51009519,0x7c00100,0x8220400,0x51009519, -0x7c00100,0x8230400,0x51009519,0x7c00100,0x8250400,0x51009519,0x7c00100,0x18220400,0x51009519,0x7c00100,0x18250400,0x51009519,0x7c00100,0x20220400,0x51009519,0x7c00100, -0x20250400,0x51009519,0x7c00100,0xc822040f,0x51009b71,0x2802100,0x40962460,0x51009b71,0x6800000,0x41329800,0x51009b71,0x6800100,0x40962540,0x51009b71,0x6804400,0x40962540, -0x51009b71,0x7c00100,0x40230400,0x51009c52,0x2802100,0x40962460,0x51009c52,0x2802400,0x40962460,0x51009c52,0x2802d00,0x40962460,0x51009c52,0x4000010,0x44400000,0x51009c52, -0x6800000,0x41329800,0x51009c52,0x6800100,0x40962540,0x51009c52,0x7c00100,0x40230400,0x51009c52,0xc000010,0x44448000,0x51009d6d,0x6800000,0x41329800,0x51009d6d,0x7c00100, -0x40230400,0x51009d6d,0x7c00500,0x40230400,0x51009d6d,0x7c00d00,0x40230400,0x51009d6d,0xc000010,0x44448000,0x51009e08,0x2802100,0x8962460,0x51009f63,0x4000010,0x44400000, -0x51009f63,0x6800000,0x41329800,0x51009f63,0x7c00100,0x40230400,0x51009f63,0x7c00100,0x48230400,0x51009f63,0x7c00900,0x40230400,0x51009f63,0xc000010,0x44448000,0x51009f63, -0xc000010,0x44b48000,0x5100a008,0x2000,0xc962460,0x5100a008,0x2802400,0x20962460,0x5100a008,0x4000000,0x4200000,0x5100a008,0x4000000,0xc200000,0x5100a008,0x7c00100, -0x8220400,0x5100a008,0x7c00100,0x8230400,0x5100a008,0x7c00100,0x8250400,0x5100a008,0x7c00500,0xfc230400,0x5100a16f,0x2806400,0x40962460,0x5100a16f,0x6800000,0x41329800, -0x5100a16f,0x6800100,0x40962540,0x5100a16f,0x7c00100,0x40230400,0x5100a16f,0xc000010,0x44448000,0x5100a24f,0x2802100,0x40962460,0x5100a24f,0x2802400,0x40962460,0x5100a24f, -0x6800000,0x41329800,0x5100a24f,0x7c00100,0x40230400,0x5100a24f,0xc000010,0x44448000,0x5100a36e,0x2802100,0x80962460,0x5100a36e,0x4000000,0x84200000,0x5100a36e,0x6800100, -0x80962540,0x5100a36e,0x6804400,0x80962540,0x5100a36e,0x7c00100,0x80230400,0x5100a442,0x2802100,0x40962460,0x5100a442,0x4000000,0x44e00000,0x5100a442,0x6800000,0x40e29800, -0x5100a442,0x6800100,0x40962540,0x5100a442,0x7c00100,0x40430400,0x5100a442,0x7c00100,0x42d30400,0x5100a442,0xc000010,0x44448000,0x5100a500,0x4000000,0x4200000,0x5100a600, -0x4000000,0xc200000,0x5100a601,0x2802000,0x8962460,0x5100a76b,0x7c00100,0x80230400,0x5100a868,0x7c00100,0x80230400,0x5100a96c,0x4000000,0x84200000,0x5100a96c,0x7c00100, -0x80230400,0x5100aa00,0x4000000,0x4e00000,0x5100ab00,0x4000000,0x4e00000,0x51086600,0x24000020,0x4810000,0x51086600,0x24000020,0x5410000,0x510a4005,0x7c00100,0xfce30400, -0x510a4711,0x7c40300,0xfce30000,0x510a7300,0x24000000,0x4200000,0x510aaa00,0x4000000,0x4e00000,0x514a82cc,0x4000000,0x4e00000,0x5150a20e,0x4000400,0x4400000,0x51802bbe, -0x2802000,0x10962460,0x51c00908,0x2802400,0x18962460,0x51c0a008,0x2802400,0x20962460,0x52000f0a,0x2802100,0x20962460,0x52000f0a,0x6800100,0x8962540,0x52000f0a,0x7c00100, -0xfc230400,0x52001004,0x4000000,0x5600000,0x52001b00,0x4000000,0x4200000,0x52001c1c,0x2802100,0xfd862460,0x52001c1c,0x6800100,0xfd862400,0x52001c1c,0x6800500,0xfd862400, -0x52001e12,0x7c00100,0xa230500,0x52001e12,0x7c00100,0xa330520,0x52002128,0x4000002,0x44400000,0x52002128,0x7c00100,0x40230400,0x52002a00,0x4000000,0x5500000,0x52002a00, -0x4000000,0x5600000,0x52002d00,0x4000000,0xc8200006,0x52003000,0x24000000,0x4200000,0x52006108,0x7c00100,0xfc220400,0x52006108,0x7c00100,0xfc250400,0x52008301,0x2802400, -0x10962460,0x52008407,0x2802400,0x80962460,0x52008407,0x2802400,0x90962460,0x52008407,0x7c00100,0x80220400,0x52008407,0x7c00100,0x80250400,0x52008b3b,0x6800000,0x41800000, -0x52008b3b,0x7c00100,0x41830000,0x52008e00,0x24000000,0xc400000,0x52009419,0x7c00100,0x8250400,0x5200975b,0x4000000,0x84200000,0x5200ac7e,0x2802000,0x80962460,0x5200ac7e, -0x2802100,0x80962460,0x5200ac7e,0x2802400,0x80962460,0x5200ac7e,0x4000010,0x84200000,0x5200ac7e,0x7c00100,0x80230400,0x5200ac7e,0xc000010,0x84248000,0x5200ad28,0x7c00100, -0x40230400,0x5200ae6a,0x2802100,0x41862460,0x5200ae6a,0x2802400,0x40962460,0x5200ae6a,0x2802400,0x41862460,0x5200ae6a,0x2806000,0x41862460,0x5200ae6a,0x4000000,0x45800000, -0x5200ae6a,0x6800000,0x41329800,0x5200ae6a,0x6800100,0x41862400,0x5200ae6a,0x6800100,0x41862540,0x5200ae6a,0x7c00100,0x41830000,0x5200ae6a,0x7c00900,0x41830000,0x5200ae6a, -0xc000010,0x45848000,0x5200b083,0x4000010,0x44400000,0x5200b083,0x7c00100,0x40230400,0x5200b083,0xc000010,0x44448000,0x5200b182,0x2802400,0x40962460,0x5200b182,0x4000000, -0x44200000,0x5200b182,0x4000010,0x44400000,0x5200b182,0x7c00100,0x40230400,0x5200b182,0xc000010,0x44448000,0x5200b30a,0x2802400,0x8962460,0x5200b30a,0x4000000,0xc200000, -0x5200b30a,0x7c00100,0x8230400,0x5200b54e,0x2802100,0x40962460,0x5200b54e,0x2802400,0x40962460,0x5200b54e,0x4000000,0x44e00000,0x5200b54e,0x4000010,0x44400000,0x5200b54e, -0x6800000,0x40e29800,0x5200b54e,0x6800100,0x40962540,0x5200b54e,0x6804400,0x42f62540,0x5200b54e,0x7c00100,0x42b30400,0x5200b54e,0xc000010,0x44448000,0x5200b61c,0x4000000, -0x5800000,0x5200b61c,0x6800500,0xfd862400,0x5200b61c,0x7c00100,0xfd830000,0x5200b61c,0x7c00900,0xfd830000,0x5200b77f,0x2802100,0x41862460,0x5200b77f,0x2802400,0x41862460, -0x5200b77f,0x4000000,0x45800000,0x5200b77f,0x4000010,0x45800000,0x5200b77f,0x7c00100,0x41830000,0x5200b77f,0x7c00500,0x41830000,0x5200b77f,0x7c00900,0x41830000,0x5200b77f, -0x7e00100,0x41830000,0x5200b873,0x2802100,0x40962460,0x5200b873,0x2806400,0x40962460,0x5200b873,0x6800000,0x41329800,0x5200b873,0x6800100,0x40962540,0x5200b873,0x6800400, -0x40962540,0x5200b873,0x7c00100,0x40230400,0x5200b873,0xc000010,0x44448000,0x5200b912,0x7c00100,0xa230500,0x5200b912,0x7c00100,0xa330520,0x5200ba74,0x4000000,0x84200000, -0x5200ba74,0x4000010,0x84400000,0x5200ba74,0x7c00100,0x80230400,0x5200bb85,0x4000000,0x84200000,0x5200bb85,0x7c00100,0x80230400,0x5200bc75,0x4000000,0x84400000,0x5200bc75, -0x4000010,0x84400000,0x5200bc75,0x7c00100,0x80230400,0x5200bd7d,0x4000000,0x84200000,0x5200bd7d,0x7c00100,0x80230400,0x5200be7a,0x4000000,0x84200000,0x5200be7a,0x7c00100, -0x80230400,0x5200bf58,0x7c00100,0x80230400,0x5200c002,0x4000000,0x4200000,0x5200c178,0x2802100,0x80962460,0x5200c178,0x2802400,0x80962460,0x5200c178,0x2806400,0x80962460, -0x5200c178,0x4000000,0x84200000,0x5200c178,0x6800100,0x80962540,0x5200c178,0x7c00100,0x80230400,0x5200c178,0x7c00100,0x80230401,0x5200c178,0xc000010,0x84448000,0x5200c178, -0x80000000,0x85329960,0x5200c247,0x7c00100,0x80230400,0x5200c247,0x7c00100,0x80830400,0x5200c247,0x7c00100,0x81430400,0x5200c300,0x4000000,0xc8200003,0x52022d00,0x4000000, -0xc8100006,0x52023700,0x24000000,0x4100000,0x52023700,0x24000000,0x4e00000,0x52023700,0x24000000,0x6800000,0x52024400,0x4000000,0x4100000,0x52027300,0x24000000,0x4100000, -0x5202c300,0x4000000,0x4100000,0x5202c300,0x4000000,0xc8100002,0x5202c300,0x4000000,0xc8100003,0x5202c300,0x4000000,0xc810000d,0x5202c300,0x4000100,0x4150400,0x5202c300, -0x4000100,0xc815040d,0x520a1e12,0x7c00100,0xa130480,0x520a3700,0x24000000,0x4e00000,0x520a3800,0x24000000,0x4100000,0x520a4711,0x7c40300,0xfce30000,0x520a4f11,0x7c00300, -0xc8e30001,0x520a7300,0x24000000,0x4100000,0x520ab412,0x7c00100,0xa130480,0x520ac400,0x4000000,0xc8e00002,0x520ac400,0x4000000,0xc8e0000d,0x520ac414,0x4000000,0xc8e0000d, -0x520ac511,0x7c40300,0xfce30000,0x5240af9c,0x7c00100,0x8230400,0x5240afa1,0x4000400,0xc200000,0x5240afa3,0x6800400,0x8962540,0x5240afa3,0x7c00100,0x8230400,0x5240afad, -0x7c00100,0x8230400,0x5240afaf,0x7c00100,0x8230400,0x5240b2d4,0x4000000,0x4200000,0x5240b2e3,0x4000000,0x4200000,0x5240b2f1,0x4000000,0x4200000,0x5240b2fc,0x4000000, -0x5500000,0x524a44cc,0x4000000,0xc8e00003,0x5250b511,0x7c00900,0x60430400,0x5280af9c,0x2802400,0x8962460,0x5280af9d,0x2802400,0x8962460,0x5280afa3,0x2802400,0x8962460, -0x5280afa5,0x2802400,0x8962460,0x5280afa7,0x2802400,0x8962460,0x52d0b308,0x2802400,0x8962460,0x52d0b30c,0x7c00100,0x8230400,0x60000c02,0x2802100,0x20962460,0x60000c02, -0x7c00100,0xfc230400,0x60000f0a,0x2802100,0xfc962460,0x60000f0a,0x6800100,0xfc962540,0x60000f0a,0x7c00100,0xfc230400,0x6000131f,0x4000000,0x4200000,0x6000171a,0x7c00100, -0xfc230400,0x6000171a,0x7c00100,0xfc230560,0x60001b27,0x2802100,0xfc962460,0x60001b27,0x4000000,0x4c00000,0x60001b27,0x7c00100,0xfc230400,0x60001f0b,0x2802400,0xfc962460, -0x60002919,0x7c00100,0xc822040e,0x60002a00,0x4000000,0x5600000,0x60003000,0x24000000,0x4200000,0x60003000,0x24000000,0x4e00000,0x60003700,0x24000000,0x4200000,0x60003800, -0x24000000,0x5710000,0x60005102,0x4000000,0x14200000,0x60006108,0x7c00100,0xfc220400,0x60006108,0x7c00100,0xfc250400,0x60006600,0x24000020,0x4200000,0x60008301,0x2802400, -0x10c62460,0x6000903c,0x2806000,0x40962460,0x6000903c,0x4000000,0x44400000,0x60009519,0x7c00100,0x8220400,0x60009519,0x7c00100,0x8250400,0x60009519,0x7c00100,0x10220400, -0x60009519,0x7c00100,0xfc250400,0x6000a008,0x7c00100,0x8220400,0x6000a008,0x7c00100,0x8250400,0x6000c300,0x4000000,0x6703580,0x6000c654,0x2802000,0x40962460,0x6000c654, -0x4000010,0x44200000,0x6000c654,0x7c00100,0x40230400,0x6000c73f,0x2802000,0x40962460,0x6000c73f,0x2802100,0x40962460,0x6000c73f,0x4000000,0x44200000,0x6000c73f,0x6800100, -0x40962540,0x6000c73f,0x6804000,0x42e62540,0x6000c73f,0x7c00100,0x42d30400,0x6000c80b,0x7c00100,0xfc230400,0x6000c941,0x2802100,0x80962460,0x6000c941,0x2806400,0x82f62460, -0x6000c941,0x4000000,0x84e00000,0x6000c941,0x4000010,0x84e00000,0x6000c941,0x6800000,0x82d29800,0x6000c941,0x6800100,0x80962540,0x6000c941,0x7c00100,0x82b30400,0x6000c941, -0x7c00100,0x82c30400,0x6000c941,0xc000010,0x84448000,0x6000ca82,0x7c00100,0x40230400,0x6000cc00,0x4000000,0x4e00000,0x6000d000,0x4000000,0x4200000,0x6002c300,0x4000000, -0x4100000,0x6002c300,0x4000000,0xc810000d,0x6002c300,0x4000100,0x4150400,0x6002c300,0x4000100,0xc815040d,0x600a3000,0x24000000,0x4200000,0x600a3000,0x24000000,0x4e00000, -0x600a3700,0x24000000,0x4200000,0x600a3800,0x24000000,0x4200000,0x600a3800,0x24000000,0x6800000,0x600a4305,0x7c00100,0xfce30400,0x600ac300,0x4000000,0x4100000,0x600ac400, -0x4000000,0xc8e0000d,0x600acb14,0x7c00100,0x8e30000,0x600acb16,0x7c00100,0x8e30c00,0x600acc00,0x4000000,0x4e00000,0x600acd00,0x4000000,0x4200000,0x600acd00,0x4000000, -0x4e00000,0x600acd00,0x4000000,0x6800000,0x600ace00,0x4000000,0x4e00000,0x600ace00,0x4000000,0x6800000,0x600acf00,0x4000000,0x4e00000,0x600acf00,0x4000000,0x6800000, -0x600ad111,0x7c40300,0xfce30000,0x604ac4cc,0x4000000,0xc8e00003,0x61000a03,0x4000000,0x5600000,0x61000c02,0x80000000,0x5329960,0x6100120f,0x4000000,0x4200000,0x61001a18, -0x7c00100,0xfd830000,0x61001d0c,0x7c00100,0xfc230400,0x61001d0c,0x7c00100,0xfc250400,0x61006600,0x24000020,0x4200000,0x61008407,0x7c00100,0x80220400,0x61008407,0x7c00100, -0x80250400,0x6100870c,0x7c00100,0xfc220400,0x61008e00,0x24000000,0x4200000,0x61008e00,0x24000000,0x4400000,0x61008e00,0x24000000,0xc200000,0x61008e00,0x24000002,0x4300000, -0x6100903c,0x7c00100,0x40230400,0x61009519,0x7c00100,0xfc220400,0x61009519,0x7c00100,0xfc250400,0x61009519,0x7c00500,0xc822040f,0x61009b71,0x2802100,0x40962460,0x61009b71, -0x2806400,0x40962460,0x61009b71,0x7c00100,0x40230400,0x6100a008,0x2802100,0x8962460,0x6100c300,0x4000000,0xc820000f,0x6100cd00,0x4000000,0x4200000,0x6100d202,0x2802400, -0x20962460,0x6100d202,0x2802500,0x20962460,0x6100d202,0x7c00100,0xfc230400,0x6100d302,0x4000020,0x4200000,0x6100d302,0x7c00120,0xc8230405,0x6100d476,0x2802100,0x40962460, -0x6100d476,0x2802100,0x40962461,0x6100d476,0x2806400,0x40962460,0x6100d476,0x4000000,0x44400000,0x6100d476,0x6800000,0x41329800,0x6100d476,0x6800100,0x40962540,0x6100d476, -0x7c00100,0x40230400,0x6100d476,0xc000010,0x44448000,0x6100d573,0x2802100,0x40962460,0x6100d573,0x2806400,0x40962460,0x6100d573,0x6800100,0x40962540,0x6100d573,0x7c00100, -0x40230400,0x6100d573,0x7c00900,0x40230400,0x6100d573,0xc000010,0x44448000,0x6100d68d,0x7c00100,0x80230400,0x6100d756,0x7c00100,0x80230400,0x6100d85c,0x2802500,0x40962460, -0x6100d85c,0x6800100,0x40962540,0x6100d85c,0x7c00100,0x40230400,0x6100d85c,0x7c00500,0x40230400,0x6100d997,0x2802100,0x80962460,0x6100d997,0x4000000,0x84200000,0x6100d997, -0x4000000,0x84400000,0x6100d997,0x6800000,0x81329800,0x6100d997,0x6800100,0x80962540,0x6100d997,0x6804400,0x80962540,0x6100d997,0x7c00100,0x80230400,0x6100d997,0x7c00100, -0x80230560,0x6100d997,0xc000010,0x84448000,0x6100da98,0x6800000,0x81329800,0x6100da98,0x7c00100,0x80230400,0x6100db71,0x4000000,0x44200000,0x6100dc99,0x2802100,0x80962460, -0x6100dc99,0x2802400,0x80962460,0x6100dc99,0x6800000,0x81329800,0x6100dc99,0x6800100,0x80962540,0x6100dc99,0x6804400,0x80962540,0x6100dc99,0x7c00100,0x80230400,0x610a4711, -0x7c40300,0xfce30000,0x610a4f11,0x7c00300,0xc8e30001,0x610ace00,0x4000000,0x4e00000,0x6140afa1,0x7c00100,0x8230400,0x6140afa3,0x7c00100,0x8230400,0x6180af9e,0x2802400, -0x8962460,0x62002a00,0x4000000,0x5600000,0x63002800,0x80000,0xc4918820,0x63c00c15,0x80000,0xc4918820,0x7000080e,0x7c00100,0x8250400,0x70000a03,0x4000000,0x4200000, -0x70000c00,0x80000000,0x5329960,0x70000f0a,0x7c00100,0x8230400,0x70001004,0x7c00100,0x8230400,0x70001524,0x2802100,0x8962460,0x70001524,0x7c00100,0x8230400,0x70001615, -0x2802100,0x8962460,0x7000171a,0x2802100,0x8962460,0x70001821,0x6800000,0x9329800,0x70002320,0x7c00100,0x80230400,0x70002a00,0x4000000,0x5500000,0x70002a00,0x4000000, -0x5600000,0x70003000,0x24000000,0x4200000,0x70003800,0x24000000,0x4e00000,0x70005201,0x2802400,0x10962460,0x7000581e,0x7c00100,0x80230400,0x70006108,0x7c00100,0x8220400, -0x70006108,0x7c00100,0x8250400,0x70006108,0x7c00100,0xfc220400,0x70006108,0x7c00100,0xfc250400,0x70006f30,0x7c00100,0x40230400,0x70007300,0x24000000,0x4200000,0x70007f0e, -0x4000000,0x4200000,0x70008301,0x2802100,0x10962460,0x70008301,0x2802400,0x10962460,0x70008e00,0x24000000,0x4200000,0x70008e00,0x24000000,0x4400000,0x70008e00,0x24000002, -0x4400000,0x70008e00,0x24000008,0x5410000,0x70008e00,0x24000010,0x4400000,0x70008e00,0x2c000010,0x4448000,0x70009519,0x7c00100,0x8220400,0x70009519,0x7c00100,0x8230400, -0x70009519,0x7c00100,0x8250400,0x70009865,0x7c00100,0x80230400,0x70009965,0x4000010,0x84400000,0x70009965,0x7c00100,0x80230400,0x7000a008,0x7c00100,0x8220400,0x7000a008, -0x7c00100,0x8250400,0x7000a008,0x7c00500,0xc822040f,0x7000a50e,0x4000000,0x4200000,0x7000b61c,0x2802500,0xfd862460,0x7000b61c,0x6800500,0xfd862400,0x7000b61c,0x7c00100, -0xfd830000,0x7000c300,0x4000000,0x4100000,0x7000c941,0x2806000,0x80c62460,0x7000cc00,0x4000000,0x4e00000,0x7000cd00,0x4000000,0x4200000,0x7000cd00,0x4000000,0x4e00000, -0x7000cd00,0x4000000,0x6800000,0x7000cf00,0x4000000,0x4e00000,0x7000d202,0x2802100,0x20962460,0x7000d202,0x7c00100,0x8230400,0x7000d202,0x7c00100,0xfc230400,0x7000d997, -0x7c00100,0x80230400,0x7000d997,0xc000010,0x84248000,0x7000dd86,0x2802400,0x80962460,0x7000dd86,0x7c00100,0x80230400,0x7000dd86,0xc000010,0x84448000,0x7000de9f,0x4000000, -0x84200000,0x7000de9f,0x7c00100,0x80230400,0x7000e001,0x2400,0x4962460,0x7000e001,0x2802400,0x8962460,0x7000e187,0x2802000,0x80962460,0x7000e187,0x2802100,0x80962460, -0x7000e187,0x4000000,0x84200000,0x7000e187,0x7c00100,0x80230400,0x7000e187,0xc000010,0x84448000,0x7000e288,0x7c00100,0x80230400,0x7000e300,0x4000000,0x4200000,0x7000e489, -0x2802100,0x80962460,0x7000e489,0x2802400,0x80962460,0x7000e489,0x6800100,0x80962540,0x7000e489,0x6800100,0x80962541,0x7000e489,0x6804400,0x82f62540,0x7000e489,0x7c00100, -0x80430400,0x7000e489,0x7c00100,0x82b30400,0x7000e489,0x7c00100,0x82d30400,0x7000e489,0x7c00900,0x80430400,0x7000e59d,0x2802100,0x80962460,0x7000e59d,0x2802400,0x80962460, -0x7000e59d,0x4000000,0x84200000,0x7000e59d,0x4000010,0x84200000,0x7000e59d,0x6800100,0x80962540,0x7000e59d,0x6804400,0x80962540,0x7000e59d,0x7c00100,0x80230400,0x7000e59d, -0xc000010,0x84448000,0x7000e691,0x2802100,0x80962460,0x7000e691,0x2802400,0x80962460,0x7000e691,0x2806400,0x80962460,0x7000e691,0x6800000,0x81329800,0x7000e691,0x6800100, -0x80962540,0x7000e691,0x7c00100,0x80230400,0x7000e700,0x4000400,0x4200400,0x7000e70e,0x7c00100,0x8220400,0x7000e719,0x7c00100,0x8220400,0x7000e719,0x7c00500,0xc822040f, -0x7000e853,0x7c00100,0x80230400,0x7000e9a0,0x2802400,0x80962460,0x7000e9a0,0x4000000,0x84200000,0x7000e9a0,0x4000000,0x84500000,0x7000e9a0,0x7c00100,0x80230400,0x7000ea79, -0x2802400,0x80962460,0x7000ea79,0x4000000,0x84200000,0x7000ea79,0x4000000,0x84f00000,0x7000ea79,0x4000010,0x84400000,0x7000ea79,0x7c00100,0x80230400,0x7000eb8c,0x2802400, -0x80962460,0x7000eb8c,0x4000000,0x84200000,0x7000eb8c,0x7c00100,0x80230400,0x7000eca3,0x2802100,0x80962460,0x7000eca3,0x2806400,0x80962460,0x7000eca3,0x4000000,0x84200000, -0x7000eca3,0x6800000,0x81329800,0x7000eca3,0x6800100,0x80962540,0x7000eca3,0x7c00100,0x80230400,0x7000eca3,0xc000010,0x84448000,0x7000ed95,0x6800000,0xa1329800,0x7000ed95, -0x7c00100,0xa0230400,0x7000ed95,0xc000010,0x84448000,0x7000ee1c,0x2802500,0x9862460,0x7000ee1c,0x6800000,0xfd329800,0x7000ee1c,0x7c00100,0x9830000,0x7000ee1c,0x7c00100, -0xfd830000,0x7000ee1c,0x7c00900,0x9830000,0x7000ef8f,0x4000000,0x84200000,0x7000ef8f,0x7c00100,0x80230400,0x7000f08e,0x4000000,0x84200000,0x7000f08e,0x7c00100,0x80230400, -0x7000f159,0x2802100,0x80962460,0x7000f159,0x7c00100,0x80230400,0x7000f200,0x4000000,0x4200000,0x7000f200,0x4000000,0x5200000,0x7000f200,0x4000000,0x5710000,0x7000f34b, -0x2802400,0x80962460,0x7000f34b,0x4000000,0x84200000,0x7000f34b,0x4000010,0x84400000,0x7000f34b,0x6800000,0x81329800,0x7000f34b,0x7c00100,0x80230400,0x7000f34b,0x7c00900, -0x80230400,0x7000f34b,0xc000010,0x84448000,0x7000f490,0x4000000,0x84200000,0x7000f490,0x7c00100,0x80230400,0x7000f5a5,0x7c00100,0x80230400,0x7000f67b,0x4000000,0x84200000, -0x7000f67b,0x4000010,0x84200000,0x7000f67b,0x7c00100,0x80230400,0x7000f8a6,0x2802100,0x80962460,0x7000f8a6,0x2802400,0x80962460,0x7000f8a6,0x2806400,0x80962460,0x7000f8a6, -0x4000000,0x84500000,0x7000f8a6,0x4000010,0x84b00000,0x7000f8a6,0x4000800,0x84200000,0x7000f8a6,0x6800100,0x80962540,0x7000f8a6,0x6800100,0x80962541,0x7000f8a6,0x7c00100, -0x80230400,0x7000f8a6,0xc000010,0x84448000,0x7000f921,0x4000000,0x4200000,0x7000fa00,0x4000000,0x4200000,0x7000fb9e,0x2802100,0x80962460,0x7000fb9e,0x2802400,0x80962460, -0x7000fb9e,0x2806400,0x80962460,0x7000fb9e,0x4000000,0x84200000,0x7000fb9e,0x6800000,0x81329800,0x7000fb9e,0x6800100,0x80962540,0x7000fb9e,0x6800100,0x80962541,0x7000fb9e, -0x7c00100,0x80230400,0x7000fc92,0x4000000,0x84200000,0x7000fc92,0x6800000,0x81329800,0x7000fc92,0x7c00100,0x80220400,0x7000fc92,0x7c00100,0x80230400,0x7000fc92,0x7c00100, -0x80250400,0x700acd00,0x4000000,0x4e00000,0x700acd00,0x4000000,0x6800000,0x700ace00,0x4000000,0x4e00000,0x700acf00,0x4000000,0x4e00000,0x700acf00,0x4000000,0x6800000, -0x7050df21,0x4000000,0xc200000,0x7050f729,0x80000,0xc4918820,0x7080afa1,0x2802400,0x8962460,0x7090df21,0x2802400,0x8962460,0x70d0e427,0x2802100,0xfc962460,0x70d0e427, -0x2802400,0xfc962460,0x70d0e427,0x6800100,0xfc962540,0x70d0ea25,0x4000010,0x84400000,0x8000120f,0x7c00100,0x20230400,0x80001524,0x7c00100,0x20230400,0x8000171a,0x7c00100, -0x8230400,0x80002006,0x7c00100,0x40220400,0x80002006,0x7c00100,0x40250400,0x80002a00,0x4000000,0x5500000,0x80002d00,0x4000000,0x24200000,0x80005208,0x2802400,0x30962460, -0x80005c00,0x4000000,0x34200000,0x80007300,0x24000000,0x24200000,0x80009519,0x7c00100,0x20220400,0x80009519,0x7c00100,0x20230400,0x80009519,0x7c00100,0x20250400,0x80009865, -0x7c00100,0x80230400,0x8000a008,0x2802100,0x28962460,0x8000b30a,0x4000000,0x2c500000,0x8000b30a,0x7c00100,0x28230400,0x8000cd00,0x4000000,0x24e00000,0x8000d202,0x2802500, -0x20962460,0x8000d202,0x7c00100,0x20230400,0x8000d68d,0x4000000,0x84200000,0x8000d997,0x2802000,0x80962460,0x8000d997,0x2802400,0x80962460,0x8000d997,0x4000000,0x84400000, -0x8000d997,0x4000000,0x84500000,0x8000d997,0x7c00100,0x80230400,0x8000d997,0xc000010,0x84448000,0x8000e489,0x2802100,0x80962460,0x8000e489,0x7c00100,0x82d30400,0x8000e719, -0x7c00100,0x20220400,0x8000f8a6,0x2802100,0x80962460,0x8000f8a6,0x7c00100,0x80230400,0x8000f8a6,0xc000010,0x84448000,0x8000fda1,0x2802100,0x81862460,0x8000fda1,0x2806400, -0x81862460,0x8000fda1,0x4000000,0x85800000,0x8000fda1,0x6800000,0x81329800,0x8000fda1,0x6800100,0x81862400,0x8000fda1,0x6800100,0x81862540,0x8000fda1,0x7c00100,0x81830000, -0x8000fda1,0xc000010,0x84448000,0x8000fe9c,0x7c00100,0x80230400,0x8000fe9c,0x7c00100,0x80830400,0x8000fe9c,0x7c00100,0x81430400,0x8000ff06,0x7c00100,0x40220400,0x80010165, -0x7c00100,0x80230400,0x800102a2,0x4000000,0x84200000,0x800102a2,0x7c00100,0x80230400,0x800103a4,0x7c00100,0x80230400,0x800103a4,0xc000010,0x84448000,0x8001044c,0x4000000, -0x84200000,0x8001044c,0x7c00100,0x80220400,0x8001044c,0x7c00100,0x80250400,0x80010670,0x2802000,0x80962460,0x80010670,0x4000000,0x84200000,0x80010670,0x4000010,0x84400000, -0x80010670,0xc000010,0x84448000,0x800a4711,0x7c40300,0xfce30000,0x800acd00,0x4000000,0x4e00000,0x800acd00,0x4000000,0x6902460,0x800ace00,0x4000000,0x4e00000,0x800acf00, -0x4000000,0x4e00000,0x800b0011,0x7c40300,0xfce30000,0x800b0500,0x4000000,0x4e00000,0x800b0500,0x4000000,0x6800000,0x90001615,0x7c00100,0xfc230400,0x9000171a,0x4000000, -0x4200000,0x9000171a,0x7c00100,0xfc230400,0x90003000,0x24000000,0x4200000,0x90007f0e,0x4000000,0x4200000,0x90008301,0x2802400,0x10962460,0x90008e00,0x24000000,0x4400000, -0x90009519,0x7c00100,0x10250400,0x9000a16f,0x2802100,0x40962460,0x9000d200,0x80000000,0x5329960,0x9000d202,0x2802000,0x20962460,0x9000d202,0x2802100,0x20962460,0x9000d202, -0x7c00100,0xfc230400,0x9000e59d,0x2802100,0x80962460,0x90010500,0x4000000,0x4e00000,0x900107a7,0x2802100,0x40962460,0x900107a7,0x2802400,0x40962460,0x900107a7,0x2802c00, -0x40962460,0x900107a7,0x4000000,0x45400000,0x900107a7,0x6800000,0x41329800,0x900107a7,0x7c00100,0x40220400,0x900107a7,0x7c00100,0x40250400,0x900108a8,0x2802100,0x80962460, -0x900108a8,0x2806400,0x80962460,0x900108a8,0x4000000,0x84200000,0x900108a8,0x4000000,0x84400000,0x900108a8,0x4000010,0x84400000,0x900108a8,0x6800000,0x81329800,0x900108a8, -0x6800100,0x80962540,0x900108a8,0x7c00100,0x80230400,0x900108a8,0xc000010,0x84448000,0x90010908,0x7c00100,0x8220400,0x90010a38,0x2802100,0x80962460,0x90010ca9,0x2802100, -0x80962460,0x90010ca9,0x4000000,0x84500000,0x90010ca9,0x4000010,0x84b00000,0x90010ca9,0x6800100,0x80962540,0x90010ca9,0x7c00100,0x80230400,0x90010d1b,0x4000000,0x84500000, -0x90010eaa,0x2802100,0x40962460,0x90010eaa,0x2802400,0x40962460,0x90010eaa,0x2806400,0x40962460,0x90010eaa,0x4000000,0x44200000,0x90010eaa,0x4000000,0x44400000,0x90010eaa, -0x4000010,0x44400000,0x90010eaa,0x6800000,0x41329800,0x90010eaa,0x6800100,0x40962540,0x90010eaa,0x7c00100,0x40230400,0x90010eaa,0xc000010,0x44448000,0x90010fab,0x7c00100, -0x40220400,0x90010fab,0x7c00100,0x40250400,0x9002c300,0x4000000,0x4100000,0x900ac400,0x4000000,0xc8e0000d,0x900acd00,0x4000000,0x4e00000,0x900acd00,0x4000000,0x6800000, -0x900acf00,0x4000000,0x4e00000,0x900b0500,0x4000000,0x4e00000,0x900b0500,0x4000000,0x6800000,0x900b0b9a,0x7c00900,0x81230400,0x900b109a,0x7c00300,0x80e30000,0x900b119a, -0x7c00300,0x80e30000,0x90408e06,0x24000000,0x4400000,0xa0001004,0x4000000,0x4200000,0xa0001004,0x7c00100,0x8230400,0xa000120f,0x2802100,0xfc962460,0xa000120f,0x2802400, -0xfc962460,0xa000171a,0x2802100,0xfc962460,0xa000171a,0x2806400,0x8962460,0xa0002a00,0x4000000,0x5600000,0xa0003000,0x24000000,0x4200000,0xa000581e,0x7c00100,0x80230400, -0xa0007300,0x24000000,0x4200000,0xa0008301,0x2802400,0x10962460,0xa0008e00,0x24000000,0x4400000,0xa000cf00,0x4000000,0x4e00000,0xa0010500,0x4000000,0x4200000,0xa00114af, -0x2802100,0x80962460,0xa00114af,0x2802400,0x80962460,0xa00114af,0x2806400,0x80962460,0xa00114af,0x6800000,0x81329800,0xa00114af,0x7c00100,0x80230400,0xa00114af,0x7c00100, -0x80230560,0xa00116b0,0x2802100,0x80962460,0xa00116b0,0x2802800,0x80962460,0xa00116b0,0x2806400,0x80962460,0xa00116b0,0x4000000,0x84400000,0xa00116b0,0x4000000,0x84500000, -0xa00116b0,0x4000010,0x84400000,0xa00116b0,0x6800100,0x80962540,0xa00116b0,0x7c00100,0x80230400,0xa00116b0,0x7c00100,0x80230560,0xa00116b0,0xc000010,0x84448000,0xa0011722, -0x7c00100,0x40230400,0xa00118b1,0x2802000,0x80962460,0xa00118b1,0x2802100,0x80962460,0xa00118b1,0x2806400,0x80962460,0xa00118b1,0x4000000,0x84200000,0xa00118b1,0x4000000, -0x84400000,0xa00118b1,0x4000000,0x84500000,0xa00118b1,0x6800100,0x80962540,0xa00118b1,0x7c00100,0x80230400,0xa00118b1,0x7c00100,0x80230560,0xa00118b1,0xc000010,0x84448000, -0xa00a4005,0x7c00100,0x8e30400,0xa00a4711,0x7c40300,0xfce30000,0xa00ac400,0x4000000,0x4e00000,0xa00acb14,0x7c00100,0x8e30000,0xa00acf00,0x4000000,0x4e00000,0xa00b0500, -0x4000000,0x4e00000,0xa00b0500,0x4000000,0x6800000,0xa00b0b96,0x7c00900,0x81230400,0xa00b1211,0x7c40300,0xfce30000,0xa00b1314,0x7c00100,0x8e30000,0xa00b1596,0x7c00300, -0x80e30000,0xa040afb9,0x6800400,0x8962540,0xa08083ba,0x2802400,0x10962460,0xb0000a03,0x7c00100,0x10220400,0xb0000b13,0x7c00100,0xfe633800,0xb0001004,0x2802000,0xfc962460, -0xb0001110,0x4000000,0x4200000,0xb0001524,0x2802100,0xfc962460,0xb0001615,0x4000000,0x4500000,0xb000251b,0x7c00100,0x80230400,0xb0007300,0x24000000,0x4200000,0xb0008939, -0x4000000,0x84200000,0xb0008939,0x7c00100,0x80230400,0xb0008e00,0x24000000,0x4200000,0xb0008e00,0x24000000,0x4400000,0xb0008e00,0x24000010,0x4400000,0xb0009257,0x2802000, -0x40962460,0xb0009257,0x4000000,0x45600000,0xb0009519,0x7c00100,0x10220400,0xb0009519,0x7c00100,0x20220400,0xb0009519,0x7c00100,0x20250400,0xb0009a00,0x4000000,0x4200000, -0xb000b30a,0x2802100,0x8962460,0xb000b30a,0x7c00100,0x8230400,0xb000c178,0x80000000,0x85329960,0xb000c300,0x4000000,0x4200000,0xb000d202,0x2802000,0x20962460,0xb000d476, -0x6800100,0x40962540,0xb000d476,0x7c00100,0x40230400,0xb000e300,0x4000000,0x4e00000,0xb000fda1,0x7c00100,0x81830000,0xb0010eaa,0x2802000,0x40962460,0xb00116b0,0x7c00100, -0x80230400,0xb0011900,0x4000000,0x4e00000,0xb0011ab2,0x2802100,0x80962460,0xb0011ab2,0x2802400,0x80962460,0xb0011ab2,0x2806400,0x80962460,0xb0011ab2,0x4000000,0x84200000, -0xb0011ab2,0x6800100,0x80962540,0xb0011ab2,0x7c00100,0x80230400,0xb0011b0c,0x7c00100,0xfc230400,0xb0011cb3,0x2802100,0x40962460,0xb0011cb3,0x2806400,0x40962460,0xb0011cb3, -0x6800000,0x41329800,0xb0011cb3,0x6800100,0x40962540,0xb0011cb3,0x7c00100,0x40230400,0xb0011db6,0x2802500,0x40962460,0xb0011db6,0x6800000,0x41329800,0xb0011db6,0x7c00100, -0x40230400,0xb0011db6,0x7c00500,0x40230400,0xb0011e00,0x4000000,0x4200000,0xb0011e00,0x4000000,0x5500000,0xb0011fb4,0x2802100,0x80962460,0xb0011fb4,0x6800100,0x80962540, -0xb0011fb4,0x7c00100,0x80430400,0xb0011fb4,0x7c00100,0x82d30400,0xb0011fb4,0xc000010,0x84448000,0xb0012000,0x4000000,0x4200000,0xb00121b5,0x4000000,0x84200000,0xb00121b5, -0x4000010,0x84400000,0xb00121b5,0x7c00100,0x80220400,0xb00121b5,0x7c00100,0x80250400,0xb00121b5,0xc000010,0x84448000,0xb00122b8,0x4000000,0x84200000,0xb00122b8,0x7c00100, -0x80230400,0xb00123b7,0x2802400,0x80962460,0xb00123b7,0x4000000,0x84200000,0xb00123b7,0x7c00100,0x80230400,0xb00123b7,0xc000010,0x84248000,0xb00a4005,0x7c00100,0xfce30400, -0xb00a4711,0x7c40300,0xfce30000,0xb00acf00,0x4000000,0x4e00000,0xb00b0500,0x4000000,0x4e00000,0xb00b0500,0x4000000,0x6800000,0xb00b109a,0x7c00300,0x80e30000,0xb080e487, -0x2802000,0xfc962460,0xc0001524,0x4000000,0x4500000,0xc0001a18,0x2806400,0xfd862460,0xc0001a18,0x7c00100,0xfd830000,0xc0007300,0x24000000,0x4200000,0xc0008e00,0x24000010, -0x4400000,0xc0009519,0x7c00100,0x10220400,0xc0009519,0x7c00100,0x10250400,0xc0009519,0x7c00100,0xfc220400,0xc0009519,0x7c00100,0xfc250400,0xc000c300,0x4000000,0xc820000f, -0xc000d85c,0x2802100,0x40962460,0xc000d85c,0x6800100,0x40962540,0xc000d85c,0x7c00100,0x40230400,0xc000dc99,0x7c00100,0x80230400,0xc000e719,0x7c00100,0xfc220400,0xc00107a7, -0x7c00100,0x40230400,0xc0010eaa,0x7c00100,0x40230400,0xc00116b0,0x7c00100,0x80230560,0xc0011900,0x4000000,0x4200000,0xc0012447,0,0x84818820,0xc0012447,0, -0x84c18820,0xc0012447,0,0x85418820,0xc00125b9,0x7c00100,0x80230400,0xc00126bb,0x2802100,0x80962460,0xc00126bb,0x2806400,0x80962460,0xc00126bb,0x4000000,0x84500000, -0xc00126bb,0x6800100,0x80962540,0xc00126bb,0x7c00100,0x80230400,0xc00127ba,0x2802400,0x40962460,0xc00127ba,0x4000000,0x44200000,0xc00127ba,0x6800000,0x41329800,0xc00127ba, -0x7c00100,0x40230400,0xc00127ba,0x7c00900,0x40230400,0xc0012800,0x4000000,0x4200000,0xc0012b23,0x4000000,0x4200000,0xc0012b23,0x4000000,0x4400000,0xc0012b23,0x4000000, -0x5500000,0xc0012cbc,0x2802400,0x40962460,0xc0012cbc,0x4000000,0x45600000,0xc0012cbc,0x6800000,0x41329800,0xc0012cbc,0x7c00100,0x40230400,0xc00acf00,0x4000000,0x4e00000, -0xc00ae300,0x4000000,0x4e00000,0xc00b0500,0x4000000,0x4e00000,0xc00b0500,0x4000000,0x6800000,0xc00b0b11,0x4000000,0x5200000,0xc00b0b11,0x7c00900,0x9230400,0xc00b109a, -0x7c00300,0x80e30000,0xc00b2914,0x7c00100,0xfe530000,0xc00b2916,0x7c00100,0xfe530c00,0xc00b2a00,0x4000000,0x4e00000,0xc040af5e,0x7c00100,0x80230400,0xc0c12b89,0x4000000, -0x4200000,0xc14a44cc,0x4000000,0xc8e0000d,0xd000131f,0x2802c00,0xfc962460,0xd000171a,0x7c00100,0x18230400,0xd0001821,0x2802100,0x10962460,0xd0007300,0x24000000,0x4200000, -0xd0008e00,0x24000000,0x4200000,0xd0008f3a,0x2806000,0x40962460,0xd0009519,0x7c00100,0x8220400,0xd0009519,0x7c00100,0x8250400,0xd0009519,0x7c00100,0xfc220400,0xd0009519, -0x7c00100,0xfc250400,0xd000a500,0x4000000,0x4200000,0xd000c300,0x4000000,0x4e00000,0xd000d202,0x7c00100,0xfc230400,0xd000d476,0x7c00100,0x40230400,0xd000d997,0x2802100, -0x80962460,0xd000d997,0x6800100,0x80962540,0xd000e001,0x2802100,0x10962460,0xd000e700,0x4000400,0x4200000,0xd000e719,0x7c00100,0x10220400,0xd000e719,0x7c00500,0xc822040f, -0xd000fa00,0x4000000,0x4e00000,0xd0010eaa,0x4000010,0x44400000,0xd0010eaa,0x7c00100,0x40230400,0xd0012dbd,0x4000000,0x84200000,0xd0012dbd,0x7c00100,0x80230400,0xd0012fbe, -0x2802100,0x80962460,0xd0012fbe,0x2802400,0x80962460,0xd0012fbe,0x2806400,0x82f62460,0xd0012fbe,0x4000000,0x84400000,0xd0012fbe,0x6800000,0x80e29800,0xd0012fbe,0x6800100, -0x80962540,0xd0012fbe,0x6800100,0x80962541,0xd0012fbe,0x6804400,0x80962540,0xd0012fbe,0x7c00100,0x82b30400,0xd0012fbe,0x7c00100,0x82c30560,0xd0012fbe,0xc000010,0x84448000, -0xd0013183,0x7c00100,0x40230400,0xd0013200,0x4000000,0x4200000,0xd0013200,0x6800000,0xc9329805,0xd00134c0,0x2802100,0x80962460,0xd00134c0,0x4000002,0x84400000,0xd00134c0, -0x7c00100,0x80230400,0xd00a4305,0x7c00100,0xfce30400,0xd00a4611,0x7c40300,0xfce30000,0xd00a4711,0x7c40300,0xfce30000,0xd00a5e11,0x7c40300,0xfce30000,0xd00acf00,0x4000000, -0x4e00000,0xd00b0500,0x4000000,0x4e00000,0xd00b0500,0x4000000,0x6800000,0xd00b0b11,0x6800500,0xfc962540,0xd00b0bbf,0x2802200,0x80c62460,0xd00b119a,0x7c00300,0x80e30000, -0xd00b2a00,0x4000000,0x4e00000,0xd00b2e11,0x7c40300,0xfce30000,0xd00b30bf,0x7c00300,0x80230000,0xd00b339a,0x7c00300,0x80e30000,0xe0000c02,0xc000010,0x4b48000,0xe0001524, -0x2802400,0xfc962460,0xe0001524,0x7c00100,0xfc230400,0xe0001615,0x7c00100,0xfc230400,0xe000251b,0x12882000,0xc4962460,0xe0002a00,0x4000000,0x5500000,0xe0005102,0x4000000, -0x14200000,0xe0005c00,0x4000000,0x14200000,0xe000622a,0x6804400,0x80962540,0xe000622a,0x7c00100,0x80230400,0xe0008838,0x7c00100,0x80220400,0xe0008838,0x7c00100,0x80250400, -0xe0008e00,0x24000000,0x4810000,0xe0008e00,0x24000000,0x5410000,0xe0008e00,0x24000002,0x4400000,0xe0008e00,0x2c000010,0x4b48000,0xe000933e,0x7c00100,0x42b30400,0xe000933e, -0xc000010,0x44448000,0xe0009519,0x7c00100,0xc822040f,0xe0009519,0x7c00100,0xfc220400,0xe0009519,0x7c00100,0xfc250400,0xe000c178,0x2802100,0x80962460,0xe000c941,0x2802100, -0x80962460,0xe000c941,0x2806400,0x80962460,0xe000c941,0x7c00100,0x82b30400,0xe000d202,0x2802400,0x20962460,0xe000d202,0x7c00100,0xfc230400,0xe000d202,0x7c00500,0xfc230400, -0xe000dc99,0x4000000,0x84200000,0xe000e001,0x2802100,0x20962460,0xe000e001,0x2802400,0x20962460,0xe000fda1,0x7c00100,0x81830000,0xe0013502,0x2802400,0x20962460,0xe0013502, -0x4000000,0x4200000,0xe0013502,0x7c00100,0xfc230400,0xe0013502,0x80000000,0x5329960,0xe00136c1,0x4000000,0x84200000,0xe00136c1,0x7c00100,0x80230400,0xe001370b,0x7c00100, -0xfc230400,0xe0013919,0x7c00500,0x20220400,0xe0013919,0x7c00500,0xc822040f,0xe0013919,0x7c00d00,0xc823040f,0xe0013a19,0x7c00100,0xfc220400,0xe0013a19,0x7c00100,0xfc230400, -0xe0013bc2,0x2802400,0x80962460,0xe0013bc2,0x7c00100,0x80230400,0xe0013bc2,0xc000010,0x84248000,0xe0013cc3,0x6800000,0x81329800,0xe0013cc3,0x7c00100,0x80230400,0xe0013dc4, -0x2802400,0x80962460,0xe0013dc4,0x7c00100,0x80230400,0xe0013e28,0x7c00100,0x40230400,0xe0013fc5,0x7c00100,0x80220400,0xe0013fc5,0x7c00100,0x80250400,0xe0014000,0x4000000, -0x14200000,0xe0014001,0x2802400,0x10962460,0xe00a4711,0x7c40300,0xfce30000,0xe00a5e11,0x7c40300,0xfce30000,0xe00ac511,0x7c40300,0xfce30000,0xe00acf00,0x4000000,0x4e00000, -0xe00ae300,0x4000000,0x4e00000,0xe00b0500,0x4000000,0x4e00000,0xe00b1314,0x7c00100,0xfce30000,0xe00b1316,0x7c00100,0xfce30c00,0xe00b2a00,0x4000000,0x4e00000,0xe00b2a00, -0x4000000,0x6800000,0xe00b3816,0x7c00500,0x20230c00,0xe0808328,0x2802400,0x50962460,0xf0001615,0x6800100,0xfc962540,0xf0001a18,0x2802000,0xfd862460,0xf000c247,0x7c00100, -0x81430400,0xf000d000,0x4000000,0x4e00000,0xf000e300,0x4000000,0x4e00000,0xf000e59d,0x2802100,0x80962460,0xf000e59d,0x7c00100,0x80230400,0xf0012447,0,0x84818820, -0xf0012447,0,0x84c18820,0xf0012447,0,0x85418820,0xf0012447,0x2802000,0x80962460,0xf0012447,0x2802400,0x80962460,0xf0012447,0x7c00100,0x80230400,0xf0013a19, -0x7c00100,0xfc220400,0xf0014102,0x2802400,0x20962460,0xf0014308,0x2802100,0xfc962460,0xf0014308,0x7c00500,0xc822040e,0xf0014308,0x7c00500,0xc822040f,0xf001440a,0x4000000, -0x4500000,0xf0014500,0x4000000,0x4200000,0xf00146c6,0x2802100,0x80962460,0xf00146c6,0x2806000,0x82f62460,0xf00146c6,0x4000000,0x84e00000,0xf00146c6,0x6800000,0x82d29800, -0xf00146c6,0x6800100,0x80962540,0xf00146c6,0x6804000,0x80962540,0xf00146c6,0x7c00100,0x82b30400,0xf00146c6,0x7c00100,0x82c30560,0xf00146c6,0xc000010,0x84448000,0xf00147c7, -0x2802000,0x80962460,0xf00147c7,0x6800000,0x81329800,0xf00147c7,0x7c00100,0x80230400,0xf00ac511,0x7c40300,0xfce30000,0xf00acf00,0x4000000,0x4e00000,0xf00b2914,0x7c00100, -0xfe530000,0xf00b2916,0x7c00100,0xfe530c00,0xf00b2a00,0x4000000,0x4e00000,0xf00b2a00,0x4000000,0x6800000,0xf00b4211,0x7c40300,0xfce30000,0xf10a3c00,0x4000000,0x4e00000, -0xf10a3c00,0x4008000,0x4e00000,0xf10a8200,0x4008000,0x4e00000,0xf10b4811,0x7c40300,0xfce30000}; +static const uint32_t propsVectors[6426]={ +0x67,0,0,0x67,0,0xe00000,0x67,0,0x1600000,0x67,0x80000,0x20,0x67,0x20000000,0,0x5067, +0,0xe00000,0x5000000,0,0x900020,0x5000000,0x80000,0xc4918820,0x5000000,0x80000,0xc5c18020,0x5000000,0x80000,0xc5e18820,0x5000000,0x180000, +0xc0918820,0x5000000,0x4000000,0x4100000,0x5000000,0x4000000,0x4200000,0x5000000,0x4000000,0x5500000,0x5000000,0x4000000,0x5600000,0x5000000,0x4000000,0xc200000, +0x5000000,0x4000000,0xc8100003,0x5000000,0x4000000,0xc8100006,0x5000000,0x4000000,0xc8200002,0x5000000,0x4000000,0xc8200006,0x5000000,0x4000000,0xc820000e,0x5000000, +0x4000000,0xc820000f,0x5000000,0x4000000,0xc9600002,0x5000000,0x4000001,0xc8445801,0x5000000,0x4000001,0xc8445802,0x5000000,0x4000001,0xc8c4000b,0x5000000,0x4000010, +0xc9071401,0x5000000,0x4000020,0x4200000,0x5000000,0x4000020,0xc820000e,0x5000000,0x4000020,0xc820000f,0x5000000,0x4000020,0xc881000e,0x5000000,0x4000020,0xc881000f, +0x5000000,0x4000020,0xc941000e,0x5000000,0x4000020,0xc941000f,0x5000000,0x4000022,0xc820000e,0x5000000,0x4000022,0xc820000f,0x5000000,0x4000400,0x4200400,0x5000000, +0x4000400,0xc8200001,0x5000000,0x4000400,0xc8200002,0x5000000,0x6800000,0x10201c00,0x5000000,0x6800010,0xc8201001,0x5000000,0x6800020,0x10201c00,0x5000000,0x7c00000, +0x10200000,0x5000000,0x7c00020,0x10200000,0x5000000,0x7c00100,0xc8220402,0x5000000,0x7c00120,0xc8220405,0x5000000,0x7c00120,0xc8230402,0x5000000,0x7c00120,0xc8250402, +0x5000000,0x7c00120,0xc8250405,0x5000000,0x7c00500,0x10220400,0x5000000,0x7c00500,0x10230400,0x5000000,0x7c00500,0x10530400,0x5000000,0x7c00500,0xfc230400,0x5000000, +0x7c00d00,0x10230400,0x5000000,0x24000000,0x4100000,0x5000000,0x24000000,0x4200000,0x5000000,0x24000000,0x4810000,0x5000000,0x24000000,0x4b00000,0x5000000,0x24000000, +0x4e00000,0x5000000,0x24000000,0x5410000,0x5000000,0x24000000,0x5500000,0x5000000,0x24000000,0x5710000,0x5000000,0x24000000,0x6800000,0x5000000,0x24000000,0xc8200002, +0x5000000,0x24000000,0xc9500002,0x5000000,0x24000002,0x4400000,0x5000000,0x24000006,0xc8c0000b,0x5000000,0x24000008,0x5410000,0x5000000,0x24000008,0x5710000,0x5000000, +0x24000020,0x4200000,0x5000000,0x24000020,0x4200001,0x5000000,0x24000020,0x4810000,0x5000000,0x24000020,0x4f00000,0x5000000,0x24000020,0x5001400,0x5000000,0x24000020, +0x5410000,0x5000000,0x24000020,0x5600000,0x5000000,0x24000020,0xc8200002,0x5000000,0x24000020,0xc9500002,0x5000000,0x24000022,0x5600000,0x5000000,0x2c000010,0x5248000, +0x5000000,0x2c000010,0xc9248002,0x5000000,0x40000001,0x4440020,0x5000000,0x40000001,0x463b020,0x5000000,0x40000001,0x4643020,0x5000000,0x40000001,0x4a5a040,0x5000000, +0x40000001,0x516a8a0,0x5000000,0x40000001,0x5d3b020,0x5000000,0x40080000,0xc4918820,0x5000000,0x80000000,0x5329960,0x5000001,0x2882000,0xc4962460,0x5000002,0x4000000, +0x4200000,0x5000002,0x4000000,0x5329400,0x5000002,0x4000000,0x5329800,0x5000002,0x4000000,0x5500000,0x5000002,0x6800000,0xfd329800,0x5000002,0x7000100,0xc8230408, +0x5000002,0x7c00100,0x8230400,0x5000002,0x7c00100,0xc8230402,0x5000002,0x7c00100,0xc8230404,0x5000002,0x7c00100,0xc8230407,0x5000002,0x7c00100,0xc8230408,0x5000002, +0x7c00100,0xc8230409,0x5000002,0x7c00100,0xfc230400,0x5000002,0x7c00100,0xfc230401,0x5000002,0x7c00500,0xfc230400,0x5000002,0x7d00100,0xc0230400,0x5000003,0x4000000, +0x4200400,0x5000003,0x4000000,0x4201000,0x5000003,0x4000000,0x4270000,0x5000003,0x7c00100,0xc8220402,0x5000003,0x7c00100,0xfc220400,0x5000003,0x7c00100,0xfc250400, +0x5000003,0x7c00500,0xfc230400,0x5000004,0x4000000,0x4200000,0x5000004,0x4000000,0x5500000,0x5000004,0x6800100,0xfc962540,0x5000004,0x6800100,0xfc962541,0x5000004, +0x7c00100,0xfc230400,0x5000007,0x7c00100,0x80220400,0x5000007,0x7c00100,0x80250400,0x5000008,0x4000000,0xc200000,0x5000008,0x7c00100,0x8220400,0x5000008,0x7c00100, +0x8220401,0x5000008,0x7c00100,0x8250400,0x5000008,0x7c00100,0x8250401,0x5000008,0x7c00100,0xfc220400,0x5000008,0x7c00100,0xfc220401,0x5000008,0x7c00100,0xfc250400, +0x5000008,0x7c00100,0xfc250401,0x500000a,0x4000000,0x4200000,0x500000a,0x6800100,0xfc962540,0x500000a,0x7c00100,0xfc230400,0x500000c,0x7c00100,0x8230400,0x500000c, +0x7c00100,0x8250400,0x500000c,0x7c00100,0xfc230400,0x500000e,0x4000400,0xc8200001,0x500000e,0x4000400,0xc8200002,0x500000e,0x4000400,0xc8500001,0x500000e,0x7000500, +0xc8220402,0x500000e,0x7c00100,0x8250400,0x500000e,0x7c00100,0x18220400,0x500000e,0x7c00100,0xc8220401,0x500000e,0x7c00100,0xc8220402,0x500000e,0x7c00100,0xc8250401, +0x500000e,0x7c00100,0xfc220400,0x500000e,0x7c00100,0xfc220401,0x500000e,0x7c00100,0xfc250401,0x500000e,0x7c00120,0xc8220402,0x500000e,0x7c00120,0xc8250402,0x500000f, +0x6800100,0xfc962540,0x500000f,0x7c00100,0xfc230400,0x5000010,0x6800100,0xfc962540,0x5000010,0x7c00100,0xc8230401,0x5000010,0x7c00100,0xfc230400,0x5000012,0x7c00100, +0xa230500,0x5000012,0x7c00100,0xa330520,0x5000012,0x7c80100,0xc6330520,0x5000013,0x4000000,0x4200000,0x5000013,0x4000000,0xf8201000,0x5000013,0x4000000,0xf8230400, +0x5000013,0x4000002,0x4400000,0x5000013,0x4000010,0x4200000,0x5000013,0x4000020,0xc8200005,0x5000013,0x7c00100,0xca633801,0x5000013,0x7c00100,0xca633802,0x5000013, +0x7c00100,0xca633805,0x5000013,0x7c00100,0xfe633800,0x5000015,0x6800100,0xfc962540,0x5000015,0x7c00100,0x8230400,0x5000015,0x7c00100,0xfc230400,0x5000018,0x6800000, +0xfd329800,0x5000018,0x7800100,0xc9830142,0x5000018,0x7c00100,0xc9830002,0x5000018,0x7c00100,0xfd830000,0x5000018,0x7c00900,0xfd830000,0x5000018,0x7e00100,0xfd830000, +0x5000019,0x7c00100,0x8220400,0x5000019,0x7c00100,0x8250400,0x5000019,0x7c00100,0x10220400,0x5000019,0x7c00100,0x10230400,0x5000019,0x7c00100,0x18220400,0x5000019, +0x7c00100,0x18230400,0x5000019,0x7c00100,0x20220400,0x5000019,0x7c00100,0x20250400,0x5000019,0x7c00100,0x30220400,0x5000019,0x7c00100,0xc8220402,0x5000019,0x7c00100, +0xc8250401,0x5000019,0x7c00100,0xc8250402,0x5000019,0x7c00100,0xfc220400,0x5000019,0x7c00100,0xfc220401,0x5000019,0x7c00100,0xfc250400,0x5000019,0x7c00100,0xfc250401, +0x5000019,0x7c00500,0xc822040f,0x500001a,0x6800000,0xfd329800,0x500001a,0x6800100,0xfc962540,0x500001a,0x6800100,0xfc962541,0x500001a,0x7c00100,0xfc230400,0x500001f, +0x4000000,0x4200000,0x500001f,0x6800000,0xfd329800,0x500001f,0x6800100,0xfc962540,0x500001f,0x6800100,0xfc962541,0x500001f,0x7c00100,0xfc230400,0x5000023,0x6800100, +0xfc962540,0x5000023,0x6800100,0xfc962541,0x5000023,0x7c00100,0xfc230400,0x5000023,0x7c00100,0xfc230401,0x5000024,0x6800000,0xfd329800,0x5000024,0x6800100,0xfc962540, +0x5000024,0x7c00100,0xfc230400,0x5000026,0x4000000,0x4200000,0x5000026,0x4000010,0x4400000,0x5000026,0x6800000,0xfd329800,0x5000026,0x7800100,0xc9830142,0x5000026, +0x7c00100,0xfd830000,0x5000026,0x7c00900,0xfd830000,0x5000026,0x7e00100,0xfd830000,0x5000067,0x1000,0,0x5000410,0x7c00500,0xfc230400,0x500041b,0x4000400, +0x4200400,0x500048e,0x7c00500,0xc8230401,0x50004a1,0x4000010,0x4b00000,0x50004a1,0x4000010,0x5071400,0x50004ad,0xc000010,0x4b48000,0x50004b5,0x7c00900,0x8230400, +0x50004e2,0xc000010,0x4448000,0x50004f7,0xc000010,0x4448000,0x500052f,0x4000000,0x4200000,0x500059b,0x4000000,0x4e00000,0x50005f8,0x24000000,0x14810000,0x50005f8, +0x24000000,0x15410000,0x5000c90,0x4000400,0xf8200000,0x5000c9f,0xc000010,0x5049400,0x5000cc3,0x6800000,0xfd329800,0x5000cc7,0xc000010,0x4b48000,0x5000d12,0x6800000, +0xfd329800,0x5000d17,0x6800000,0xfd329800,0x5000d1b,0x6800000,0xfd329800,0x5000d1f,0x6800000,0xfd329800,0x5000d23,0x4000000,0x4200000,0x5000d23,0x6800000,0xfd329800, +0x5000d28,0x6800000,0xfd329800,0x5000dfc,0x7c00100,0xc8230408,0x5001000,0x80004,0xc4418820,0x5001000,0x4000000,0x4100000,0x5001000,0x4000000,0xc8100002,0x5001000, +0x4000000,0xc8100003,0x5001000,0x4000000,0xc8100006,0x5001000,0x4000000,0xc810000e,0x5001000,0x4000000,0xc810000f,0x5001000,0x4000000,0xc9500002,0x5001000,0x4000000, +0xc9600002,0x5001000,0x4000100,0xc8120403,0x5001000,0x4000100,0xc8150403,0x5001000,0x4000400,0x4200400,0x5001000,0x4000400,0xc8100002,0x5001000,0x4000400,0xc8500002, +0x5001000,0x7c00120,0xc8120405,0x5001000,0x7c00d00,0x10130400,0x5001000,0x24000000,0x4100000,0x5001000,0x24000000,0x4200000,0x5001000,0x24000000,0x4e00000,0x5001000, +0x24000000,0x5400000,0x5001000,0x24000000,0x5500000,0x5001000,0x24000000,0x5600000,0x5001000,0x24000000,0xc8200002,0x5001000,0x24000000,0xc8f00002,0x5001000,0x24000000, +0xf8401000,0x5001000,0x24000002,0x4100000,0x5001000,0x24000002,0x4370000,0x5001000,0x24000002,0x4470000,0x5001000,0x24000006,0xf8400000,0x5001000,0x24000008,0x5710000, +0x5001000,0x24000008,0x5712c00,0x5001000,0x24000008,0xf9712c00,0x5001000,0x24000020,0x4100000,0x5001000,0x24000020,0x4100001,0x5001000,0x24000020,0x5500000,0x5001000, +0x24000020,0x5600000,0x5001000,0x24000020,0xc8100002,0x5001000,0x24000020,0xc9500002,0x5001000,0x2c000010,0xc8f0ac02,0x5001008,0x7c00100,0xfc220400,0x5001008,0x7c00100, +0xfc220401,0x5001008,0x7c00100,0xfc250400,0x5001008,0x7c00100,0xfc250401,0x500100e,0x7c00100,0xc8250401,0x500100e,0x7c00100,0xfc220400,0x500100e,0x7c00100,0xfc250400, +0x5001019,0x7c00100,0x10220400,0x5001019,0x7c00100,0xc8120402,0x5001019,0x7c00100,0xc812040f,0x5001019,0x7c00100,0xc8150401,0x5001019,0x7c00100,0xc8150402,0x5001019, +0x7c00100,0xc8220402,0x5001019,0x7c00100,0xc8250402,0x5001019,0x7c00100,0xfc220400,0x5001019,0x7c00100,0xfc220401,0x5001019,0x7c00100,0xfc250400,0x5001019,0x7d00100, +0xc0220402,0x5001067,0,0,0x5001400,0x6800c00,0xf8101000,0x5001417,0x4000400,0xc8100002,0x5001417,0x7c00500,0x10130400,0x5001419,0x7c00500,0x10130400, +0x5002000,0x4000000,0x5600000,0x5002000,0x4000000,0xc820000a,0x5002000,0x4000020,0xc820000a,0x5002012,0x7c00100,0xc8e3040a,0x5002012,0x7c80100,0xc4e3040a,0x5002016, +0x7c00100,0xc8e30c0a,0x5002016,0x7c00100,0xca530c0a,0x5002581,0x4000008,0xc881000a,0x5002581,0x4000008,0xc941000a,0x5002581,0x4000010,0xc887000a,0x5002581,0x6800004, +0xc920000a,0x5002581,0xc000010,0xc884800a,0x5002599,0x7c00d00,0xca530c0a,0x5003000,0x4000000,0xc8810011,0x5003000,0x4000000,0xc8e00011,0x5003000,0x4000000,0xc9410011, +0x5003000,0x4000000,0xc9500011,0x5003000,0x4000000,0xc9600011,0x5003000,0x4000001,0xc8445811,0x5003000,0x4000006,0xc8e70011,0x5003000,0x4000008,0xc8e00011,0x5003000, +0x4000008,0xc8e02c11,0x5003000,0x4000010,0xc8871411,0x5003000,0x4000010,0xc9271011,0x5003000,0x4000010,0xc9271411,0x5003000,0x4000020,0xc8e00011,0x5003000,0x4000400, +0xc8e00011,0x5003000,0x4000420,0xc8e00011,0x5003000,0x6800000,0xc8e01c11,0x5003000,0x6800040,0xc8e29811,0x5003000,0xc000010,0xc880ac11,0x5003000,0xc000010,0xc8b48011, +0x5003019,0x7c00100,0xc8e20411,0x5003019,0x7c00100,0xc8e50411,0x5003019,0x7c00140,0xc8e20411,0x5003019,0x7c00140,0xc8e50411,0x5004000,0x4000400,0xc8200002,0x5004000, +0x6800000,0xfc201c00,0x5004000,0x68000c0,0xfd329800,0x5004000,0x24000000,0x4200000,0x5004000,0x24000000,0x4810000,0x5004000,0x24000000,0x5410000,0x5004000,0x24000000, +0x5500000,0x5004000,0x24000000,0x5600000,0x5004000,0x24000000,0x5b00000,0x5004000,0x24000000,0x6410000,0x5004000,0x24000006,0xf8d70000,0x5004000,0x24000008,0x5714000, +0x5004000,0x24000008,0xf9713c00,0x5004000,0x24000010,0x5071400,0x5004000,0x24000010,0xf9071000,0x5004000,0x24000020,0x4200000,0x5004000,0x24000020,0x4400000,0x5004000, +0x24000020,0x5600000,0x5004000,0x24000400,0x4200000,0x5004000,0x24000420,0x4200000,0x5004000,0x2c000010,0x4b48000,0x5004000,0x2c000010,0xf900ac00,0x5004000,0x44000001, +0x5a45800,0x5004019,0x7c00100,0xfc220400,0x5004019,0x7c00100,0xfc250400,0x5004019,0x7c001c0,0xfc220400,0x5004019,0x7c001c0,0xfc250400,0x5005000,0x4000000,0x4e00000, +0x5005000,0x4000000,0x14e00000,0x5005000,0x4000000,0xc881000c,0x5005000,0x4000000,0xc8810010,0x5005000,0x4000000,0xc8e00002,0x5005000,0x4000000,0xc8e0000c,0x5005000, +0x4000000,0xc8e0000d,0x5005000,0x4000000,0xc8e00010,0x5005000,0x4000000,0xc941000c,0x5005000,0x4000000,0xc9410010,0x5005000,0x4000000,0xc950000c,0x5005000,0x4000000, +0xc960000c,0x5005000,0x4000002,0xc8e7000c,0x5005000,0x4000002,0xc8e70010,0x5005000,0x4000008,0xc8810010,0x5005000,0x4000008,0xc9410010,0x5005000,0x4000010,0xc887140c, +0x5005000,0x4000010,0xc8e7000c,0x5005000,0x4000010,0xc927100c,0x5005000,0x4000010,0xc927140c,0x5005000,0x4000020,0xc8e0000c,0x5005000,0x4000026,0xc8e7000c,0x5005000, +0x6800000,0xc8e01c02,0x5005000,0x6800000,0xc8e01c10,0x5005000,0xc000010,0xc880ac0c,0x5005000,0xc000010,0xc8b4800c,0x5005000,0x24000000,0x4200000,0x5005000,0x24000000, +0x4e00000,0x5005000,0x24100000,0xc0810001,0x5005000,0x24100000,0xc1410001,0x5005005,0x7c00100,0xfce30400,0x5005011,0x7c00300,0x10e30000,0x5005011,0x7c00300,0xc8e30001, +0x5005011,0x7c00300,0xfce30000,0x5005011,0x7c00900,0xfd230400,0x5005011,0x7c40300,0xfce30000,0x5005012,0x4000000,0xc8e00002,0x5005012,0x4000000,0xc8e00003,0x5005012, +0x7c00100,0xa130480,0x5005012,0x7c00100,0xc8e30402,0x5005012,0x7c80100,0xc4e30402,0x5005012,0x7c80100,0xc6130480,0x5005014,0x7c00100,0xfce30000,0x5005014,0x7c00100, +0xfce30001,0x5005014,0x7c00100,0xfe530000,0x5005014,0x7c00900,0xfd230000,0x5005014,0x7c00900,0xfd230001,0x5005016,0x4000000,0xc8e00c03,0x5005016,0x4000000,0xc8e00c0d, +0x5005016,0x7c00100,0xfce30c00,0x5005016,0x7c00100,0xfce30c01,0x5005016,0x7c00100,0xfe530c00,0x5005016,0x7c00900,0xfd230c00,0x5005016,0x7c00900,0xfd230c01,0x5005581, +0x6800004,0xf9200000,0x5005581,0x24000000,0x4810000,0x5005581,0x24000000,0x5410000,0x5005581,0x24000008,0x4810000,0x5005581,0x24000008,0x5410000,0x5005587,0x24000010, +0x4870000,0x500558e,0x2c000010,0x4848000,0x5005596,0x4000000,0x4e00000,0x5005596,0x24000000,0x4e00000,0x5005596,0x24000002,0x4e00000,0x5005596,0x24000002,0x5200000, +0x5005596,0x24000008,0x4810000,0x5005596,0x24000008,0x5410000,0x5005596,0x24000008,0xc810000,0x5005599,0x7000400,0xc9200c02,0x5005599,0x7c00900,0x10930c00,0x5005599, +0x7c00900,0x10e30c00,0x5005599,0x7c00d00,0xfe530c00,0x500559b,0x4000000,0x4e00000,0x500559b,0x4000000,0xc8e00002,0x500559b,0x4000000,0xc8e00003,0x500559b,0x4000000, +0xc8e0000d,0x500559b,0x4000000,0xc8e0000f,0x500559b,0x7c00300,0xfce30000,0x500559c,0x24000000,0x4810000,0x500559c,0x24000000,0x5410000,0x50055a4,0x24000000,0x4810000, +0x50055a4,0x24000000,0x5410000,0x5008004,0x7c00100,0xc8230401,0x5008004,0x7c00100,0xfc230400,0x500800a,0x7c00100,0xc8230401,0x500800a,0x7c00100,0xfc230400,0x500800a, +0x7c00100,0xfc230401,0x500800f,0x7c00100,0xfc230400,0x500801a,0x7c00100,0xfc230400,0x500801f,0x7c00100,0xc8230401,0x500801f,0x7c00100,0xfc230400,0x5008024,0x7c00100, +0xfc230400,0x5010001,0x2000,0x14962460,0x5010001,0x2802020,0x10962460,0x5010001,0x2802400,0x10962460,0x5010001,0x2802400,0x10c62460,0x5010001,0x2880000,0xc6a65620, +0x5010002,0x2802100,0x20962460,0x5010002,0x2802400,0x20962460,0x5010004,0x2802100,0xfc962460,0x5010004,0x2802400,0xfc962460,0x501000a,0x2802100,0xfc962460,0x501000a, +0x2802400,0xfc962460,0x501000f,0x2802100,0xfc962460,0x501000f,0x2802400,0xfc962460,0x5010010,0x2802100,0xfc962460,0x5010010,0x2802400,0xfc962460,0x5010010,0x2802900, +0xfc962460,0x5010010,0x2806400,0xfc962460,0x5010013,0x2802500,0x20962460,0x5010013,0x2802500,0x30962460,0x5010013,0x2802500,0xfc962460,0x5010015,0x2802100,0xfc962460, +0x5010015,0x2802100,0xfc962461,0x5010015,0x2806400,0xfc962460,0x5010018,0x2802100,0xfd862460,0x5010018,0x2802400,0xfd862460,0x501001a,0x2802100,0xfc962460,0x501001f, +0x2802100,0xfc962460,0x501001f,0x2802400,0xfc962460,0x5010023,0x2802100,0xfc962460,0x5010023,0x2806400,0xfc962460,0x5010024,0x2802100,0xfc962460,0x5010024,0x2802100, +0xfc962461,0x5010026,0x2802100,0xfd862460,0x5010026,0x2802400,0xfd862460,0x5010026,0x2806500,0xfd862460,0x501089a,0x2802400,0x18962460,0x50108be,0x2802100,0xfc962460, +0x50108be,0x2802500,0xfc962460,0x50108c9,0x2802400,0x8962460,0x50108d6,0x2802400,0x8962460,0x5010c94,0x2802400,0x8962460,0x5010c98,0x2802400,0x18962460,0x5011001, +0x2802400,0x10962460,0x5011001,0x2802400,0x10c62460,0x5011001,0x2802400,0x20962460,0x5011001,0x2802400,0xc8962461,0x5011001,0x2802400,0xfc962460,0x501181d,0x2802400, +0xfc962460,0x5011825,0x2802400,0xfc962460,0x501182d,0x2802400,0xfc962460,0x501182f,0x2802400,0xfc962460,0x5011831,0x2802400,0xfc962460,0x5011836,0x2802400,0xfc962460, +0x5011841,0x2802400,0x20962460,0x5011847,0x2802400,0xfc962460,0x501184b,0x2802400,0xfc962460,0x5011854,0x2802400,0xfc962460,0x501185e,0x2802400,0xfc962460,0x5011861, +0x2802400,0xfc962460,0x5011865,0x2802400,0xfc962460,0x5011868,0x2802400,0x20962460,0x5011868,0x2802400,0xfc962460,0x501186a,0x2802400,0x10962460,0x501186c,0x2802400, +0xfc962460,0x501186f,0x2802400,0xfc962460,0x5011873,0x2802400,0x10962460,0x5011873,0x2802400,0xfc962460,0x5011875,0x2802400,0xfc962460,0x501187a,0x2802400,0xfc962460, +0x501187e,0x2802400,0xfc962460,0x5011881,0x2802400,0xfc962460,0x5011884,0x2802400,0xfc962460,0x501188a,0x2802400,0xfc962460,0x501188a,0x2802500,0xfc962460,0x5012599, +0x3802500,0xc926246a,0x5015012,0x2802400,0x18962460,0x5015999,0x2802400,0xfc962460,0x50159ad,0x2802400,0x10962460,0x5018004,0x2806400,0xfc962460,0x501800a,0x2806400, +0xfc962460,0x501800f,0x2806400,0xfc962460,0x501801a,0x2806400,0xfc962460,0x501801f,0x2806400,0xfc962460,0x5018024,0x2806400,0xfc962460,0x8000000,0x4000000,0x5600000, +0x8000019,0x7c00100,0xc8220401,0x8000027,0x4000000,0x4200000,0x8000027,0x4000000,0x4400000,0x8000027,0x4000000,0x4500000,0x8000027,0x4000000,0x4810000,0x8000027, +0x4000000,0x4b00000,0x8000027,0x4000000,0x5410000,0x8000027,0x4000000,0xc8c0000b,0x8000027,0x4000000,0xf8400000,0x8000027,0x4000010,0x4b00000,0x8000027,0x4000010, +0x4c00000,0x8000027,0x6800000,0xfd329800,0x8000027,0x6800100,0xfc462540,0x8000027,0x6800400,0xfc962540,0x8000027,0x7c00100,0xc8230401,0x8000027,0x7c00100,0xfc230400, +0x8000067,0,0x1900000,0x8000067,0x1000,0,0x8001067,0,0,0x8005012,0x7c00100,0xfdf304c1,0x8005012,0x7c00100,0xfe0304e1,0x8010013, +0x2802400,0x20962460,0x8010013,0x2802500,0x20962460,0x8010027,0x2802100,0xc8962461,0x8010027,0x2802100,0xfc962460,0x8010027,0x2802400,0x10962460,0x8010027,0x2802400, +0x20962460,0x8010027,0x2802400,0xfc962460,0x8010027,0x2802500,0xfc962460,0x8010027,0x2806400,0xfc962460,0x8010027,0x2902100,0xc0962462,0x9000000,0x4000000,0x4700000, +0x9001000,0x4000000,0x5600000,0xc000000,0,0x4918820,0xc000000,0x4000000,0x4200000,0xc000000,0x4000000,0x5600000,0xc000000,0x4000400,0x4200400,0xc000000, +0x7c00100,0xc8220405,0xc000000,0x7c00500,0x10230400,0xc000000,0x7c00500,0xfc230400,0xc000000,0x24000000,0x4200000,0xc000000,0x2c000010,0xc9248002,0xc000002,0x4000000, +0xf8200000,0xc000002,0x7c00100,0xfc230400,0xc000003,0x4000006,0xf8400400,0xc000005,0x4000400,0x4200400,0xc000006,0x7c00100,0x40250400,0xc000008,0x7c00100,0xfc220400, +0xc000008,0x7c00100,0xfc220401,0xc000008,0x7c00100,0xfc250400,0xc000008,0x7c00100,0xfc250401,0xc00000b,0x4000000,0x4200000,0xc00000b,0x4000010,0x4200000,0xc00000b, +0x4000010,0x4400000,0xc00000b,0x6800000,0x8200000,0xc00000b,0x7c00100,0xfc230400,0xc00000b,0xc000010,0x4248000,0xc00000e,0x7c00100,0x8220400,0xc00000e,0x7c00100, +0x10220400,0xc000013,0x7c00100,0xca633801,0xc000017,0x4000000,0x4200000,0xc000017,0x4000000,0x5600000,0xc000017,0x4000000,0xc400000,0xc000017,0x4000010,0x4400000, +0xc000017,0x4000010,0x5200000,0xc000017,0x6800000,0xfd329800,0xc000017,0x6800100,0xfd862540,0xc000017,0x7c00100,0x9830000,0xc000017,0x7c00100,0xfd830000,0xc000017, +0x7d00100,0xc1830000,0xc000017,0xc000010,0x4448000,0xc000019,0x7c00100,0x8220400,0xc000019,0x7c00100,0x8250400,0xc000019,0x7c00100,0x10220400,0xc000019,0x7c00100, +0x18250400,0xc000019,0x7c00100,0x20220400,0xc000019,0x7c00100,0x20250400,0xc000019,0x7c00100,0xfc220401,0xc000019,0x7c00100,0xfc250401,0xc00001b,0x80000,0xc4c18820, +0xc00001b,0x4000000,0x84200000,0xc00001b,0x4000006,0x84500000,0xc00001b,0x4000010,0x84400000,0xc00001b,0x4000010,0x84b70000,0xc00001b,0x4000800,0x84200000,0xc00001b, +0x6800000,0x81329800,0xc00001b,0x7c00100,0x80230400,0xc00001b,0x7c00900,0x80230400,0xc00001b,0xc000010,0x84b48000,0xc00001c,0x4000000,0x4200000,0xc00001c,0x6800100, +0xfd862400,0xc00001c,0x6800100,0xfd862540,0xc00001c,0x7c00100,0xfd830000,0xc00001c,0x7c00100,0xfd830001,0xc00001c,0xc000010,0x4448000,0xc00001d,0x4000000,0x84810000, +0xc00001d,0x4000000,0x85410000,0xc00001d,0x4000001,0x84445800,0xc00001d,0x7c00100,0x80230400,0xc000020,0x7c00100,0x80230400,0xc000021,0x4000000,0x4200000,0xc000021, +0x6800100,0x30962540,0xc000021,0x6800100,0xfc962540,0xc000021,0x6800100,0xfc962541,0xc000021,0x7c00100,0x30230400,0xc000021,0x7c00100,0xfc230400,0xc000022,0x4000000, +0x44200000,0xc000022,0x4000010,0x44200000,0xc000022,0x7c00100,0x40230400,0xc000022,0xc000010,0x44248000,0xc000022,0x80000000,0x44218560,0xc000025,0x7c00100,0xfc230400, +0xc000027,0x4000000,0x4200000,0xc000027,0x4000000,0x4400000,0xc000027,0x7c00100,0xfc230400,0xc000028,0x4000000,0x44200000,0xc000028,0x7c00100,0x40230400,0xc000028, +0xc000010,0x44248000,0xc00002e,0x24000000,0x14200000,0xc000532,0x4000010,0x84400000,0xc000537,0x4000010,0x84400000,0xc000537,0x4000010,0x84b70000,0xc000537,0xc000010, +0x84b48000,0xc00055f,0x4000001,0xc8c41c0b,0xc000d2d,0x6800000,0xfd329800,0xc001000,0x4000400,0x4500400,0xc005005,0x7c00100,0xfce30400,0xc005011,0x4020000,0x4e00000, +0xc005011,0x4020000,0xc8e00002,0xc005011,0x7c00300,0xc8e30002,0xc005011,0x7c40300,0xfce30000,0xc005029,0x4000000,0x44e00000,0xc005029,0x7c00100,0x40e30400,0xc005029, +0x7c00900,0x41230400,0xc00557f,0x4008000,0x4e00000,0xc00557f,0x4010000,0x4e00000,0xc00559b,0x4000000,0x4e00000,0xc010001,0x2000,0x14962460,0xc010008,0x2000, +0xc962460,0xc010017,0x2802100,0xfd862460,0xc010017,0x2802400,0x9862460,0xc010017,0x2802400,0x11862460,0xc010017,0x2802400,0x19862460,0xc010017,0x2802400,0xfd862460, +0xc010017,0x2806400,0xfd862460,0xc010017,0x2882000,0xc5862460,0xc01001b,0x2802100,0xa0962460,0xc01001b,0x3c02100,0x80962460,0xc01001b,0x12882000,0xc4962460,0xc01001c, +0x2802100,0xfd862460,0xc01001c,0x2802400,0xfd862460,0xc01001c,0x2806400,0xfd862460,0xc010021,0x2802100,0x30962460,0xc010021,0x2802100,0xfc962460,0xc010021,0x2806400, +0xfc962460,0xc010022,0x2802100,0x40962460,0xc010022,0x2802400,0x50962460,0xc010022,0x2802500,0x40962460,0xc010025,0x2802500,0xfc962460,0xc010027,0x2802100,0xfc962460, +0xc010027,0x2802400,0xfc962460,0xc0108be,0x2802100,0xfc962460,0xc011001,0x2802400,0x10962460,0xc011001,0x2802400,0x10c62460,0xd000000,0x80000,0xc4918820,0xd000000, +0x180000,0xc0918820,0xd000000,0x4000000,0x14200000,0xd000000,0x4000000,0xc8200001,0xd000000,0x4000020,0xc8200005,0xd000000,0x6800020,0xc9329805,0xd000000,0x7c00120, +0xc8220405,0xd000000,0x7c00120,0xc8250405,0xd000009,0x7c00100,0x80220400,0xd000009,0x7c00100,0x80250400,0xd00000d,0x7c00100,0x80230400,0xd00000e,0x7c00120,0xc8220402, +0xd00000e,0x7c00120,0xc8250402,0xd00001e,0x4000000,0x84200000,0xd00001e,0x7c00100,0x80230400,0xd000067,0x1000,0,0xd005011,0x7c00300,0xc8e30001,0xd005011, +0x7c40300,0xfce30000,0xd010000,0x82000,0xc4962460,0xd010000,0x2802000,0x10962460,0xd010000,0x2802400,0x10962460,0xd010001,0x2802400,0x10962460,0xe000000,0x80000, +0xc5e18820,0xe000000,0x80020,0xc4218820,0xe000000,0x4000000,0x4200000,0xe000000,0x4000000,0x5600000,0xe000000,0x4000001,0xc8445802,0xe000000,0x4000020,0x4200000, +0xe000000,0x4000020,0xc8200005,0xe000000,0x7c00120,0xc8220405,0xe000000,0x7c00120,0xc8250405,0xe000000,0x24000000,0x4100000,0xe000000,0x24000000,0x4200000,0xe000000, +0x24000000,0x4810000,0xe000000,0x24000000,0x5410000,0xe000000,0x24000000,0xc9500002,0xe000000,0x24000020,0x4200000,0xe000000,0x24000020,0x4810000,0xe000000,0x24000020, +0x5410000,0xe000000,0x24000020,0xc8200001,0xe000000,0x24000020,0xc8200002,0xe000000,0x2c000010,0xc9248002,0xe000002,0x4000000,0xc9500008,0xe000002,0x7c00100,0x8230400, +0xe000002,0x7c00100,0x10230400,0xe000008,0x7c00100,0x8220400,0xe000008,0x7c00100,0x8250400,0xe000008,0x7c00100,0xfc220400,0xe000008,0x7c00100,0xfc250400,0xe00000c, +0x7c00100,0xfc230400,0xe00000e,0x4000020,0x4200000,0xe00000e,0x7c00100,0x8220400,0xe00000e,0x7c00100,0x8250400,0xe000019,0x7c00100,0x20250400,0xe000019,0x7c00100, +0xc822040f,0xe000025,0x7c00100,0xfc230400,0xe00002a,0x7c00100,0x80230400,0xe00002b,0x7c00100,0x80230400,0xe00002c,0x7c00100,0x80230400,0xe00002d,0x7c00100,0x80230400, +0xe000533,0xc000010,0x84448000,0xe000562,0x24000000,0x4200000,0xe001000,0x4000000,0x14100000,0xe003000,0x4000000,0xc8810011,0xe003000,0x4000000,0xc9410011,0xe004000, +0x24000020,0x4810000,0xe004000,0x24000020,0x5410000,0xe005000,0x4000000,0xc8e00003,0xe005000,0x24000020,0x4200000,0xe005011,0x7c00100,0x11230400,0xe005011,0x7c00300, +0xc8e30001,0xe005014,0x7c00100,0xc8e30010,0xe005014,0x7c00100,0xfe530000,0xe005016,0x7c00100,0xa530c00,0xe005016,0x7c00100,0xc8e30c10,0xe005029,0x4000000,0x44e00000, +0xe005596,0x24000000,0x14e00000,0xe005599,0x4000002,0xf9200c00,0xe0055af,0x4000000,0x4e00000,0xe0055af,0x7c00100,0x11230400,0xe010001,0x2000,0x14962460,0xe010001, +0x2802000,0x10962460,0xe010001,0x2802020,0x10962460,0xe01002a,0x2802100,0x80962460,0xe01002a,0x2806400,0x80962460,0xe01002b,0x2802100,0x80962460,0xe01002b,0x2806400, +0x80962460,0xe01002c,0x2802100,0x80962460,0xe01002d,0x2802100,0x80962460,0xe011001,0x2882000,0xc4c62460,0xe011001,0x12882000,0xc4962460,0xe011818,0x2802100,0x8962460, +0x10000000,0x4000000,0xc8200002,0x10000000,0x4000400,0x4200400,0x10000000,0x6800000,0x20201c00,0x10000000,0x7c00120,0xc8220405,0x10000000,0x24000000,0x4200000,0x10000000, +0x24000002,0x4200000,0x10000000,0x24000020,0x4200000,0x10000002,0x4000000,0x4200000,0x10000002,0x4000000,0x5071400,0x10000002,0x7c00100,0xfc230400,0x10000002,0x80000000, +0x5329960,0x10000004,0x7c00100,0xfc230400,0x10000008,0x7c00100,0x10220400,0x10000009,0x7c00100,0x80220400,0x10000009,0x7c00100,0x80250400,0x1000000a,0x7c00100,0xfc230400, +0x1000000e,0x7c00100,0x8220400,0x1000000e,0x7c00100,0x8250400,0x1000000e,0x7c00100,0x10220400,0x1000000e,0x7c00100,0xc8250402,0x1000000e,0x7c00500,0xc822040e,0x1000000e, +0x7c00500,0xc822040f,0x1000000f,0x4000000,0x5600000,0x1000000f,0x7c00100,0xfc230400,0x10000010,0x6800100,0xfc962540,0x10000015,0x7c00100,0xfc230400,0x10000017,0x4000000, +0x4200000,0x10000019,0x7c00100,0x10220400,0x10000019,0x7c00100,0x20220400,0x10000019,0x7c00500,0x10220400,0x10000019,0x7c00500,0xc822040e,0x10000019,0x7c00500,0xc822040f, +0x10000022,0x7c00100,0x40230400,0x10000023,0x4000000,0x4200000,0x10000023,0x4000000,0x5600000,0x1000002f,0x7c00100,0x80230400,0x10000030,0x4000000,0x44200000,0x10000030, +0x6800000,0x41329800,0x10000030,0x6800100,0x40962540,0x10000030,0x7c00100,0x40230400,0x10000030,0xc000010,0x44b48000,0x10000031,0x7c00100,0x80230400,0x10000032,0x6800000, +0x81329800,0x10000032,0x7c00100,0x80230400,0x10000033,0x7c00100,0x80230400,0x10000034,0x7c00100,0x41830000,0x10000035,0x4000010,0x84400000,0x10000035,0x7c00100,0x80230400, +0x100005fe,0x4000000,0x84200000,0x10000601,0x4000000,0x84400000,0x10000604,0x4000000,0x84200000,0x10000604,0x4000000,0x84400000,0x10000d23,0x4000000,0x4200000,0x10000dfc, +0x4000000,0x14200000,0x10001000,0x4000000,0x14200000,0x10005000,0x4000000,0x14200000,0x10005000,0x4000000,0xc8810010,0x10005000,0x4000000,0xc8e0000d,0x10005000,0x4000000, +0xc9410010,0x10005000,0x24000000,0x4200000,0x10005000,0x24000000,0x4e00000,0x10005012,0x4000000,0xc8e00002,0x10005012,0x4000000,0xc8e00003,0x1000801f,0x7c00100,0xfc230400, +0x10010002,0x2802100,0x20962460,0x10010002,0x2802400,0x20962460,0x10010002,0x2802500,0x20962460,0x1001000f,0x2802100,0xfc962460,0x10010010,0x2802100,0xfc962460,0x10010015, +0x2802400,0xfc962460,0x10010017,0x2802400,0x19862460,0x10010030,0x2802100,0x40962460,0x10010030,0x2802400,0x40962460,0x10011001,0x2802400,0x10962460,0x10011001,0x2802400, +0x10c62460,0x10011001,0x12882000,0xc4962460,0x1001188b,0x2802400,0x10c62460,0x11000000,0x4000000,0x4200000,0x11000000,0x4000000,0x5600000,0x11000000,0x4000400,0x14200400, +0x11000000,0x7c00120,0xc8220405,0x11000000,0x24000000,0x4200000,0x11000000,0x24000000,0x4e00000,0x11000000,0x24000000,0x5710000,0x11000000,0x24000000,0xc200000,0x11000000, +0x24000000,0xc400000,0x11000000,0x24000000,0x1d710000,0x11000000,0x24000020,0x4200000,0x11000000,0x24000020,0x4810000,0x11000000,0x24000020,0x5410000,0x11000002,0x4000000, +0x5500000,0x11000002,0x7c00100,0xfc230400,0x11000002,0xc000010,0x4b48000,0x11000004,0x7c00100,0xfc230400,0x11000007,0x4000000,0x84200000,0x11000007,0x4000000,0x84400000, +0x11000007,0x4000000,0x84b00000,0x11000007,0x7c00100,0x80220400,0x11000007,0x7c00100,0x80250400,0x11000007,0xc000010,0x84448000,0x11000007,0xc000010,0x84b48000,0x11000008, +0x7c00100,0xc822040f,0x11000008,0x7c00100,0xfc220400,0x11000008,0x7c00100,0xfc250400,0x1100000b,0x4000000,0x4200000,0x1100000b,0x7c00100,0xfc230400,0x1100000c,0x7c00100, +0x8220400,0x1100000c,0x7c00100,0xc822040f,0x1100000c,0x7c00100,0xfc230400,0x1100000e,0x4000000,0x4200000,0x1100000e,0x4000000,0xc200000,0x1100000e,0x7c00100,0x8230400, +0x1100000e,0x7c00100,0xc822040f,0x1100000e,0x7c00100,0xfc220400,0x1100000e,0x7c00100,0xfc250400,0x11000013,0x4000000,0xcb00000,0x11000019,0x7c00100,0x10220400,0x11000019, +0x7c00100,0x20220400,0x11000019,0x7c00100,0x20250400,0x11000019,0x7c00100,0xc822040e,0x11000019,0x7c00100,0xc822040f,0x11000023,0x7c00100,0xfc230400,0x11000027,0x4000000, +0x4500000,0x11000037,0x4000000,0x84200000,0x11000037,0x6800100,0x80962540,0x11000037,0x7c00100,0x80230400,0x11000038,0x7c00100,0x80220400,0x11000038,0x7c00100,0x80250400, +0x11000039,0x4000000,0x84200000,0x11000039,0x4000000,0x84400000,0x11000039,0x7c00100,0x80230400,0x11000039,0xc000010,0x84448000,0x1100003a,0x4000000,0x44200000,0x1100003a, +0x6800100,0x40962540,0x1100003a,0x7c00100,0x40230400,0x1100003b,0x4000000,0x45800000,0x1100003b,0x6800000,0x41329800,0x1100003b,0x7c00100,0x41830000,0x1100003b,0x7e00100, +0x41830000,0x1100003c,0x7c00100,0x40230400,0x1100003c,0x7c00100,0xc823040f,0x1100003d,0x4000010,0x84400000,0x1100003d,0x7c00100,0x80230400,0x11000564,0x24000000,0xc400000, +0x1100056a,0x24000000,0xc400000,0x11000571,0x24000006,0x4400000,0x110005b2,0x4000400,0xc200000,0x11000d23,0x6800000,0xfd329800,0x11005000,0x4000000,0xc8810010,0x11005000, +0x4000000,0xc8870010,0x11005000,0x4000000,0xc8f00010,0x11005000,0x4000000,0xc9270010,0x11005000,0x4000000,0xc9271010,0x11005000,0x4000000,0xc9410010,0x11005000,0xc000010, +0xc8848010,0x11005000,0xc000010,0xc8b48010,0x11005000,0x24000000,0x4200000,0x11005000,0x24000000,0x4e00000,0x11005011,0x7c00300,0xc8e30001,0x11005011,0x7c40300,0xfce30000, +0x11005012,0x4000000,0xc8e00003,0x1100559b,0x4000000,0x4e00000,0x1100800a,0x7c00100,0xfc230400,0x11010001,0x2802000,0x18962460,0x11010001,0x2802020,0x10962460,0x11010002, +0x2802100,0x20962460,0x1101000b,0x2802400,0xfc962460,0x1101000e,0x2802000,0x18962460,0x11010013,0x2802000,0x28962460,0x11010013,0x2802100,0x28962460,0x11010013,0x2802100, +0x30962460,0x11010037,0x2802100,0x80962460,0x11010039,0x2802100,0x80962460,0x11010039,0x2802400,0x80962460,0x11010039,0x2806400,0x80962460,0x1101003a,0x2802100,0x40962460, +0x1101003a,0x2806400,0x40962460,0x1101088a,0x2802000,0x18962460,0x11011001,0x2802000,0x10962460,0x11011001,0x2802000,0x10c62460,0x11011863,0x2802000,0x20962460,0x14000000, +0x4000000,0x4200000,0x14000000,0x4000400,0x4200400,0x14000000,0x7c00120,0xc8220405,0x14000000,0x7c00120,0xc8250405,0x14000000,0x7c00500,0xfc230400,0x14000000,0x24000000, +0x4200000,0x14000000,0x24000020,0x4200000,0x14000008,0x7c00100,0xfc220400,0x14000008,0x7c00100,0xfc250400,0x1400000e,0x7c00100,0xfc220400,0x14000015,0x7c00100,0xfc230400, +0x14000019,0x7c00100,0x8220400,0x14000019,0x7c00100,0x8250400,0x14000019,0x7c00100,0x10220400,0x14000019,0x7c00100,0x10250400,0x14000019,0x7c00100,0x20220400,0x14000019, +0x7c00100,0x20250400,0x1400003e,0x4000000,0x44400000,0x1400003e,0x4000000,0x44e00000,0x1400003e,0x4000010,0x44400000,0x1400003e,0x6800000,0x42d29800,0x1400003e,0x6800100, +0x40962540,0x1400003e,0x6800100,0x40962541,0x1400003e,0x7c00100,0x42b30400,0x1400003e,0x7c00100,0x42b30401,0x1400003e,0xc000010,0x44448000,0x14000057,0x4000000,0x44200000, +0x14000057,0x4000010,0x45071400,0x14000057,0x6800000,0x41329800,0x14000057,0x7c00100,0x40230400,0x14000057,0x7c00100,0x48230400,0x14000057,0x7c00500,0x40230400,0x14000057, +0x7c00900,0x48230400,0x14000057,0xc000010,0x44b48000,0x1400005a,0x4000000,0x84500000,0x1400005a,0x7c00100,0x80230400,0x1400005a,0xc000010,0x84b48000,0x1400005b,0x4000000, +0x84200000,0x1400005b,0x4000010,0x84400000,0x1400005b,0x7c00100,0x80230400,0x14000065,0x4000010,0x84400000,0x14000065,0x7c00100,0x80230400,0x1400559b,0x4000000,0x4200000, +0x1400800a,0x7c00100,0xfc230400,0x14010001,0x2802020,0x10962460,0x14010001,0x2802400,0x10962460,0x14010013,0x2802500,0x20962460,0x14010015,0x2802100,0xfc962460,0x1401003e, +0x2802100,0x40962460,0x1401003e,0x2802100,0x40962461,0x1401003e,0x2802400,0x40962460,0x1401003e,0x2802400,0x50962460,0x1401003e,0x2806400,0x42f62460,0x14010057,0x2802400, +0x40962460,0x15000000,0x80020,0xc4218820,0x15000000,0x4000000,0x4200000,0x15000000,0x4000000,0x4e00000,0x15000000,0x4000000,0xc200000,0x15000000,0x4000000,0x14200000, +0x15000000,0x4000400,0x4200400,0x15000000,0x7c00500,0xfc230400,0x15000000,0x24000000,0x4200000,0x15000000,0x24000000,0x4400000,0x15000000,0x24000000,0x4810000,0x15000000, +0x24000000,0x4e00000,0x15000000,0x24000000,0x5400000,0x15000000,0x24000000,0x5410000,0x15000000,0x24000000,0x5710000,0x15000000,0x24000000,0xc400000,0x15000000,0x24000002, +0x4200000,0x15000000,0x24000020,0x4200000,0x15000000,0x24000020,0x4810000,0x15000000,0x24000020,0x5410000,0x15000000,0x24000500,0xc230400,0x15000000,0x2c000010,0xcb48000, +0x15000002,0x4000000,0x5500000,0x15000002,0x4000020,0x4200000,0x15000002,0x7c00100,0xfc230400,0x15000008,0x4000000,0x4200000,0x15000008,0x4000000,0xc200000,0x15000008, +0x7c00100,0x8220400,0x15000008,0x7c00100,0x8230400,0x15000008,0x7c00100,0x8250400,0x15000008,0x7c00100,0xfc220400,0x15000008,0x7c00100,0xfc250400,0x15000008,0x7c00500, +0xfc230400,0x1500000a,0x7c00100,0xfc230400,0x1500000a,0x7c00500,0xfc230400,0x1500000e,0x7c00100,0x8220400,0x1500000e,0x7c00100,0x8250400,0x1500000e,0x7c00100,0x10250400, +0x15000019,0x7c00100,0x8220400,0x15000019,0x7c00100,0x8230400,0x15000019,0x7c00100,0x8250400,0x15000019,0x7c00100,0x10220400,0x15000019,0x7c00100,0x10250400,0x15000019, +0x7c00100,0x18220400,0x15000019,0x7c00100,0x18250400,0x15000019,0x7c00100,0x20220400,0x15000019,0x7c00100,0x20250400,0x15000019,0x7c00100,0xc822040e,0x15000019,0x7c00100, +0xc822040f,0x15000019,0x7c00100,0xfc250400,0x1500001a,0x4000000,0x4200000,0x1500001a,0x4000000,0x5500000,0x1500001a,0x7c00100,0xfc230400,0x1500001b,0x7c00100,0x80230400, +0x1500001c,0x4000000,0x5800000,0x1500001c,0x6800000,0xfd329800,0x1500001c,0x6800100,0xfd862400,0x1500001c,0x6800100,0xfd862540,0x1500001c,0x6800500,0xfd862400,0x1500001c, +0x7c00100,0xfd830000,0x15000023,0x7c00100,0xfc230400,0x15000024,0x4000000,0x4200000,0x15000024,0x7c00100,0xfc230400,0x15000027,0x4000000,0x4200000,0x15000027,0x4000000, +0x4400000,0x15000027,0x4000000,0x4500000,0x15000027,0x7c00100,0xfc230400,0x15000042,0x4000000,0x44e00000,0x15000042,0x6800000,0x42d29800,0x15000042,0x6800100,0x40962540, +0x15000042,0x7c00100,0x40430400,0x15000042,0x7c00100,0x42d30400,0x15000042,0xc000010,0x44448000,0x1500004f,0x6800000,0x41329800,0x1500004f,0x7c00100,0x40230400,0x1500004f, +0xc000010,0x44448000,0x15000052,0x4000010,0x44400000,0x15000052,0x6800000,0x41329800,0x15000052,0x6800100,0x40962540,0x15000052,0x7c00100,0x40230400,0x15000052,0xc000010, +0x44448000,0x15000063,0x4000010,0x44400000,0x15000063,0x6800000,0x41329800,0x15000063,0x7c00100,0x40230400,0x15000063,0x7c00100,0x48230400,0x15000063,0x7c00900,0x40230400, +0x15000063,0xc000010,0x44448000,0x15000063,0xc000010,0x44b48000,0x15000068,0x7c00100,0x80230400,0x1500006b,0x7c00100,0x80230400,0x1500006c,0x4000000,0x84200000,0x1500006c, +0x7c00100,0x80230400,0x1500006d,0x6800000,0x41329800,0x1500006d,0x7c00100,0x40230400,0x1500006d,0x7c00500,0x40230400,0x1500006d,0x7c00d00,0x40230400,0x1500006d,0xc000010, +0x44448000,0x1500006e,0x4000000,0x84200000,0x1500006e,0x6800100,0x80962540,0x1500006e,0x7c00100,0x80230400,0x1500006f,0x6800000,0x41329800,0x1500006f,0x6800100,0x40962540, +0x1500006f,0x7c00100,0x40230400,0x1500006f,0xc000010,0x44448000,0x15000071,0x6800000,0x41329800,0x15000071,0x6800100,0x40962540,0x15000071,0x7c00100,0x40230400,0x15000573, +0x24000000,0x84400000,0x150005f3,0x4000400,0x4400000,0x15004000,0x24000020,0x4810000,0x15004000,0x24000020,0x5410000,0x15005000,0x4000000,0x4e00000,0x15005000,0x24000000, +0x4200000,0x15005005,0x7c00100,0xfce30400,0x15005011,0x7c40300,0xfce30000,0x1500559b,0x4000000,0x4e00000,0x15008024,0x7c00100,0x8230400,0x15010001,0x2802000,0x8962460, +0x15010001,0x2802000,0x10962460,0x15010001,0x2802000,0x18962460,0x15010001,0x2802100,0x18962460,0x15010001,0x2802400,0x10962460,0x15010001,0x2802400,0x10c62460,0x15010001, +0x2802400,0x18962460,0x15010002,0x2802100,0x20962460,0x15010008,0x2000,0xc962460,0x15010008,0x2802100,0x8962460,0x15010008,0x2802400,0x20962460,0x15010010,0x2802100, +0x20962460,0x1501001a,0x2802100,0x20962460,0x1501001c,0x2802100,0xfd862460,0x1501001c,0x2802500,0xfd862460,0x1501001c,0x2806400,0xfd862460,0x1501001f,0x2802100,0x20962460, +0x15010024,0x2802100,0x20962460,0x15010042,0x2802100,0x40962460,0x1501004f,0x2802100,0x40962460,0x1501004f,0x2802400,0x40962460,0x15010052,0x2802100,0x40962460,0x15010052, +0x2802400,0x40962460,0x15010052,0x2802d00,0x40962460,0x1501006e,0x2802100,0x80962460,0x1501006e,0x2806400,0x80962460,0x1501006f,0x2806400,0x40962460,0x15010071,0x2802100, +0x40962460,0x15010071,0x2806400,0x40962460,0x1501096e,0x2802000,0x10962460,0x15010c98,0x2802400,0x18962460,0x15010c98,0x2802400,0x20962460,0x16000000,0x4000000,0x4200000, +0x16000000,0x4000000,0x5500000,0x16000000,0x4000000,0x5600000,0x16000000,0x4000000,0xc8100006,0x16000000,0x4000000,0xc8200003,0x16000000,0x24000000,0x4200000,0x16000002, +0x4000000,0x4200000,0x16000004,0x4000000,0x5600000,0x16000007,0x7c00100,0x80220400,0x16000007,0x7c00100,0x80250400,0x16000008,0x7c00100,0xfc220400,0x16000008,0x7c00100, +0xfc250400,0x1600000a,0x4000000,0xc200000,0x1600000a,0x6800100,0x8962540,0x1600000a,0x7c00100,0x8230400,0x16000012,0x7c00100,0xa230500,0x16000012,0x7c00100,0xa330520, +0x16000019,0x7c00100,0x8250400,0x1600001c,0x4000000,0x5800000,0x1600001c,0x6800100,0xfd862400,0x1600001c,0x6800500,0xfd862400,0x1600001c,0x7c00100,0xfd830000,0x1600001c, +0x7c00900,0xfd830000,0x16000028,0x4000002,0x44400000,0x16000028,0x7c00100,0x40230400,0x1600003b,0x6800000,0x41329800,0x1600003b,0x7c00100,0x41830000,0x16000047,0x7c00100, +0x80230400,0x16000047,0x7c00100,0x80830400,0x16000047,0x7c00100,0x81430400,0x1600004e,0x4000000,0x44e00000,0x1600004e,0x4000010,0x44400000,0x1600004e,0x6800000,0x42d29800, +0x1600004e,0x6800100,0x40962540,0x1600004e,0x7c00100,0x42b30400,0x1600004e,0xc000010,0x44448000,0x16000058,0x7c00100,0x80230400,0x1600005b,0x4000000,0x84200000,0x1600006a, +0x4000000,0x45800000,0x1600006a,0x6800000,0x41329800,0x1600006a,0x6800100,0x41862400,0x1600006a,0x6800100,0x41862540,0x1600006a,0x7c00100,0x41830000,0x1600006a,0x7c00900, +0x41830000,0x1600006a,0xc000010,0x45848000,0x16000073,0x6800000,0x41329800,0x16000073,0x6800100,0x40962540,0x16000073,0x6800400,0x40962540,0x16000073,0x7c00100,0x40230400, +0x16000073,0xc000010,0x44448000,0x16000074,0x4000000,0x84200000,0x16000074,0x4000010,0x84400000,0x16000074,0x7c00100,0x80230400,0x16000075,0x4000000,0x84400000,0x16000075, +0x4000010,0x84400000,0x16000075,0x7c00100,0x80230400,0x16000078,0x4000000,0x84200000,0x16000078,0x6800100,0x80962540,0x16000078,0x7c00100,0x80230400,0x16000078,0x7c00100, +0x80230401,0x16000078,0xc000010,0x84448000,0x16000078,0x80000000,0x85329960,0x1600007a,0x4000000,0x84200000,0x1600007a,0x7c00100,0x80230400,0x1600007d,0x4000000,0x84200000, +0x1600007d,0x7c00100,0x80230400,0x1600007e,0x4000000,0x84200000,0x1600007e,0x4000010,0x84200000,0x1600007e,0x7c00100,0x80230400,0x1600007e,0xc000010,0x84248000,0x1600007f, +0x4000000,0x45800000,0x1600007f,0x4000010,0x45800000,0x1600007f,0x7c00100,0x41830000,0x1600007f,0x7c00500,0x41830000,0x1600007f,0x7c00900,0x41830000,0x1600007f,0x7e00100, +0x41830000,0x16000082,0x4000000,0x44200000,0x16000082,0x4000010,0x44400000,0x16000082,0x7c00100,0x40230400,0x16000082,0xc000010,0x44448000,0x16000083,0x4000010,0x44400000, +0x16000083,0x7c00100,0x40230400,0x16000083,0xc000010,0x44448000,0x16000085,0x4000000,0x84200000,0x16000085,0x7c00100,0x80230400,0x16000539,0x7c00100,0x8230400,0x1600053b, +0x4000400,0xc200000,0x1600053e,0x6800400,0x8962540,0x1600053e,0x7c00100,0x8230400,0x16000548,0x7c00100,0x8230400,0x1600054a,0x7c00100,0x8230400,0x16000575,0x24000000, +0xc400000,0x160005b4,0x4000000,0x4200000,0x160005c4,0x4000000,0x4200000,0x160005d3,0x4000000,0x4200000,0x160005de,0x4000000,0x5500000,0x160005f6,0x7c00900,0x60430400, +0x16000df1,0x7c00100,0x8230400,0x16001000,0x4000000,0x4100000,0x16001000,0x4000000,0xc8100002,0x16001000,0x4000000,0xc8100003,0x16001000,0x4000000,0xc8100006,0x16001000, +0x4000000,0xc810000d,0x16001000,0x4000100,0x4150400,0x16001000,0x4000100,0xc815040d,0x16001000,0x24000000,0x4100000,0x16001000,0x24000000,0x4e00000,0x16001000,0x24000000, +0x6800000,0x16005000,0x4000000,0xc8e00002,0x16005000,0x4000000,0xc8e0000d,0x16005000,0x24000000,0x4100000,0x16005000,0x24000000,0x4e00000,0x16005011,0x7c00300,0xc8e30001, +0x16005011,0x7c40300,0xfce30000,0x16005012,0x7c00100,0xa130480,0x16005014,0x4000000,0xc8e0000d,0x1600559b,0x4000000,0xc8e00003,0x1600800a,0x7c00100,0xfc230400,0x16010001, +0x2802400,0x10962460,0x16010007,0x2802400,0x80962460,0x16010007,0x2802400,0x90962460,0x1601000a,0x2802100,0x20962460,0x1601000a,0x2802400,0x8962460,0x1601001c,0x2802100, +0xfd862460,0x1601004e,0x2802100,0x40962460,0x1601004e,0x2802400,0x40962460,0x1601004e,0x2806400,0x42f62460,0x1601006a,0x2802100,0x41862460,0x1601006a,0x2802400,0x40962460, +0x1601006a,0x2802400,0x41862460,0x1601006a,0x2806400,0x41862460,0x16010073,0x2802100,0x40962460,0x16010073,0x2806400,0x40962460,0x16010078,0x2802100,0x80962460,0x16010078, +0x2802400,0x80962460,0x16010078,0x2806400,0x80962460,0x1601007e,0x2802000,0x80962460,0x1601007e,0x2802100,0x80962460,0x1601007e,0x2802400,0x80962460,0x1601007f,0x2802100, +0x41862460,0x1601007f,0x2802400,0x41862460,0x16010082,0x2802400,0x40962460,0x16010939,0x2802400,0x8962460,0x1601093a,0x2802400,0x8962460,0x1601093e,0x2802400,0x8962460, +0x16010940,0x2802400,0x8962460,0x16010942,0x2802400,0x8962460,0x16010ded,0x2802400,0x8962460,0x18000000,0x4000000,0x4200000,0x18000000,0x4000000,0x4e00000,0x18000000, +0x4000000,0x5600000,0x18000000,0x4000000,0x6703580,0x18000000,0x24000000,0x4200000,0x18000000,0x24000000,0x4e00000,0x18000000,0x24000000,0x5710000,0x18000000,0x24000020, +0x4200000,0x18000002,0x4000000,0x14200000,0x18000002,0x7c00100,0xfc230400,0x18000008,0x7c00100,0x8220400,0x18000008,0x7c00100,0x8250400,0x18000008,0x7c00100,0xfc220400, +0x18000008,0x7c00100,0xfc250400,0x1800000a,0x6800100,0xfc962540,0x1800000a,0x7c00100,0xfc230400,0x1800000b,0x7c00100,0xfc230400,0x18000019,0x7c00100,0x8220400,0x18000019, +0x7c00100,0x8250400,0x18000019,0x7c00100,0x10220400,0x18000019,0x7c00100,0xc822040e,0x18000019,0x7c00100,0xfc250400,0x1800001a,0x7c00100,0xfc230560,0x1800001f,0x4000000, +0x4200000,0x18000027,0x4000000,0x4c00000,0x18000027,0x7c00100,0xfc230400,0x1800003c,0x4000000,0x44400000,0x1800003f,0x4000000,0x44200000,0x1800003f,0x6800100,0x40962540, +0x1800003f,0x7c00100,0x42d30400,0x18000041,0x4000000,0x84e00000,0x18000041,0x4000010,0x84e00000,0x18000041,0x6800000,0x82d29800,0x18000041,0x6800100,0x80962540,0x18000041, +0x7c00100,0x82b30400,0x18000041,0x7c00100,0x82c30400,0x18000041,0xc000010,0x84448000,0x18000054,0x4000010,0x44200000,0x18000054,0x7c00100,0x40230400,0x18000082,0x7c00100, +0x40230400,0x18001000,0x4000000,0x4100000,0x18001000,0x4000000,0xc810000d,0x18001000,0x4000100,0x4150400,0x18001000,0x4000100,0xc815040d,0x18005000,0x4000000,0x4100000, +0x18005000,0x4000000,0x4200000,0x18005000,0x4000000,0x4e00000,0x18005000,0x4000000,0x6800000,0x18005000,0x4000000,0xc8e0000d,0x18005000,0x24000000,0x4200000,0x18005000, +0x24000000,0x4e00000,0x18005000,0x24000000,0x6800000,0x18005005,0x7c00100,0xfce30400,0x18005011,0x7c40300,0xfce30000,0x18005014,0x7c00100,0x8e30000,0x18005016,0x7c00100, +0x8e30c00,0x1800559b,0x4000000,0xc8e00003,0x1800801a,0x7c00100,0xfc230400,0x18010001,0x2802400,0x10c62460,0x18010002,0x2802100,0x20962460,0x1801000a,0x2802100,0xfc962460, +0x1801000b,0x2802400,0xfc962460,0x18010027,0x2802100,0xfc962460,0x1801003c,0x2806000,0x40962460,0x1801003f,0x2802100,0x40962460,0x1801003f,0x2802400,0x40962460,0x1801003f, +0x2806400,0x42e62460,0x18010041,0x2802100,0x80962460,0x18010041,0x2806400,0x82f62460,0x18010054,0x2802000,0x40962460,0x19000000,0x4000000,0x4200000,0x19000000,0x4000000, +0xc820000f,0x19000000,0x24000000,0x4200000,0x19000000,0x24000000,0x4400000,0x19000000,0x24000000,0xc200000,0x19000000,0x24000002,0x4300000,0x19000000,0x24000020,0x4200000, +0x19000002,0x4000020,0x4200000,0x19000002,0x7c00100,0xfc230400,0x19000002,0x7c00120,0xc8230405,0x19000002,0x80000000,0x5329960,0x19000003,0x4000000,0x5600000,0x19000007, +0x7c00100,0x80220400,0x19000007,0x7c00100,0x80250400,0x1900000c,0x7c00100,0xfc220400,0x1900000c,0x7c00100,0xfc230400,0x1900000c,0x7c00100,0xfc250400,0x1900000f,0x4000000, +0x4200000,0x19000018,0x7c00100,0xfd830000,0x19000019,0x7c00100,0xfc220400,0x19000019,0x7c00100,0xfc250400,0x19000019,0x7c00500,0xc822040f,0x1900003c,0x7c00100,0x40230400, +0x19000056,0x7c00100,0x80230400,0x1900005c,0x6800100,0x40962540,0x1900005c,0x7c00100,0x40230400,0x1900005c,0x7c00500,0x40230400,0x19000071,0x4000000,0x44200000,0x19000071, +0x7c00100,0x40230400,0x19000073,0x6800100,0x40962540,0x19000073,0x7c00100,0x40230400,0x19000073,0x7c00900,0x40230400,0x19000073,0xc000010,0x44448000,0x19000076,0x4000000, +0x44400000,0x19000076,0x6800000,0x41329800,0x19000076,0x6800100,0x40962540,0x19000076,0x7c00100,0x40230400,0x19000076,0xc000010,0x44448000,0x1900008d,0x7c00100,0x80230400, +0x19000097,0x4000000,0x84200000,0x19000097,0x4000000,0x84400000,0x19000097,0x6800000,0x81329800,0x19000097,0x6800100,0x80962540,0x19000097,0x7c00100,0x80230400,0x19000097, +0x7c00100,0x80230560,0x19000097,0xc000010,0x84448000,0x19000098,0x6800000,0x81329800,0x19000098,0x7c00100,0x80230400,0x19000099,0x6800000,0x81329800,0x19000099,0x6800100, +0x80962540,0x19000099,0x7c00100,0x80230400,0x1900053e,0x7c00100,0x8230400,0x19000555,0x7c00100,0x8230400,0x19005000,0x4000000,0x4e00000,0x19005011,0x7c00300,0xc8e30001, +0x19005011,0x7c40300,0xfce30000,0x19010002,0x2802400,0x20962460,0x19010002,0x2802500,0x20962460,0x19010008,0x2802100,0x8962460,0x1901005c,0x2802500,0x40962460,0x19010071, +0x2802100,0x40962460,0x19010071,0x2806400,0x40962460,0x19010073,0x2802100,0x40962460,0x19010073,0x2806400,0x40962460,0x19010076,0x2802100,0x40962460,0x19010076,0x2802100, +0x40962461,0x19010076,0x2806400,0x40962460,0x19010097,0x2802100,0x80962460,0x19010097,0x2806400,0x80962460,0x19010099,0x2802100,0x80962460,0x19010099,0x2802400,0x80962460, +0x19010099,0x2806400,0x80962460,0x19010957,0x2802400,0x8962460,0x1a000000,0x4000000,0x5600000,0x1b000000,0x80000,0xc4918820,0x1b000cab,0x80000,0xc4918820,0x1c000000, +0x4000000,0x4100000,0x1c000000,0x4000000,0x4200000,0x1c000000,0x4000000,0x4e00000,0x1c000000,0x4000000,0x5200000,0x1c000000,0x4000000,0x5500000,0x1c000000,0x4000000, +0x5600000,0x1c000000,0x4000000,0x5710000,0x1c000000,0x4000000,0x6800000,0x1c000000,0x4000400,0x4200400,0x1c000000,0x24000000,0x4200000,0x1c000000,0x24000000,0x4400000, +0x1c000000,0x24000000,0x4e00000,0x1c000000,0x24000002,0x4400000,0x1c000000,0x24000008,0x5410000,0x1c000000,0x80000000,0x5329960,0x1c000002,0x7c00100,0x8230400,0x1c000002, +0x7c00100,0xfc230400,0x1c000003,0x4000000,0x4200000,0x1c000004,0x7c00100,0x8230400,0x1c000008,0x7c00100,0x8220400,0x1c000008,0x7c00100,0x8250400,0x1c000008,0x7c00100, +0xfc220400,0x1c000008,0x7c00100,0xfc250400,0x1c000008,0x7c00500,0xc822040f,0x1c00000e,0x4000000,0x4200000,0x1c00000e,0x7c00100,0x8220400,0x1c00000e,0x7c00100,0x8250400, +0x1c000019,0x7c00100,0x8220400,0x1c000019,0x7c00100,0x8230400,0x1c000019,0x7c00100,0x8250400,0x1c000019,0x7c00500,0xc822040f,0x1c00001c,0x6800000,0xfd329800,0x1c00001c, +0x6800500,0xfd862400,0x1c00001c,0x7c00100,0x9830000,0x1c00001c,0x7c00100,0xfd830000,0x1c00001c,0x7c00900,0x9830000,0x1c00001e,0x7c00100,0x80230400,0x1c000020,0x7c00100, +0x80230400,0x1c000021,0x4000000,0x4200000,0x1c000021,0x6800000,0x9329800,0x1c000030,0x7c00100,0x40230400,0x1c00004b,0x4000000,0x84200000,0x1c00004b,0x4000010,0x84400000, +0x1c00004b,0x6800000,0x81329800,0x1c00004b,0x7c00100,0x80230400,0x1c00004b,0x7c00900,0x80230400,0x1c00004b,0xc000010,0x84448000,0x1c000053,0x7c00100,0x80230400,0x1c000059, +0x7c00100,0x80230400,0x1c000065,0x4000010,0x84400000,0x1c000065,0x7c00100,0x80230400,0x1c000079,0x4000000,0x84200000,0x1c000079,0x4000000,0x84f00000,0x1c000079,0x4000010, +0x84400000,0x1c000079,0x7c00100,0x80230400,0x1c00007b,0x4000000,0x84200000,0x1c00007b,0x4000010,0x84200000,0x1c00007b,0x7c00100,0x80230400,0x1c000086,0x7c00100,0x80230400, +0x1c000086,0xc000010,0x84448000,0x1c000087,0x4000000,0x84200000,0x1c000087,0x7c00100,0x80230400,0x1c000087,0xc000010,0x84448000,0x1c000088,0x7c00100,0x80230400,0x1c000089, +0x6800100,0x80962540,0x1c000089,0x6800100,0x80962541,0x1c000089,0x7c00100,0x80430400,0x1c000089,0x7c00100,0x82b30400,0x1c000089,0x7c00100,0x82d30400,0x1c000089,0x7c00900, +0x80430400,0x1c00008c,0x4000000,0x84200000,0x1c00008c,0x7c00100,0x80230400,0x1c00008e,0x4000000,0x84200000,0x1c00008e,0x7c00100,0x80230400,0x1c00008f,0x4000000,0x84200000, +0x1c00008f,0x7c00100,0x80230400,0x1c000090,0x4000000,0x84200000,0x1c000090,0x7c00100,0x80230400,0x1c000091,0x6800000,0x81329800,0x1c000091,0x6800100,0x80962540,0x1c000091, +0x7c00100,0x80230400,0x1c000092,0x4000000,0x84200000,0x1c000092,0x6800000,0x81329800,0x1c000092,0x7c00100,0x80220400,0x1c000092,0x7c00100,0x80230400,0x1c000092,0x7c00100, +0x80250400,0x1c000095,0x6800000,0xa1329800,0x1c000095,0x7c00100,0xa0230400,0x1c000095,0xc000010,0x84448000,0x1c000097,0x7c00100,0x80230400,0x1c000097,0xc000010,0x84248000, +0x1c00009d,0x4000000,0x84200000,0x1c00009d,0x4000010,0x84200000,0x1c00009d,0x6800100,0x80962540,0x1c00009d,0x7c00100,0x80230400,0x1c00009d,0xc000010,0x84448000,0x1c00009e, +0x4000000,0x84200000,0x1c00009e,0x6800000,0x81329800,0x1c00009e,0x6800100,0x80962540,0x1c00009e,0x6800100,0x80962541,0x1c00009e,0x7c00100,0x80230400,0x1c00009f,0x4000000, +0x84200000,0x1c00009f,0x7c00100,0x80230400,0x1c0000a0,0x4000000,0x84200000,0x1c0000a0,0x4000000,0x84500000,0x1c0000a0,0x7c00100,0x80230400,0x1c0000a3,0x4000000,0x84200000, +0x1c0000a3,0x6800000,0x81329800,0x1c0000a3,0x6800100,0x80962540,0x1c0000a3,0x7c00100,0x80230400,0x1c0000a3,0xc000010,0x84448000,0x1c0000a5,0x7c00100,0x80230400,0x1c0000a6, +0x4000000,0x84500000,0x1c0000a6,0x4000010,0x84b00000,0x1c0000a6,0x4000800,0x84200000,0x1c0000a6,0x6800100,0x80962540,0x1c0000a6,0x6800100,0x80962541,0x1c0000a6,0x7c00100, +0x80230400,0x1c0000a6,0xc000010,0x84448000,0x1c00045d,0x80000,0xc4918820,0x1c00045d,0x2c000010,0x84448000,0x1c00057c,0x24000010,0x4400000,0x1c000606,0x4000000,0xc200000, +0x1c000e0a,0x4000010,0x84400000,0x1c000e0c,0x6800100,0xfc962540,0x1c005000,0x4000000,0x4e00000,0x1c005000,0x4000000,0x6800000,0x1c00800a,0x7c00100,0x8230400,0x1c008024, +0x7c00100,0x8230400,0x1c010001,0x2400,0x4962460,0x1c010001,0x2802100,0x10962460,0x1c010001,0x2802400,0x8962460,0x1c010001,0x2802400,0x10962460,0x1c010001,0x2802400, +0x10c62460,0x1c010002,0x2802100,0x20962460,0x1c010015,0x2802100,0x8962460,0x1c01001a,0x2802100,0x8962460,0x1c01001c,0x2802500,0x9862460,0x1c01001c,0x2802500,0xfd862460, +0x1c010024,0x2802100,0x8962460,0x1c010041,0x2806000,0x80c62460,0x1c01004b,0x2802400,0x80962460,0x1c010059,0x2802100,0x80962460,0x1c010079,0x2802400,0x80962460,0x1c010086, +0x2802400,0x80962460,0x1c010087,0x2802000,0x80962460,0x1c010087,0x2802100,0x80962460,0x1c010089,0x2802100,0x80962460,0x1c010089,0x2802400,0x80962460,0x1c010089,0x2806400, +0x82f62460,0x1c01008c,0x2802400,0x80962460,0x1c010091,0x2802100,0x80962460,0x1c010091,0x2802400,0x80962460,0x1c010091,0x2806400,0x80962460,0x1c01009d,0x2802100,0x80962460, +0x1c01009d,0x2802400,0x80962460,0x1c01009d,0x2802900,0x80962460,0x1c01009d,0x2806400,0x80962460,0x1c01009e,0x2802100,0x80962460,0x1c01009e,0x2802400,0x80962460,0x1c01009e, +0x2806400,0x80962460,0x1c0100a0,0x2802400,0x80962460,0x1c0100a3,0x2802100,0x80962460,0x1c0100a3,0x2806400,0x80962460,0x1c0100a6,0x2802100,0x80962460,0x1c0100a6,0x2802400, +0x80962460,0x1c0100a6,0x2806400,0x80962460,0x1c010955,0x2802400,0x8962460,0x1c010a06,0x2802400,0x8962460,0x1c010e0c,0x2802100,0xfc962460,0x1c010e0c,0x2802400,0xfc962460, +0x20000000,0x4000000,0x5500000,0x20000000,0x4000000,0x24200000,0x20000000,0x4000000,0x24e00000,0x20000000,0x4000000,0x34200000,0x20000000,0x24000000,0x24200000,0x20000002, +0x7c00100,0x20230400,0x20000006,0x7c00100,0x40220400,0x20000006,0x7c00100,0x40250400,0x2000000a,0x4000000,0x2c500000,0x2000000a,0x7c00100,0x28230400,0x20000019,0x7c00100, +0x20220400,0x20000019,0x7c00100,0x20230400,0x20000019,0x7c00100,0x20250400,0x2000001a,0x7c00100,0x8230400,0x2000004c,0x4000000,0x84200000,0x2000004c,0x7c00100,0x80220400, +0x2000004c,0x7c00100,0x80250400,0x20000065,0x7c00100,0x80230400,0x20000070,0x4000000,0x84200000,0x20000070,0x4000010,0x84400000,0x20000070,0xc000010,0x84448000,0x20000089, +0x7c00100,0x82d30400,0x2000008d,0x4000000,0x84200000,0x20000097,0x4000000,0x84400000,0x20000097,0x4000000,0x84500000,0x20000097,0x7c00100,0x80230400,0x20000097,0xc000010, +0x84448000,0x2000009c,0x7c00100,0x80230400,0x2000009c,0x7c00100,0x80830400,0x2000009c,0x7c00100,0x81430400,0x200000a1,0x4000000,0x85800000,0x200000a1,0x6800000,0x81329800, +0x200000a1,0x6800100,0x81862400,0x200000a1,0x6800100,0x81862540,0x200000a1,0x7c00100,0x81830000,0x200000a1,0xc000010,0x84448000,0x200000a2,0x4000000,0x84200000,0x200000a2, +0x7c00100,0x80230400,0x200000a4,0x7c00100,0x80230400,0x200000a4,0xc000010,0x84448000,0x200000a6,0x7c00100,0x80230400,0x200000a6,0xc000010,0x84448000,0x20005000,0x4000000, +0x4e00000,0x20005000,0x4000000,0x6800000,0x20005011,0x7c40300,0xfce30000,0x2000800f,0x7c00100,0x20230400,0x20008024,0x7c00100,0x20230400,0x20010002,0x2802500,0x20962460, +0x20010008,0x2802100,0x28962460,0x20010008,0x2802400,0x30962460,0x20010008,0x2802400,0x30c62460,0x20010070,0x2802000,0x80962460,0x20010089,0x2802100,0x80962460,0x20010097, +0x2802000,0x80962460,0x20010097,0x2802400,0x80962460,0x200100a1,0x2802100,0x81862460,0x200100a1,0x2806400,0x81862460,0x200100a6,0x2802100,0x80962460,0x20015000,0x4000000, +0x6902460,0x24000000,0x4000000,0x4e00000,0x24000000,0x24000000,0x4200000,0x24000000,0x24000000,0x4400000,0x24000000,0x80000000,0x5329960,0x24000002,0x7c00100,0xfc230400, +0x24000008,0x7c00100,0x8220400,0x2400000e,0x4000000,0x4200000,0x24000015,0x7c00100,0xfc230400,0x24000019,0x7c00100,0x10250400,0x2400001a,0x4000000,0x4200000,0x2400001a, +0x7c00100,0xfc230400,0x2400001b,0x4000000,0x84500000,0x240000a7,0x4000000,0x45400000,0x240000a7,0x6800000,0x41329800,0x240000a7,0x7c00100,0x40220400,0x240000a7,0x7c00100, +0x40250400,0x240000a8,0x4000000,0x84200000,0x240000a8,0x4000000,0x84400000,0x240000a8,0x4000010,0x84400000,0x240000a8,0x6800000,0x81329800,0x240000a8,0x6800100,0x80962540, +0x240000a8,0x7c00100,0x80230400,0x240000a8,0xc000010,0x84448000,0x240000a9,0x4000000,0x84500000,0x240000a9,0x4000010,0x84b00000,0x240000a9,0x6800100,0x80962540,0x240000a9, +0x7c00100,0x80230400,0x240000aa,0x4000000,0x44200000,0x240000aa,0x4000000,0x44400000,0x240000aa,0x4000010,0x44400000,0x240000aa,0x6800000,0x41329800,0x240000aa,0x6800100, +0x40962540,0x240000aa,0x7c00100,0x40230400,0x240000aa,0xc000010,0x44448000,0x240000ab,0x7c00100,0x40220400,0x240000ab,0x7c00100,0x40250400,0x24000496,0x24000000,0x4400000, +0x24001000,0x4000000,0x4100000,0x24005000,0x4000000,0x4e00000,0x24005000,0x4000000,0x6800000,0x24005000,0x4000000,0xc8e0000d,0x2400509a,0x7c00300,0x80e30000,0x2400509a, +0x7c00900,0x81230400,0x24010001,0x2802400,0x10962460,0x24010002,0x2802000,0x20962460,0x24010002,0x2802100,0x20962460,0x24010038,0x2802100,0x80962460,0x2401006f,0x2802100, +0x40962460,0x2401009d,0x2802100,0x80962460,0x240100a7,0x2802100,0x40962460,0x240100a7,0x2802400,0x40962460,0x240100a7,0x2802c00,0x40962460,0x240100a8,0x2802100,0x80962460, +0x240100a8,0x2806400,0x80962460,0x240100a9,0x2802100,0x80962460,0x240100aa,0x2802100,0x40962460,0x240100aa,0x2802400,0x40962460,0x240100aa,0x2806400,0x40962460,0x28000000, +0x4000000,0x4200000,0x28000000,0x4000000,0x4e00000,0x28000000,0x4000000,0x5600000,0x28000000,0x24000000,0x4200000,0x28000000,0x24000000,0x4400000,0x28000004,0x4000000, +0x4200000,0x28000004,0x7c00100,0x8230400,0x2800001e,0x7c00100,0x80230400,0x28000022,0x7c00100,0x40230400,0x280000af,0x6800000,0x81329800,0x280000af,0x7c00100,0x80230400, +0x280000af,0x7c00100,0x80230560,0x280000b0,0x4000000,0x84400000,0x280000b0,0x4000000,0x84500000,0x280000b0,0x4000010,0x84400000,0x280000b0,0x6800100,0x80962540,0x280000b0, +0x7c00100,0x80230400,0x280000b0,0x7c00100,0x80230560,0x280000b0,0xc000010,0x84448000,0x280000b1,0x4000000,0x84200000,0x280000b1,0x4000000,0x84400000,0x280000b1,0x4000000, +0x84500000,0x280000b1,0x6800100,0x80962540,0x280000b1,0x7c00100,0x80230400,0x280000b1,0x7c00100,0x80230560,0x280000b1,0xc000010,0x84448000,0x2800055b,0x6800400,0x8962540, +0x28005000,0x4000000,0x4e00000,0x28005000,0x4000000,0x6800000,0x28005005,0x7c00100,0x8e30400,0x28005011,0x7c40300,0xfce30000,0x28005014,0x7c00100,0x8e30000,0x28005096, +0x7c00300,0x80e30000,0x28005096,0x7c00900,0x81230400,0x28010001,0x2802400,0x10962460,0x2801000f,0x2802100,0xfc962460,0x2801000f,0x2802400,0xfc962460,0x2801000f,0x2802900, +0xfc962460,0x2801001a,0x2802100,0xfc962460,0x2801001a,0x2806400,0x8962460,0x280100af,0x2802100,0x80962460,0x280100af,0x2802400,0x80962460,0x280100af,0x2806400,0x80962460, +0x280100b0,0x2802100,0x80962460,0x280100b0,0x2802800,0x80962460,0x280100b0,0x2806400,0x80962460,0x280100b1,0x2802000,0x80962460,0x280100b1,0x2802100,0x80962460,0x280100b1, +0x2806400,0x80962460,0x2801095c,0x2802400,0x10962460,0x2c000000,0x4000000,0x4200000,0x2c000000,0x4000000,0x4e00000,0x2c000000,0x4000000,0x5500000,0x2c000000,0x24000000, +0x4200000,0x2c000000,0x24000000,0x4400000,0x2c000000,0x24000010,0x4400000,0x2c000003,0x7c00100,0x10220400,0x2c00000a,0x7c00100,0x8230400,0x2c00000c,0x7c00100,0xfc230400, +0x2c000010,0x4000000,0x4200000,0x2c000013,0x7c00100,0xfe633800,0x2c000015,0x4000000,0x4500000,0x2c000019,0x7c00100,0x10220400,0x2c000019,0x7c00100,0x20220400,0x2c000019, +0x7c00100,0x20250400,0x2c00001b,0x7c00100,0x80230400,0x2c000039,0x4000000,0x84200000,0x2c000039,0x7c00100,0x80230400,0x2c000057,0x4000000,0x45600000,0x2c000076,0x6800100, +0x40962540,0x2c000076,0x7c00100,0x40230400,0x2c000078,0x80000000,0x85329960,0x2c0000a1,0x7c00100,0x81830000,0x2c0000b0,0x7c00100,0x80230400,0x2c0000b2,0x4000000,0x84200000, +0x2c0000b2,0x6800100,0x80962540,0x2c0000b2,0x7c00100,0x80230400,0x2c0000b3,0x6800000,0x41329800,0x2c0000b3,0x6800100,0x40962540,0x2c0000b3,0x7c00100,0x40230400,0x2c0000b4, +0x6800100,0x80962540,0x2c0000b4,0x7c00100,0x80430400,0x2c0000b4,0x7c00100,0x82d30400,0x2c0000b4,0xc000010,0x84448000,0x2c0000b5,0x4000000,0x84200000,0x2c0000b5,0x4000010, +0x84400000,0x2c0000b5,0x7c00100,0x80220400,0x2c0000b5,0x7c00100,0x80250400,0x2c0000b5,0xc000010,0x84448000,0x2c0000b6,0x6800000,0x41329800,0x2c0000b6,0x7c00100,0x40230400, +0x2c0000b6,0x7c00500,0x40230400,0x2c0000b7,0x4000000,0x84200000,0x2c0000b7,0x7c00100,0x80230400,0x2c0000b7,0xc000010,0x84248000,0x2c0000b8,0x4000000,0x84200000,0x2c0000b8, +0x7c00100,0x80230400,0x2c005000,0x4000000,0x4200000,0x2c005000,0x4000000,0x4e00000,0x2c005000,0x4000000,0x6800000,0x2c005005,0x7c00100,0xfce30400,0x2c005011,0x7c40300, +0xfce30000,0x2c00509a,0x7c00300,0x80e30000,0x2c010002,0x2802000,0x20962460,0x2c010004,0x2802000,0xfc962460,0x2c01000a,0x2802100,0x8962460,0x2c010024,0x2802100,0xfc962460, +0x2c010057,0x2802000,0x40962460,0x2c0100aa,0x2802000,0x40962460,0x2c0100b2,0x2802100,0x80962460,0x2c0100b2,0x2802400,0x80962460,0x2c0100b2,0x2806400,0x80962460,0x2c0100b3, +0x2802100,0x40962460,0x2c0100b3,0x2806400,0x40962460,0x2c0100b4,0x2802100,0x80962460,0x2c0100b6,0x2802500,0x40962460,0x2c0100b7,0x2802400,0x80962460,0x2c010921,0x2802400, +0xfc962460,0x30000000,0x4000000,0x4200000,0x30000000,0x4000000,0xc820000f,0x30000000,0x24000000,0x4200000,0x30000000,0x24000010,0x4400000,0x30000018,0x7c00100,0xfd830000, +0x30000019,0x7c00100,0x10220400,0x30000019,0x7c00100,0x10250400,0x30000019,0x7c00100,0xfc220400,0x30000019,0x7c00100,0xfc250400,0x30000023,0x4000000,0x4200000,0x30000023, +0x4000000,0x4400000,0x30000023,0x4000000,0x5500000,0x30000024,0x4000000,0x4500000,0x30000047,0,0x84818820,0x30000047,0,0x84c18820,0x30000047,0, +0x85418820,0x3000005c,0x6800100,0x40962540,0x3000005c,0x7c00100,0x40230400,0x30000099,0x7c00100,0x80230400,0x300000a7,0x7c00100,0x40230400,0x300000aa,0x7c00100,0x40230400, +0x300000b0,0x7c00100,0x80230560,0x300000b9,0x7c00100,0x80230400,0x300000ba,0x4000000,0x44200000,0x300000ba,0x6800000,0x41329800,0x300000ba,0x7c00100,0x40230400,0x300000ba, +0x7c00900,0x40230400,0x300000bb,0x4000000,0x84500000,0x300000bb,0x6800100,0x80962540,0x300000bb,0x7c00100,0x80230400,0x300000bc,0x4000000,0x45600000,0x300000bc,0x6800000, +0x41329800,0x300000bc,0x7c00100,0x40230400,0x30000549,0x7c00100,0x80230400,0x30000d23,0x4000000,0x4200000,0x30005000,0x4000000,0x4e00000,0x30005000,0x4000000,0x6800000, +0x30005011,0x4000000,0x5200000,0x30005011,0x7c00900,0x9230400,0x30005014,0x7c00100,0xfe530000,0x30005016,0x7c00100,0xfe530c00,0x3000509a,0x7c00300,0x80e30000,0x30010018, +0x2806400,0xfd862460,0x3001005c,0x2802100,0x40962460,0x300100ba,0x2802400,0x40962460,0x300100bb,0x2802100,0x80962460,0x300100bb,0x2806400,0x80962460,0x300100bc,0x2802400, +0x40962460,0x3100559b,0x4000000,0xc8e0000d,0x34000000,0x4000000,0x4200000,0x34000000,0x4000400,0x4200000,0x34000000,0x6800000,0xc9329805,0x34000000,0x24000000,0x4200000, +0x34000002,0x7c00100,0xfc230400,0x34000019,0x7c00100,0x8220400,0x34000019,0x7c00100,0x8250400,0x34000019,0x7c00100,0x10220400,0x34000019,0x7c00100,0xfc220400,0x34000019, +0x7c00100,0xfc250400,0x34000019,0x7c00500,0xc822040f,0x3400001a,0x7c00100,0x18230400,0x34000076,0x7c00100,0x40230400,0x34000083,0x7c00100,0x40230400,0x34000097,0x6800100, +0x80962540,0x340000aa,0x4000010,0x44400000,0x340000aa,0x7c00100,0x40230400,0x340000bd,0x4000000,0x84200000,0x340000bd,0x7c00100,0x80230400,0x340000be,0x4000000,0x84400000, +0x340000be,0x6800000,0x82d29800,0x340000be,0x6800100,0x80962540,0x340000be,0x6800100,0x80962541,0x340000be,0x7c00100,0x82b30400,0x340000be,0x7c00100,0x82c30560,0x340000be, +0xc000010,0x84448000,0x340000c0,0x4000002,0x84400000,0x340000c0,0x7c00100,0x80230400,0x34005000,0x4000000,0x4e00000,0x34005000,0x4000000,0x6800000,0x34005005,0x7c00100, +0xfce30400,0x34005011,0x7c40300,0xfce30000,0x3400509a,0x7c00300,0x80e30000,0x340050bf,0x7c00300,0x80230000,0x34010001,0x2802100,0x10962460,0x3401001f,0x2802c00,0xfc962460, +0x34010021,0x2802100,0x10962460,0x3401003a,0x2806400,0x40962460,0x34010097,0x2802100,0x80962460,0x340100be,0x2802100,0x80962460,0x340100be,0x2802400,0x80962460,0x340100be, +0x2806400,0x80962460,0x340100be,0x2806400,0x82f62460,0x340100c0,0x2802100,0x80962460,0x34015011,0x2802500,0xfc962460,0x340150bf,0x2802200,0x80c62460,0x38000000,0x4000000, +0x5500000,0x38000000,0x4000000,0x14200000,0x38000000,0x24000000,0x5410000,0x38000000,0x24000000,0x6410000,0x38000000,0x24000002,0x4400000,0x38000000,0x2c000010,0x4b48000, +0x38000002,0x4000000,0x4200000,0x38000002,0x4000000,0x14200000,0x38000002,0x7c00100,0xfc230400,0x38000002,0x7c00500,0xfc230400,0x38000002,0xc000010,0x4b48000,0x38000002, +0x80000000,0x5329960,0x3800000b,0x7c00100,0xfc230400,0x38000015,0x7c00100,0xfc230400,0x38000019,0x7c00100,0xc822040f,0x38000019,0x7c00100,0xfc220400,0x38000019,0x7c00100, +0xfc230400,0x38000019,0x7c00100,0xfc250400,0x38000019,0x7c00500,0x20220400,0x38000019,0x7c00500,0xc822040f,0x38000019,0x7c00d00,0xc823040f,0x38000024,0x7c00100,0xfc230400, +0x38000028,0x7c00100,0x40230400,0x3800002a,0x7c00100,0x80230400,0x38000038,0x7c00100,0x80220400,0x38000038,0x7c00100,0x80250400,0x3800003e,0x7c00100,0x42b30400,0x3800003e, +0xc000010,0x44448000,0x38000041,0x7c00100,0x82b30400,0x38000099,0x4000000,0x84200000,0x380000a1,0x7c00100,0x81830000,0x380000c1,0x4000000,0x84200000,0x380000c1,0x7c00100, +0x80230400,0x380000c2,0x7c00100,0x80230400,0x380000c2,0xc000010,0x84248000,0x380000c3,0x6800000,0x81329800,0x380000c3,0x7c00100,0x80230400,0x380000c4,0x7c00100,0x80230400, +0x380000c5,0x7c00100,0x80220400,0x380000c5,0x7c00100,0x80250400,0x38005000,0x4000000,0x4e00000,0x38005000,0x4000000,0x6800000,0x38005011,0x7c40300,0xfce30000,0x38005014, +0x7c00100,0xfce30000,0x38005016,0x7c00100,0xfce30c00,0x38005016,0x7c00500,0x20230c00,0x38010001,0x2802100,0x20962460,0x38010001,0x2802400,0x10962460,0x38010001,0x2802400, +0x20962460,0x38010002,0x2802400,0x20962460,0x3801001b,0x12882000,0xc4962460,0x38010024,0x2802400,0xfc962460,0x3801002a,0x2806400,0x80962460,0x38010041,0x2802100,0x80962460, +0x38010041,0x2806400,0x80962460,0x38010078,0x2802100,0x80962460,0x380100c2,0x2802400,0x80962460,0x380100c4,0x2802400,0x80962460,0x38010874,0x2802400,0x50962460,0x3c000000, +0x4000000,0x4200000,0x3c000000,0x4000000,0x4e00000,0x3c000008,0x7c00500,0xc822040e,0x3c000008,0x7c00500,0xc822040f,0x3c00000a,0x4000000,0x4500000,0x3c000015,0x6800100, +0xfc962540,0x3c000019,0x7c00100,0xfc220400,0x3c000047,0,0x84818820,0x3c000047,0,0x84c18820,0x3c000047,0,0x85418820,0x3c000047,0x7c00100,0x80230400, +0x3c000047,0x7c00100,0x81430400,0x3c00009d,0x7c00100,0x80230400,0x3c0000c6,0x4000000,0x84e00000,0x3c0000c6,0x6800000,0x82d29800,0x3c0000c6,0x6800100,0x80962540,0x3c0000c6, +0x7c00100,0x82b30400,0x3c0000c6,0x7c00100,0x82c30560,0x3c0000c6,0xc000010,0x84448000,0x3c0000c7,0x6800000,0x81329800,0x3c0000c7,0x7c00100,0x80230400,0x3c005000,0x4000000, +0x4e00000,0x3c005000,0x4000000,0x6800000,0x3c005011,0x7c40300,0xfce30000,0x3c005014,0x7c00100,0xfe530000,0x3c005016,0x7c00100,0xfe530c00,0x3c010002,0x2802400,0x20962460, +0x3c010008,0x2802100,0xfc962460,0x3c010018,0x2802000,0xfd862460,0x3c010047,0x2802000,0x80962460,0x3c010047,0x2802400,0x80962460,0x3c01009d,0x2802100,0x80962460,0x3c0100c6, +0x2802100,0x80962460,0x3c0100c6,0x2806400,0x80962460,0x3c0100c6,0x2806400,0x82f62460,0x3c0100c7,0x2802000,0x80962460,0x3d005011,0x7c40300,0xfce30000,0x3d00557f,0x4000000, +0x4e00000,0x3d00557f,0x4008000,0x4e00000,0x40000000,0x4000000,0x4200000,0x40000000,0x4000000,0xc8200005,0x40000000,0x6800000,0xc9329805,0x40000000,0x24000000,0x4200000, +0x40000002,0x7c00100,0x20230400,0x40000008,0x7c00100,0x20220400,0x40000008,0x7c00100,0x20250400,0x40000019,0x7c00100,0x20220400,0x40000019,0x7c00100,0x20250400,0x4000001c, +0x6800000,0x21329800,0x4000003e,0xc000010,0x44448000,0x40000047,0x7c00100,0x80230400,0x400000c9,0x4000002,0x84400000,0x400000c9,0x4000020,0x84200000,0x400000c9,0x6800000, +0x81329800,0x400000c9,0x7c00100,0x80220400,0x400000c9,0x7c00100,0x80230400,0x400000c9,0x7c00100,0x80250400,0x400000c9,0x7c00900,0x80230400,0x400000c9,0x7c00d00,0x80230400, +0x400000ca,0x6800000,0x82d29800,0x400000ca,0x6800100,0x80962540,0x400000ca,0x7c00100,0x82d30400,0x400000cb,0x4000000,0x84200000,0x400000cb,0x6800000,0x81329800,0x400000cb, +0x7c00100,0x80230400,0x400000cb,0x7c00100,0x80230520,0x400000cb,0x7c00100,0x80230521,0x400000cb,0x7c00500,0x80230400,0x400000cb,0xc000010,0x84448000,0x400000cc,0x4000000, +0x84200000,0x400000cc,0x6800000,0x81329800,0x400000cc,0x7c00100,0x80230400,0x400000cd,0x4000000,0x84200000,0x400000cd,0x6800000,0x81329800,0x400000cd,0x7c00100,0x80230400, +0x400000ce,0x7c00100,0x80230400,0x400000ce,0x7c00100,0x80230401,0x400000cf,0x4000000,0x84e00000,0x400000cf,0x6800100,0x80962540,0x400000cf,0x7c00100,0x80e30400,0x400000cf, +0x7c00100,0x82b30400,0x400000cf,0x7c00100,0x82c30560,0x400000cf,0x7c00100,0x82d30400,0x400000cf,0x7c00100,0x82d30401,0x400000cf,0x7c00d00,0x80e30400,0x400000cf,0xc000010, +0x84e48000,0x40005000,0x4000000,0x4e00000,0x400050bf,0x7c00300,0x80230000,0x4000559b,0x4000000,0x4e00000,0x40010002,0x2802100,0x20962460,0x400100c6,0x2802400,0x80962460, +0x400100c9,0x2802400,0x80962460,0x400100c9,0x2802500,0x80962460,0x400100c9,0x2802c00,0x80962460,0x400100ca,0x2802100,0x80962460,0x400100ca,0x2802100,0x80962461,0x400100ca, +0x2806400,0x80962460,0x400100cc,0x2802400,0x80962460,0x400100cc,0x2802c00,0x80962460,0x400100cf,0x2802100,0x80962460,0x400100cf,0x2802100,0x80962461,0x400100cf,0x2802400, +0x80962460,0x400100cf,0x2802c00,0x80962460,0x400100cf,0x2806400,0x80962460,0x400100cf,0x2806400,0x82f62460}; -static const int32_t countPropsVectors=7497; +static const int32_t countPropsVectors=6426; static const int32_t propsVectorsColumns=3; -static const uint16_t scriptExtensions[298]={ -0x800e,0x8019,8,0x8059,8,2,8,0x8038,8,6,8,0x8019,2,0x22,0x25,0x57, -0xb6,0x80c0,2,0x22,0x8025,2,0x12,2,0x22,0x25,0x57,0xa7,0xb6,0x80c0,2,0x22, -0x54,0x79,0x7b,0xa7,0xb6,0xb7,0x80c2,2,0x8022,2,0x25,0x80c0,2,0x29,2,0x80b6, -2,0x2e,4,0xa,0xf,0x10,0x15,0x19,0x1a,0x1f,0x23,0x24,0x89,0x97,0x809e,4, -0xa,0xf,0x10,0x15,0x19,0x1a,0x1f,0x23,0x24,0x89,0x809e,4,0xa,0xf,0x10,0x15, -0x1a,0x1f,0x21,0x23,0x24,0x3a,0x89,0x91,0x99,0x9e,0xa0,0xaf,0xb2,0xb3,0x80bb,4, -0xa,0xf,0x10,0x15,0x1a,0x1f,0x21,0x23,0x24,0x30,0x3a,0x89,0x91,0x99,0x9e,0xa0, -0xaf,0xb2,0xb3,0x80bb,0xa,0x78,0xa0,0x80b2,0xa,0x74,4,0x3a,0x8076,4,0x7a,0x10, -0x80a4,0x10,0x7f,0xf,0x809d,0xf,0x83,0x23,0x8089,0x23,0x87,0x15,0x80bb,0x15,0x8b,0x1c, -0x34,0x8076,0x1c,0x8f,0xc,0x8019,0x2a,0x2b,0x2c,0x802d,0x1b,0x805a,0x800a,4,0xa,0x15, -0x8089,0xa,0x8089,4,0x800a,0xa,0x8097,0xa,0x15,0x1a,0x1f,0x23,0x8024,0xa,0x80bb,4, -0xa,0x15,0x1a,0x1f,0x21,0x24,0x89,0x9e,0x80bb,0x8004,8,0x8022,0x19,0x801b,0xa,0x19, -0x8089,5,0x11,0x12,0x14,0x16,0x8029,5,0x11,0x12,0x14,0x8016,0x8011,5,0x8011,0x11, +static const uint16_t scriptExtensions[526]={ +7,0xc,0xd,0xe,0x11,0x19,0x33,0x38,0x59,0x68,0x6c,0x75,0x87,0x88,0xa0,0x80b3, +4,8,0xa,0x19,0x26,0x83,0x80c4,5,0x8019,0x19,0x8083,0x19,0x8026,6,7,8, +0xe,0x19,0x34,0x59,0x80cd,6,8,0xe,0x19,0x34,0xab,0xcd,0x80ce,6,8,0x19, +0x803c,0x19,0x22,0x26,0x38,0x80cd,6,7,8,0xd,0xe,0x19,0x22,0x3c,0x9f,0xab, +0x80ce,7,0xd,0x16,0x19,0x38,0x8088,8,0xe,0x19,0x8059,7,0x13,0x19,0x22,0x34, +0x3c,0x59,0x87,0x80ce,3,8,0xd,0xe,0x13,0x19,0x22,0x34,0x59,0x8087,0x19,0x22, +0x8087,6,8,0x19,0x80ab,6,0x19,0x8034,0x19,0x80cd,0xb,0x8019,8,0x19,0x80ce,0xe, +0x19,0x59,0x80ce,0x19,0x8022,6,0x16,0x19,0x22,0x8087,6,0x19,0x22,0x8087,0x19,0x22, +0x80cd,6,0x19,0x8022,6,0xd,0x19,0x26,0x9f,0x80cd,0x800e,0x19,0x9f,0x80ce,7,0x800e, +0xe,0x8e,8,0x8059,8,0x92,8,0x8038,8,0x96,8,0x8019,3,0xc,0x8038,3, +0x9c,2,0x22,0x25,0x57,0xb6,0xc0,0x80c9,2,0x22,0x8025,2,0xa8,2,0x22,0x25, +0x57,0xa7,0xb6,0xc0,0x80c9,2,0x22,0x54,0x79,0x7b,0xa7,0xb6,0xb7,0x80c2,2,0x8022, +2,0x25,0x80c0,2,0xc0,2,0x80b6,2,0xc5,4,0xa,0xf,0x10,0x15,0x19,0x1a, +0x1f,0x23,0x24,0x89,0x97,0x809e,4,0xa,0xf,0x10,0x15,0x19,0x1a,0x1f,0x23,0x24, +0x89,0x809e,4,0xa,0xf,0x10,0x15,0x1a,0x1f,0x21,0x23,0x24,0x3a,0x89,0x91,0x99, +0x9e,0xa0,0xaf,0xb2,0xb3,0xbb,0x80cc,4,0xa,0xf,0x10,0x15,0x1a,0x1f,0x21,0x23, +0x24,0x30,0x3a,0x89,0x91,0x99,0x9e,0xa0,0xaf,0xb2,0xb3,0xbb,0xca,0x80cc,0xa,0x78, +0xa0,0x80b2,0xa,0x10e,4,0x3a,0x8076,4,0x114,0x10,0x80a4,0x10,0x119,0xf,0x809d,0xf, +0x11d,0x23,0x8089,0x23,0x121,0x15,0xbb,0x80cf,0x15,0x125,0x1c,0x34,0x8076,0x1c,0x12a,0xc, +0x19,0x8038,0x8020,0x2a,0x2b,0x2c,0x802d,0x1b,0x805a,0x800a,4,0xa,0x15,0x8089,4,0x800a, +0xa,0x8097,0xa,0x15,0x1a,0x1f,0x23,0x8024,0xa,0x80bb,4,0xa,0x15,0x1a,0x1f,0x21, +0x24,0x89,0x9e,0xbb,0x80cf,0xa,0x8089,0xa,0x15,0x89,0x80cf,0x8004,8,0x19,0x8022,0x19, +0x1b,0x805a,2,0x80a7,0xc,0x38,0x4c,0x58,0x68,0x806b,0xe,0x4c,0x56,0x8068,0xa,0x19, +0x8089,7,0x8019,0x58,0x8075,0xc,0x4c,0x68,0x6c,0x75,0x78,0x807e,2,0x4c,0x80a7,0x11, +0x809a,5,0x11,0x12,0x14,0x16,0x8029,5,0x11,0x12,0x14,0x16,0x1b,0x8029,5,0x11, +0x12,0x14,0x16,0x1b,0x29,0x805a,5,0x11,0x12,0x14,0x8016,0x8011,5,0x11,0x12,0x14, +0x16,0x1b,0x27,0x8029,5,0x11,0x12,0x14,0x16,0x1b,0x27,0x29,0x8083,5,0x8011,0x11, 0x14,0x8016,0x11,0x8019,0xa,0xf,0x10,0x15,0x1a,0x78,0x91,0x97,0x99,0x9d,0x9e,0xa0, -0xa3,0xb2,0x80bb,0xa,0xf,0x10,0x15,0x78,0x91,0x97,0x99,0x9d,0x9e,0xa0,0xa3,0xb2, -0x80bb,0xa,0xf,0x10,0x78,0x91,0x99,0x9d,0x9e,0xa0,0xa3,0x80b2,0xa,0xf,0x10,0x78, -0x91,0x97,0x99,0x9d,0x9e,0xa0,0xa3,0x80b2,0xa,0xa3,0xa,0x8023,0xa,0x10a,0x19,0x1c, -0x804f,0x37,0x804e,2,0x8057,2,0x8025,2,0x115,0x2f,0x31,0x8053,0x2f,0x31,0x80c1,0x2f, -0x8031,2,0x8007,0x79,0x80c2,0x79,0x123,0x89,0x87,0x8087}; +0xa3,0xb2,0xbb,0x80cf,0xa,0xf,0x10,0x15,0x78,0x91,0x97,0x99,0x9d,0x9e,0xa0,0xa3, +0xb2,0xbb,0x80cf,0xa,0xf,0x10,0x78,0x91,0x99,0x9d,0x9e,0xa0,0xa3,0x80b2,0xa,0xf, +0x10,0x78,0x91,0x97,0x99,0x9d,0x9e,0xa0,0xa3,0x80b2,4,0xa,0x80cf,0xa,0x1ea,0xa, +0x8023,0xa,0x1ef,0x19,0x1c,0x804f,0x37,0x804e,2,0x8057,2,0x8025,2,0x1fa,0x2f,0x31, +0x8053,0x2f,0x31,0x80c1,0x2f,0x8031,2,0x8007,0x79,0x80c2,0x79,0x208,0x89,0x121}; + +static const uint16_t block_trieIndex[817]={ +0,0x40,0x80,0xc0,0x100,0x140,0x180,0x1c0,0x200,0x240,0x280,0x2c0,0x300,0x340,0x340,0x340, +0x340,0x340,0x340,0x364,0x384,0x384,0x384,0x384,0x384,0x384,0x384,0x384,0x384,0x384,0x384,0x384, +0x384,0x384,0x384,0x384,0x384,0x384,0x384,0x384,0x3c4,0x3fb,0x43b,0x47b,0x47b,0x47b,0x47b,0x47b, +0x47b,0x47b,0x47b,0x47b,0x47b,0x480,0x4c0,0x500,0x540,0x540,0x540,0x540,0x540,0x540,0x570,0x5a5, +0x2df,0x2f9,0x2f9,0x309,0x329,0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0, +0xb0,0xc0,0xd0,0xe0,0xf0,0x100,0x110,0x120,0x130,0x140,0x150,0x160,0x170,0x180,0x190,0x1a0, +0x1b0,0x1c0,0x1d0,0x1e0,0x1f0,0x200,0x210,0x220,0x230,0x240,0x250,0x260,0x270,0x280,0x290,0x2a0, +0x2b0,0x2c0,0x2d0,0x2e0,0x2f0,0x300,0x310,0x320,0x330,0x340,0x350,0x360,0x370,0x340,0x350,0x360, +0x370,0x340,0x350,0x360,0x370,0x364,0x374,0x384,0x394,0x384,0x394,0x3a4,0x3b4,0x384,0x394,0x3a4, +0x3b4,0x384,0x394,0x3a4,0x3b4,0x384,0x394,0x3a4,0x3b4,0x384,0x394,0x3a4,0x3b4,0x384,0x394,0x3a4, +0x3b4,0x384,0x394,0x3a4,0x3b4,0x384,0x394,0x3a4,0x3b4,0x3c4,0x3d4,0x3e4,0x3f4,0x3fb,0x40b,0x41b, +0x42b,0x43b,0x44b,0x45b,0x46b,0x47b,0x48b,0x49b,0x4ab,0x47b,0x48b,0x49b,0x4ab,0x47b,0x48b,0x49b, +0x4ab,0x47b,0x48b,0x49b,0x4ab,0x47b,0x48b,0x49b,0x4ab,0x480,0x490,0x4a0,0x4b0,0x4c0,0x4d0,0x4e0, +0x4f0,0x500,0x510,0x520,0x530,0x540,0x550,0x560,0x570,0x540,0x550,0x560,0x570,0x540,0x550,0x560, +0x570,0x540,0x550,0x560,0x570,0x540,0x550,0x560,0x570,0x540,0x550,0x560,0x570,0x570,0x580,0x590, +0x5a0,0x5a5,0x5b5,0x5c5,0x5d5,0x5e5,0x5f5,0x605,0x615,0x625,0x635,0x645,0x64d,0x65d,0x66d,0x67d, +0x68d,0x69d,0x6ad,0x6b7,0x6c7,0x6d7,0x6e7,0x6f7,0x707,0x717,0x725,0x735,0x745,0x755,0x765,0x775, +0x785,0x795,0x7a5,0x7b0,0x7c0,0x7d0,0x7d0,0x7d0,0x7d0,0x7e0,0x7eb,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f7,0x807,0x807,0x807,0x807,0x814,0x81a,0x81a,0x81a,0x81a,0x81a,0x81a, +0x81a,0x81a,0x81a,0x81a,0x81a,0x82a,0x82a,0x832,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x842,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x852,0x852,0x85e,0x86e,0x7f0,0x87a,0x886,0x896, +0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6,0x8a6, +0x8b6,0x8b6,0x8b6,0x8c6,0x8c6,0x8d6,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x8de,0x8ee,0x8fe,0x905,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x915,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x925,0x925,0x929,0x939,0x949,0x959,0x969,0x979,0x989,0x989,0x989,0x989,0x999,0x999, +0x99e,0x7f0,0x7f0,0x7f0,0x7f0,0x9ae,0x9be,0x9ce,0x9d5,0x7f0,0x9e5,0x9f5,0x7f0,0xa05,0xa15,0xa25, +0x7f0,0x7f0,0xa2e,0xa3e,0xa4e,0x7f0,0xa5e,0xa6e,0xa7e,0xa8e,0xa8e,0xa8e,0xa9e,0xaae,0xabe,0xace, +0xade,0xaee,0x7f0,0x7f0,0x7f0,0x7f0,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe, +0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xafe, +0xafe,0xafe,0xafe,0xafe,0xafe,0xafe,0xb00,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10, +0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb1c,0xb2a,0xb2c,0xb2c,0xb2c,0xb2c,0xb2c,0xb2c,0xb2c, +0xb2c,0xb2c,0xb2c,0xb2c,0xb2c,0xb2c,0xb2c,0xb31,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c, +0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3c,0xb3d,0xb4c,0xb4c,0xb56,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0xb66,0xb66,0xb74,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0xb84,0xb84, +0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84,0xb84, +0xb84,0xb8f,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb94,0xb99,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0xba9, +0xbb9,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0, +0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0x7f0,0xbc9, +0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9, +0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbc9,0xbd9, +0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9, +0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0x45, +0x65,0x79,0x89,0x89,0xa9,0xb5,0xd5,0xf5,0x115,0x131,0x150,0x168,0x179,0x196,0x1b6,0x1d6, +0x1d6,0x1d6,0x1d6,0x1d6,0x1f0,0x209,0x21e,0x23e,0x25b,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f, +0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f, +0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f,0x27f,0x25f,0x25f,0x25f,0x25f,0x25f,0x25f, +0x25f,0x29f,0x29f,0x29f,0x29f,0x29f,0x29f,0x29f,0x29f,0x2bf,0x2bf,0x2bf,0x2bf,0x2bf,0x2bf,0x2bf, +0x2bf +}; + +static const uint16_t block_trieData[3051]={ +1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, +3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4, +4,4,4,4,4,5,5,5,5,5,5,6,6,6,6,6, +7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8, +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, +0x61,0x61,0x61,0xa,0xa,0xa,0xa,0xa,0xa,0xb,0xb,0xb,0xb,0xb,0xb,0xb, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, +0xd,0xd,0xd,0xd,0xd,0x80,0x80,0x80,0xe,0xe,0xe,0xe,0x92,0x92,0x92,0x92, +0xac,0xac,0xac,0xac,0xc6,0xc6,0x117,0x135,0x135,0x135,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, +0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, +0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, +0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x86,0x86,0x20,0x20,0x20,0x20,0x20,0x20, +0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, +0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, +0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x22,0x22,0x23,0x23,0x23,0x23,0x23,0x23, +0x62,0x62,0x63,0x63,0x64,0x64,0x65,0x65,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, +0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0xad,0xad,0xad,0xad,0xad, +0x6f,0x6f,0x6f,0x6f,0x6f,0x70,0x70,0x70,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x71,0x71, +0x81,0x81,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xe0,0xe0,0xe0,0xe0,0xe0, +0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x9b,0x9b,0x9b,0x9b,0xc7,0xc7,0xc7,0xc7, +0x9c,0x9c,0x9c,0x9c,0x9c,0x9d,0x9d,0x9d,0x109,0x11b,0x11b,0x11b,0xdb,0xaf,0xaf,0xaf, +0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x8d,0x8d,0x8d,0x8d,0x83,0x83,0x83,0x83, +0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26, +0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27, +0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b, +0x2c,0x2c,0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e, +0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f, +0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, +0x31,0x31,0x31,0x31,0x32,0x32,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, +0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x35,0x35,0x36,0x36,0x36,0x36,0x36,0x36, +0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37, +0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x66,0x66,0x66,0x67, +0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, +0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69, +0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a, +0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73, +0x88,0x88,0x88,0x88,0x88,0x88,0x94,0x94,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, +0x87,0x87,0x87,0x90,0x90,0x90,0x90,0x90,0x85,0x85,0x85,0x85,0x85,0x85,0x9e,0x9e, +0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a, +0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0,0x3c, +0x3d,0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, +0x40,0x40,0x40,0x41,0x41,0x41,0x41,0x41,0x41,0x42,0x43,0x43,0x82,0x82,0x82,0x6b, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45, +0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, +0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, +0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, +0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, +0x74,0x74,0x74,0x74,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, +0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, +0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, +0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, +0x47,0x47,0x47,0x47,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48, +0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48, +0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48, +0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48, +0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x49,0xb0,0xb0,0xb0,0x9f,0x9f,0x9f,0x9f,0x9f, +0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0xa0, +0xa0,0xa0,0xa0,0xa0,0xa0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x8a,0x8a,0x95,0x95,0x95, +0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x8f,0x8f,0x8f,0xb2,0x96, +0x96,0x96,0x96,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xb3,0xb3,0xa2,0xa2,0xa2,0xa3,0xa3, +0xa3,0xb4,0xb4,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xee,0xee,0xa4,0xa4,0xa4,0xa4,0xa4, +0xa4,0xb6,0xb6,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xd5,0xd5,0xc8,0xc8,0xc8,0xe7,0xe7, +0xe7,0xe7,0xff,0xff,0xff,0xff,0xff,0xb8,0xb8,0xb8,0xb8,0x4a,0x4a,0x4a,0x4a,0x4a, +0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, +0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, +0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, +0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0xb9,0xb9,0xb9,0xb9,0xb9, +0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, +0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, +0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, +0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, +0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, +0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, +0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, +0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f, +0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f, +0x50,0x50,0x50,0x50,0x50,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51, +0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51, +0x51,0x51,0x51,0x51,0x51,0x6c,0x91,0x52,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x55, +0x55,0x55,0x55,0x55,0x55,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57, +0x57,0x57,0x57,0x57,0x56,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x76,0x76,0x76, +0x76,0x76,0x76,0x76,0x76,0x77,0x77,0x77,0x77,0x7f,0x7f,0x7f,0x7f,0x7f,0xa5,0xa5, +0xa5,0xa5,0xa6,0xa6,0xa6,0,0,0,0,0,0,0,0,0xa7,0xa7,0xa8, +0xa8,0xa8,0xa8,0xdf,0xdf,0x58,0x58,0x58,0x59,0x59,0xf1,0xf1,0xf1,0x78,0x78,0x8c, +0x8c,0x8c,0x8c,0,0,0x5a,0x5a,0x5a,0x5a,0x5a,0x79,0x79,0x79,0x7a,0x7a,0x7a, +0x10f,0x10f,0x10f,0x10f,0x10f,0xe2,0xe2,0xe2,0xde,0xde,0xde,0xde,0x13f,0x13f,0x13f,0x13f, +0x13f,0x151,0x151,0x151,0x151,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8, +0xe8,0xe8,0xe8,0xe8,0xe8,0x139,0x139,0x139,0x139,0,0,0,0,0x7b,0x7b,0x7b, +0x7b,0xba,0xba,0xf4,0xf4,0xef,0xef,0xef,0,0,0,0x102,0x102,0x97,0x97,0xa9, +0xa9,0,0,0,0,0xd7,0xd7,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0x89,0x89,0x89, +0x89,0x89,0x89,0xbb,0xbb,0xf0,0xf0,0,0,0xea,0xea,0xea,0xea,0xbc,0xbc,0xbc, +0xbc,0xbd,0xbd,0xbe,0xbe,0xf6,0xf6,0xf6,0,0,0,0,0,0xbf,0xbf,0xbf, +0xbf,0xbf,0,0,0,0x104,0x104,0x104,0x104,0x104,0x104,0x104,0x104,0x11d,0x11d,0x11d, +0x11d,0x14a,0x14a,0x14a,0x14a,0x14a,0,0,0,0,0,0,0,0xc0,0xc0,0x134, +0x134,0x134,0x134,0x141,0x141,0x141,0x141,0x122,0x122,0x122,0x123,0x123,0x123,0x123,0x13b,0x13b, +0x13b,0x13b,0x12d,0x12d,0x12d,0x125,0x125,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc1, +0xc1,0xc1,0xc1,0xc1,0xda,0xda,0xda,0xd4,0xd4,0xd4,0xd4,0xd4,0xe9,0xe9,0xe9,0xd9, +0xd9,0xd9,0xd9,0xd9,0xd9,0xf9,0xf9,0xe5,0xe5,0xe5,0xe5,0xe5,0,0,0,0x103, +0x103,0x103,0xe6,0xe6,0xe6,0xe6,0xe6,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0x152, +0x152,0x152,0x152,0x152,0x152,0x152,0x152,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0xfb, +0xfb,0xfb,0xfb,0xfb,0xfb,0,0,0,0,0,0,0,0,0xf8,0xf8,0xf8, +0xf8,0xf8,0xf8,0xf8,0xf8,0xec,0xec,0xec,0xec,0xec,0xec,0x10d,0x10d,0xdc,0xdc,0xdc, +0xdc,0xdc,0x14d,0x14d,0x14d,0xfd,0xfd,0xfd,0xfd,0xfd,0,0,0,0,0,0, +0,0,0,0,0,0x11a,0x11a,0x11a,0x11a,0x11a,0,0,0,0,0,0xfc, +0xfc,0xfc,0xfc,0xfc,0xfc,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0,0,0,0,0x126, +0x126,0x126,0x126,0x126,0x126,0x118,0x118,0x118,0x118,0x118,0x116,0x116,0x116,0x116,0x116,0x116, +0x13e,0xf5,0xf5,0xf5,0xf5,0x144,0x144,0x144,0x144,0x144,0x144,0,0,0,0,0, +0,0x14f,0x14f,0x14f,0x14f,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x10c,0x10c,0x10c,0x10c, +0x10c,0,0,0,0,0x114,0x114,0x114,0x114,0x114,0x114,0x11c,0x11c,0x11c,0x11c,0x11c, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x11f,0x11f, +0x146,0x146,0x146,0x146,0x146,0x146,0,0,0,0,0,0x131,0x12b,0x12b,0x12b,0x12b, +0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98, +0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x101,0x101,0x101,0x101,0x101,0x101,0x101,0x101, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x136,0x136,0x136,0x136,0x136,0x136,0x136,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2, +0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0x124,0x124,0x124,0x149,0x149,0x149,0x149,0x149,0x149, +0x149,0x149,0x149,0x149,0x149,0x149,0x149,0x149,0x149,0x149,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, +0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0,0,0,0,0,0, +0,0,0x14b,0x14b,0x14b,0x14b,0,0,0,0,0,0,0,0,0,0, +0,0,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca, +0xca,0xca,0xed,0xed,0xed,0x13c,0x13c,0x13c,0x13c,0x13c,0x13c,0xdd,0xdd,0xdd,0xf3,0xf3, +0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0,0,0,0,0,0,0,0x14c,0x14c, +0x14c,0x14c,0,0,0,0,0,0,0,0,0x121,0x121,0x121,0x121,0x121,0x121, +0,0,0,0,0,0,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, +0,0,0,0,0x10b,0x10b,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111, +0x111,0x111,0x111,0x111,0x111,0x111,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130, +0x130,0x130,0x130,0x130,0x130,0x130,0x133,0x133,0x133,0x133,0x133,0x133,0x133,0x133,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x138,0xcb,0xcb, +0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0x113,0x113, +0x113,0x129,0x129,0x129,0x129,0x115,0x115,0x115,0x115,0x115,0x115,0x115,0x115,0x115,0x115,0x115, +0x115,0x115,0x115,0x115,0x115,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xf7, +0,0,0,0,0,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150, +0x150,0x150,0x150,0x150,0x150,0,0,0,0,0x140,0x140,0x140,0x140,0x140,0x140,0x140, +0x140,0x140,0x140,0x140,0x140,0x140,0,0,0,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, +0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, +0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x7e,0x7e,0x7e,0x7e,0x7e,0,0, +0,0,0,0,0,0x145,0x145,0x120,0x120,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x9a, +0x9a,0,0,0,0,0,0,0,0,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, +0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x106,0x106,0x106,0x106,0x106,0x106,0x106, +0x106,0x106,0x106,0x106,0x106,0x106,0x106,0x106,0x106,0,0,0,0,0,0x13a,0x13a, +0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x13a,0x10a,0x10a, +0x10a,0x143,0x143,0x143,0x143,0x143,0x143,0,0,0,0,0,0,0,0x127,0x127, +0x127,0x127,0x127,0,0,0,0,0,0,0,0,0,0,0,0x13d,0x13d, +0x13d,0x12c,0x12c,0x12c,0x12c,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x147,0x147,0x147,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x14e,0x14e,0x14e,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x137,0x137,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb, +0xeb,0xeb,0xeb,0,0,0x107,0x107,0x107,0x107,0x107,0x107,0,0,0,0,0, +0,0,0,0,0,0x11e,0x11e,0x11e,0x11e,0x11e,0,0,0,0,0x128,0x128, +0x128,0x128,0x128,0,0,0,0,0,0,0,0,0,0,0,0xd3,0xd3, +0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xaa,0xaa, +0xaa,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xc3,0xc3, +0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xcd,0xcd, +0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xce,0xce, +0xce,0xce,0xce,0xf2,0xf2,0xf2,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xd0,0xd0, +0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xfa,0xfa, +0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0x105,0x105, +0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x119,0x119, +0x119,0x119,0x119,0x119,0x119,0x12a,0x12a,0x12a,0x12a,0x12a,0x12a,0x12a,0x12a,0x12a,0x132,0x132, +0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x5e,0x5e, +0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0,0, +0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5, +0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0x100,0x100,0x100,0x100, +0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x112,0x112,0x112,0x112, +0x112,0x112,0x112,0x112,0x112,0x112,0x112,0x112,0x112,0x112,0x112,0x112,0x148,0x148,0x148,0x148, +0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0,0,0,0, +0,0,0,0,0,0,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f, +0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x12e,0x12e,0x12e,0x12e,0x12e,0x12e,0x12e,0x12e,0x12e,0x12e,0x12e,0x12e, +0x12e,0x12e,0x12e,0x12e,0x142,0x142,0x142,0x142,0x142,0x142,0x142,0x142,0x142,0x142,0x142,0x142, +0x142,0x142,0x142,0x142,0,0,0,0,0,0x60,0x60,0x60,0x60,0x60,0x60,0x60, +0x60,0,0,0,0,0,0,0,0,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d, +0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d, +0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0,0 +}; + +static const UCPTrie block_trie={ + block_trieIndex, + { block_trieData }, + 817, 3051, + 0x11000, 0x11, + 1, 0, + 0, 0, + 0x25f, 0x7f0, + 0x0, +}; -static const int32_t indexes[UPROPS_INDEX_COUNT]={0x2d4e,0x2d4e,0x2d4e,0x2d4e,0x6d5a,3,0x8aa3,0x8b38,0x8b38,0x8b38,0xb48c8,0x2f75a31,0,0,0,0}; +static const int32_t indexes[UPROPS_INDEX_COUNT]={0x2e8e,0x2e8e,0x2e8e,0x2e8e,0x6db4,3,0x86ce,0x87d5,0x8f67,0x8f67,0x50cf,0x2f75a31,0x152,0,0,0}; #endif // INCLUDED_FROM_UCHAR_C diff --git a/thirdparty/icu4c/common/ucharstrie.cpp b/thirdparty/icu4c/common/ucharstrie.cpp index ba9cea7ba3..4c48323c91 100644 --- a/thirdparty/icu4c/common/ucharstrie.cpp +++ b/thirdparty/icu4c/common/ucharstrie.cpp @@ -297,7 +297,7 @@ UCharsTrie::findUniqueValueFromBranch(const char16_t *pos, int32_t length, ++pos; // ignore a comparison unit // handle its value int32_t node=*pos++; - UBool isFinal=(UBool)(node>>15); + UBool isFinal = static_cast<UBool>(node >> 15); node&=0x7fff; int32_t value=readValue(pos, node); pos=skipValue(pos, node); @@ -339,7 +339,7 @@ UCharsTrie::findUniqueValue(const char16_t *pos, UBool haveUniqueValue, int32_t pos+=node-kMinLinearMatch+1; // Ignore the match units. node=*pos++; } else { - UBool isFinal=(UBool)(node>>15); + UBool isFinal = static_cast<UBool>(node >> 15); int32_t value; if(isFinal) { value=readValue(pos, node&0x7fff); diff --git a/thirdparty/icu4c/common/ucharstriebuilder.cpp b/thirdparty/icu4c/common/ucharstriebuilder.cpp index 95b32711a8..bf3216bd1b 100644 --- a/thirdparty/icu4c/common/ucharstriebuilder.cpp +++ b/thirdparty/icu4c/common/ucharstriebuilder.cpp @@ -75,7 +75,7 @@ UCharsTrieElement::setTo(const UnicodeString &s, int32_t val, return; } stringOffset=strings.length(); - strings.append((char16_t)length); + strings.append(static_cast<char16_t>(length)); value=val; strings.append(s); } @@ -186,7 +186,7 @@ UCharsTrieBuilder::buildUChars(UStringTrieBuildOption buildOption, UErrorCode &e errorCode=U_MEMORY_ALLOCATION_ERROR; return; } - uprv_sortArray(elements, elementsLength, (int32_t)sizeof(UCharsTrieElement), + uprv_sortArray(elements, elementsLength, static_cast<int32_t>(sizeof(UCharsTrieElement)), compareElementStrings, &strings, false, // need not be a stable sort &errorCode); @@ -351,7 +351,7 @@ UCharsTrieBuilder::write(int32_t unit) { int32_t newLength=ucharsLength+1; if(ensureCapacity(newLength)) { ucharsLength=newLength; - uchars[ucharsCapacity-ucharsLength]=(char16_t)unit; + uchars[ucharsCapacity - ucharsLength] = static_cast<char16_t>(unit); } return ucharsLength; } @@ -379,19 +379,19 @@ UCharsTrieBuilder::writeValueAndFinal(int32_t i, UBool isFinal) { char16_t intUnits[3]; int32_t length; if(i<0 || i>UCharsTrie::kMaxTwoUnitValue) { - intUnits[0]=(char16_t)(UCharsTrie::kThreeUnitValueLead); - intUnits[1]=(char16_t)((uint32_t)i>>16); - intUnits[2]=(char16_t)i; + intUnits[0] = static_cast<char16_t>(UCharsTrie::kThreeUnitValueLead); + intUnits[1] = static_cast<char16_t>(static_cast<uint32_t>(i) >> 16); + intUnits[2] = static_cast<char16_t>(i); length=3; // } else if(i<=UCharsTrie::kMaxOneUnitValue) { // intUnits[0]=(char16_t)(i); // length=1; } else { - intUnits[0]=(char16_t)(UCharsTrie::kMinTwoUnitValueLead+(i>>16)); - intUnits[1]=(char16_t)i; + intUnits[0] = static_cast<char16_t>(UCharsTrie::kMinTwoUnitValueLead + (i >> 16)); + intUnits[1] = static_cast<char16_t>(i); length=2; } - intUnits[0]=(char16_t)(intUnits[0]|(isFinal<<15)); + intUnits[0] = static_cast<char16_t>(intUnits[0] | (isFinal << 15)); return write(intUnits, length); } @@ -403,19 +403,19 @@ UCharsTrieBuilder::writeValueAndType(UBool hasValue, int32_t value, int32_t node char16_t intUnits[3]; int32_t length; if(value<0 || value>UCharsTrie::kMaxTwoUnitNodeValue) { - intUnits[0]=(char16_t)(UCharsTrie::kThreeUnitNodeValueLead); - intUnits[1]=(char16_t)((uint32_t)value>>16); - intUnits[2]=(char16_t)value; + intUnits[0] = static_cast<char16_t>(UCharsTrie::kThreeUnitNodeValueLead); + intUnits[1] = static_cast<char16_t>(static_cast<uint32_t>(value) >> 16); + intUnits[2] = static_cast<char16_t>(value); length=3; } else if(value<=UCharsTrie::kMaxOneUnitNodeValue) { - intUnits[0]=(char16_t)((value+1)<<6); + intUnits[0] = static_cast<char16_t>((value + 1) << 6); length=1; } else { - intUnits[0]=(char16_t)(UCharsTrie::kMinTwoUnitNodeValueLead+((value>>10)&0x7fc0)); - intUnits[1]=(char16_t)value; + intUnits[0] = static_cast<char16_t>(UCharsTrie::kMinTwoUnitNodeValueLead + ((value >> 10) & 0x7fc0)); + intUnits[1] = static_cast<char16_t>(value); length=2; } - intUnits[0]|=(char16_t)node; + intUnits[0] |= static_cast<char16_t>(node); return write(intUnits, length); } @@ -429,14 +429,14 @@ UCharsTrieBuilder::writeDeltaTo(int32_t jumpTarget) { char16_t intUnits[3]; int32_t length; if(i<=UCharsTrie::kMaxTwoUnitDelta) { - intUnits[0]=(char16_t)(UCharsTrie::kMinTwoUnitDeltaLead+(i>>16)); + intUnits[0] = static_cast<char16_t>(UCharsTrie::kMinTwoUnitDeltaLead + (i >> 16)); length=1; } else { - intUnits[0]=(char16_t)(UCharsTrie::kThreeUnitDeltaLead); - intUnits[1]=(char16_t)(i>>16); + intUnits[0] = static_cast<char16_t>(UCharsTrie::kThreeUnitDeltaLead); + intUnits[1] = static_cast<char16_t>(i >> 16); length=2; } - intUnits[length++]=(char16_t)i; + intUnits[length++] = static_cast<char16_t>(i); return write(intUnits, length); } diff --git a/thirdparty/icu4c/common/ucharstrieiterator.cpp b/thirdparty/icu4c/common/ucharstrieiterator.cpp index 176aed6825..8a212b8b36 100644 --- a/thirdparty/icu4c/common/ucharstrieiterator.cpp +++ b/thirdparty/icu4c/common/ucharstrieiterator.cpp @@ -114,7 +114,7 @@ UCharsTrie::Iterator::next(UErrorCode &errorCode) { pos=uchars_+stack_->elementAti(stackSize-2); stack_->setSize(stackSize-2); str_.truncate(length&0xffff); - length=(int32_t)((uint32_t)length>>16); + length = static_cast<int32_t>(static_cast<uint32_t>(length) >> 16); if(length>1) { pos=branchNext(pos, length, errorCode); if(pos==nullptr) { @@ -138,7 +138,7 @@ UCharsTrie::Iterator::next(UErrorCode &errorCode) { skipValue_=false; } else { // Deliver value for the string so far. - UBool isFinal=(UBool)(node>>15); + UBool isFinal = static_cast<UBool>(node >> 15); if(isFinal) { value_=readValue(pos, node&0x7fff); } else { @@ -187,7 +187,7 @@ UCharsTrie::Iterator::branchNext(const char16_t *pos, int32_t length, UErrorCode while(length>kMaxBranchLinearSubNodeLength) { ++pos; // ignore the comparison unit // Push state for the greater-or-equal edge. - stack_->addElement((int32_t)(skipDelta(pos)-uchars_), errorCode); + stack_->addElement(static_cast<int32_t>(skipDelta(pos) - uchars_), errorCode); stack_->addElement(((length-(length>>1))<<16)|str_.length(), errorCode); // Follow the less-than edge. length>>=1; @@ -197,10 +197,10 @@ UCharsTrie::Iterator::branchNext(const char16_t *pos, int32_t length, UErrorCode // Read the first (key, value) pair. char16_t trieUnit=*pos++; int32_t node=*pos++; - UBool isFinal=(UBool)(node>>15); + UBool isFinal = static_cast<UBool>(node >> 15); int32_t value=readValue(pos, node&=0x7fff); pos=skipValue(pos, node); - stack_->addElement((int32_t)(pos-uchars_), errorCode); + stack_->addElement(static_cast<int32_t>(pos - uchars_), errorCode); stack_->addElement(((length-1)<<16)|str_.length(), errorCode); str_.append(trieUnit); if(isFinal) { diff --git a/thirdparty/icu4c/common/uchriter.cpp b/thirdparty/icu4c/common/uchriter.cpp index c8b86e5d4d..903eb46c3b 100644 --- a/thirdparty/icu4c/common/uchriter.cpp +++ b/thirdparty/icu4c/common/uchriter.cpp @@ -172,7 +172,7 @@ UCharCharacterIterator::nextPostInc() { UBool UCharCharacterIterator::hasNext() { - return (UBool)(pos < end ? true : false); + return pos < end; } char16_t @@ -186,7 +186,7 @@ UCharCharacterIterator::previous() { UBool UCharCharacterIterator::hasPrevious() { - return (UBool)(pos > begin ? true : false); + return pos > begin; } UChar32 diff --git a/thirdparty/icu4c/common/ucmndata.cpp b/thirdparty/icu4c/common/ucmndata.cpp index 69575d4e83..45717ffd71 100644 --- a/thirdparty/icu4c/common/ucmndata.cpp +++ b/thirdparty/icu4c/common/ucmndata.cpp @@ -108,8 +108,8 @@ strcmpAfterPrefix(const char *s1, const char *s2, int32_t *pPrefixLength) { s1+=pl; s2+=pl; for(;;) { - int32_t c1=(uint8_t)*s1++; - int32_t c2=(uint8_t)*s2++; + int32_t c1 = static_cast<uint8_t>(*s1++); + int32_t c2 = static_cast<uint8_t>(*s2++); cmp=c1-c2; if(cmp!=0 || c1==0) { /* different or done */ break; @@ -271,7 +271,7 @@ offsetTOCLookupFn(const UDataMemory *pData, static uint32_t U_CALLCONV pointerTOCEntryCount(const UDataMemory *pData) { const PointerTOC *toc = (PointerTOC *)pData->toc; - return (uint32_t)((toc != nullptr) ? (toc->count) : 0); + return toc != nullptr ? toc->count : 0; } static const DataHeader * U_CALLCONV pointerTOCLookupFn(const UDataMemory *pData, diff --git a/thirdparty/icu4c/common/ucnv.cpp b/thirdparty/icu4c/common/ucnv.cpp index 34a5a203d0..c66200b793 100644 --- a/thirdparty/icu4c/common/ucnv.cpp +++ b/thirdparty/icu4c/common/ucnv.cpp @@ -916,7 +916,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { * s<sourceLimit before converterSawEndOfInput is checked */ converterSawEndOfInput= - (UBool)(U_SUCCESS(*err) && + static_cast<UBool>(U_SUCCESS(*err) && pArgs->flush && pArgs->source==pArgs->sourceLimit && cnv->fromUChar32==0); } else { @@ -941,7 +941,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { for(;;) { /* update offsets if we write any */ if(offsets!=nullptr) { - int32_t length=(int32_t)(pArgs->target-t); + int32_t length = static_cast<int32_t>(pArgs->target - t); if(length>0) { _updateOffsets(offsets, length, sourceIndex, errorInputLength); @@ -956,7 +956,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { } if(sourceIndex>=0) { - sourceIndex+=(int32_t)(pArgs->source-s); + sourceIndex += static_cast<int32_t>(pArgs->source - s); } } @@ -1066,10 +1066,10 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { U_ASSERT(cnv->preFromULength==0); - length=(int32_t)(pArgs->sourceLimit-pArgs->source); + length = static_cast<int32_t>(pArgs->sourceLimit - pArgs->source); if(length>0) { u_memcpy(cnv->preFromU, pArgs->source, length); - cnv->preFromULength=(int8_t)-length; + cnv->preFromULength = static_cast<int8_t>(-length); } pArgs->source=realSource; @@ -1089,7 +1089,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { codePoint=cnv->fromUChar32; errorInputLength=0; U16_APPEND_UNSAFE(cnv->invalidUCharBuffer, errorInputLength, codePoint); - cnv->invalidUCharLength=(int8_t)errorInputLength; + cnv->invalidUCharLength = static_cast<int8_t>(errorInputLength); /* set the converter state to deal with the next character */ cnv->fromUChar32=0; @@ -1134,7 +1134,7 @@ ucnv_outputOverflowFromUnicode(UConverter *cnv, offsets=nullptr; } - overflow=(char *)cnv->charErrorBuffer; + overflow = reinterpret_cast<char*>(cnv->charErrorBuffer); length=cnv->charErrorBufferLength; i=0; while(i<length) { @@ -1146,7 +1146,7 @@ ucnv_outputOverflowFromUnicode(UConverter *cnv, overflow[j++]=overflow[i++]; } while(i<length); - cnv->charErrorBufferLength=(int8_t)j; + cnv->charErrorBufferLength = static_cast<int8_t>(j); *target=t; if(offsets!=nullptr) { *pOffsets=offsets; @@ -1361,7 +1361,7 @@ _toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) { * s<sourceLimit before converterSawEndOfInput is checked */ converterSawEndOfInput= - (UBool)(U_SUCCESS(*err) && + static_cast<UBool>(U_SUCCESS(*err) && pArgs->flush && pArgs->source==pArgs->sourceLimit && cnv->toULength==0); } else { @@ -1386,7 +1386,7 @@ _toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) { for(;;) { /* update offsets if we write any */ if(offsets!=nullptr) { - int32_t length=(int32_t)(pArgs->target-t); + int32_t length = static_cast<int32_t>(pArgs->target - t); if(length>0) { _updateOffsets(offsets, length, sourceIndex, errorInputLength); @@ -1401,7 +1401,7 @@ _toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) { } if(sourceIndex>=0) { - sourceIndex+=(int32_t)(pArgs->source-s); + sourceIndex += static_cast<int32_t>(pArgs->source - s); } } @@ -1513,10 +1513,10 @@ _toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) { U_ASSERT(cnv->preToULength==0); - length=(int32_t)(pArgs->sourceLimit-pArgs->source); + length = static_cast<int32_t>(pArgs->sourceLimit - pArgs->source); if(length>0) { uprv_memcpy(cnv->preToU, pArgs->source, length); - cnv->preToULength=(int8_t)-length; + cnv->preToULength = static_cast<int8_t>(-length); } pArgs->source=realSource; @@ -1592,7 +1592,7 @@ ucnv_outputOverflowToUnicode(UConverter *cnv, overflow[j++]=overflow[i++]; } while(i<length); - cnv->UCharErrorBufferLength=(int8_t)j; + cnv->UCharErrorBufferLength = static_cast<int8_t>(j); *target=t; if(offsets!=nullptr) { *pOffsets=offsets; @@ -2437,7 +2437,7 @@ ucnv_internalConvert(UConverter *outConverter, UConverter *inConverter, false, true, pErrorCode); - targetLength=(int32_t)(myTarget-target); + targetLength = static_cast<int32_t>(myTarget - target); } /* @@ -2460,7 +2460,7 @@ ucnv_internalConvert(UConverter *outConverter, UConverter *inConverter, false, true, pErrorCode); - targetLength+=(int32_t)(myTarget-targetBuffer); + targetLength += static_cast<int32_t>(myTarget - targetBuffer); } while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR); /* done with preflighting, set warnings and errors as appropriate */ @@ -2684,7 +2684,7 @@ ucnv_fixFileSeparator(const UConverter *cnv, U_CAPI UBool U_EXPORT2 ucnv_isAmbiguous(const UConverter *cnv) { - return (UBool)(ucnv_getAmbiguous(cnv)!=nullptr); + return ucnv_getAmbiguous(cnv)!=nullptr; } U_CAPI void U_EXPORT2 diff --git a/thirdparty/icu4c/common/ucnv2022.cpp b/thirdparty/icu4c/common/ucnv2022.cpp index 5989c1b405..7572ce477a 100644 --- a/thirdparty/icu4c/common/ucnv2022.cpp +++ b/thirdparty/icu4c/common/ucnv2022.cpp @@ -436,10 +436,10 @@ fromUWriteUInt8(UConverter *cnv, int32_t sourceIndex, UErrorCode *pErrorCode) { - char *targetChars = (char *)*target; + char* targetChars = reinterpret_cast<char*>(*target); ucnv_fromUWriteBytes(cnv, bytes, length, &targetChars, targetLimit, offsets, sourceIndex, pErrorCode); - *target = (uint8_t*)targetChars; + *target = reinterpret_cast<uint8_t*>(targetChars); } @@ -484,7 +484,7 @@ _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ if(cnv->extraInfo != nullptr) { UConverterNamePieces stackPieces; UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER; - UConverterDataISO2022 *myConverterData=(UConverterDataISO2022 *) cnv->extraInfo; + UConverterDataISO2022* myConverterData = static_cast<UConverterDataISO2022*>(cnv->extraInfo); uint32_t version; stackArgs.onlyTestIsLoadable = pArgs->onlyTestIsLoadable; @@ -528,12 +528,12 @@ _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ } /* set the function pointers to appropriate functions */ - cnv->sharedData=(UConverterSharedData*)(&_ISO2022JPData); + cnv->sharedData = const_cast<UConverterSharedData*>(&_ISO2022JPData); uprv_strcpy(myConverterData->locale,"ja"); (void)uprv_strcpy(myConverterData->name,"ISO_2022,locale=ja,version="); size_t len = uprv_strlen(myConverterData->name); - myConverterData->name[len]=(char)(myConverterData->version+(int)'0'); + myConverterData->name[len] = static_cast<char>(myConverterData->version + static_cast<int>('0')); myConverterData->name[len+1]='\0'; } #if !UCONFIG_ONLY_HTML_CONVERSION @@ -579,7 +579,7 @@ _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ setInitialStateFromUnicodeKR(cnv, myConverterData); /* set the function pointers to appropriate functions */ - cnv->sharedData=(UConverterSharedData*)&_ISO2022KRData; + cnv->sharedData = const_cast<UConverterSharedData*>(&_ISO2022KRData); uprv_strcpy(myConverterData->locale,"ko"); } } @@ -606,7 +606,7 @@ _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ /* set the function pointers to appropriate functions */ - cnv->sharedData=(UConverterSharedData*)&_ISO2022CNData; + cnv->sharedData = const_cast<UConverterSharedData*>(&_ISO2022CNData); uprv_strcpy(myConverterData->locale,"cn"); if (version==0){ @@ -655,7 +655,7 @@ _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ static void U_CALLCONV _ISO2022Close(UConverter *converter) { - UConverterDataISO2022* myData =(UConverterDataISO2022 *) (converter->extraInfo); + UConverterDataISO2022* myData = static_cast<UConverterDataISO2022*>(converter->extraInfo); UConverterSharedData **array = myData->myConverterArray; int32_t i; @@ -678,7 +678,7 @@ _ISO2022Close(UConverter *converter) { static void U_CALLCONV _ISO2022Reset(UConverter *converter, UConverterResetChoice choice) { - UConverterDataISO2022 *myConverterData=(UConverterDataISO2022 *) (converter->extraInfo); + UConverterDataISO2022* myConverterData = static_cast<UConverterDataISO2022*>(converter->extraInfo); if(choice<=UCNV_RESET_TO_UNICODE) { uprv_memset(&myConverterData->toU2022State, 0, sizeof(ISO2022State)); myConverterData->key = 0; @@ -784,7 +784,7 @@ getKey_2022(char c,int32_t* key,int32_t* offset){ int32_t hi = MAX_STATES_2022; int32_t oldmid=0; - togo = normalize_esq_chars_2022[(uint8_t)c]; + togo = normalize_esq_chars_2022[static_cast<uint8_t>(c)]; if(togo == 0) { /* not a valid character anywhere in an escape sequence */ *key = 0; @@ -809,7 +809,7 @@ getKey_2022(char c,int32_t* key,int32_t* offset){ else /*we found it*/{ *key = togo; *offset = mid; - return (UCNV_TableStates_2022)escSeqStateTable_Value_2022[mid]; + return static_cast<UCNV_TableStates_2022>(escSeqStateTable_Value_2022[mid]); } oldmid = mid; @@ -829,7 +829,7 @@ changeState_2022(UConverter* _this, Variant2022 var, UErrorCode* err){ UCNV_TableStates_2022 value; - UConverterDataISO2022* myData2022 = ((UConverterDataISO2022*)_this->extraInfo); + UConverterDataISO2022* myData2022 = static_cast<UConverterDataISO2022*>(_this->extraInfo); uint32_t key = myData2022->key; int32_t offset = 0; int8_t initialToULength = _this->toULength; @@ -838,8 +838,8 @@ changeState_2022(UConverter* _this, value = VALID_NON_TERMINAL_2022; while (*source < sourceLimit) { c = *(*source)++; - _this->toUBytes[_this->toULength++]=(uint8_t)c; - value = getKey_2022(c,(int32_t *) &key, &offset); + _this->toUBytes[_this->toULength++] = static_cast<uint8_t>(c); + value = getKey_2022(c, reinterpret_cast<int32_t*>(&key), &offset); switch (value){ @@ -910,7 +910,7 @@ DONE: #endif case ISO_2022_JP: { - StateEnum tempState=(StateEnum)nextStateToUnicodeJP[offset]; + StateEnum tempState = static_cast<StateEnum>(nextStateToUnicodeJP[offset]); switch(tempState) { case INVALID_STATE: *err = U_UNSUPPORTED_ESCAPE_SEQUENCE; @@ -933,7 +933,7 @@ DONE: *err = U_UNSUPPORTED_ESCAPE_SEQUENCE; } else { /* G2 charset for SS2 */ - myData2022->toU2022State.cs[2]=(int8_t)tempState; + myData2022->toU2022State.cs[2] = static_cast<int8_t>(tempState); } break; default: @@ -941,7 +941,7 @@ DONE: *err = U_UNSUPPORTED_ESCAPE_SEQUENCE; } else { /* G0 charset */ - myData2022->toU2022State.cs[0]=(int8_t)tempState; + myData2022->toU2022State.cs[0] = static_cast<int8_t>(tempState); } break; } @@ -950,7 +950,7 @@ DONE: #if !UCONFIG_ONLY_HTML_CONVERSION case ISO_2022_CN: { - StateEnum tempState=(StateEnum)nextStateToUnicodeCN[offset]; + StateEnum tempState = static_cast<StateEnum>(nextStateToUnicodeCN[offset]); switch(tempState) { case INVALID_STATE: *err = U_UNSUPPORTED_ESCAPE_SEQUENCE; @@ -986,17 +986,17 @@ DONE: case GB2312_1: U_FALLTHROUGH; case CNS_11643_1: - myData2022->toU2022State.cs[1]=(int8_t)tempState; + myData2022->toU2022State.cs[1] = static_cast<int8_t>(tempState); break; case CNS_11643_2: - myData2022->toU2022State.cs[2]=(int8_t)tempState; + myData2022->toU2022State.cs[2] = static_cast<int8_t>(tempState); break; default: /* other CNS 11643 planes */ if(myData2022->version==0) { *err = U_UNSUPPORTED_ESCAPE_SEQUENCE; } else { - myData2022->toU2022State.cs[3]=(int8_t)tempState; + myData2022->toU2022State.cs[3] = static_cast<int8_t>(tempState); } break; } @@ -1039,7 +1039,7 @@ DONE: *source-=backOutDistance; } else { /* Back out bytes from the previous buffer: Need to replay them. */ - _this->preToULength=(int8_t)(bytesFromThisBuffer-backOutDistance); + _this->preToULength = static_cast<int8_t>(bytesFromThisBuffer - backOutDistance); /* same as -(initialToULength-1) */ /* preToULength is negative! */ uprv_memcpy(_this->preToU, _this->toUBytes+1, -_this->preToULength); @@ -1145,7 +1145,7 @@ MBCS_FROM_UCHAR32_ISO2022(UConverterSharedData* sharedData, } } else /* outputType==MBCS_OUTPUT_3 */ { p=MBCS_POINTER_3_FROM_STAGE_2(sharedData->mbcs.fromUnicodeBytes, stage2Entry, c); - myValue=((uint32_t)*p<<16)|((uint32_t)p[1]<<8)|p[2]; + myValue = (static_cast<uint32_t>(*p) << 16) | (static_cast<uint32_t>(p[1]) << 8) | p[2]; if(myValue<=0xff) { length=1; } else if(myValue<=0xffff) { @@ -1201,7 +1201,7 @@ MBCS_SINGLE_FROM_UCHAR32(UConverterSharedData* sharedData, /* get the byte for the output */ value=MBCS_SINGLE_RESULT_FROM_U(table, (uint16_t *)sharedData->mbcs.fromUnicodeBytes, c); /* is this code point assigned, or do we use fallbacks? */ - *retval=(uint32_t)(value&0xff); + *retval = static_cast<uint32_t>(value & 0xff); if(value>=0xf00) { return 1; /* roundtrip */ } else if(useFallback ? value>=0x800 : value>=0xc00) { @@ -1219,8 +1219,8 @@ MBCS_SINGLE_FROM_UCHAR32(UConverterSharedData* sharedData, */ static inline uint32_t _2022FromGR94DBCS(uint32_t value) { - if( (uint16_t)(value - 0xa1a1) <= (0xfefe - 0xa1a1) && - (uint8_t)(value - 0xa1) <= (0xfe - 0xa1) + if (static_cast<uint16_t>(value - 0xa1a1) <= (0xfefe - 0xa1a1) && + static_cast<uint8_t>(value - 0xa1) <= (0xfe - 0xa1) ) { return value - 0x8080; /* shift down to 21..7e byte range */ } else { @@ -1368,12 +1368,12 @@ toUnicodeCallback(UConverter *cnv, const uint32_t sourceChar, const uint32_t targetUniChar, UErrorCode* err){ if(sourceChar>0xff){ - cnv->toUBytes[0] = (uint8_t)(sourceChar>>8); - cnv->toUBytes[1] = (uint8_t)sourceChar; + cnv->toUBytes[0] = static_cast<uint8_t>(sourceChar >> 8); + cnv->toUBytes[1] = static_cast<uint8_t>(sourceChar); cnv->toULength = 2; } else{ - cnv->toUBytes[0] =(char) sourceChar; + cnv->toUBytes[0] = static_cast<char>(sourceChar); cnv->toULength = 1; } @@ -1527,7 +1527,7 @@ _2022FromSJIS(uint32_t value) { return 0; /* beyond JIS X 0208 */ } - trail = (uint8_t)value; + trail = static_cast<uint8_t>(value); value &= 0xff00; /* lead byte */ if(value <= 0x9f00) { @@ -1569,7 +1569,7 @@ _2022ToSJIS(uint8_t c1, uint8_t c2, char bytes[2]) { c2 = 0; /* invalid */ } } else { - if((uint8_t)(c2-0x21) <= ((0x7e)-0x21)) { + if (static_cast<uint8_t>(c2 - 0x21) <= ((0x7e) - 0x21)) { c2 += 0x7e; } else { c2 = 0; /* invalid */ @@ -1583,8 +1583,8 @@ _2022ToSJIS(uint8_t c1, uint8_t c2, char bytes[2]) { } else { c1 = 0; /* invalid */ } - bytes[0] = (char)c1; - bytes[1] = (char)c2; + bytes[0] = static_cast<char>(c1); + bytes[1] = static_cast<char>(c2); } /* @@ -1665,8 +1665,8 @@ UConverter_fromUnicode_ISO_2022_JP_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args UConverter *cnv = args->converter; UConverterDataISO2022 *converterData; ISO2022State *pFromU2022State; - uint8_t *target = (uint8_t *) args->target; - const uint8_t *targetLimit = (const uint8_t *) args->targetLimit; + uint8_t* target = reinterpret_cast<uint8_t*>(args->target); + const uint8_t* targetLimit = reinterpret_cast<const uint8_t*>(args->targetLimit); const char16_t* source = args->source; const char16_t* sourceLimit = args->sourceLimit; int32_t* offsets = args->offsets; @@ -1682,7 +1682,7 @@ UConverter_fromUnicode_ISO_2022_JP_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args int8_t cs, g; /* set up the state */ - converterData = (UConverterDataISO2022*)cnv->extraInfo; + converterData = static_cast<UConverterDataISO2022*>(cnv->extraInfo); pFromU2022State = &converterData->fromU2022State; choiceCount = 0; @@ -1703,7 +1703,7 @@ getTrail: /*look ahead to find the trail surrogate*/ if(source < sourceLimit) { /* test the following code unit */ - char16_t trail=(char16_t) *source; + char16_t trail = *source; if(U16_IS_TRAIL(trail)) { source++; sourceChar=U16_GET_SUPPLEMENTARY(sourceChar, trail); @@ -1753,7 +1753,7 @@ getTrail: /* JIS7/8: try single-byte half-width Katakana before JISX208 */ if(converterData->version == 3 || converterData->version == 4) { - choices[choiceCount++] = (int8_t)HWKANA_7BIT; + choices[choiceCount++] = static_cast<int8_t>(HWKANA_7BIT); } /* Do not try single-byte half-width Katakana for other versions. */ csm &= ~CSM(HWKANA_7BIT); @@ -1770,7 +1770,7 @@ getTrail: /* try all the other possible charsets */ for(i = 0; i < UPRV_LENGTHOF(jpCharsetPref); ++i) { - cs = (int8_t)jpCharsetPref[i]; + cs = static_cast<int8_t>(jpCharsetPref[i]); if(CSM(cs) & csm) { choices[choiceCount++] = cs; csm &= ~CSM(cs); @@ -1800,7 +1800,7 @@ getTrail: switch(cs0) { case ASCII: if(sourceChar <= 0x7f) { - targetValue = (uint32_t)sourceChar; + targetValue = static_cast<uint32_t>(sourceChar); len = 1; cs = cs0; g = 0; @@ -1808,31 +1808,31 @@ getTrail: break; case ISO8859_1: if(GR96_START <= sourceChar && sourceChar <= GR96_END) { - targetValue = (uint32_t)sourceChar - 0x80; + targetValue = static_cast<uint32_t>(sourceChar) - 0x80; len = 1; cs = cs0; g = 2; } break; case HWKANA_7BIT: - if((uint32_t)(sourceChar - HWKANA_START) <= (HWKANA_END - HWKANA_START)) { + if (static_cast<uint32_t>(sourceChar - HWKANA_START) <= (HWKANA_END - HWKANA_START)) { if(converterData->version==3) { /* JIS7: use G1 (SO) */ /* Shift U+FF61..U+FF9F to bytes 21..5F. */ - targetValue = (uint32_t)(sourceChar - (HWKANA_START - 0x21)); + targetValue = static_cast<uint32_t>(sourceChar - (HWKANA_START - 0x21)); len = 1; pFromU2022State->cs[1] = cs = cs0; /* do not output an escape sequence */ g = 1; } else if(converterData->version==4) { /* JIS8: use 8-bit bytes with any single-byte charset, see escape sequence output below */ /* Shift U+FF61..U+FF9F to bytes A1..DF. */ - targetValue = (uint32_t)(sourceChar - (HWKANA_START - 0xa1)); + targetValue = static_cast<uint32_t>(sourceChar - (HWKANA_START - 0xa1)); len = 1; cs = pFromU2022State->cs[0]; if(IS_JP_DBCS(cs)) { /* switch from a DBCS charset to JISX201 */ - cs = (int8_t)JISX201; + cs = static_cast<int8_t>(JISX201); } /* else stay in the current G0 charset */ g = 0; @@ -1867,7 +1867,7 @@ getTrail: useFallback = false; } } else if(len == 0 && useFallback && - (uint32_t)(sourceChar - HWKANA_START) <= (HWKANA_END - HWKANA_START)) { + static_cast<uint32_t>(sourceChar - HWKANA_START) <= (HWKANA_END - HWKANA_START)) { targetValue = hwkana_fb[sourceChar - HWKANA_START]; len = -2; cs = cs0; @@ -1958,10 +1958,10 @@ getTrail: /* write the output bytes */ if(len == 1) { - buffer[outLen++] = (char)targetValue; + buffer[outLen++] = static_cast<char>(targetValue); } else /* len == 2 */ { - buffer[outLen++] = (char)(targetValue >> 8); - buffer[outLen++] = (char)targetValue; + buffer[outLen++] = static_cast<char>(targetValue >> 8); + buffer[outLen++] = static_cast<char>(targetValue); } } else { /* @@ -1983,13 +1983,13 @@ getTrail: if(outLen == 1) { *target++ = buffer[0]; if(offsets) { - *offsets++ = (int32_t)(source - args->source - 1); /* -1: known to be ASCII */ + *offsets++ = static_cast<int32_t>(source - args->source - 1); /* -1: known to be ASCII */ } } else if(outLen == 2 && (target + 2) <= targetLimit) { *target++ = buffer[0]; *target++ = buffer[1]; if(offsets) { - int32_t sourceIndex = (int32_t)(source - args->source - U16_LENGTH(sourceChar)); + int32_t sourceIndex = static_cast<int32_t>(source - args->source - U16_LENGTH(sourceChar)); *offsets++ = sourceIndex; *offsets++ = sourceIndex; } @@ -1997,8 +1997,8 @@ getTrail: fromUWriteUInt8( cnv, buffer, outLen, - &target, (const char *)targetLimit, - &offsets, (int32_t)(source - args->source - U16_LENGTH(sourceChar)), + &target, reinterpret_cast<const char*>(targetLimit), + &offsets, static_cast<int32_t>(source - args->source - U16_LENGTH(sourceChar)), err); if(U_FAILURE(*err)) { break; @@ -2039,7 +2039,7 @@ getTrail: int32_t escLen = escSeqCharsLen[ASCII]; uprv_memcpy(buffer + outLen, escSeqChars[ASCII], escLen); outLen += escLen; - pFromU2022State->cs[0] = (int8_t)ASCII; + pFromU2022State->cs[0] = static_cast<int8_t>(ASCII); } /* get the source index of the last input character */ @@ -2050,7 +2050,7 @@ getTrail: * this code gives an incorrect result for the rare case of an unmatched * trail surrogate that is alone in the last buffer of the text stream */ - sourceIndex=(int32_t)(source-args->source); + sourceIndex = static_cast<int32_t>(source - args->source); if(sourceIndex>0) { --sourceIndex; if( U16_IS_TRAIL(args->source[sourceIndex]) && @@ -2065,14 +2065,14 @@ getTrail: fromUWriteUInt8( cnv, buffer, outLen, - &target, (const char *)targetLimit, + &target, reinterpret_cast<const char*>(targetLimit), &offsets, sourceIndex, err); } /*save the state and return */ args->source = source; - args->target = (char*)target; + args->target = reinterpret_cast<char*>(target); } /*************** to unicode *******************/ @@ -2081,7 +2081,7 @@ static void U_CALLCONV UConverter_toUnicode_ISO_2022_JP_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, UErrorCode* err){ char tempBuf[2]; - const char *mySource = (char *) args->source; + const char* mySource = const_cast<char*>(args->source); char16_t *myTarget = args->target; const char *mySourceLimit = args->sourceLimit; uint32_t targetUniChar = 0x0000; @@ -2091,7 +2091,7 @@ UConverter_toUnicode_ISO_2022_JP_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, ISO2022State *pToU2022State; StateEnum cs; - myData=(UConverterDataISO2022*)(args->converter->extraInfo); + myData = static_cast<UConverterDataISO2022*>(args->converter->extraInfo); pToU2022State = &myData->toU2022State; if(myData->key != 0) { @@ -2101,7 +2101,7 @@ UConverter_toUnicode_ISO_2022_JP_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, /* continue with a partial double-byte character */ mySourceChar = args->converter->toUBytes[0]; args->converter->toULength = 0; - cs = (StateEnum)pToU2022State->cs[pToU2022State->g]; + cs = static_cast<StateEnum>(pToU2022State->cs[pToU2022State->g]); targetUniChar = missingCharMarker; goto getTrailByte; } @@ -2112,7 +2112,7 @@ UConverter_toUnicode_ISO_2022_JP_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, if(myTarget < args->targetLimit){ - mySourceChar= (unsigned char) *mySource++; + mySourceChar = static_cast<unsigned char>(*mySource++); switch(mySourceChar) { case UCNV_SI: @@ -2128,7 +2128,7 @@ UConverter_toUnicode_ISO_2022_JP_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, case UCNV_SO: if(myData->version==3) { /* JIS7: switch to G1 half-width Katakana */ - pToU2022State->cs[1] = (int8_t)HWKANA_7BIT; + pToU2022State->cs[1] = static_cast<int8_t>(HWKANA_7BIT); pToU2022State->g=1; continue; } else { @@ -2151,7 +2151,7 @@ escape: if(myData->version==0 && myData->key==0 && U_SUCCESS(*err) && myData->isEmptySegment) { *err = U_ILLEGAL_ESCAPE_SEQUENCE; args->converter->toUCallbackReason = UCNV_IRREGULAR; - args->converter->toULength = (int8_t)(toULengthBefore + (mySource - mySourceBefore)); + args->converter->toULength = static_cast<int8_t>(toULengthBefore + (mySource - mySourceBefore)); } } @@ -2173,8 +2173,9 @@ escape: case CR: case LF: /* automatically reset to single-byte mode */ - if((StateEnum)pToU2022State->cs[0] != ASCII && (StateEnum)pToU2022State->cs[0] != JISX201) { - pToU2022State->cs[0] = (int8_t)ASCII; + if (static_cast<StateEnum>(pToU2022State->cs[0]) != ASCII && + static_cast<StateEnum>(pToU2022State->cs[0]) != JISX201) { + pToU2022State->cs[0] = static_cast<int8_t>(ASCII); } pToU2022State->cs[2] = 0; pToU2022State->g = 0; @@ -2182,8 +2183,8 @@ escape: default: /* convert one or two bytes */ myData->isEmptySegment = false; - cs = (StateEnum)pToU2022State->cs[pToU2022State->g]; - if( (uint8_t)(mySourceChar - 0xa1) <= (0xdf - 0xa1) && myData->version==4 && + cs = static_cast<StateEnum>(pToU2022State->cs[pToU2022State->g]); + if (static_cast<uint8_t>(mySourceChar - 0xa1) <= (0xdf - 0xa1) && myData->version == 4 && !IS_JP_DBCS(cs) ) { /* 8-bit halfwidth katakana in any single-byte mode for JIS8 */ @@ -2223,7 +2224,7 @@ escape: } break; case HWKANA_7BIT: - if((uint8_t)(mySourceChar - 0x21) <= (0x5f - 0x21)) { + if (static_cast<uint8_t>(mySourceChar - 0x21) <= (0x5f - 0x21)) { /* 7-bit halfwidth Katakana */ targetUniChar = mySourceChar + (HWKANA_START - 0x21); } @@ -2234,7 +2235,7 @@ escape: int leadIsOk, trailIsOk; uint8_t trailByte; getTrailByte: - trailByte = (uint8_t)*mySource; + trailByte = static_cast<uint8_t>(*mySource); /* * Ticket 5691: consistent illegal sequences: * - We include at least the first byte in the illegal sequence. @@ -2245,13 +2246,13 @@ getTrailByte: * an ESC/SO/SI, we report only the first byte as the illegal sequence. * Otherwise we convert or report the pair of bytes. */ - leadIsOk = (uint8_t)(mySourceChar - 0x21) <= (0x7e - 0x21); - trailIsOk = (uint8_t)(trailByte - 0x21) <= (0x7e - 0x21); + leadIsOk = static_cast<uint8_t>(mySourceChar - 0x21) <= (0x7e - 0x21); + trailIsOk = static_cast<uint8_t>(trailByte - 0x21) <= (0x7e - 0x21); if (leadIsOk && trailIsOk) { ++mySource; tmpSourceChar = (mySourceChar << 8) | trailByte; if(cs == JISX208) { - _2022ToSJIS((uint8_t)mySourceChar, trailByte, tempBuf); + _2022ToSJIS(static_cast<uint8_t>(mySourceChar), trailByte, tempBuf); mySourceChar = tmpSourceChar; } else { /* Copy before we modify tmpSourceChar so toUnicodeCallback() sees the correct bytes. */ @@ -2259,8 +2260,8 @@ getTrailByte: if (cs == KSC5601) { tmpSourceChar += 0x8080; /* = _2022ToGR94DBCS(tmpSourceChar) */ } - tempBuf[0] = (char)(tmpSourceChar >> 8); - tempBuf[1] = (char)(tmpSourceChar); + tempBuf[0] = static_cast<char>(tmpSourceChar >> 8); + tempBuf[1] = static_cast<char>(tmpSourceChar); } targetUniChar = ucnv_MBCSSimpleGetNextUChar(myData->myConverterArray[cs], tempBuf, 2, false); } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) { @@ -2270,7 +2271,7 @@ getTrailByte: mySourceChar = 0x10000 | (mySourceChar << 8) | trailByte; } } else { - args->converter->toUBytes[0] = (uint8_t)mySourceChar; + args->converter->toUBytes[0] = static_cast<uint8_t>(mySourceChar); args->converter->toULength = 1; goto endloop; } @@ -2279,27 +2280,27 @@ getTrailByte: } /* End of outer switch */ if(targetUniChar < (missingCharMarker-1/*0xfffe*/)){ if(args->offsets){ - args->offsets[myTarget - args->target] = (int32_t)(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); + args->offsets[myTarget - args->target] = static_cast<int32_t>(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); } - *(myTarget++)=(char16_t)targetUniChar; + *(myTarget++) = static_cast<char16_t>(targetUniChar); } else if(targetUniChar > missingCharMarker){ /* disassemble the surrogate pair and write to output*/ targetUniChar-=0x0010000; - *myTarget = (char16_t)(0xd800+(char16_t)(targetUniChar>>10)); + *myTarget = static_cast<char16_t>(0xd800 + static_cast<char16_t>(targetUniChar >> 10)); if(args->offsets){ - args->offsets[myTarget - args->target] = (int32_t)(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); + args->offsets[myTarget - args->target] = static_cast<int32_t>(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); } ++myTarget; if(myTarget< args->targetLimit){ - *myTarget = (char16_t)(0xdc00+(char16_t)(targetUniChar&0x3ff)); + *myTarget = static_cast<char16_t>(0xdc00 + static_cast<char16_t>(targetUniChar & 0x3ff)); if(args->offsets){ - args->offsets[myTarget - args->target] = (int32_t)(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); + args->offsets[myTarget - args->target] = static_cast<int32_t>(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); } ++myTarget; }else{ args->converter->UCharErrorBuffer[args->converter->UCharErrorBufferLength++]= - (char16_t)(0xdc00+(char16_t)(targetUniChar&0x3ff)); + static_cast<char16_t>(0xdc00 + static_cast<char16_t>(targetUniChar & 0x3ff)); } } @@ -2333,7 +2334,7 @@ static void U_CALLCONV UConverter_fromUnicode_ISO_2022_KR_OFFSETS_LOGIC_IBM(UConverterFromUnicodeArgs* args, UErrorCode* err){ UConverter* saveConv = args->converter; - UConverterDataISO2022 *myConverterData=(UConverterDataISO2022*)saveConv->extraInfo; + UConverterDataISO2022* myConverterData = static_cast<UConverterDataISO2022*>(saveConv->extraInfo); args->converter=myConverterData->currentConverter; myConverterData->currentConverter->fromUChar32 = saveConv->fromUChar32; @@ -2358,8 +2359,8 @@ UConverter_fromUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args const char16_t *source = args->source; const char16_t *sourceLimit = args->sourceLimit; - unsigned char *target = (unsigned char *) args->target; - unsigned char *targetLimit = (unsigned char *) args->targetLimit; + unsigned char *target = reinterpret_cast<unsigned char*>(args->target); + unsigned char *targetLimit = reinterpret_cast<unsigned char*>(const_cast<char*>(args->targetLimit)); int32_t* offsets = args->offsets; uint32_t targetByteUnit = 0x0000; UChar32 sourceChar = 0x0000; @@ -2370,7 +2371,7 @@ UConverter_fromUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args UBool useFallback; int32_t length =0; - converterData=(UConverterDataISO2022*)args->converter->extraInfo; + converterData = static_cast<UConverterDataISO2022*>(args->converter->extraInfo); /* if the version is 1 then the user is requesting * conversion with ibm-25546 pass the arguments to * MBCS converter and return @@ -2383,10 +2384,10 @@ UConverter_fromUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args /* initialize data */ sharedData = converterData->currentConverter->sharedData; useFallback = args->converter->useFallback; - isTargetByteDBCS=(UBool)args->converter->fromUnicodeStatus; + isTargetByteDBCS = static_cast<UBool>(args->converter->fromUnicodeStatus); oldIsTargetByteDBCS = isTargetByteDBCS; - isTargetByteDBCS = (UBool) args->converter->fromUnicodeStatus; + isTargetByteDBCS = static_cast<UBool>(args->converter->fromUnicodeStatus); if((sourceChar = args->converter->fromUChar32)!=0 && target <targetLimit) { goto getTrail; } @@ -2414,15 +2415,15 @@ UConverter_fromUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args if( length > 2 || length==0 || (length == 1 && targetByteUnit > 0x7f) || (length == 2 && - ((uint16_t)(targetByteUnit - 0xa1a1) > (0xfefe - 0xa1a1) || - (uint8_t)(targetByteUnit - 0xa1) > (0xfe - 0xa1))) + (static_cast<uint16_t>(targetByteUnit - 0xa1a1) > (0xfefe - 0xa1a1) || + static_cast<uint8_t>(targetByteUnit - 0xa1) > (0xfe - 0xa1))) ) { targetByteUnit=missingCharMarker; } if (targetByteUnit != missingCharMarker){ oldIsTargetByteDBCS = isTargetByteDBCS; - isTargetByteDBCS = (UBool)(targetByteUnit>0x00FF); + isTargetByteDBCS = static_cast<UBool>(targetByteUnit > 0x00FF); /* append the shift sequence */ if (oldIsTargetByteDBCS != isTargetByteDBCS ){ @@ -2431,38 +2432,38 @@ UConverter_fromUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args else *target++ = UCNV_SI; if(offsets) - *(offsets++) = (int32_t)(source - args->source-1); + *(offsets++) = static_cast<int32_t>(source - args->source - 1); } /* write the targetUniChar to target */ if(targetByteUnit <= 0x00FF){ if( target < targetLimit){ - *(target++) = (unsigned char) targetByteUnit; + *(target++) = static_cast<unsigned char>(targetByteUnit); if(offsets){ - *(offsets++) = (int32_t)(source - args->source-1); + *(offsets++) = static_cast<int32_t>(source - args->source - 1); } }else{ - args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = (unsigned char) (targetByteUnit); + args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = static_cast<unsigned char>(targetByteUnit); *err = U_BUFFER_OVERFLOW_ERROR; } }else{ if(target < targetLimit){ - *(target++) =(unsigned char) ((targetByteUnit>>8) -0x80); + *(target++) = static_cast<unsigned char>((targetByteUnit >> 8) - 0x80); if(offsets){ - *(offsets++) = (int32_t)(source - args->source-1); + *(offsets++) = static_cast<int32_t>(source - args->source - 1); } if(target < targetLimit){ - *(target++) =(unsigned char) (targetByteUnit -0x80); + *(target++) = static_cast<unsigned char>(targetByteUnit - 0x80); if(offsets){ - *(offsets++) = (int32_t)(source - args->source-1); + *(offsets++) = static_cast<int32_t>(source - args->source - 1); } }else{ - args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = (unsigned char) (targetByteUnit -0x80); + args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = static_cast<unsigned char>(targetByteUnit - 0x80); *err = U_BUFFER_OVERFLOW_ERROR; } }else{ - args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = (unsigned char) ((targetByteUnit>>8) -0x80); - args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = (unsigned char) (targetByteUnit-0x80); + args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = static_cast<unsigned char>((targetByteUnit >> 8) - 0x80); + args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = static_cast<unsigned char>(targetByteUnit - 0x80); *err = U_BUFFER_OVERFLOW_ERROR; } } @@ -2480,7 +2481,7 @@ getTrail: /*look ahead to find the trail surrogate*/ if(source < sourceLimit) { /* test the following code unit */ - char16_t trail=(char16_t) *source; + char16_t trail = *source; if(U16_IS_TRAIL(trail)) { source++; sourceChar=U16_GET_SUPPLEMENTARY(sourceChar, trail); @@ -2544,7 +2545,7 @@ getTrail: * this code gives an incorrect result for the rare case of an unmatched * trail surrogate that is alone in the last buffer of the text stream */ - sourceIndex=(int32_t)(source-args->source); + sourceIndex = static_cast<int32_t>(source - args->source); if(sourceIndex>0) { --sourceIndex; if( U16_IS_TRAIL(args->source[sourceIndex]) && @@ -2559,15 +2560,15 @@ getTrail: fromUWriteUInt8( args->converter, SHIFT_IN_STR, 1, - &target, (const char *)targetLimit, + &target, reinterpret_cast<const char*>(targetLimit), &offsets, sourceIndex, err); } /*save the state and return */ args->source = source; - args->target = (char*)target; - args->converter->fromUnicodeStatus = (uint32_t)isTargetByteDBCS; + args->target = reinterpret_cast<char*>(target); + args->converter->fromUnicodeStatus = static_cast<uint32_t>(isTargetByteDBCS); } /************************ To Unicode ***************************************/ @@ -2576,7 +2577,7 @@ static void U_CALLCONV UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC_IBM(UConverterToUnicodeArgs *args, UErrorCode* err){ char const* sourceStart; - UConverterDataISO2022* myData=(UConverterDataISO2022*)(args->converter->extraInfo); + UConverterDataISO2022* myData = static_cast<UConverterDataISO2022*>(args->converter->extraInfo); UConverterToUnicodeArgs subArgs; int32_t minArgsSize; @@ -2585,11 +2586,11 @@ UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC_IBM(UConverterToUnicodeArgs *args if(args->size<sizeof(UConverterToUnicodeArgs)) { minArgsSize = args->size; } else { - minArgsSize = (int32_t)sizeof(UConverterToUnicodeArgs); + minArgsSize = static_cast<int32_t>(sizeof(UConverterToUnicodeArgs)); } uprv_memcpy(&subArgs, args, minArgsSize); - subArgs.size = (uint16_t)minArgsSize; + subArgs.size = static_cast<uint16_t>(minArgsSize); subArgs.converter = myData->currentConverter; /* remember the original start of the input for offsets */ @@ -2628,7 +2629,7 @@ UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC_IBM(UConverterToUnicodeArgs *args /* update offsets to base them on the actual start of the input */ int32_t *offsets = args->offsets; char16_t *target = args->target; - int32_t delta = (int32_t)(args->source - sourceStart); + int32_t delta = static_cast<int32_t>(args->source - sourceStart); while(target < subArgs.target) { if(*offsets >= 0) { *offsets += delta; @@ -2674,7 +2675,7 @@ static void U_CALLCONV UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, UErrorCode* err){ char tempBuf[2]; - const char *mySource = ( char *) args->source; + const char* mySource = const_cast<char*>(args->source); char16_t *myTarget = args->target; const char *mySourceLimit = args->sourceLimit; UChar32 targetUniChar = 0x0000; @@ -2683,7 +2684,7 @@ UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, UConverterSharedData* sharedData ; UBool useFallback; - myData=(UConverterDataISO2022*)(args->converter->extraInfo); + myData = static_cast<UConverterDataISO2022*>(args->converter->extraInfo); if(myData->version==1){ UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC_IBM(args,err); return; @@ -2707,7 +2708,7 @@ UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, if(myTarget < args->targetLimit){ - mySourceChar= (unsigned char) *mySource++; + mySourceChar = static_cast<unsigned char>(*mySource++); if(mySourceChar==UCNV_SI){ myData->toU2022State.g = 0; @@ -2715,7 +2716,7 @@ UConverter_toUnicode_ISO_2022_KR_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, myData->isEmptySegment = false; /* we are handling it, reset to avoid future spurious errors */ *err = U_ILLEGAL_ESCAPE_SEQUENCE; args->converter->toUCallbackReason = UCNV_IRREGULAR; - args->converter->toUBytes[0] = (uint8_t)mySourceChar; + args->converter->toUBytes[0] = static_cast<uint8_t>(mySourceChar); args->converter->toULength = 1; args->target = myTarget; args->source = mySource; @@ -2749,7 +2750,7 @@ escape: uint8_t trailByte; getTrailByte: targetUniChar = missingCharMarker; - trailByte = (uint8_t)*mySource; + trailByte = static_cast<uint8_t>(*mySource); /* * Ticket 5691: consistent illegal sequences: * - We include at least the first byte in the illegal sequence. @@ -2760,12 +2761,12 @@ getTrailByte: * an ESC/SO/SI, we report only the first byte as the illegal sequence. * Otherwise we convert or report the pair of bytes. */ - leadIsOk = (uint8_t)(mySourceChar - 0x21) <= (0x7e - 0x21); - trailIsOk = (uint8_t)(trailByte - 0x21) <= (0x7e - 0x21); + leadIsOk = static_cast<uint8_t>(mySourceChar - 0x21) <= (0x7e - 0x21); + trailIsOk = static_cast<uint8_t>(trailByte - 0x21) <= (0x7e - 0x21); if (leadIsOk && trailIsOk) { ++mySource; - tempBuf[0] = (char)(mySourceChar + 0x80); - tempBuf[1] = (char)(trailByte + 0x80); + tempBuf[0] = static_cast<char>(mySourceChar + 0x80); + tempBuf[1] = static_cast<char>(trailByte + 0x80); targetUniChar = ucnv_MBCSSimpleGetNextUChar(sharedData, tempBuf, 2, useFallback); mySourceChar = (mySourceChar << 8) | trailByte; } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) { @@ -2775,7 +2776,7 @@ getTrailByte: mySourceChar = static_cast<char16_t>(0x10000 | (mySourceChar << 8) | trailByte); } } else { - args->converter->toUBytes[0] = (uint8_t)mySourceChar; + args->converter->toUBytes[0] = static_cast<uint8_t>(mySourceChar); args->converter->toULength = 1; break; } @@ -2787,9 +2788,9 @@ getTrailByte: } if(targetUniChar < 0xfffe){ if(args->offsets) { - args->offsets[myTarget - args->target] = (int32_t)(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); + args->offsets[myTarget - args->target] = static_cast<int32_t>(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); } - *(myTarget++)=(char16_t)targetUniChar; + *(myTarget++) = static_cast<char16_t>(targetUniChar); } else { /* Call the callback function*/ @@ -2917,8 +2918,8 @@ UConverter_fromUnicode_ISO_2022_CN_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args UConverter *cnv = args->converter; UConverterDataISO2022 *converterData; ISO2022State *pFromU2022State; - uint8_t *target = (uint8_t *) args->target; - const uint8_t *targetLimit = (const uint8_t *) args->targetLimit; + uint8_t* target = reinterpret_cast<uint8_t*>(args->target); + const uint8_t* targetLimit = reinterpret_cast<const uint8_t*>(args->targetLimit); const char16_t* source = args->source; const char16_t* sourceLimit = args->sourceLimit; int32_t* offsets = args->offsets; @@ -2931,7 +2932,7 @@ UConverter_fromUnicode_ISO_2022_CN_OFFSETS_LOGIC(UConverterFromUnicodeArgs* args UBool useFallback; /* set up the state */ - converterData = (UConverterDataISO2022*)cnv->extraInfo; + converterData = static_cast<UConverterDataISO2022*>(cnv->extraInfo); pFromU2022State = &converterData->fromU2022State; choiceCount = 0; @@ -2952,7 +2953,7 @@ getTrail: /*look ahead to find the trail surrogate*/ if(source < sourceLimit) { /* test the following code unit */ - char16_t trail=(char16_t) *source; + char16_t trail = *source; if(U16_IS_TRAIL(trail)) { source++; sourceChar=U16_GET_SUPPLEMENTARY(sourceChar, trail); @@ -2992,11 +2993,11 @@ getTrail: /* US-ASCII */ if(pFromU2022State->g == 0) { - buffer[0] = (char)sourceChar; + buffer[0] = static_cast<char>(sourceChar); len = 1; } else { buffer[0] = UCNV_SI; - buffer[1] = (char)sourceChar; + buffer[1] = static_cast<char>(sourceChar); len = 2; pFromU2022State->g = 0; choiceCount = 0; @@ -3026,9 +3027,9 @@ getTrail: /* try the other SO/G1 converter; a CNS_11643_1 lookup may result in any plane */ if(choices[0] == GB2312_1) { - choices[1] = (int8_t)CNS_11643_1; + choices[1] = static_cast<int8_t>(CNS_11643_1); } else { - choices[1] = (int8_t)GB2312_1; + choices[1] = static_cast<int8_t>(GB2312_1); } choiceCount = 2; @@ -3038,23 +3039,23 @@ getTrail: /* try one of the other converters */ switch(choices[0]) { case GB2312_1: - choices[1] = (int8_t)CNS_11643_1; - choices[2] = (int8_t)ISO_IR_165; + choices[1] = static_cast<int8_t>(CNS_11643_1); + choices[2] = static_cast<int8_t>(ISO_IR_165); break; case ISO_IR_165: - choices[1] = (int8_t)GB2312_1; - choices[2] = (int8_t)CNS_11643_1; + choices[1] = static_cast<int8_t>(GB2312_1); + choices[2] = static_cast<int8_t>(CNS_11643_1); break; default: /* CNS_11643_x */ - choices[1] = (int8_t)GB2312_1; - choices[2] = (int8_t)ISO_IR_165; + choices[1] = static_cast<int8_t>(GB2312_1); + choices[2] = static_cast<int8_t>(ISO_IR_165); break; } choiceCount = 3; } else { - choices[0] = (int8_t)CNS_11643_1; - choices[1] = (int8_t)GB2312_1; + choices[0] = static_cast<int8_t>(CNS_11643_1); + choices[1] = static_cast<int8_t>(GB2312_1); } } @@ -3087,7 +3088,7 @@ getTrail: MBCS_OUTPUT_3); if(len2 == 3 || (len2 == -3 && len == 0)) { targetValue = value; - cs = (int8_t)(CNS_11643_0 + (value >> 16) - 0x80); + cs = static_cast<int8_t>(CNS_11643_0 + (value >> 16) - 0x80); if(len2 >= 0) { len = 2; } else { @@ -3165,8 +3166,8 @@ getTrail: } /* write the two output bytes */ - buffer[len++] = (char)(targetValue >> 8); - buffer[len++] = (char)targetValue; + buffer[len++] = static_cast<char>(targetValue >> 8); + buffer[len++] = static_cast<char>(targetValue); } else { /* if we cannot find the character after checking all codepages * then this is an error @@ -3181,13 +3182,13 @@ getTrail: if(len == 1) { *target++ = buffer[0]; if(offsets) { - *offsets++ = (int32_t)(source - args->source - 1); /* -1: known to be ASCII */ + *offsets++ = static_cast<int32_t>(source - args->source - 1); /* -1: known to be ASCII */ } } else if(len == 2 && (target + 2) <= targetLimit) { *target++ = buffer[0]; *target++ = buffer[1]; if(offsets) { - int32_t sourceIndex = (int32_t)(source - args->source - U16_LENGTH(sourceChar)); + int32_t sourceIndex = static_cast<int32_t>(source - args->source - U16_LENGTH(sourceChar)); *offsets++ = sourceIndex; *offsets++ = sourceIndex; } @@ -3195,8 +3196,8 @@ getTrail: fromUWriteUInt8( cnv, buffer, len, - &target, (const char *)targetLimit, - &offsets, (int32_t)(source - args->source - U16_LENGTH(sourceChar)), + &target, reinterpret_cast<const char*>(targetLimit), + &offsets, static_cast<int32_t>(source - args->source - U16_LENGTH(sourceChar)), err); if(U_FAILURE(*err)) { break; @@ -3237,7 +3238,7 @@ getTrail: * this code gives an incorrect result for the rare case of an unmatched * trail surrogate that is alone in the last buffer of the text stream */ - sourceIndex=(int32_t)(source-args->source); + sourceIndex = static_cast<int32_t>(source - args->source); if(sourceIndex>0) { --sourceIndex; if( U16_IS_TRAIL(args->source[sourceIndex]) && @@ -3252,14 +3253,14 @@ getTrail: fromUWriteUInt8( cnv, SHIFT_IN_STR, 1, - &target, (const char *)targetLimit, + &target, reinterpret_cast<const char*>(targetLimit), &offsets, sourceIndex, err); } /*save the state and return */ args->source = source; - args->target = (char*)target; + args->target = reinterpret_cast<char*>(target); } @@ -3267,7 +3268,7 @@ static void U_CALLCONV UConverter_toUnicode_ISO_2022_CN_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, UErrorCode* err){ char tempBuf[3]; - const char *mySource = (char *) args->source; + const char* mySource = const_cast<char*>(args->source); char16_t *myTarget = args->target; const char *mySourceLimit = args->sourceLimit; uint32_t targetUniChar = 0x0000; @@ -3275,7 +3276,7 @@ UConverter_toUnicode_ISO_2022_CN_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, UConverterDataISO2022* myData; ISO2022State *pToU2022State; - myData=(UConverterDataISO2022*)(args->converter->extraInfo); + myData = static_cast<UConverterDataISO2022*>(args->converter->extraInfo); pToU2022State = &myData->toU2022State; if(myData->key != 0) { @@ -3295,7 +3296,7 @@ UConverter_toUnicode_ISO_2022_CN_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, if(myTarget < args->targetLimit){ - mySourceChar= (unsigned char) *mySource++; + mySourceChar = static_cast<unsigned char>(*mySource++); switch(mySourceChar){ case UCNV_SI: @@ -3337,7 +3338,7 @@ escape: if(myData->key==0 && U_SUCCESS(*err) && myData->isEmptySegment) { *err = U_ILLEGAL_ESCAPE_SEQUENCE; args->converter->toUCallbackReason = UCNV_IRREGULAR; - args->converter->toULength = (int8_t)(toULengthBefore + (mySource - mySourceBefore)); + args->converter->toULength = static_cast<int8_t>(toULengthBefore + (mySource - mySourceBefore)); } } @@ -3367,7 +3368,7 @@ escape: int leadIsOk, trailIsOk; uint8_t trailByte; getTrailByte: - trailByte = (uint8_t)*mySource; + trailByte = static_cast<uint8_t>(*mySource); /* * Ticket 5691: consistent illegal sequences: * - We include at least the first byte in the illegal sequence. @@ -3378,23 +3379,23 @@ getTrailByte: * an ESC/SO/SI, we report only the first byte as the illegal sequence. * Otherwise we convert or report the pair of bytes. */ - leadIsOk = (uint8_t)(mySourceChar - 0x21) <= (0x7e - 0x21); - trailIsOk = (uint8_t)(trailByte - 0x21) <= (0x7e - 0x21); + leadIsOk = static_cast<uint8_t>(mySourceChar - 0x21) <= (0x7e - 0x21); + trailIsOk = static_cast<uint8_t>(trailByte - 0x21) <= (0x7e - 0x21); if (leadIsOk && trailIsOk) { ++mySource; - tempState = (StateEnum)pToU2022State->cs[pToU2022State->g]; + tempState = static_cast<StateEnum>(pToU2022State->cs[pToU2022State->g]); if(tempState >= CNS_11643_0) { cnv = myData->myConverterArray[CNS_11643]; - tempBuf[0] = (char) (0x80+(tempState-CNS_11643_0)); - tempBuf[1] = (char) (mySourceChar); - tempBuf[2] = (char) trailByte; + tempBuf[0] = static_cast<char>(0x80 + (tempState - CNS_11643_0)); + tempBuf[1] = static_cast<char>(mySourceChar); + tempBuf[2] = static_cast<char>(trailByte); tempBufLen = 3; }else{ U_ASSERT(tempState<UCNV_2022_MAX_CONVERTERS); cnv = myData->myConverterArray[tempState]; - tempBuf[0] = (char) (mySourceChar); - tempBuf[1] = (char) trailByte; + tempBuf[0] = static_cast<char>(mySourceChar); + tempBuf[1] = static_cast<char>(trailByte); tempBufLen = 2; } targetUniChar = ucnv_MBCSSimpleGetNextUChar(cnv, tempBuf, tempBufLen, false); @@ -3410,41 +3411,41 @@ getTrailByte: pToU2022State->g=pToU2022State->prevG; } } else { - args->converter->toUBytes[0] = (uint8_t)mySourceChar; + args->converter->toUBytes[0] = static_cast<uint8_t>(mySourceChar); args->converter->toULength = 1; goto endloop; } } else{ if(mySourceChar <= 0x7f) { - targetUniChar = (char16_t) mySourceChar; + targetUniChar = static_cast<char16_t>(mySourceChar); } } break; } if(targetUniChar < (missingCharMarker-1/*0xfffe*/)){ if(args->offsets){ - args->offsets[myTarget - args->target] = (int32_t)(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); + args->offsets[myTarget - args->target] = static_cast<int32_t>(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); } - *(myTarget++)=(char16_t)targetUniChar; + *(myTarget++) = static_cast<char16_t>(targetUniChar); } else if(targetUniChar > missingCharMarker){ /* disassemble the surrogate pair and write to output*/ targetUniChar-=0x0010000; - *myTarget = (char16_t)(0xd800+(char16_t)(targetUniChar>>10)); + *myTarget = static_cast<char16_t>(0xd800 + static_cast<char16_t>(targetUniChar >> 10)); if(args->offsets){ - args->offsets[myTarget - args->target] = (int32_t)(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); + args->offsets[myTarget - args->target] = static_cast<int32_t>(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); } ++myTarget; if(myTarget< args->targetLimit){ - *myTarget = (char16_t)(0xdc00+(char16_t)(targetUniChar&0x3ff)); + *myTarget = static_cast<char16_t>(0xdc00 + static_cast<char16_t>(targetUniChar & 0x3ff)); if(args->offsets){ - args->offsets[myTarget - args->target] = (int32_t)(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); + args->offsets[myTarget - args->target] = static_cast<int32_t>(mySource - args->source - (mySourceChar <= 0xff ? 1 : 2)); } ++myTarget; }else{ args->converter->UCharErrorBuffer[args->converter->UCharErrorBufferLength++]= - (char16_t)(0xdc00+(char16_t)(targetUniChar&0x3ff)); + static_cast<char16_t>(0xdc00 + static_cast<char16_t>(targetUniChar & 0x3ff)); } } @@ -3468,13 +3469,13 @@ endloop: static void U_CALLCONV _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorCode *err) { UConverter *cnv = args->converter; - UConverterDataISO2022 *myConverterData=(UConverterDataISO2022 *) cnv->extraInfo; + UConverterDataISO2022* myConverterData = static_cast<UConverterDataISO2022*>(cnv->extraInfo); ISO2022State *pFromU2022State=&myConverterData->fromU2022State; char *p, *subchar; char buffer[8]; int32_t length; - subchar=(char *)cnv->subChars; + subchar = reinterpret_cast<char*>(cnv->subChars); length=cnv->subCharLen; /* assume length==1 for most variants */ p = buffer; @@ -3492,7 +3493,7 @@ _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorC cs = pFromU2022State->cs[0]; if(cs != ASCII && cs != JISX201) { /* not in ASCII or JIS X 0201: switch to ASCII */ - pFromU2022State->cs[0] = (int8_t)ASCII; + pFromU2022State->cs[0] = static_cast<int8_t>(ASCII); *p++ = '\x1b'; *p++ = '\x28'; *p++ = '\x42'; @@ -3534,8 +3535,8 @@ _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorC int8_t currentSubCharLen = myConverterData->currentConverter->subCharLen; /* set our substitution string into the subconverter */ - myConverterData->currentConverter->subChars = (uint8_t *)subchar; - myConverterData->currentConverter->subCharLen = (int8_t)length; + myConverterData->currentConverter->subChars = reinterpret_cast<uint8_t*>(subchar); + myConverterData->currentConverter->subCharLen = static_cast<int8_t>(length); /* let the subconverter write the subchar, set/retrieve fromUChar32 state */ args->converter = myConverterData->currentConverter; @@ -3565,7 +3566,7 @@ _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorC break; } ucnv_cbFromUWriteBytes(args, - buffer, (int32_t)(p - buffer), + buffer, static_cast<int32_t>(p - buffer), offsetIndex, err); } @@ -3656,7 +3657,7 @@ _ISO_2022_GetUnicodeSet(const UConverter *cnv, } #endif - cnvData = (UConverterDataISO2022*)cnv->extraInfo; + cnvData = static_cast<UConverterDataISO2022*>(cnv->extraInfo); /* open a set and initialize it with code points that are algorithmically round-tripped */ switch(cnvData->locale[0]){ diff --git a/thirdparty/icu4c/common/ucnv_bld.cpp b/thirdparty/icu4c/common/ucnv_bld.cpp index 564b645bed..1e768ae224 100644 --- a/thirdparty/icu4c/common/ucnv_bld.cpp +++ b/thirdparty/icu4c/common/ucnv_bld.cpp @@ -231,7 +231,7 @@ static void ucnv_flushAvailableConverterCache() { gAvailableConverterCount = 0; if (gAvailableConverters) { - uprv_free((char **)gAvailableConverters); + uprv_free(const_cast<char**>(gAvailableConverters)); gAvailableConverters = nullptr; } gAvailableConvertersInitOnce.reset(); @@ -270,7 +270,7 @@ static UBool U_CALLCONV isCnvAcceptable(void * /*context*/, const char * /*type*/, const char * /*name*/, const UDataInfo *pInfo) { - return (UBool)( + return pInfo->size>=20 && pInfo->isBigEndian==U_IS_BIG_ENDIAN && pInfo->charsetFamily==U_CHARSET_FAMILY && @@ -279,7 +279,7 @@ isCnvAcceptable(void * /*context*/, pInfo->dataFormat[1]==0x6e && pInfo->dataFormat[2]==0x76 && pInfo->dataFormat[3]==0x74 && - pInfo->formatVersion[0]==6); /* Everything will be version 6 */ + pInfo->formatVersion[0]==6; /* Everything will be version 6 */ } /** @@ -289,15 +289,15 @@ static UConverterSharedData* ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCode *status) { /* UDataInfo info; -- necessary only if some converters have different formatVersion */ - const uint8_t *raw = (const uint8_t *)udata_getMemory(pData); - const UConverterStaticData *source = (const UConverterStaticData *) raw; + const uint8_t* raw = static_cast<const uint8_t*>(udata_getMemory(pData)); + const UConverterStaticData* source = reinterpret_cast<const UConverterStaticData*>(raw); UConverterSharedData *data; - UConverterType type = (UConverterType)source->conversionType; + UConverterType type = static_cast<UConverterType>(source->conversionType); if(U_FAILURE(*status)) return nullptr; - if( (uint16_t)type >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES || + if (static_cast<uint16_t>(type) >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES || converterData[type] == nullptr || !converterData[type]->isReferenceCounted || converterData[type]->referenceCounter != 1 || @@ -307,7 +307,7 @@ ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCo return nullptr; } - data = (UConverterSharedData *)uprv_malloc(sizeof(UConverterSharedData)); + data = static_cast<UConverterSharedData*>(uprv_malloc(sizeof(UConverterSharedData))); if(data == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -397,7 +397,7 @@ getAlgorithmicTypeFromName(const char *realName) lastMid = UINT32_MAX; for (;;) { - mid = (uint32_t)((start + limit) / 2); + mid = (start + limit) / 2; if (lastMid == mid) { /* Have we moved? */ break; /* We haven't moved, and it wasn't found. */ } @@ -491,7 +491,7 @@ ucnv_getSharedConverterData(const char *name) { UConverterSharedData *rc; - rc = (UConverterSharedData*)uhash_get(SHARED_DATA_HASHTABLE, name); + rc = static_cast<UConverterSharedData*>(uhash_get(SHARED_DATA_HASHTABLE, name)); UCNV_DEBUG_LOG("get",name,rc); return rc; } @@ -682,8 +682,8 @@ parseConverterOptions(const char *inName, if(c==0) { pArgs->options=(pPieces->options&=~UCNV_OPTION_VERSION); return; - } else if((uint8_t)(c-'0')<10) { - pArgs->options=pPieces->options=(pPieces->options&~UCNV_OPTION_VERSION)|(uint32_t)(c-'0'); + } else if (static_cast<uint8_t>(c - '0') < 10) { + pArgs->options = pPieces->options = (pPieces->options & ~UCNV_OPTION_VERSION) | static_cast<uint32_t>(c - '0'); ++inName; } } else if(uprv_strncmp(inName, "swaplfnl", 8)==0) { @@ -909,7 +909,7 @@ ucnv_createAlgorithmicConverter(UConverter *myUConverter, stackArgs.options = options; stackArgs.locale=locale; cnv = ucnv_createConverterFromSharedData( - myUConverter, (UConverterSharedData *)sharedData, + myUConverter, const_cast<UConverterSharedData*>(sharedData), &stackArgs, err); UTRACE_EXIT_PTR_STATUS(cnv, *err); @@ -1112,7 +1112,7 @@ static void U_CALLCONV initAvailableConvertersList(UErrorCode &errCode) { } /* We can't have more than "*converterTable" converters to open */ - gAvailableConverters = (const char **) uprv_malloc(allConverterCount * sizeof(char*)); + gAvailableConverters = static_cast<const char**>(uprv_malloc(allConverterCount * sizeof(char*))); if (!gAvailableConverters) { errCode = U_MEMORY_ALLOCATION_ERROR; return; @@ -1440,7 +1440,7 @@ ucnv_swap(const UDataSwapper *ds, MBCS_OPT_UNKNOWN_INCOMPATIBLE_MASK)==0 ) { mbcsHeaderLength=mbcsHeader.options&MBCS_OPT_LENGTH_MASK; - noFromU=(UBool)((mbcsHeader.options&MBCS_OPT_NO_FROM_U)!=0); + noFromU = (mbcsHeader.options & MBCS_OPT_NO_FROM_U) != 0; } else { udata_printError(ds, "ucnv_swap(): unsupported _MBCSHeader.version %d.%d\n", inMBCSHeader->version[0], inMBCSHeader->version[1]); diff --git a/thirdparty/icu4c/common/ucnv_ct.cpp b/thirdparty/icu4c/common/ucnv_ct.cpp index 46f30e5ece..aa0a6a1169 100644 --- a/thirdparty/icu4c/common/ucnv_ct.cpp +++ b/thirdparty/icu4c/common/ucnv_ct.cpp @@ -368,7 +368,7 @@ getTrail: /*look ahead to find the trail surrogate*/ if(source < sourceLimit) { /* test the following code unit */ - char16_t trail=(char16_t) *source; + char16_t trail = *source; if(U16_IS_TRAIL(trail)) { source++; sourceChar=U16_GET_SUPPLEMENTARY(sourceChar, trail); diff --git a/thirdparty/icu4c/common/ucnv_ext.cpp b/thirdparty/icu4c/common/ucnv_ext.cpp index 10d00a62c2..1f12d05b26 100644 --- a/thirdparty/icu4c/common/ucnv_ext.cpp +++ b/thirdparty/icu4c/common/ucnv_ext.cpp @@ -41,8 +41,8 @@ ucnv_extFindToU(const uint32_t *toUSection, int32_t length, uint8_t byte) { int32_t i, start, limit; /* check the input byte against the lowest and highest section bytes */ - start=(int32_t)UCNV_EXT_TO_U_GET_BYTE(toUSection[0]); - limit=(int32_t)UCNV_EXT_TO_U_GET_BYTE(toUSection[length-1]); + start = static_cast<int32_t>(UCNV_EXT_TO_U_GET_BYTE(toUSection[0])); + limit = static_cast<int32_t>(UCNV_EXT_TO_U_GET_BYTE(toUSection[length - 1])); if(byte<start || limit<byte) { return 0; /* the byte is out of range */ } @@ -180,9 +180,9 @@ ucnv_extMatchToU(const int32_t *cx, int8_t sisoState, /* match pre[] then src[] */ if(i<preLength) { - b=(uint8_t)pre[i++]; + b = static_cast<uint8_t>(pre[i++]); } else if(j<srcLength) { - b=(uint8_t)src[j++]; + b = static_cast<uint8_t>(src[j++]); } else { /* all input consumed, partial match */ if(flush || (length=(i+j))>UCNV_EXT_MAX_BYTES) { @@ -206,7 +206,7 @@ ucnv_extMatchToU(const int32_t *cx, int8_t sisoState, } else { if(UCNV_EXT_TO_U_IS_PARTIAL(value)) { /* partial match, continue */ - idx=(int32_t)UCNV_EXT_TO_U_GET_PARTIAL_INDEX(value); + idx = static_cast<int32_t>(UCNV_EXT_TO_U_GET_PARTIAL_INDEX(value)); } else { if( (UCNV_EXT_TO_U_IS_ROUNDTRIP(value) || TO_U_USE_FALLBACK(useFallback)) && @@ -572,7 +572,7 @@ ucnv_extMatchFromU(const int32_t *cx, if(UCNV_EXT_TO_U_IS_PARTIAL(value)) { /* partial match, enter the loop below */ - idx=(int32_t)UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value); + idx = static_cast<int32_t>(UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value)); /* initialize */ fromUTableUChars=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_UCHARS_INDEX, char16_t); @@ -627,7 +627,7 @@ ucnv_extMatchFromU(const int32_t *cx, value=fromUSectionValues[idx]; if(UCNV_EXT_FROM_U_IS_PARTIAL(value)) { /* partial match, continue */ - idx=(int32_t)UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value); + idx = static_cast<int32_t>(UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value)); } else { if(extFromUUseMapping(useFallback, value, firstCP)) { /* full match, stop with result */ @@ -679,7 +679,7 @@ ucnv_extWriteFromU(UConverter *cnv, const int32_t *cx, int32_t length, prevLength; length=UCNV_EXT_FROM_U_GET_LENGTH(value); - value=(uint32_t)UCNV_EXT_FROM_U_GET_DATA(value); + value = UCNV_EXT_FROM_U_GET_DATA(value); /* output the result */ if(length<=UCNV_EXT_FROM_U_MAX_DIRECT_LENGTH) { @@ -692,13 +692,13 @@ ucnv_extWriteFromU(UConverter *cnv, const int32_t *cx, uint8_t *p=buffer+1; /* reserve buffer[0] for shiftByte below */ switch(length) { case 3: - *p++=(uint8_t)(value>>16); + *p++ = static_cast<uint8_t>(value >> 16); U_FALLTHROUGH; case 2: - *p++=(uint8_t)(value>>8); + *p++ = static_cast<uint8_t>(value >> 8); U_FALLTHROUGH; case 1: - *p++=(uint8_t)value; + *p++ = static_cast<uint8_t>(value); U_FALLTHROUGH; default: break; /* will never occur */ @@ -716,11 +716,11 @@ ucnv_extWriteFromU(UConverter *cnv, const int32_t *cx, if(prevLength>1 && length==1) { /* change from double-byte mode to single-byte */ - shiftByte=(uint8_t)UCNV_SI; + shiftByte = static_cast<uint8_t>(UCNV_SI); cnv->fromUnicodeStatus=1; } else if(prevLength==1 && length>1) { /* change from single-byte mode to double-byte */ - shiftByte=(uint8_t)UCNV_SO; + shiftByte = static_cast<uint8_t>(UCNV_SO); cnv->fromUnicodeStatus=2; } else { shiftByte=0; @@ -737,7 +737,7 @@ ucnv_extWriteFromU(UConverter *cnv, const int32_t *cx, } } - ucnv_fromUWriteBytes(cnv, (const char *)result, length, + ucnv_fromUWriteBytes(cnv, reinterpret_cast<const char*>(result), length, target, targetLimit, offsets, srcIndex, pErrorCode); @@ -830,7 +830,7 @@ ucnv_extSimpleMatchFromU(const int32_t *cx, isRoundtrip=UCNV_EXT_FROM_U_IS_ROUNDTRIP(value); length=UCNV_EXT_FROM_U_GET_LENGTH(value); - value=(uint32_t)UCNV_EXT_FROM_U_GET_DATA(value); + value = UCNV_EXT_FROM_U_GET_DATA(value); if(length<=UCNV_EXT_FROM_U_MAX_DIRECT_LENGTH) { *pValue=value; @@ -1018,7 +1018,7 @@ ucnv_extGetUnicodeSetString(const UConverterSharedData *sharedData, ucnv_extGetUnicodeSetString( sharedData, cx, sa, which, minLength, firstCP, s, length+1, - (int32_t)UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value), + static_cast<int32_t>(UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value)), pErrorCode); } else if(extSetUseMapping(which, minLength, value)) { sa->addString(sa->set, s, length+1); diff --git a/thirdparty/icu4c/common/ucnv_io.cpp b/thirdparty/icu4c/common/ucnv_io.cpp index 48bb5be42b..7207de397e 100644 --- a/thirdparty/icu4c/common/ucnv_io.cpp +++ b/thirdparty/icu4c/common/ucnv_io.cpp @@ -205,7 +205,7 @@ static UBool U_CALLCONV isAcceptable(void * /*context*/, const char * /*type*/, const char * /*name*/, const UDataInfo *pInfo) { - return (UBool)( + return pInfo->size>=20 && pInfo->isBigEndian==U_IS_BIG_ENDIAN && pInfo->charsetFamily==U_CHARSET_FAMILY && @@ -213,7 +213,7 @@ isAcceptable(void * /*context*/, pInfo->dataFormat[1]==0x76 && pInfo->dataFormat[2]==0x41 && pInfo->dataFormat[3]==0x6c && - pInfo->formatVersion[0]==3); + pInfo->formatVersion[0]==3; } static UBool U_CALLCONV ucnv_io_cleanup() @@ -244,8 +244,8 @@ static void U_CALLCONV initAliasData(UErrorCode &errCode) { return; } - sectionSizes = (const uint32_t *)udata_getMemory(data); - table = (const uint16_t *)sectionSizes; + sectionSizes = static_cast<const uint32_t*>(udata_getMemory(data)); + table = reinterpret_cast<const uint16_t*>(sectionSizes); tableStart = sectionSizes[0]; if (tableStart < minTocLength) { @@ -289,10 +289,10 @@ static void U_CALLCONV initAliasData(UErrorCode &errCode) { currOffset += gMainTable.taggedAliasListsSize; if (gMainTable.optionTableSize > 0 - && ((const UConverterAliasOptions *)(table + currOffset))->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT) + && reinterpret_cast<const UConverterAliasOptions*>(table + currOffset)->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT) { /* Faster table */ - gMainTable.optionTable = (const UConverterAliasOptions *)(table + currOffset); + gMainTable.optionTable = reinterpret_cast<const UConverterAliasOptions*>(table + currOffset); } else { /* Smaller table, or I can't handle this normalization mode! @@ -321,7 +321,7 @@ isAlias(const char *alias, UErrorCode *pErrorCode) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return false; } - return (UBool)(*alias!=0); + return *alias != 0; } static uint32_t getTagNumber(const char *tagname) { @@ -574,7 +574,7 @@ findConverter(const char *alias, UBool *containsOption, UErrorCode *pErrorCode) lastMid = UINT32_MAX; for (;;) { - mid = (uint32_t)((start + limit) / 2); + mid = (start + limit) / 2; if (lastMid == mid) { /* Have we moved? */ break; /* We haven't moved, and it wasn't found. */ } @@ -601,8 +601,8 @@ findConverter(const char *alias, UBool *containsOption, UErrorCode *pErrorCode) /* State whether the canonical converter name contains an option. This information is contained in this list in order to maintain backward & forward compatibility. */ if (containsOption) { - UBool containsCnvOptionInfo = (UBool)gMainTable.optionTable->containsCnvOptionInfo; - *containsOption = (UBool)((containsCnvOptionInfo + UBool containsCnvOptionInfo = static_cast<UBool>(gMainTable.optionTable->containsCnvOptionInfo); + *containsOption = static_cast<UBool>((containsCnvOptionInfo && ((gMainTable.untaggedConvArray[mid] & UCNV_CONTAINS_OPTION_BIT) != 0)) || !containsCnvOptionInfo); } @@ -939,7 +939,7 @@ static uint16_t ucnv_io_countStandards(UErrorCode *pErrorCode) { if (haveAliasData(pErrorCode)) { /* Don't include the empty list */ - return (uint16_t)(gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS); + return static_cast<uint16_t>(gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS); } return 0; @@ -1130,8 +1130,9 @@ io_compareRows(const void *context, const void *left, const void *right) { TempAliasTable *tempTable=(TempAliasTable *)context; const char *chars=tempTable->chars; - return (int32_t)uprv_strcmp(tempTable->stripForCompare(strippedLeft, chars+2*((const TempRow *)left)->strIndex), - tempTable->stripForCompare(strippedRight, chars+2*((const TempRow *)right)->strIndex)); + return static_cast<int32_t>(uprv_strcmp( + tempTable->stripForCompare(strippedLeft, chars + 2 * static_cast<const TempRow*>(left)->strIndex), + tempTable->stripForCompare(strippedRight, chars + 2 * static_cast<const TempRow*>(right)->strIndex))); } U_CAPI int32_t U_EXPORT2 diff --git a/thirdparty/icu4c/common/ucnv_lmb.cpp b/thirdparty/icu4c/common/ucnv_lmb.cpp index ab14a119ef..bbcf2d579a 100644 --- a/thirdparty/icu4c/common/ucnv_lmb.cpp +++ b/thirdparty/icu4c/common/ucnv_lmb.cpp @@ -633,7 +633,7 @@ _LMBCSOpenWorker(UConverter* _this, UErrorCode* err, ulmbcs_byte_t OptGroup) { - UConverterDataLMBCS * extraInfo = (UConverterDataLMBCS*)uprv_malloc (sizeof (UConverterDataLMBCS)); + UConverterDataLMBCS* extraInfo = static_cast<UConverterDataLMBCS*>(uprv_malloc(sizeof(UConverterDataLMBCS))); _this->extraInfo = extraInfo; if(extraInfo != nullptr) { diff --git a/thirdparty/icu4c/common/ucnv_u16.cpp b/thirdparty/icu4c/common/ucnv_u16.cpp index c3bcfef50c..a5963e1202 100644 --- a/thirdparty/icu4c/common/ucnv_u16.cpp +++ b/thirdparty/icu4c/common/ucnv_u16.cpp @@ -236,10 +236,10 @@ _UTF16BEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, /* output length bytes with overflow (length>targetCapacity>0) */ ucnv_fromUWriteBytes(cnv, overflow, length, - (char **)&target, pArgs->targetLimit, + &target, pArgs->targetLimit, &offsets, sourceIndex, pErrorCode); - targetCapacity=(uint32_t)(pArgs->targetLimit-(char *)target); + targetCapacity = static_cast<uint32_t>(pArgs->targetLimit - target); } if(U_SUCCESS(*pErrorCode) && source<pArgs->sourceLimit && targetCapacity==0) { @@ -248,7 +248,7 @@ _UTF16BEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, /* write back the updated pointers */ pArgs->source=source; - pArgs->target=(char *)target; + pArgs->target = target; pArgs->offsets=offsets; } @@ -840,7 +840,7 @@ _UTF16LEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, &target, pArgs->targetLimit, &offsets, sourceIndex, pErrorCode); - targetCapacity=(uint32_t)(pArgs->targetLimit-(char *)target); + targetCapacity = static_cast<uint32_t>(pArgs->targetLimit - target); } if(U_SUCCESS(*pErrorCode) && source<pArgs->sourceLimit && targetCapacity==0) { diff --git a/thirdparty/icu4c/common/ucnv_u8.cpp b/thirdparty/icu4c/common/ucnv_u8.cpp index cf3bb22a02..cca6e603ae 100644 --- a/thirdparty/icu4c/common/ucnv_u8.cpp +++ b/thirdparty/icu4c/common/ucnv_u8.cpp @@ -49,8 +49,8 @@ U_CFUNC void ucnv_fromUnicode_UTF8_OFFSETS_LOGIC(UConverterFromUnicodeArgs *args #define MAXIMUM_UCS2 0x0000FFFF static const uint32_t offsetsFromUTF8[5] = {0, - (uint32_t) 0x00000000, (uint32_t) 0x00003080, (uint32_t) 0x000E2080, - (uint32_t) 0x03C82080 + static_cast<uint32_t>(0x00000000), static_cast<uint32_t>(0x00003080), + static_cast<uint32_t>(0x000E2080), static_cast<uint32_t>(0x03C82080) }; static UBool hasCESU8Data(const UConverter *cnv) @@ -58,7 +58,7 @@ static UBool hasCESU8Data(const UConverter *cnv) #if UCONFIG_ONLY_HTML_CONVERSION return false; #else - return (UBool)(cnv->sharedData == &_CESU8Data); + return cnv->sharedData == &_CESU8Data; #endif } U_CDECL_BEGIN @@ -571,7 +571,7 @@ static UChar32 U_CALLCONV ucnv_getNextUChar_UTF8(UConverterToUnicodeArgs *args, return 0xffff; } - myByte = (uint8_t)*(source++); + myByte = *(source++); if (U8_IS_SINGLE(myByte)) { args->source = (const char *)source; diff --git a/thirdparty/icu4c/common/ucnvbocu.cpp b/thirdparty/icu4c/common/ucnvbocu.cpp index 3b736aa1e9..5c9bb3ac45 100644 --- a/thirdparty/icu4c/common/ucnvbocu.cpp +++ b/thirdparty/icu4c/common/ucnvbocu.cpp @@ -338,7 +338,7 @@ packDiff(int32_t diff) { */ result|=BOCU1_TRAIL_TO_BYTE(diff)<<16; - result|=((uint32_t)BOCU1_START_POS_4)<<24; + result |= static_cast<uint32_t>(BOCU1_START_POS_4) << 24; } } else { /* two- to four-byte negative differences */ @@ -405,13 +405,13 @@ _Bocu1FromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, cnv=pArgs->converter; source=pArgs->source; sourceLimit=pArgs->sourceLimit; - target=(uint8_t *)pArgs->target; - targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target); + target = reinterpret_cast<uint8_t*>(pArgs->target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target); offsets=pArgs->offsets; /* get the converter state from UConverter */ c=cnv->fromUChar32; - prev=(int32_t)cnv->fromUnicodeStatus; + prev = static_cast<int32_t>(cnv->fromUnicodeStatus); if(prev==0) { prev=BOCU1_ASCII_PREV; } @@ -428,7 +428,7 @@ _Bocu1FromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, fastSingle: /* fast loop for single-byte differences */ /* use only one loop counter variable, targetCapacity, not also source */ - diff=(int32_t)(sourceLimit-source); + diff = static_cast<int32_t>(sourceLimit - source); if(targetCapacity>diff) { targetCapacity=diff; } @@ -437,7 +437,7 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(uint8_t)c; + *target++ = static_cast<uint8_t>(c); *offsets++=nextSourceIndex++; ++source; --targetCapacity; @@ -445,7 +445,7 @@ fastSingle: diff=c-prev; if(DIFF_IS_SINGLE(diff)) { prev=BOCU1_SIMPLE_PREV(c); - *target++=(uint8_t)PACK_SINGLE_DIFF(diff); + *target++ = static_cast<uint8_t>(PACK_SINGLE_DIFF(diff)); *offsets++=nextSourceIndex++; ++source; --targetCapacity; @@ -455,7 +455,7 @@ fastSingle: } } /* restore real values */ - targetCapacity=(int32_t)((const uint8_t *)pArgs->targetLimit-target); + targetCapacity = static_cast<int32_t>(reinterpret_cast<const uint8_t*>(pArgs->targetLimit) - target); sourceIndex=nextSourceIndex; /* wrong if offsets==nullptr but does not matter */ /* regular loop for all cases */ @@ -473,7 +473,7 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(uint8_t)c; + *target++ = static_cast<uint8_t>(c); *offsets++=sourceIndex; --targetCapacity; @@ -510,7 +510,7 @@ getTrail: diff=c-prev; prev=BOCU1_PREV(c); if(DIFF_IS_SINGLE(diff)) { - *target++=(uint8_t)PACK_SINGLE_DIFF(diff); + *target++ = static_cast<uint8_t>(PACK_SINGLE_DIFF(diff)); *offsets++=sourceIndex; --targetCapacity; sourceIndex=nextSourceIndex; @@ -531,8 +531,8 @@ getTrail: NEGDIVMOD(diff, BOCU1_TRAIL_COUNT, m); diff+=BOCU1_START_NEG_2; } - *target++=(uint8_t)diff; - *target++=(uint8_t)BOCU1_TRAIL_TO_BYTE(m); + *target++ = static_cast<uint8_t>(diff); + *target++ = static_cast<uint8_t>(BOCU1_TRAIL_TO_BYTE(m)); *offsets++=sourceIndex; *offsets++=sourceIndex; targetCapacity-=2; @@ -549,18 +549,18 @@ getTrail: switch(length) { /* each branch falls through to the next one */ case 4: - *target++=(uint8_t)(diff>>24); + *target++ = static_cast<uint8_t>(diff >> 24); *offsets++=sourceIndex; U_FALLTHROUGH; case 3: - *target++=(uint8_t)(diff>>16); + *target++ = static_cast<uint8_t>(diff >> 16); *offsets++=sourceIndex; U_FALLTHROUGH; case 2: - *target++=(uint8_t)(diff>>8); + *target++ = static_cast<uint8_t>(diff >> 8); *offsets++=sourceIndex; /* case 1: handled above */ - *target++=(uint8_t)diff; + *target++ = static_cast<uint8_t>(diff); *offsets++=sourceIndex; U_FALLTHROUGH; default: @@ -584,34 +584,34 @@ getTrail: switch(length) { /* each branch falls through to the next one */ case 3: - *charErrorBuffer++=(uint8_t)(diff>>16); + *charErrorBuffer++ = static_cast<uint8_t>(diff >> 16); U_FALLTHROUGH; case 2: - *charErrorBuffer++=(uint8_t)(diff>>8); + *charErrorBuffer++ = static_cast<uint8_t>(diff >> 8); U_FALLTHROUGH; case 1: - *charErrorBuffer=(uint8_t)diff; + *charErrorBuffer = static_cast<uint8_t>(diff); U_FALLTHROUGH; default: /* will never occur */ break; } - cnv->charErrorBufferLength=(int8_t)length; + cnv->charErrorBufferLength = static_cast<int8_t>(length); /* now output what fits into the regular target */ diff>>=8*length; /* length was reduced by targetCapacity */ switch(targetCapacity) { /* each branch falls through to the next one */ case 3: - *target++=(uint8_t)(diff>>16); + *target++ = static_cast<uint8_t>(diff >> 16); *offsets++=sourceIndex; U_FALLTHROUGH; case 2: - *target++=(uint8_t)(diff>>8); + *target++ = static_cast<uint8_t>(diff >> 8); *offsets++=sourceIndex; U_FALLTHROUGH; case 1: - *target++=(uint8_t)diff; + *target++ = static_cast<uint8_t>(diff); *offsets++=sourceIndex; U_FALLTHROUGH; default: @@ -634,11 +634,11 @@ getTrail: /* set the converter state back into UConverter */ cnv->fromUChar32= c<0 ? -c : 0; - cnv->fromUnicodeStatus=(uint32_t)prev; + cnv->fromUnicodeStatus = static_cast<uint32_t>(prev); /* write back the updated pointers */ pArgs->source=source; - pArgs->target=(char *)target; + pArgs->target = reinterpret_cast<char*>(target); pArgs->offsets=offsets; } @@ -663,12 +663,12 @@ _Bocu1FromUnicode(UConverterFromUnicodeArgs *pArgs, cnv=pArgs->converter; source=pArgs->source; sourceLimit=pArgs->sourceLimit; - target=(uint8_t *)pArgs->target; - targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target); + target = reinterpret_cast<uint8_t*>(pArgs->target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target); /* get the converter state from UConverter */ c=cnv->fromUChar32; - prev=(int32_t)cnv->fromUnicodeStatus; + prev = static_cast<int32_t>(cnv->fromUnicodeStatus); if(prev==0) { prev=BOCU1_ASCII_PREV; } @@ -681,7 +681,7 @@ _Bocu1FromUnicode(UConverterFromUnicodeArgs *pArgs, fastSingle: /* fast loop for single-byte differences */ /* use only one loop counter variable, targetCapacity, not also source */ - diff=(int32_t)(sourceLimit-source); + diff = static_cast<int32_t>(sourceLimit - source); if(targetCapacity>diff) { targetCapacity=diff; } @@ -690,12 +690,12 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(uint8_t)c; + *target++ = static_cast<uint8_t>(c); } else { diff=c-prev; if(DIFF_IS_SINGLE(diff)) { prev=BOCU1_SIMPLE_PREV(c); - *target++=(uint8_t)PACK_SINGLE_DIFF(diff); + *target++ = static_cast<uint8_t>(PACK_SINGLE_DIFF(diff)); } else { break; } @@ -704,7 +704,7 @@ fastSingle: --targetCapacity; } /* restore real values */ - targetCapacity=(int32_t)((const uint8_t *)pArgs->targetLimit-target); + targetCapacity = static_cast<int32_t>(reinterpret_cast<const uint8_t*>(pArgs->targetLimit) - target); /* regular loop for all cases */ while(source<sourceLimit) { @@ -720,7 +720,7 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(uint8_t)c; + *target++ = static_cast<uint8_t>(c); --targetCapacity; continue; } @@ -753,7 +753,7 @@ getTrail: diff=c-prev; prev=BOCU1_PREV(c); if(DIFF_IS_SINGLE(diff)) { - *target++=(uint8_t)PACK_SINGLE_DIFF(diff); + *target++ = static_cast<uint8_t>(PACK_SINGLE_DIFF(diff)); --targetCapacity; if(c<0x3000) { goto fastSingle; @@ -772,8 +772,8 @@ getTrail: NEGDIVMOD(diff, BOCU1_TRAIL_COUNT, m); diff+=BOCU1_START_NEG_2; } - *target++=(uint8_t)diff; - *target++=(uint8_t)BOCU1_TRAIL_TO_BYTE(m); + *target++ = static_cast<uint8_t>(diff); + *target++ = static_cast<uint8_t>(BOCU1_TRAIL_TO_BYTE(m)); targetCapacity-=2; } else { int32_t length; /* will be 2..4 */ @@ -787,14 +787,14 @@ getTrail: switch(length) { /* each branch falls through to the next one */ case 4: - *target++=(uint8_t)(diff>>24); + *target++ = static_cast<uint8_t>(diff >> 24); U_FALLTHROUGH; case 3: - *target++=(uint8_t)(diff>>16); + *target++ = static_cast<uint8_t>(diff >> 16); /* case 2: handled above */ - *target++=(uint8_t)(diff>>8); + *target++ = static_cast<uint8_t>(diff >> 8); /* case 1: handled above */ - *target++=(uint8_t)diff; + *target++ = static_cast<uint8_t>(diff); U_FALLTHROUGH; default: /* will never occur */ @@ -816,32 +816,32 @@ getTrail: switch(length) { /* each branch falls through to the next one */ case 3: - *charErrorBuffer++=(uint8_t)(diff>>16); + *charErrorBuffer++ = static_cast<uint8_t>(diff >> 16); U_FALLTHROUGH; case 2: - *charErrorBuffer++=(uint8_t)(diff>>8); + *charErrorBuffer++ = static_cast<uint8_t>(diff >> 8); U_FALLTHROUGH; case 1: - *charErrorBuffer=(uint8_t)diff; + *charErrorBuffer = static_cast<uint8_t>(diff); U_FALLTHROUGH; default: /* will never occur */ break; } - cnv->charErrorBufferLength=(int8_t)length; + cnv->charErrorBufferLength = static_cast<int8_t>(length); /* now output what fits into the regular target */ diff>>=8*length; /* length was reduced by targetCapacity */ switch(targetCapacity) { /* each branch falls through to the next one */ case 3: - *target++=(uint8_t)(diff>>16); + *target++ = static_cast<uint8_t>(diff >> 16); U_FALLTHROUGH; case 2: - *target++=(uint8_t)(diff>>8); + *target++ = static_cast<uint8_t>(diff >> 8); U_FALLTHROUGH; case 1: - *target++=(uint8_t)diff; + *target++ = static_cast<uint8_t>(diff); U_FALLTHROUGH; default: /* will never occur */ @@ -863,11 +863,11 @@ getTrail: /* set the converter state back into UConverter */ cnv->fromUChar32= c<0 ? -c : 0; - cnv->fromUnicodeStatus=(uint32_t)prev; + cnv->fromUnicodeStatus = static_cast<uint32_t>(prev); /* write back the updated pointers */ pArgs->source=source; - pArgs->target=(char *)target; + pArgs->target = reinterpret_cast<char*>(target); } /* BOCU-1-to-Unicode conversion functions ----------------------------------- */ @@ -887,11 +887,11 @@ decodeBocu1LeadByte(int32_t b) { /* positive difference */ if(b<BOCU1_START_POS_3) { /* two bytes */ - diff=((int32_t)b-BOCU1_START_POS_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_1+1; + diff = (b - BOCU1_START_POS_2) * BOCU1_TRAIL_COUNT + BOCU1_REACH_POS_1 + 1; count=1; } else if(b<BOCU1_START_POS_4) { /* three bytes */ - diff=((int32_t)b-BOCU1_START_POS_3)*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_2+1; + diff = (b - BOCU1_START_POS_3) * BOCU1_TRAIL_COUNT * BOCU1_TRAIL_COUNT + BOCU1_REACH_POS_2 + 1; count=2; } else { /* four bytes */ @@ -902,11 +902,11 @@ decodeBocu1LeadByte(int32_t b) { /* negative difference */ if(b>=BOCU1_START_NEG_3) { /* two bytes */ - diff=((int32_t)b-BOCU1_START_NEG_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_1; + diff = (b - BOCU1_START_NEG_2) * BOCU1_TRAIL_COUNT + BOCU1_REACH_NEG_1; count=1; } else if(b>BOCU1_MIN) { /* three bytes */ - diff=((int32_t)b-BOCU1_START_NEG_3)*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_2; + diff = (b - BOCU1_START_NEG_3) * BOCU1_TRAIL_COUNT * BOCU1_TRAIL_COUNT + BOCU1_REACH_NEG_2; count=2; } else { /* four bytes */ @@ -916,7 +916,7 @@ decodeBocu1LeadByte(int32_t b) { } /* return the state for decoding the trail byte(s) */ - return ((uint32_t)diff<<2)|count; + return (static_cast<uint32_t>(diff) << 2) | count; } /** @@ -970,14 +970,14 @@ _Bocu1ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, /* set up the local pointers */ cnv=pArgs->converter; - source=(const uint8_t *)pArgs->source; - sourceLimit=(const uint8_t *)pArgs->sourceLimit; + source = reinterpret_cast<const uint8_t*>(pArgs->source); + sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit); target=pArgs->target; targetLimit=pArgs->targetLimit; offsets=pArgs->offsets; /* get the converter state from UConverter */ - prev=(int32_t)cnv->toUnicodeStatus; + prev = static_cast<int32_t>(cnv->toUnicodeStatus); if(prev==0) { prev=BOCU1_ASCII_PREV; } @@ -1000,8 +1000,8 @@ _Bocu1ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, fastSingle: /* fast loop for single-byte differences */ /* use count as the only loop counter variable */ - diff=(int32_t)(sourceLimit-source); - count=(int32_t)(pArgs->targetLimit-target); + diff = static_cast<int32_t>(sourceLimit - source); + count = static_cast<int32_t>(pArgs->targetLimit - target); if(count>diff) { count=diff; } @@ -1009,7 +1009,7 @@ fastSingle: if(BOCU1_START_NEG_2<=(c=*source) && c<BOCU1_START_POS_2) { c=prev+(c-BOCU1_MIDDLE); if(c<0x3000) { - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); *offsets++=nextSourceIndex++; prev=BOCU1_SIMPLE_PREV(c); } else { @@ -1019,7 +1019,7 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); *offsets++=nextSourceIndex++; } else { break; @@ -1043,7 +1043,7 @@ fastSingle: /* Write a code point directly from a single-byte difference. */ c=prev+(c-BOCU1_MIDDLE); if(c<0x3000) { - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); *offsets++=sourceIndex; prev=BOCU1_SIMPLE_PREV(c); sourceIndex=nextSourceIndex; @@ -1057,22 +1057,22 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); *offsets++=sourceIndex; sourceIndex=nextSourceIndex; continue; } else if(BOCU1_START_NEG_3<=c && c<BOCU1_START_POS_3 && source<sourceLimit) { /* Optimize two-byte case. */ if(c>=BOCU1_MIDDLE) { - diff=((int32_t)c-BOCU1_START_POS_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_1+1; + diff = (c - BOCU1_START_POS_2) * BOCU1_TRAIL_COUNT + BOCU1_REACH_POS_1 + 1; } else { - diff=((int32_t)c-BOCU1_START_NEG_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_1; + diff = (c - BOCU1_START_NEG_2) * BOCU1_TRAIL_COUNT + BOCU1_REACH_NEG_1; } /* trail byte */ ++nextSourceIndex; c=decodeBocu1TrailByte(1, *source++); - if(c<0 || (uint32_t)(c=prev+diff+c)>0x10ffff) { + if (c < 0 || static_cast<uint32_t>(c = prev + diff + c) > 0x10ffff) { bytes[0]=source[-2]; bytes[1]=source[-1]; byteIndex=2; @@ -1090,7 +1090,7 @@ fastSingle: * with the partial difference value from the lead byte and * with the number of trail bytes. */ - bytes[0]=(uint8_t)c; + bytes[0] = static_cast<uint8_t>(c); byteIndex=1; diff=decodeBocu1LeadByte(c); @@ -1116,7 +1116,7 @@ getTrail: /* final trail byte, deliver a code point */ byteIndex=0; c=prev+diff; - if((uint32_t)c>0x10ffff) { + if (static_cast<uint32_t>(c) > 0x10ffff) { *pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop; } @@ -1128,7 +1128,7 @@ getTrail: /* calculate the next prev and output c */ prev=BOCU1_PREV(c); if(c<=0xffff) { - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); *offsets++=sourceIndex; } else { /* output surrogate pair */ @@ -1156,13 +1156,13 @@ endloop: cnv->mode=0; } else { /* set the converter state back into UConverter */ - cnv->toUnicodeStatus=(uint32_t)prev; - cnv->mode=(int32_t)((uint32_t)diff<<2)|count; + cnv->toUnicodeStatus = static_cast<uint32_t>(prev); + cnv->mode = static_cast<int32_t>(static_cast<uint32_t>(diff) << 2) | count; } cnv->toULength=byteIndex; /* write back the updated pointers */ - pArgs->source=(const char *)source; + pArgs->source = reinterpret_cast<const char*>(source); pArgs->target=target; pArgs->offsets=offsets; } @@ -1189,13 +1189,13 @@ _Bocu1ToUnicode(UConverterToUnicodeArgs *pArgs, /* set up the local pointers */ cnv=pArgs->converter; - source=(const uint8_t *)pArgs->source; - sourceLimit=(const uint8_t *)pArgs->sourceLimit; + source = reinterpret_cast<const uint8_t*>(pArgs->source); + sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit); target=pArgs->target; targetLimit=pArgs->targetLimit; /* get the converter state from UConverter */ - prev=(int32_t)cnv->toUnicodeStatus; + prev = static_cast<int32_t>(cnv->toUnicodeStatus); if(prev==0) { prev=BOCU1_ASCII_PREV; } @@ -1214,8 +1214,8 @@ _Bocu1ToUnicode(UConverterToUnicodeArgs *pArgs, fastSingle: /* fast loop for single-byte differences */ /* use count as the only loop counter variable */ - diff=(int32_t)(sourceLimit-source); - count=(int32_t)(pArgs->targetLimit-target); + diff = static_cast<int32_t>(sourceLimit - source); + count = static_cast<int32_t>(pArgs->targetLimit - target); if(count>diff) { count=diff; } @@ -1223,7 +1223,7 @@ fastSingle: if(BOCU1_START_NEG_2<=(c=*source) && c<BOCU1_START_POS_2) { c=prev+(c-BOCU1_MIDDLE); if(c<0x3000) { - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); prev=BOCU1_SIMPLE_PREV(c); } else { break; @@ -1232,7 +1232,7 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); } else { break; } @@ -1253,7 +1253,7 @@ fastSingle: /* Write a code point directly from a single-byte difference. */ c=prev+(c-BOCU1_MIDDLE); if(c<0x3000) { - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); prev=BOCU1_SIMPLE_PREV(c); goto fastSingle; } @@ -1265,19 +1265,19 @@ fastSingle: if(c!=0x20) { prev=BOCU1_ASCII_PREV; } - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); continue; } else if(BOCU1_START_NEG_3<=c && c<BOCU1_START_POS_3 && source<sourceLimit) { /* Optimize two-byte case. */ if(c>=BOCU1_MIDDLE) { - diff=((int32_t)c-BOCU1_START_POS_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_1+1; + diff = (c - BOCU1_START_POS_2) * BOCU1_TRAIL_COUNT + BOCU1_REACH_POS_1 + 1; } else { - diff=((int32_t)c-BOCU1_START_NEG_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_1; + diff = (c - BOCU1_START_NEG_2) * BOCU1_TRAIL_COUNT + BOCU1_REACH_NEG_1; } /* trail byte */ c=decodeBocu1TrailByte(1, *source++); - if(c<0 || (uint32_t)(c=prev+diff+c)>0x10ffff) { + if (c < 0 || static_cast<uint32_t>(c = prev + diff + c) > 0x10ffff) { bytes[0]=source[-2]; bytes[1]=source[-1]; byteIndex=2; @@ -1294,7 +1294,7 @@ fastSingle: * with the partial difference value from the lead byte and * with the number of trail bytes. */ - bytes[0]=(uint8_t)c; + bytes[0] = static_cast<uint8_t>(c); byteIndex=1; diff=decodeBocu1LeadByte(c); @@ -1319,7 +1319,7 @@ getTrail: /* final trail byte, deliver a code point */ byteIndex=0; c=prev+diff; - if((uint32_t)c>0x10ffff) { + if (static_cast<uint32_t>(c) > 0x10ffff) { *pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop; } @@ -1331,7 +1331,7 @@ getTrail: /* calculate the next prev and output c */ prev=BOCU1_PREV(c); if(c<=0xffff) { - *target++=(char16_t)c; + *target++ = static_cast<char16_t>(c); } else { /* output surrogate pair */ *target++=U16_LEAD(c); @@ -1354,13 +1354,13 @@ endloop: cnv->mode=0; } else { /* set the converter state back into UConverter */ - cnv->toUnicodeStatus=(uint32_t)prev; - cnv->mode=((uint32_t)diff<<2)|count; + cnv->toUnicodeStatus = static_cast<uint32_t>(prev); + cnv->mode = (static_cast<uint32_t>(diff) << 2) | count; } cnv->toULength=byteIndex; /* write back the updated pointers */ - pArgs->source=(const char *)source; + pArgs->source = reinterpret_cast<const char*>(source); pArgs->target=target; } diff --git a/thirdparty/icu4c/common/ucnvhz.cpp b/thirdparty/icu4c/common/ucnvhz.cpp index fa0f2b40ea..aea5da65c1 100644 --- a/thirdparty/icu4c/common/ucnvhz.cpp +++ b/thirdparty/icu4c/common/ucnvhz.cpp @@ -345,7 +345,7 @@ UConverter_fromUnicode_HZ_OFFSETS_LOGIC (UConverterFromUnicodeArgs * args, uint32_t targetUniChar = 0x0000; UChar32 mySourceChar = 0x0000; UConverterDataHZ *myConverterData=(UConverterDataHZ*)args->converter->extraInfo; - UBool isTargetUCharDBCS = (UBool) myConverterData->isTargetUCharDBCS; + UBool isTargetUCharDBCS = myConverterData->isTargetUCharDBCS; UBool oldIsTargetUCharDBCS; int len =0; const char* escSeq=nullptr; @@ -363,7 +363,7 @@ UConverter_fromUnicode_HZ_OFFSETS_LOGIC (UConverterFromUnicodeArgs * args, targetUniChar = missingCharMarker; if (myTargetIndex < targetLength){ - mySourceChar = (char16_t) mySource[mySourceIndex++]; + mySourceChar = mySource[mySourceIndex++]; oldIsTargetUCharDBCS = isTargetUCharDBCS; @@ -389,7 +389,7 @@ UConverter_fromUnicode_HZ_OFFSETS_LOGIC (UConverterFromUnicodeArgs * args, } } if (targetUniChar != missingCharMarker){ - myConverterData->isTargetUCharDBCS = isTargetUCharDBCS = (UBool)(targetUniChar>0x00FF); + myConverterData->isTargetUCharDBCS = isTargetUCharDBCS = targetUniChar > 0x00FF; if(oldIsTargetUCharDBCS != isTargetUCharDBCS || !myConverterData->isEscapeAppended ){ /*Shifting from a double byte to single byte mode*/ if(!isTargetUCharDBCS){ diff --git a/thirdparty/icu4c/common/ucnvisci.cpp b/thirdparty/icu4c/common/ucnvisci.cpp index c14dbaa08c..c5f5832dcf 100644 --- a/thirdparty/icu4c/common/ucnvisci.cpp +++ b/thirdparty/icu4c/common/ucnvisci.cpp @@ -174,7 +174,7 @@ isPNJConsonant(UChar32 c) { if (c < 0xa00 || 0xa50 <= c) { return false; } else { - return (UBool)(pnjMap[c - 0xa00] & 1); + return pnjMap[c - 0xa00] & 1; } } @@ -183,7 +183,7 @@ isPNJBindiTippi(UChar32 c) { if (c < 0xa00 || 0xa50 <= c) { return false; } else { - return (UBool)(pnjMap[c - 0xa00] >> 1); + return pnjMap[c - 0xa00] >> 1; } } U_CDECL_BEGIN @@ -1484,7 +1484,7 @@ UConverter_toUnicode_ISCII_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, UErrorCo */ *err = U_INVALID_CHAR_FOUND; CALLBACK: - args->converter->toUBytes[0] = (uint8_t) sourceChar; + args->converter->toUBytes[0] = sourceChar; args->converter->toULength = 1; break; } diff --git a/thirdparty/icu4c/common/ucnvlat1.cpp b/thirdparty/icu4c/common/ucnvlat1.cpp index 0920688526..09473ef16c 100644 --- a/thirdparty/icu4c/common/ucnvlat1.cpp +++ b/thirdparty/icu4c/common/ucnvlat1.cpp @@ -381,7 +381,7 @@ ucnv_Latin1FromUTF8(UConverterFromUnicodeArgs *pFromUArgs, b=*source++; if(U8_IS_SINGLE(b)) { /* convert ASCII */ - *target++=(uint8_t)b; + *target++ = b; --targetCapacity; } else if( /* handle U+0080..U+00FF inline */ b>=0xc2 && b<=0xc3 && diff --git a/thirdparty/icu4c/common/ucnvmbcs.cpp b/thirdparty/icu4c/common/ucnvmbcs.cpp index d760603980..f5507043bf 100644 --- a/thirdparty/icu4c/common/ucnvmbcs.cpp +++ b/thirdparty/icu4c/common/ucnvmbcs.cpp @@ -665,7 +665,7 @@ enumToU(UConverterMBCSTable *mbcsTable, int8_t stateProps[], if(!enumToU( mbcsTable, stateProps, nextState, offset+MBCS_ENTRY_TRANSITION_OFFSET(entry), - value|(uint32_t)b, + value | static_cast<uint32_t>(b), callback, context, pErrorCode)) { return false; @@ -683,7 +683,7 @@ enumToU(UConverterMBCSTable *mbcsTable, int8_t stateProps[], action=MBCS_ENTRY_FINAL_ACTION(entry); if(action==MBCS_STATE_VALID_DIRECT_16) { /* output BMP code point */ - c=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + c = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); } else if(action==MBCS_STATE_VALID_16) { int32_t finalOffset=offset+MBCS_ENTRY_FINAL_VALUE_16(entry); c=unicodeCodeUnits[finalOffset]; @@ -708,7 +708,7 @@ enumToU(UConverterMBCSTable *mbcsTable, int8_t stateProps[], } } else if(action==MBCS_STATE_VALID_DIRECT_20) { /* output supplementary code point */ - c=(UChar32)(MBCS_ENTRY_FINAL_VALUE(entry)+0x10000); + c = static_cast<UChar32>(MBCS_ENTRY_FINAL_VALUE(entry) + 0x10000); } else { c=U_SENTINEL; } @@ -718,7 +718,7 @@ enumToU(UConverterMBCSTable *mbcsTable, int8_t stateProps[], } if(((++b)&0x1f)==0) { if(anyCodePoints>=0) { - if(!callback(context, value|(uint32_t)(b-0x20), codePoints)) { + if (!callback(context, value | static_cast<uint32_t>(b - 0x20), codePoints)) { return false; } anyCodePoints=-1; @@ -760,7 +760,7 @@ getStateProp(const int32_t (*stateTable)[256], int8_t stateProps[], int state) { return stateProps[state]; } } - stateProps[state]|=(int8_t)((min>>5)<<3); + stateProps[state] |= static_cast<int8_t>((min >> 5) << 3); /* find last non-ignorable state */ for(max=0xff; min<max; --max) { @@ -777,7 +777,7 @@ getStateProp(const int32_t (*stateTable)[256], int8_t stateProps[], int state) { break; } } - stateProps[state]|=(int8_t)(max>>5); + stateProps[state] |= static_cast<int8_t>(max >> 5); /* recurse further and collect direct-state information */ while(min<=max) { @@ -924,7 +924,7 @@ ucnv_MBCSGetFilteredUnicodeSetForUnicode(const UConverterSharedData *sharedData, bytes=mbcsTable->fromUnicodeBytes; - useFallback=(UBool)(which==UCNV_ROUNDTRIP_AND_FALLBACK_SET); + useFallback = which == UCNV_ROUNDTRIP_AND_FALLBACK_SET; switch(mbcsTable->outputType) { case MBCS_OUTPUT_3: @@ -1117,7 +1117,7 @@ _extFromU(UConverter *cnv, const UConverterSharedData *sharedData, ucnv_extInitialMatchFromU( cnv, cx, cp, source, sourceLimit, - (char **)target, (char *)targetLimit, + reinterpret_cast<char**>(target), reinterpret_cast<const char*>(targetLimit), offsets, sourceIndex, flush, pErrorCode) @@ -1132,7 +1132,7 @@ _extFromU(UConverter *cnv, const UConverterSharedData *sharedData, range=gb18030Ranges[0]; for(i=0; i<UPRV_LENGTHOF(gb18030Ranges); range+=4, ++i) { - if(range[0]<=(uint32_t)cp && (uint32_t)cp<=range[1]) { + if (range[0] <= static_cast<uint32_t>(cp) && static_cast<uint32_t>(cp) <= range[1]) { /* found the Unicode code point, output the four-byte sequence for it */ uint32_t linear; char bytes[4]; @@ -1141,17 +1141,17 @@ _extFromU(UConverter *cnv, const UConverterSharedData *sharedData, linear=range[2]-LINEAR_18030_BASE; /* add the offset from the beginning of the range */ - linear+=((uint32_t)cp-range[0]); + linear += (static_cast<uint32_t>(cp) - range[0]); /* turn this into a four-byte sequence */ - bytes[3]=(char)(0x30+linear%10); linear/=10; - bytes[2]=(char)(0x81+linear%126); linear/=126; - bytes[1]=(char)(0x30+linear%10); linear/=10; - bytes[0]=(char)(0x81+linear); + bytes[3] = static_cast<char>(0x30 + linear % 10); linear /= 10; + bytes[2] = static_cast<char>(0x81 + linear % 126); linear /= 126; + bytes[1] = static_cast<char>(0x30 + linear % 10); linear /= 10; + bytes[0] = static_cast<char>(0x81 + linear); /* output this sequence */ ucnv_fromUWriteBytes(cnv, - bytes, 4, (char **)target, (char *)targetLimit, + bytes, 4, reinterpret_cast<char**>(target), reinterpret_cast<const char*>(targetLimit), offsets, sourceIndex, pErrorCode); return 0; } @@ -1181,7 +1181,7 @@ _extToU(UConverter *cnv, const UConverterSharedData *sharedData, if( (cx=sharedData->mbcs.extIndexes)!=nullptr && ucnv_extInitialMatchToU( cnv, cx, - length, (const char **)source, (const char *)sourceLimit, + length, reinterpret_cast<const char**>(source), reinterpret_cast<const char*>(sourceLimit), target, targetLimit, offsets, sourceIndex, flush, @@ -1273,7 +1273,7 @@ _EBCDICSwapLFNL(UConverterSharedData *sharedData, UErrorCode *pErrorCode) { table=mbcsTable->fromUnicodeTable; bytes=mbcsTable->fromUnicodeBytes; - results=(const uint16_t *)bytes; + results = reinterpret_cast<const uint16_t*>(bytes); /* * Check that this is an EBCDIC table with SBCS portion - @@ -1348,21 +1348,21 @@ _EBCDICSwapLFNL(UConverterSharedData *sharedData, UErrorCode *pErrorCode) { mbcsTable->countStates*1024+ sizeofFromUBytes+ UCNV_MAX_CONVERTER_NAME_LENGTH+20; - p=(uint8_t *)uprv_malloc(size); + p = static_cast<uint8_t*>(uprv_malloc(size)); if(p==nullptr) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return false; } /* copy and modify the to-Unicode state table */ - newStateTable=(int32_t (*)[256])p; + newStateTable = reinterpret_cast<int32_t(*)[256]>(p); uprv_memcpy(newStateTable, mbcsTable->stateTable, mbcsTable->countStates*1024); newStateTable[0][EBCDIC_LF]=MBCS_ENTRY_FINAL(0, MBCS_STATE_VALID_DIRECT_16, U_NL); newStateTable[0][EBCDIC_NL]=MBCS_ENTRY_FINAL(0, MBCS_STATE_VALID_DIRECT_16, U_LF); /* copy and modify the from-Unicode result table */ - newResults=(uint16_t *)newStateTable[mbcsTable->countStates]; + newResults = reinterpret_cast<uint16_t*>(newStateTable[mbcsTable->countStates]); uprv_memcpy(newResults, bytes, sizeofFromUBytes); /* conveniently, the table access macros work on the left side of expressions */ @@ -1378,7 +1378,7 @@ _EBCDICSwapLFNL(UConverterSharedData *sharedData, UErrorCode *pErrorCode) { } /* set the canonical converter name */ - name=(char *)newResults+sizeofFromUBytes; + name = reinterpret_cast<char*>(newResults) + sizeofFromUBytes; uprv_strcpy(name, sharedData->staticData->name); uprv_strcat(name, UCNV_SWAP_LFNL_OPTION_STRING); @@ -1386,7 +1386,7 @@ _EBCDICSwapLFNL(UConverterSharedData *sharedData, UErrorCode *pErrorCode) { icu::umtx_lock(nullptr); if(mbcsTable->swapLFNLStateTable==nullptr) { mbcsTable->swapLFNLStateTable=newStateTable; - mbcsTable->swapLFNLFromUnicodeBytes=(uint8_t *)newResults; + mbcsTable->swapLFNLFromUnicodeBytes = reinterpret_cast<uint8_t*>(newResults); mbcsTable->swapLFNLName=name; newStateTable=nullptr; @@ -1413,7 +1413,7 @@ writeStage3Roundtrip(const void *context, uint32_t value, UChar32 codePoints[32] int32_t i, st3; table=mbcsTable->fromUnicodeTable; - bytes=(uint8_t *)mbcsTable->fromUnicodeBytes; + bytes = const_cast<uint8_t*>(mbcsTable->fromUnicodeBytes); /* for EUC outputTypes, modify the value like genmbcs.c's transformEUC() */ switch(mbcsTable->outputType) { @@ -1454,23 +1454,23 @@ writeStage3Roundtrip(const void *context, uint32_t value, UChar32 codePoints[32] /* locate the stage 2 & 3 data */ stage2=((uint32_t *)table)+table[c>>10]+((c>>4)&0x3f); p=bytes; - st3=(int32_t)(uint16_t)*stage2*16+(c&0xf); + st3 = static_cast<int32_t>(static_cast<uint16_t>(*stage2)) * 16 + (c & 0xf); /* write the codepage bytes into stage 3 */ switch(mbcsTable->outputType) { case MBCS_OUTPUT_3: case MBCS_OUTPUT_4_EUC: p+=st3*3; - p[0]=(uint8_t)(value>>16); - p[1]=(uint8_t)(value>>8); - p[2]=(uint8_t)value; + p[0] = static_cast<uint8_t>(value >> 16); + p[1] = static_cast<uint8_t>(value >> 8); + p[2] = static_cast<uint8_t>(value); break; case MBCS_OUTPUT_4: - ((uint32_t *)p)[st3]=value; + reinterpret_cast<uint32_t*>(p)[st3] = value; break; default: /* 2 bytes per character */ - ((uint16_t *)p)[st3]=(uint16_t)value; + reinterpret_cast<uint16_t*>(p)[st3] = static_cast<uint16_t>(value); break; } @@ -1488,7 +1488,7 @@ reconstituteData(UConverterMBCSTable *mbcsTable, uint16_t *stage1; uint32_t *stage2; uint32_t dataLength=stage1Length*2+fullStage2Length*4+mbcsTable->fromUBytesLength; - mbcsTable->reconstitutedData=(uint8_t *)uprv_malloc(dataLength); + mbcsTable->reconstitutedData = static_cast<uint8_t*>(uprv_malloc(dataLength)); if(mbcsTable->reconstitutedData==nullptr) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return; @@ -1496,29 +1496,29 @@ reconstituteData(UConverterMBCSTable *mbcsTable, uprv_memset(mbcsTable->reconstitutedData, 0, dataLength); /* copy existing data and reroute the pointers */ - stage1=(uint16_t *)mbcsTable->reconstitutedData; + stage1 = reinterpret_cast<uint16_t*>(mbcsTable->reconstitutedData); uprv_memcpy(stage1, mbcsTable->fromUnicodeTable, stage1Length*2); - stage2=(uint32_t *)(stage1+stage1Length); + stage2 = reinterpret_cast<uint32_t*>(stage1 + stage1Length); uprv_memcpy(stage2+(fullStage2Length-stage2Length), mbcsTable->fromUnicodeTable+stage1Length, stage2Length*4); mbcsTable->fromUnicodeTable=stage1; - mbcsTable->fromUnicodeBytes=(uint8_t *)(stage2+fullStage2Length); + mbcsTable->fromUnicodeBytes = reinterpret_cast<uint8_t*>(stage2 + fullStage2Length); /* indexes into stage 2 count from the bottom of the fromUnicodeTable */ - stage2=(uint32_t *)stage1; + stage2 = reinterpret_cast<uint32_t*>(stage1); /* reconstitute the initial part of stage 2 from the mbcsIndex */ { - int32_t stageUTF8Length=((int32_t)mbcsTable->maxFastUChar+1)>>6; + int32_t stageUTF8Length = (static_cast<int32_t>(mbcsTable->maxFastUChar) + 1) >> 6; int32_t stageUTF8Index=0; int32_t st1, st2, st3, i; for(st1=0; stageUTF8Index<stageUTF8Length; ++st1) { st2=stage1[st1]; - if(st2!=(int32_t)stage1Length/2) { + if (st2 != static_cast<int32_t>(stage1Length) / 2) { /* each stage 2 block has 64 entries corresponding to 16 entries in the mbcsIndex */ for(i=0; i<16; ++i) { st3=mbcsTable->mbcsIndex[stageUTF8Index++]; @@ -1568,13 +1568,13 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, } else if(header->version[0]==5 && header->version[1]>=3 && (header->options&MBCS_OPT_UNKNOWN_INCOMPATIBLE_MASK)==0) { headerLength=header->options&MBCS_OPT_LENGTH_MASK; - noFromU=(UBool)((header->options&MBCS_OPT_NO_FROM_U)!=0); + noFromU = static_cast<UBool>((header->options & MBCS_OPT_NO_FROM_U) != 0); } else { *pErrorCode=U_INVALID_TABLE_FORMAT; return; } - mbcsTable->outputType=(uint8_t)header->flags; + mbcsTable->outputType = static_cast<uint8_t>(header->flags); if(noFromU && mbcsTable->outputType==MBCS_OUTPUT_1) { *pErrorCode=U_INVALID_TABLE_FORMAT; return; @@ -1583,7 +1583,7 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, /* extension data, header version 4.2 and higher */ offset=header->flags>>8; if(offset!=0) { - mbcsTable->extIndexes=(const int32_t *)(raw+offset); + mbcsTable->extIndexes = reinterpret_cast<const int32_t*>(raw + offset); } if(mbcsTable->outputType==MBCS_OUTPUT_EXT_ONLY) { @@ -1606,7 +1606,7 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, } /* load the base table */ - baseName=(const char *)header+headerLength*4; + baseName = reinterpret_cast<const char*>(header) + headerLength * 4; if(0==uprv_strcmp(baseName, sharedData->staticData->name)) { /* forbid loading this same extension-only file */ *pErrorCode=U_INVALID_TABLE_FORMAT; @@ -1685,7 +1685,7 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, MBCS_ENTRY_FINAL_ACTION(entry)==MBCS_STATE_CHANGE_ONLY && MBCS_ENTRY_FINAL_STATE(entry)!=0 ) { - mbcsTable->dbcsOnlyState=(uint8_t)MBCS_ENTRY_FINAL_STATE(entry); + mbcsTable->dbcsOnlyState = static_cast<uint8_t>(MBCS_ENTRY_FINAL_STATE(entry)); mbcsTable->outputType=MBCS_OUTPUT_DBCS_ONLY; } @@ -1702,7 +1702,7 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, /* allocate a new state table and copy the base state table contents */ count=mbcsTable->countStates; - newStateTable=(int32_t (*)[256])uprv_malloc((count+1)*1024); + newStateTable = static_cast<int32_t(*)[256]>(uprv_malloc((count + 1) * 1024)); if(newStateTable==nullptr) { ucnv_unload(baseSharedData); *pErrorCode=U_MEMORY_ALLOCATION_ERROR; @@ -1725,7 +1725,7 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, state[i]=MBCS_ENTRY_FINAL(0, MBCS_STATE_ILLEGAL, 0); } mbcsTable->stateTable=(const int32_t (*)[256])newStateTable; - mbcsTable->countStates=(uint8_t)(count+1); + mbcsTable->countStates = static_cast<uint8_t>(count + 1); mbcsTable->stateTableOwned=true; mbcsTable->outputType=MBCS_OUTPUT_DBCS_ONLY; @@ -1766,14 +1766,14 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, return; } - mbcsTable->countStates=(uint8_t)header->countStates; + mbcsTable->countStates = static_cast<uint8_t>(header->countStates); mbcsTable->countToUFallbacks=header->countToUFallbacks; - mbcsTable->stateTable=(const int32_t (*)[256])(raw+headerLength*4); - mbcsTable->toUFallbacks=(const _MBCSToUFallback *)(mbcsTable->stateTable+header->countStates); - mbcsTable->unicodeCodeUnits=(const uint16_t *)(raw+header->offsetToUCodeUnits); + mbcsTable->stateTable = reinterpret_cast<const int32_t(*)[256]>(raw + headerLength * 4); + mbcsTable->toUFallbacks = reinterpret_cast<const _MBCSToUFallback*>(mbcsTable->stateTable + header->countStates); + mbcsTable->unicodeCodeUnits = reinterpret_cast<const uint16_t*>(raw + header->offsetToUCodeUnits); - mbcsTable->fromUnicodeTable=(const uint16_t *)(raw+header->offsetFromUTable); - mbcsTable->fromUnicodeBytes=(const uint8_t *)(raw+header->offsetFromUBytes); + mbcsTable->fromUnicodeTable = reinterpret_cast<const uint16_t*>(raw + header->offsetFromUTable); + mbcsTable->fromUnicodeBytes = raw + header->offsetFromUBytes; mbcsTable->fromUBytesLength=header->fromUBytesLength; /* @@ -1784,7 +1784,7 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, udata_getInfo((UDataMemory *)sharedData->dataMemory, &info); if(info.formatVersion[0]>6 || (info.formatVersion[0]==6 && info.formatVersion[1]>=1)) { /* mask off possible future extensions to be safe */ - mbcsTable->unicodeMask=(uint8_t)(sharedData->staticData->unicodeMask&3); + mbcsTable->unicodeMask = static_cast<uint8_t>(sharedData->staticData->unicodeMask & 3); } else { /* for older versions, assume worst case: contains anything possible (prevent over-optimizations) */ mbcsTable->unicodeMask=UCNV_HAS_SUPPLEMENTARY|UCNV_HAS_SURROGATES; @@ -1825,10 +1825,10 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, * The .cnv file is prebuilt with an additional stage table with indexes * to each block. */ - mbcsTable->mbcsIndex=(const uint16_t *) - (mbcsTable->fromUnicodeBytes+ + mbcsTable->mbcsIndex = reinterpret_cast<const uint16_t*>( + mbcsTable->fromUnicodeBytes + (noFromU ? 0 : mbcsTable->fromUBytesLength)); - mbcsTable->maxFastUChar=(((char16_t)header->version[2])<<8)|0xff; + mbcsTable->maxFastUChar = (static_cast<char16_t>(header->version[2]) << 8) | 0xff; } } @@ -1839,7 +1839,7 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData, for(i=0; i<0x80; ++i) { if(mbcsTable->stateTable[0][i]!=MBCS_ENTRY_FINAL(0, MBCS_STATE_VALID_DIRECT_16, i)) { - asciiRoundtrips&=~((uint32_t)1<<(i>>2)); + asciiRoundtrips &= ~(static_cast<uint32_t>(1) << (i >> 2)); } } mbcsTable->asciiRoundtrips=asciiRoundtrips; @@ -1958,7 +1958,7 @@ ucnv_MBCSOpen(UConverter *cnv, extIndexes=mbcsTable->extIndexes; if(extIndexes!=nullptr) { - maxBytesPerUChar=(int8_t)UCNV_GET_MAX_BYTES_PER_UCHAR(extIndexes); + maxBytesPerUChar = static_cast<int8_t>(UCNV_GET_MAX_BYTES_PER_UCHAR(extIndexes)); if(outputType==MBCS_OUTPUT_2_SISO) { ++maxBytesPerUChar; /* SO + multiple DBCS */ } @@ -2048,8 +2048,8 @@ ucnv_MBCSSingleToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, /* set up the local pointers */ cnv=pArgs->converter; - source=(const uint8_t *)pArgs->source; - sourceLimit=(const uint8_t *)pArgs->sourceLimit; + source = reinterpret_cast<const uint8_t*>(pArgs->source); + sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit); target=pArgs->target; targetLimit=pArgs->targetLimit; offsets=pArgs->offsets; @@ -2085,7 +2085,7 @@ ucnv_MBCSSingleToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, /* test the most common case first */ if(MBCS_ENTRY_FINAL_IS_VALID_DIRECT_16(entry)) { /* output BMP code point */ - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); if(offsets!=nullptr) { *offsets++=sourceIndex; } @@ -2099,17 +2099,17 @@ ucnv_MBCSSingleToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, * An if-else-if chain provides more reliable performance for * the most common cases compared to a switch. */ - action=(uint8_t)(MBCS_ENTRY_FINAL_ACTION(entry)); + action = static_cast<uint8_t>(MBCS_ENTRY_FINAL_ACTION(entry)); if(action==MBCS_STATE_VALID_DIRECT_20 || (action==MBCS_STATE_FALLBACK_DIRECT_20 && UCNV_TO_U_USE_FALLBACK(cnv)) ) { entry=MBCS_ENTRY_FINAL_VALUE(entry); /* output surrogate pair */ - *target++=(char16_t)(0xd800|(char16_t)(entry>>10)); + *target++ = static_cast<char16_t>(0xd800 | static_cast<char16_t>(entry >> 10)); if(offsets!=nullptr) { *offsets++=sourceIndex; } - c=(char16_t)(0xdc00|(char16_t)(entry&0x3ff)); + c = static_cast<char16_t>(0xdc00 | static_cast<char16_t>(entry & 0x3ff)); if(target<targetLimit) { *target++=c; if(offsets!=nullptr) { @@ -2128,7 +2128,7 @@ ucnv_MBCSSingleToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, } else if(action==MBCS_STATE_FALLBACK_DIRECT_16) { if(UCNV_TO_U_USE_FALLBACK(cnv)) { /* output BMP code point */ - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); if(offsets!=nullptr) { *offsets++=sourceIndex; } @@ -2152,7 +2152,7 @@ ucnv_MBCSSingleToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, break; } else /* unassigned sequences indicated with byteIndex>0 */ { /* try an extension mapping */ - pArgs->source=(const char *)source; + pArgs->source = reinterpret_cast<const char*>(source); cnv->toUBytes[0]=*(source-1); cnv->toULength=_extToU(cnv, cnv->sharedData, 1, &source, sourceLimit, @@ -2160,7 +2160,7 @@ ucnv_MBCSSingleToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, &offsets, sourceIndex, pArgs->flush, pErrorCode); - sourceIndex+=1+(int32_t)(source-(const uint8_t *)pArgs->source); + sourceIndex += 1 + static_cast<int32_t>(source - reinterpret_cast<const uint8_t*>(pArgs->source)); if(U_FAILURE(*pErrorCode)) { /* not mappable or buffer overflow */ @@ -2170,7 +2170,7 @@ ucnv_MBCSSingleToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, } /* write back the updated pointers */ - pArgs->source=(const char *)source; + pArgs->source = reinterpret_cast<const char*>(source); pArgs->target=target; pArgs->offsets=offsets; } @@ -2199,10 +2199,10 @@ ucnv_MBCSSingleToBMPWithOffsets(UConverterToUnicodeArgs *pArgs, /* set up the local pointers */ cnv=pArgs->converter; - source=(const uint8_t *)pArgs->source; - sourceLimit=(const uint8_t *)pArgs->sourceLimit; + source = reinterpret_cast<const uint8_t*>(pArgs->source); + sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit); target=pArgs->target; - targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target); offsets=pArgs->offsets; if((cnv->options&UCNV_OPTION_SWAP_LFNL)!=0) { @@ -2219,7 +2219,7 @@ ucnv_MBCSSingleToBMPWithOffsets(UConverterToUnicodeArgs *pArgs, * since the conversion here is 1:1 char16_t:uint8_t, we need only one counter * for the minimum of the sourceLength and targetCapacity */ - length=(int32_t)(sourceLimit-source); + length = static_cast<int32_t>(sourceLimit - source); if(length<targetCapacity) { targetCapacity=length; } @@ -2234,37 +2234,37 @@ unrolled: loops=count=targetCapacity>>4; do { oredEntries=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); oredEntries|=entry=stateTable[0][*source++]; - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); /* were all 16 entries really valid? */ if(!MBCS_ENTRY_FINAL_IS_VALID_DIRECT_16(oredEntries)) { @@ -2310,7 +2310,7 @@ unrolled: /* test the most common case first */ if(MBCS_ENTRY_FINAL_IS_VALID_DIRECT_16(entry)) { /* output BMP code point */ - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); --targetCapacity; continue; } @@ -2319,11 +2319,11 @@ unrolled: * An if-else-if chain provides more reliable performance for * the most common cases compared to a switch. */ - action=(uint8_t)(MBCS_ENTRY_FINAL_ACTION(entry)); + action = static_cast<uint8_t>(MBCS_ENTRY_FINAL_ACTION(entry)); if(action==MBCS_STATE_FALLBACK_DIRECT_16) { if(UCNV_TO_U_USE_FALLBACK(cnv)) { /* output BMP code point */ - *target++=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + *target++ = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); --targetCapacity; continue; } @@ -2339,7 +2339,7 @@ unrolled: /* set offsets since the start or the last extension */ if(offsets!=nullptr) { - int32_t count=(int32_t)(source-lastSource); + int32_t count = static_cast<int32_t>(source - lastSource); /* predecrement: do not set the offset for the callback-causing character */ while(--count>0) { @@ -2361,7 +2361,7 @@ unrolled: &offsets, sourceIndex, pArgs->flush, pErrorCode); - sourceIndex+=1+(int32_t)(source-lastSource); + sourceIndex += 1 + static_cast<int32_t>(source - lastSource); if(U_FAILURE(*pErrorCode)) { /* not mappable or buffer overflow */ @@ -2369,8 +2369,8 @@ unrolled: } /* recalculate the targetCapacity after an extension mapping */ - targetCapacity=(int32_t)(pArgs->targetLimit-target); - length=(int32_t)(sourceLimit-source); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - target); + length = static_cast<int32_t>(sourceLimit - source); if(length<targetCapacity) { targetCapacity=length; } @@ -2397,7 +2397,7 @@ unrolled: } /* write back the updated pointers */ - pArgs->source=(const char *)source; + pArgs->source = reinterpret_cast<const char*>(source); pArgs->target=target; pArgs->offsets=offsets; } @@ -2432,7 +2432,7 @@ hasValidTrailBytes(const int32_t (*stateTable)[256], uint8_t state) { for(b=0; b<=0xff; ++b) { entry=row[b]; if( MBCS_ENTRY_IS_TRANSITION(entry) && - hasValidTrailBytes(stateTable, (uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry)) + hasValidTrailBytes(stateTable, static_cast<uint8_t>(MBCS_ENTRY_TRANSITION_STATE(entry))) ) { return true; } @@ -2450,9 +2450,9 @@ isSingleOrLead(const int32_t (*stateTable)[256], uint8_t state, UBool isDBCSOnly const int32_t *row=stateTable[state]; int32_t entry=row[b]; if(MBCS_ENTRY_IS_TRANSITION(entry)) { /* lead byte */ - return hasValidTrailBytes(stateTable, (uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry)); + return hasValidTrailBytes(stateTable, static_cast<uint8_t>(MBCS_ENTRY_TRANSITION_STATE(entry))); } else { - uint8_t action=(uint8_t)(MBCS_ENTRY_FINAL_ACTION(entry)); + uint8_t action = static_cast<uint8_t>(MBCS_ENTRY_FINAL_ACTION(entry)); if(action==MBCS_STATE_CHANGE_ONLY && isDBCSOnly) { return false; /* SI/SO are illegal for DBCS-only conversion */ } else { @@ -2823,7 +2823,7 @@ ucnv_MBCSToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, * - If any of the non-initial bytes could be the start of a character, * we stop the illegal sequence before the first one of those. */ - UBool isDBCSOnly=(UBool)(cnv->sharedData->mbcs.dbcsOnlyState!=0); + UBool isDBCSOnly = cnv->sharedData->mbcs.dbcsOnlyState != 0; int8_t i; for(i=1; i<byteIndex && !isSingleOrLead(stateTable, state, isDBCSOnly, bytes[i]); @@ -2890,8 +2890,8 @@ ucnv_MBCSSingleGetNextUChar(UConverterToUnicodeArgs *pArgs, /* set up the local pointers */ cnv=pArgs->converter; - source=(const uint8_t *)pArgs->source; - sourceLimit=(const uint8_t *)pArgs->sourceLimit; + source = reinterpret_cast<const uint8_t*>(pArgs->source); + sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit); if((cnv->options&UCNV_OPTION_SWAP_LFNL)!=0) { stateTable=(const int32_t (*)[256])cnv->sharedData->mbcs.swapLFNLStateTable; } else { @@ -2904,27 +2904,27 @@ ucnv_MBCSSingleGetNextUChar(UConverterToUnicodeArgs *pArgs, /* MBCS_ENTRY_IS_FINAL(entry) */ /* write back the updated pointer early so that we can return directly */ - pArgs->source=(const char *)source; + pArgs->source = reinterpret_cast<const char*>(source); if(MBCS_ENTRY_FINAL_IS_VALID_DIRECT_16(entry)) { /* output BMP code point */ - return (char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + return static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); } /* * An if-else-if chain provides more reliable performance for * the most common cases compared to a switch. */ - action=(uint8_t)(MBCS_ENTRY_FINAL_ACTION(entry)); + action = static_cast<uint8_t>(MBCS_ENTRY_FINAL_ACTION(entry)); if( action==MBCS_STATE_VALID_DIRECT_20 || (action==MBCS_STATE_FALLBACK_DIRECT_20 && UCNV_TO_U_USE_FALLBACK(cnv)) ) { /* output supplementary code point */ - return (UChar32)(MBCS_ENTRY_FINAL_VALUE(entry)+0x10000); + return static_cast<UChar32>(MBCS_ENTRY_FINAL_VALUE(entry) + 0x10000); } else if(action==MBCS_STATE_FALLBACK_DIRECT_16) { if(UCNV_TO_U_USE_FALLBACK(cnv)) { /* output BMP code point */ - return (char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + return static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); } } else if(action==MBCS_STATE_UNASSIGNED) { /* just fall through */ @@ -2941,7 +2941,7 @@ ucnv_MBCSSingleGetNextUChar(UConverterToUnicodeArgs *pArgs, break; } else /* unassigned sequence */ { /* defer to the generic implementation */ - pArgs->source=(const char *)source-1; + pArgs->source = reinterpret_cast<const char*>(source) - 1; return UCNV_GET_NEXT_UCHAR_USE_TO_U; } } @@ -2999,8 +2999,8 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, } /* set up the local pointers */ - source=lastSource=(const uint8_t *)pArgs->source; - sourceLimit=(const uint8_t *)pArgs->sourceLimit; + source = lastSource = reinterpret_cast<const uint8_t*>(pArgs->source); + sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit); if((cnv->options&UCNV_OPTION_SWAP_LFNL)!=0) { stateTable=(const int32_t (*)[256])cnv->sharedData->mbcs.swapLFNLStateTable; @@ -3017,7 +3017,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, * then load the DBCS state from the MBCS data * (dbcsOnlyState==0 if it is not a DBCS-only converter) */ - if((state=(uint8_t)(cnv->mode))==0) { + if ((state = static_cast<uint8_t>(cnv->mode)) == 0) { state=cnv->sharedData->mbcs.dbcsOnlyState; } @@ -3026,7 +3026,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, while(source<sourceLimit) { entry=stateTable[state][*source++]; if(MBCS_ENTRY_IS_TRANSITION(entry)) { - state=(uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry); + state = static_cast<uint8_t>(MBCS_ENTRY_TRANSITION_STATE(entry)); offset+=MBCS_ENTRY_TRANSITION_OFFSET(entry); /* optimization for 1/2-byte input and BMP output */ @@ -3036,7 +3036,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, (c=unicodeCodeUnits[offset+MBCS_ENTRY_FINAL_VALUE_16(entry)])<0xfffe ) { ++source; - state=(uint8_t)MBCS_ENTRY_FINAL_STATE(entry); /* typically 0 */ + state = static_cast<uint8_t>(MBCS_ENTRY_FINAL_STATE(entry)); /* typically 0 */ /* output BMP code point */ break; } @@ -3045,16 +3045,16 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, cnv->mode=state; /* set the next state early so that we can reuse the entry variable */ - state=(uint8_t)MBCS_ENTRY_FINAL_STATE(entry); /* typically 0 */ + state = static_cast<uint8_t>(MBCS_ENTRY_FINAL_STATE(entry)); /* typically 0 */ /* * An if-else-if chain provides more reliable performance for * the most common cases compared to a switch. */ - action=(uint8_t)(MBCS_ENTRY_FINAL_ACTION(entry)); + action = static_cast<uint8_t>(MBCS_ENTRY_FINAL_ACTION(entry)); if(action==MBCS_STATE_VALID_DIRECT_16) { /* output BMP code point */ - c=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + c = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); break; } else if(action==MBCS_STATE_VALID_16) { offset+=MBCS_ENTRY_FINAL_VALUE_16(entry); @@ -3092,7 +3092,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, (action==MBCS_STATE_FALLBACK_DIRECT_20 && UCNV_TO_U_USE_FALLBACK(cnv)) ) { /* output supplementary code point */ - c=(UChar32)(MBCS_ENTRY_FINAL_VALUE(entry)+0x10000); + c = static_cast<UChar32>(MBCS_ENTRY_FINAL_VALUE(entry) + 0x10000); break; } else if(action==MBCS_STATE_CHANGE_ONLY) { /* @@ -3104,7 +3104,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, */ if(cnv->sharedData->mbcs.dbcsOnlyState!=0) { /* SI/SO are illegal for DBCS-only conversion */ - state=(uint8_t)(cnv->mode); /* restore the previous state */ + state = static_cast<uint8_t>(cnv->mode); /* restore the previous state */ /* callback(illegal) */ *pErrorCode=U_ILLEGAL_CHAR_FOUND; @@ -3112,7 +3112,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, } else if(action==MBCS_STATE_FALLBACK_DIRECT_16) { if(UCNV_TO_U_USE_FALLBACK(cnv)) { /* output BMP code point */ - c=(char16_t)MBCS_ENTRY_FINAL_VALUE_16(entry); + c = static_cast<char16_t>(MBCS_ENTRY_FINAL_VALUE_16(entry)); break; } } else if(action==MBCS_STATE_UNASSIGNED) { @@ -3137,7 +3137,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, /* defer to the generic implementation */ cnv->toUnicodeStatus=0; cnv->mode=state; - pArgs->source=(const char *)lastSource; + pArgs->source = reinterpret_cast<const char*>(lastSource); return UCNV_GET_NEXT_UCHAR_USE_TO_U; } } @@ -3147,7 +3147,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, if(U_SUCCESS(*pErrorCode) && source==sourceLimit && lastSource<source) { /* incomplete character byte sequence */ uint8_t *bytes=cnv->toUBytes; - cnv->toULength=(int8_t)(source-lastSource); + cnv->toULength = static_cast<int8_t>(source - lastSource); do { *bytes++=*lastSource++; } while(lastSource<source); @@ -3160,7 +3160,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, * - If any of the non-initial bytes could be the start of a character, * we stop the illegal sequence before the first one of those. */ - UBool isDBCSOnly=(UBool)(cnv->sharedData->mbcs.dbcsOnlyState!=0); + UBool isDBCSOnly = static_cast<UBool>(cnv->sharedData->mbcs.dbcsOnlyState != 0); uint8_t *bytes=cnv->toUBytes; *bytes++=*lastSource++; /* first byte */ if(lastSource==source) { @@ -3188,7 +3188,7 @@ ucnv_MBCSGetNextUChar(UConverterToUnicodeArgs *pArgs, cnv->mode=state; /* write back the updated pointer */ - pArgs->source=(const char *)source; + pArgs->source = reinterpret_cast<const char*>(source); return c; } @@ -3431,8 +3431,8 @@ ucnv_MBCSDoubleFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, /* set up the local pointers */ source=pArgs->source; sourceLimit=pArgs->sourceLimit; - target=(uint8_t *)pArgs->target; - targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target); + target = reinterpret_cast<uint8_t*>(pArgs->target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target); offsets=pArgs->offsets; table=cnv->sharedData->mbcs.fromUnicodeTable; @@ -3474,7 +3474,7 @@ ucnv_MBCSDoubleFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, c=*source++; ++nextSourceIndex; if(c<=0x7f && IS_ASCII_ROUNDTRIP(c, asciiRoundtrips)) { - *target++=(uint8_t)c; + *target++ = static_cast<uint8_t>(c); if(offsets!=nullptr) { *offsets++=sourceIndex; sourceIndex=nextSourceIndex; @@ -3562,7 +3562,7 @@ unassigned: &offsets, sourceIndex, pArgs->flush, pErrorCode); - nextSourceIndex+=(int32_t)(source-pArgs->source); + nextSourceIndex += static_cast<int32_t>(source - pArgs->source); if(U_FAILURE(*pErrorCode)) { /* not mappable or buffer overflow */ @@ -3571,7 +3571,7 @@ unassigned: /* a mapping was written to the target, continue */ /* recalculate the targetCapacity after an extension mapping */ - targetCapacity=(int32_t)(pArgs->targetLimit-(char *)target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - reinterpret_cast<char*>(target)); /* normal end of conversion: prepare for a new character */ sourceIndex=nextSourceIndex; @@ -3584,15 +3584,15 @@ unassigned: /* from the first if in the loop we know that targetCapacity>0 */ if(value<=0xff) { /* this is easy because we know that there is enough space */ - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); if(offsets!=nullptr) { *offsets++=sourceIndex; } --targetCapacity; } else /* length==2 */ { - *target++=(uint8_t)(value>>8); + *target++ = static_cast<uint8_t>(value >> 8); if(2<=targetCapacity) { - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); if(offsets!=nullptr) { *offsets++=sourceIndex; *offsets++=sourceIndex; @@ -3602,7 +3602,7 @@ unassigned: if(offsets!=nullptr) { *offsets++=sourceIndex; } - cnv->charErrorBuffer[0]=(char)value; + cnv->charErrorBuffer[0] = static_cast<char>(value); cnv->charErrorBufferLength=1; /* target overflow */ @@ -3629,7 +3629,7 @@ unassigned: /* write back the updated pointers */ pArgs->source=source; - pArgs->target=(char *)target; + pArgs->target = reinterpret_cast<char*>(target); pArgs->offsets=offsets; } @@ -3657,13 +3657,13 @@ ucnv_MBCSSingleFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, cnv=pArgs->converter; source=pArgs->source; sourceLimit=pArgs->sourceLimit; - target=(uint8_t *)pArgs->target; - targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target); + target = reinterpret_cast<uint8_t*>(pArgs->target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target); offsets=pArgs->offsets; table=cnv->sharedData->mbcs.fromUnicodeTable; if((cnv->options&UCNV_OPTION_SWAP_LFNL)!=0) { - results=(uint16_t *)cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes; + results = reinterpret_cast<uint16_t*>(cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes); } else { results=(uint16_t *)cnv->sharedData->mbcs.fromUnicodeBytes; } @@ -3675,7 +3675,7 @@ ucnv_MBCSSingleFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, /* use only roundtrips and fallbacks from private-use characters */ minValue=0xc00; } - hasSupplementary=(UBool)(cnv->sharedData->mbcs.unicodeMask&UCNV_HAS_SUPPLEMENTARY); + hasSupplementary = static_cast<UBool>(cnv->sharedData->mbcs.unicodeMask & UCNV_HAS_SUPPLEMENTARY); /* get the converter state from UConverter */ c=cnv->fromUChar32; @@ -3749,7 +3749,7 @@ getTrail: /* assigned, write the output character bytes from value and length */ /* length==1 */ /* this is easy because we know that there is enough space */ - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); if(offsets!=nullptr) { *offsets++=sourceIndex; } @@ -3768,7 +3768,7 @@ unassigned: &offsets, sourceIndex, pArgs->flush, pErrorCode); - nextSourceIndex+=(int32_t)(source-pArgs->source); + nextSourceIndex += static_cast<int32_t>(source - pArgs->source); if(U_FAILURE(*pErrorCode)) { /* not mappable or buffer overflow */ @@ -3777,7 +3777,7 @@ unassigned: /* a mapping was written to the target, continue */ /* recalculate the targetCapacity after an extension mapping */ - targetCapacity=(int32_t)(pArgs->targetLimit-(char *)target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - reinterpret_cast<char*>(target)); /* normal end of conversion: prepare for a new character */ sourceIndex=nextSourceIndex; @@ -3795,7 +3795,7 @@ unassigned: /* write back the updated pointers */ pArgs->source=source; - pArgs->target=(char *)target; + pArgs->target = reinterpret_cast<char*>(target); pArgs->offsets=offsets; } @@ -3833,13 +3833,13 @@ ucnv_MBCSSingleFromBMPWithOffsets(UConverterFromUnicodeArgs *pArgs, cnv=pArgs->converter; source=pArgs->source; sourceLimit=pArgs->sourceLimit; - target=(uint8_t *)pArgs->target; - targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target); + target = reinterpret_cast<uint8_t*>(pArgs->target); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target); offsets=pArgs->offsets; table=cnv->sharedData->mbcs.fromUnicodeTable; if((cnv->options&UCNV_OPTION_SWAP_LFNL)!=0) { - results=(uint16_t *)cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes; + results = reinterpret_cast<uint16_t*>(cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes); } else { results=(uint16_t *)cnv->sharedData->mbcs.fromUnicodeBytes; } @@ -3864,7 +3864,7 @@ ucnv_MBCSSingleFromBMPWithOffsets(UConverterFromUnicodeArgs *pArgs, * since the conversion here is 1:1 char16_t:uint8_t, we need only one counter * for the minimum of the sourceLength and targetCapacity */ - length=(int32_t)(sourceLimit-source); + length = static_cast<int32_t>(sourceLimit - source); if(length<targetCapacity) { targetCapacity=length; } @@ -3937,7 +3937,7 @@ unrolled: */ /* convert the Unicode code point in c into codepage bytes */ if(c<=0x7f && IS_ASCII_ROUNDTRIP(c, asciiRoundtrips)) { - *target++=(uint8_t)c; + *target++ = static_cast<uint8_t>(c); --targetCapacity; c=0; continue; @@ -3948,7 +3948,7 @@ unrolled: /* assigned, write the output character bytes from value and length */ /* length==1 */ /* this is easy because we know that there is enough space */ - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); --targetCapacity; /* normal end of conversion: prepare for a new character */ @@ -3993,7 +3993,7 @@ getTrail: /* set offsets since the start or the last extension */ if(offsets!=nullptr) { - int32_t count=(int32_t)(source-lastSource); + int32_t count = static_cast<int32_t>(source - lastSource); /* do not set the offset for this character */ count-=length; @@ -4009,11 +4009,11 @@ getTrail: lastSource=source; c=_extFromU(cnv, cnv->sharedData, c, &source, sourceLimit, - &target, (const uint8_t *)(pArgs->targetLimit), + &target, reinterpret_cast<const uint8_t*>(pArgs->targetLimit), &offsets, sourceIndex, pArgs->flush, pErrorCode); - sourceIndex+=length+(int32_t)(source-lastSource); + sourceIndex += length + static_cast<int32_t>(source - lastSource); lastSource=source; if(U_FAILURE(*pErrorCode)) { @@ -4023,8 +4023,8 @@ getTrail: /* a mapping was written to the target, continue */ /* recalculate the targetCapacity after an extension mapping */ - targetCapacity=(int32_t)(pArgs->targetLimit-(char *)target); - length=(int32_t)(sourceLimit-source); + targetCapacity = static_cast<int32_t>(pArgs->targetLimit - reinterpret_cast<char*>(target)); + length = static_cast<int32_t>(sourceLimit - source); if(length<targetCapacity) { targetCapacity=length; } @@ -4063,7 +4063,7 @@ getTrail: /* write back the updated pointers */ pArgs->source=source; - pArgs->target=(char *)target; + pArgs->target = reinterpret_cast<char*>(target); pArgs->offsets=offsets; } @@ -4777,14 +4777,14 @@ unassigned: ) { /* EBCDIC_STATEFUL ending with DBCS: emit an SI to return the output stream to SBCS */ if(targetCapacity>0) { - *target++=(uint8_t)siBytes[0]; + *target++ = siBytes[0]; if (siLength == 2) { if (targetCapacity<2) { - cnv->charErrorBuffer[0]=(uint8_t)siBytes[1]; + cnv->charErrorBuffer[0] = siBytes[1]; cnv->charErrorBufferLength=1; *pErrorCode=U_BUFFER_OVERFLOW_ERROR; } else { - *target++=(uint8_t)siBytes[1]; + *target++ = siBytes[1]; } } if(offsets!=nullptr) { @@ -4793,9 +4793,9 @@ unassigned: } } else { /* target is full */ - cnv->charErrorBuffer[0]=(uint8_t)siBytes[0]; + cnv->charErrorBuffer[0] = siBytes[0]; if (siLength == 2) { - cnv->charErrorBuffer[1]=(uint8_t)siBytes[1]; + cnv->charErrorBuffer[1] = siBytes[1]; } cnv->charErrorBufferLength=siLength; *pErrorCode=U_BUFFER_OVERFLOW_ERROR; @@ -5042,13 +5042,13 @@ ucnv_SBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, cnv=pFromUArgs->converter; source=(uint8_t *)pToUArgs->source; sourceLimit=(uint8_t *)pToUArgs->sourceLimit; - target=(uint8_t *)pFromUArgs->target; - targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target); + target = reinterpret_cast<uint8_t*>(pFromUArgs->target); + targetCapacity = static_cast<int32_t>(pFromUArgs->targetLimit - pFromUArgs->target); table=cnv->sharedData->mbcs.fromUnicodeTable; sbcsIndex=cnv->sharedData->mbcs.sbcsIndex; if((cnv->options&UCNV_OPTION_SWAP_LFNL)!=0) { - results=(uint16_t *)cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes; + results = reinterpret_cast<uint16_t*>(cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes); } else { results=(uint16_t *)cnv->sharedData->mbcs.fromUnicodeBytes; } @@ -5061,13 +5061,13 @@ ucnv_SBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, /* use only roundtrips and fallbacks from private-use characters */ minValue=0xc00; } - hasSupplementary=(UBool)(cnv->sharedData->mbcs.unicodeMask&UCNV_HAS_SUPPLEMENTARY); + hasSupplementary = static_cast<UBool>(cnv->sharedData->mbcs.unicodeMask & UCNV_HAS_SUPPLEMENTARY); /* get the converter state from the UTF-8 UConverter */ if(utf8->toULength > 0) { toULength=oldToULength=utf8->toULength; - toULimit=(int8_t)utf8->mode; - c=(UChar32)utf8->toUnicodeStatus; + toULimit = static_cast<int8_t>(utf8->mode); + c = static_cast<UChar32>(utf8->toUnicodeStatus); } else { toULength=oldToULength=toULimit=0; c = 0; @@ -5080,7 +5080,7 @@ ucnv_SBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, { // Do not go back into the bytes that will be read for finishing a partial // sequence from the previous buffer. - int32_t length=(int32_t)(sourceLimit-source) - (toULimit-oldToULength); + int32_t length = static_cast<int32_t>(sourceLimit - source) - (toULimit - oldToULength); if(length>0) { uint8_t b1=*(sourceLimit-1); if(U8_IS_SINGLE(b1)) { @@ -5130,7 +5130,7 @@ ucnv_SBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, if(U8_IS_SINGLE(b)) { /* convert ASCII */ if(IS_ASCII_ROUNDTRIP(b, asciiRoundtrips)) { - *target++=(uint8_t)b; + *target++ = b; --targetCapacity; continue; } else { @@ -5141,13 +5141,13 @@ ucnv_SBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, if(b<0xe0) { if( /* handle U+0080..U+07FF inline */ b>=0xc2 && - (t1=(uint8_t)(*source-0x80)) <= 0x3f + (t1 = static_cast<uint8_t>(*source - 0x80)) <= 0x3f ) { c=b&0x1f; ++source; value=SBCS_RESULT_FROM_UTF8(sbcsIndex, results, c, t1); if(value>=minValue) { - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); --targetCapacity; continue; } else { @@ -5158,14 +5158,14 @@ ucnv_SBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, } } else if(b==0xe0) { if( /* handle U+0800..U+0FFF inline */ - (t1=(uint8_t)(source[0]-0x80)) <= 0x3f && t1 >= 0x20 && - (t2=(uint8_t)(source[1]-0x80)) <= 0x3f + (t1 = static_cast<uint8_t>(source[0] - 0x80)) <= 0x3f && t1 >= 0x20 && + (t2 = static_cast<uint8_t>(source[1] - 0x80)) <= 0x3f ) { c=t1; source+=2; value=SBCS_RESULT_FROM_UTF8(sbcsIndex, results, c, t2); if(value>=minValue) { - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); --targetCapacity; continue; } else { @@ -5212,7 +5212,7 @@ moreBytes: utf8->toULength=toULength; utf8->mode=toULimit; pToUArgs->source=(char *)source; - pFromUArgs->target=(char *)target; + pFromUArgs->target = reinterpret_cast<char*>(target); return; } } @@ -5238,7 +5238,7 @@ moreBytes: } utf8->toULength=toULength; pToUArgs->source=(char *)source; - pFromUArgs->target=(char *)target; + pFromUArgs->target = reinterpret_cast<char*>(target); *pErrorCode=U_ILLEGAL_CHAR_FOUND; return; } @@ -5247,7 +5247,7 @@ moreBytes: if(value>=minValue) { /* output the mapping for c */ - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); --targetCapacity; } else { /* value<minValue means c is unassigned (unmappable) */ @@ -5283,7 +5283,7 @@ moreBytes: /* a mapping was written to the target, continue */ /* recalculate the targetCapacity after an extension mapping */ - targetCapacity=(int32_t)(pFromUArgs->targetLimit-(char *)target); + targetCapacity = static_cast<int32_t>(pFromUArgs->targetLimit - reinterpret_cast<char*>(target)); } } } else { @@ -5315,7 +5315,7 @@ moreBytes: /* write back the updated pointers */ pToUArgs->source=(char *)source; - pFromUArgs->target=(char *)target; + pFromUArgs->target = reinterpret_cast<char*>(target); } static void U_CALLCONV @@ -5345,25 +5345,25 @@ ucnv_DBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, cnv=pFromUArgs->converter; source=(uint8_t *)pToUArgs->source; sourceLimit=(uint8_t *)pToUArgs->sourceLimit; - target=(uint8_t *)pFromUArgs->target; - targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target); + target = reinterpret_cast<uint8_t*>(pFromUArgs->target); + targetCapacity = static_cast<int32_t>(pFromUArgs->targetLimit - pFromUArgs->target); table=cnv->sharedData->mbcs.fromUnicodeTable; mbcsIndex=cnv->sharedData->mbcs.mbcsIndex; if((cnv->options&UCNV_OPTION_SWAP_LFNL)!=0) { - results=(uint16_t *)cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes; + results = reinterpret_cast<uint16_t*>(cnv->sharedData->mbcs.swapLFNLFromUnicodeBytes); } else { results=(uint16_t *)cnv->sharedData->mbcs.fromUnicodeBytes; } asciiRoundtrips=cnv->sharedData->mbcs.asciiRoundtrips; - hasSupplementary=(UBool)(cnv->sharedData->mbcs.unicodeMask&UCNV_HAS_SUPPLEMENTARY); + hasSupplementary = static_cast<UBool>(cnv->sharedData->mbcs.unicodeMask & UCNV_HAS_SUPPLEMENTARY); /* get the converter state from the UTF-8 UConverter */ if(utf8->toULength > 0) { toULength=oldToULength=utf8->toULength; - toULimit=(int8_t)utf8->mode; - c=(UChar32)utf8->toUnicodeStatus; + toULimit = static_cast<int8_t>(utf8->mode); + c = static_cast<UChar32>(utf8->toUnicodeStatus); } else { toULength=oldToULength=toULimit=0; c = 0; @@ -5376,7 +5376,7 @@ ucnv_DBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, { // Do not go back into the bytes that will be read for finishing a partial // sequence from the previous buffer. - int32_t length=(int32_t)(sourceLimit-source) - (toULimit-oldToULength); + int32_t length = static_cast<int32_t>(sourceLimit - source) - (toULimit - oldToULength); if(length>0) { uint8_t b1=*(sourceLimit-1); if(U8_IS_SINGLE(b1)) { @@ -5423,7 +5423,7 @@ ucnv_DBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, if( /* handle U+0800..U+D7FF inline */ b<=0xed && // do not assume maxFastUChar>0xd7ff U8_IS_VALID_LEAD3_AND_T1(b, t1=source[0]) && - (t2=(uint8_t)(source[1]-0x80)) <= 0x3f + (t2 = static_cast<uint8_t>(source[1] - 0x80)) <= 0x3f ) { c=((b&0xf)<<6)|(t1&0x3f); source+=2; @@ -5438,7 +5438,7 @@ ucnv_DBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs, } else { if( /* handle U+0080..U+07FF inline */ b>=0xc2 && - (t1=(uint8_t)(*source-0x80)) <= 0x3f + (t1 = static_cast<uint8_t>(*source - 0x80)) <= 0x3f ) { c=b&0x1f; ++source; @@ -5486,7 +5486,7 @@ moreBytes: utf8->toULength=toULength; utf8->mode=toULimit; pToUArgs->source=(char *)source; - pFromUArgs->target=(char *)target; + pFromUArgs->target = reinterpret_cast<char*>(target); return; } } @@ -5512,7 +5512,7 @@ moreBytes: } utf8->toULength=toULength; pToUArgs->source=(char *)source; - pFromUArgs->target=(char *)target; + pFromUArgs->target = reinterpret_cast<char*>(target); *pErrorCode=U_ILLEGAL_CHAR_FOUND; return; } @@ -5534,15 +5534,15 @@ moreBytes: /* from the first if in the loop we know that targetCapacity>0 */ if(value<=0xff) { /* this is easy because we know that there is enough space */ - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); --targetCapacity; } else /* length==2 */ { - *target++=(uint8_t)(value>>8); + *target++ = static_cast<uint8_t>(value >> 8); if(2<=targetCapacity) { - *target++=(uint8_t)value; + *target++ = static_cast<uint8_t>(value); targetCapacity-=2; } else { - cnv->charErrorBuffer[0]=(char)value; + cnv->charErrorBuffer[0] = static_cast<char>(value); cnv->charErrorBufferLength=1; /* target overflow */ @@ -5586,7 +5586,7 @@ unassigned: /* a mapping was written to the target, continue */ /* recalculate the targetCapacity after an extension mapping */ - targetCapacity=(int32_t)(pFromUArgs->targetLimit-(char *)target); + targetCapacity = static_cast<int32_t>(pFromUArgs->targetLimit - reinterpret_cast<char*>(target)); continue; } } @@ -5619,7 +5619,7 @@ unassigned: /* write back the updated pointers */ pToUArgs->source=(char *)source; - pFromUArgs->target=(char *)target; + pFromUArgs->target = reinterpret_cast<char*>(target); } /* miscellaneous ------------------------------------------------------------ */ @@ -5634,7 +5634,7 @@ ucnv_MBCSGetStarters(const UConverter* cnv, state0=cnv->sharedData->mbcs.stateTable[cnv->sharedData->mbcs.dbcsOnlyState]; for(i=0; i<256; ++i) { /* all bytes that cause a state transition from state 0 are lead bytes */ - starters[i]= (UBool)MBCS_ENTRY_IS_TRANSITION(state0[i]); + starters[i] = static_cast<UBool>(MBCS_ENTRY_IS_TRANSITION(state0[i])); } } @@ -5644,7 +5644,7 @@ ucnv_MBCSGetStarters(const UConverter* cnv, */ U_CFUNC UBool ucnv_MBCSIsLeadByte(UConverterSharedData *sharedData, char byte) { - return (UBool)MBCS_ENTRY_IS_TRANSITION(sharedData->mbcs.stateTable[0][(uint8_t)byte]); + return MBCS_ENTRY_IS_TRANSITION(sharedData->mbcs.stateTable[0][(uint8_t)byte]); } static void U_CALLCONV @@ -5663,11 +5663,11 @@ ucnv_MBCSWriteSub(UConverterFromUnicodeArgs *pArgs, (cnv->invalidUCharBuffer[0]<=0xff)) ) { /* select subChar1 if it is set (not 0) and the unmappable Unicode code point is up to U+00ff (IBM MBCS behavior) */ - subchar=(char *)&cnv->subChar1; + subchar = reinterpret_cast<char*>(&cnv->subChar1); length=1; } else { /* select subChar in all other cases */ - subchar=(char *)cnv->subChars; + subchar = reinterpret_cast<char*>(cnv->subChars); length=cnv->subCharLen; } @@ -5701,7 +5701,7 @@ ucnv_MBCSWriteSub(UConverterFromUnicodeArgs *pArgs, return; } subchar=buffer; - length=(int32_t)(p-buffer); + length = static_cast<int32_t>(p - buffer); } ucnv_cbFromUWriteBytes(pArgs, subchar, length, offsetIndex, pErrorCode); diff --git a/thirdparty/icu4c/common/ucnvscsu.cpp b/thirdparty/icu4c/common/ucnvscsu.cpp index e6f8660df4..5412136a34 100644 --- a/thirdparty/icu4c/common/ucnvscsu.cpp +++ b/thirdparty/icu4c/common/ucnvscsu.cpp @@ -883,8 +883,8 @@ static int8_t getWindow(const uint32_t offsets[8], uint32_t c) { int i; for(i=0; i<8; ++i) { - if((uint32_t)(c-offsets[i])<=0x7f) { - return (int8_t)(i); + if (c - offsets[i] <= 0x7f) { + return static_cast<int8_t>(i); } } return -1; @@ -893,9 +893,9 @@ getWindow(const uint32_t offsets[8], uint32_t c) { /* is the character in the dynamic window starting at the offset, or in the direct-encoded range? */ static UBool isInOffsetWindowOrDirect(uint32_t offset, uint32_t c) { - return (UBool)(c<=offset+0x7f && + return c<=offset+0x7f && (c>=offset || (c<=0x7f && - (c>=0x20 || (1UL<<c)&0x2601)))); + (c>=0x20 || (1UL<<c)&0x2601))); /* binary 0010 0110 0000 0001, check for b==0xd || b==0xa || b==9 || b==0 */ } @@ -963,7 +963,7 @@ getDynamicOffset(uint32_t c, uint32_t *pOffset) { int i; for(i=0; i<7; ++i) { - if((uint32_t)(c-fixedOffsets[i])<=0x7f) { + if (c - fixedOffsets[i] <= 0x7f) { *pOffset=fixedOffsets[i]; return 0xf9+i; } @@ -973,16 +973,16 @@ getDynamicOffset(uint32_t c, uint32_t *pOffset) { /* No dynamic window for US-ASCII. */ return -1; } else if(c<0x3400 || - (uint32_t)(c-0x10000)<(0x14000-0x10000) || - (uint32_t)(c-0x1d000)<=(0x1ffff-0x1d000) + c - 0x10000 < 0x14000 - 0x10000 || + c - 0x1d000 <= 0x1ffff - 0x1d000 ) { /* This character is in a code range for a "small", i.e., reasonably windowable, script. */ *pOffset=c&0x7fffff80; - return (int)(c>>7); + return static_cast<int>(c >> 7); } else if(0xe000<=c && c!=0xfeff && c<0xfff0) { /* For these characters we need to take the gapOffset into account. */ *pOffset=c&0x7fffff80; - return (int)((c-gapOffset)>>7); + return static_cast<int>((c - gapOffset) >> 7); } else { return -1; } @@ -1208,8 +1208,8 @@ getTrailSingle: c=((uint32_t)(SD0+dynamicWindow)<<16)|((uint32_t)code<<8)|(c-currentOffset)|0x80; length=3; goto outputBytes; - } else if((uint32_t)(c-0x3400)<(0xd800-0x3400) && - (source>=sourceLimit || (uint32_t)(*source-0x3400)<(0xd800-0x3400)) + } else if ((c - 0x3400) < (0xd800 - 0x3400) && + (source >= sourceLimit || (uint32_t)(*source - 0x3400) < (0xd800 - 0x3400)) ) { /* * this character is not compressible (a BMP ideograph or similar); @@ -1248,7 +1248,7 @@ getTrailSingle: c=*source++; ++nextSourceIndex; - if((uint32_t)(c-0x3400)<(0xd800-0x3400)) { + if ((c - 0x3400) < (0xd800 - 0x3400)) { /* not compressible, write character directly */ if(targetCapacity>=2) { *target++=(uint8_t)(c>>8); @@ -1262,10 +1262,10 @@ getTrailSingle: length=2; goto outputBytes; } - } else if((uint32_t)(c-0x3400)>=(0xf300-0x3400) /* c<0x3400 || c>=0xf300 */) { + } else if (c - 0x3400 >= 0xf300 - 0x3400 /* c<0x3400 || c>=0xf300 */) { /* compress BMP character if the following one is not an uncompressible ideograph */ if(!(source<sourceLimit && (uint32_t)(*source-0x3400)<(0xd800-0x3400))) { - if(((uint32_t)(c-0x30)<10 || (uint32_t)(c-0x61)<26 || (uint32_t)(c-0x41)<26)) { + if (c - 0x30 < 10 || c - 0x61 < 26 || c - 0x41 < 26) { /* ASCII digit or letter */ isSingleByteMode=true; c|=((uint32_t)(UC0+dynamicWindow)<<8)|c; @@ -1691,8 +1691,8 @@ getTrailSingle: c=((uint32_t)(SD0+dynamicWindow)<<16)|((uint32_t)code<<8)|(c-currentOffset)|0x80; length=3; goto outputBytes; - } else if((uint32_t)(c-0x3400)<(0xd800-0x3400) && - (source>=sourceLimit || (uint32_t)(*source-0x3400)<(0xd800-0x3400)) + } else if (c - 0x3400 < 0xd800 - 0x3400 && + (source >= sourceLimit || static_cast<uint32_t>(*source - 0x3400) < 0xd800 - 0x3400) ) { /* * this character is not compressible (a BMP ideograph or similar); @@ -1729,7 +1729,7 @@ getTrailSingle: } c=*source++; - if((uint32_t)(c-0x3400)<(0xd800-0x3400)) { + if (c - 0x3400 < 0xd800 - 0x3400) { /* not compressible, write character directly */ if(targetCapacity>=2) { *target++=(uint8_t)(c>>8); @@ -1739,10 +1739,10 @@ getTrailSingle: length=2; goto outputBytes; } - } else if((uint32_t)(c-0x3400)>=(0xf300-0x3400) /* c<0x3400 || c>=0xf300 */) { + } else if (c - 0x3400 >= 0xf300 - 0x3400 /* c<0x3400 || c>=0xf300 */) { /* compress BMP character if the following one is not an uncompressible ideograph */ if(!(source<sourceLimit && (uint32_t)(*source-0x3400)<(0xd800-0x3400))) { - if(((uint32_t)(c-0x30)<10 || (uint32_t)(c-0x61)<26 || (uint32_t)(c-0x41)<26)) { + if (c - 0x30 < 10 || c - 0x61 < 26 || c - 0x41 < 26) { /* ASCII digit or letter */ isSingleByteMode=true; c|=((uint32_t)(UC0+dynamicWindow)<<8)|c; diff --git a/thirdparty/icu4c/common/ucnvsel.cpp b/thirdparty/icu4c/common/ucnvsel.cpp index a286646395..01d9c7e0c2 100644 --- a/thirdparty/icu4c/common/ucnvsel.cpp +++ b/thirdparty/icu4c/common/ucnvsel.cpp @@ -377,7 +377,7 @@ ucnvsel_swap(const UDataSwapper *ds, } /* check data format and format version */ - const UDataInfo *pInfo = (const UDataInfo *)((const char *)inData + 4); + const UDataInfo* pInfo = reinterpret_cast<const UDataInfo*>(static_cast<const char*>(inData) + 4); if(!( pInfo->dataFormat[0] == 0x43 && /* dataFormat="CSel" */ pInfo->dataFormat[1] == 0x53 && @@ -407,11 +407,11 @@ ucnvsel_swap(const UDataSwapper *ds, } } - const uint8_t *inBytes = (const uint8_t *)inData + headerSize; - uint8_t *outBytes = (uint8_t *)outData + headerSize; + const uint8_t* inBytes = static_cast<const uint8_t*>(inData) + headerSize; + uint8_t* outBytes = static_cast<uint8_t*>(outData) + headerSize; /* read the indexes */ - const int32_t *inIndexes = (const int32_t *)inBytes; + const int32_t* inIndexes = reinterpret_cast<const int32_t*>(inBytes); int32_t indexes[16]; int32_t i; for(i = 0; i < 16; ++i) { diff --git a/thirdparty/icu4c/common/ucol_swp.cpp b/thirdparty/icu4c/common/ucol_swp.cpp index b5894a1fef..ea72bb8b8d 100644 --- a/thirdparty/icu4c/common/ucol_swp.cpp +++ b/thirdparty/icu4c/common/ucol_swp.cpp @@ -108,11 +108,11 @@ swapFormatVersion3(const UDataSwapper *ds, return 0; } - inBytes=(const uint8_t *)inData; - outBytes=(uint8_t *)outData; + inBytes = static_cast<const uint8_t*>(inData); + outBytes = static_cast<uint8_t*>(outData); - inHeader=(const UCATableHeader *)inData; - outHeader=(UCATableHeader *)outData; + inHeader = static_cast<const UCATableHeader*>(inData); + outHeader = static_cast<UCATableHeader*>(outData); /* * The collation binary must contain at least the UCATableHeader, @@ -175,7 +175,7 @@ swapFormatVersion3(const UDataSwapper *ds, header.leadByteToScript= ds->readUInt32(inHeader->leadByteToScript); /* swap the 32-bit integers in the header */ - ds->swapArray32(ds, inHeader, (int32_t)((const char *)&inHeader->jamoSpecial-(const char *)inHeader), + ds->swapArray32(ds, inHeader, static_cast<int32_t>(reinterpret_cast<const char*>(&inHeader->jamoSpecial) - reinterpret_cast<const char*>(inHeader)), outHeader, pErrorCode); ds->swapArray32(ds, &(inHeader->scriptToLeadByte), sizeof(header.scriptToLeadByte) + sizeof(header.leadByteToScript), &(outHeader->scriptToLeadByte), pErrorCode); @@ -198,7 +198,7 @@ swapFormatVersion3(const UDataSwapper *ds, /* no contractions: expansions bounded by the main trie */ count=header.mappingPosition-header.expansion; } - ds->swapArray32(ds, inBytes+header.expansion, (int32_t)count, + ds->swapArray32(ds, inBytes + header.expansion, static_cast<int32_t>(count), outBytes+header.expansion, pErrorCode); } @@ -216,7 +216,7 @@ swapFormatVersion3(const UDataSwapper *ds, /* swap the main trie */ if(header.mappingPosition!=0) { count=header.endExpansionCE-header.mappingPosition; - utrie_swap(ds, inBytes+header.mappingPosition, (int32_t)count, + utrie_swap(ds, inBytes + header.mappingPosition, static_cast<int32_t>(count), outBytes+header.mappingPosition, pErrorCode); } @@ -241,7 +241,7 @@ swapFormatVersion3(const UDataSwapper *ds, /* swap UCA contractions */ if(header.contractionUCACombosSize!=0) { count=header.contractionUCACombosSize*inHeader->contractionUCACombosWidth*U_SIZEOF_UCHAR; - ds->swapArray16(ds, inBytes+header.contractionUCACombos, (int32_t)count, + ds->swapArray16(ds, inBytes + header.contractionUCACombos, static_cast<int32_t>(count), outBytes+header.contractionUCACombos, pErrorCode); } @@ -306,10 +306,10 @@ swapFormatVersion4(const UDataSwapper *ds, UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return 0; } - const uint8_t *inBytes=(const uint8_t *)inData; - uint8_t *outBytes=(uint8_t *)outData; + const uint8_t* inBytes = static_cast<const uint8_t*>(inData); + uint8_t* outBytes = static_cast<uint8_t*>(outData); - const int32_t *inIndexes=(const int32_t *)inBytes; + const int32_t* inIndexes = reinterpret_cast<const int32_t*>(inBytes); int32_t indexes[IX_TOTAL_SIZE+1]; // Need at least IX_INDEXES_LENGTH and IX_OPTIONS. diff --git a/thirdparty/icu4c/common/ucptrie.cpp b/thirdparty/icu4c/common/ucptrie.cpp index 0004160a23..3e4b6a606e 100644 --- a/thirdparty/icu4c/common/ucptrie.cpp +++ b/thirdparty/icu4c/common/ucptrie.cpp @@ -258,11 +258,11 @@ inline uint32_t maybeFilterValue(uint32_t value, uint32_t trieNullValue, uint32_ UChar32 getRange(const void *t, UChar32 start, UCPMapValueFilter *filter, const void *context, uint32_t *pValue) { - if ((uint32_t)start > MAX_UNICODE) { + if (static_cast<uint32_t>(start) > MAX_UNICODE) { return U_SENTINEL; } const UCPTrie *trie = reinterpret_cast<const UCPTrie *>(t); - UCPTrieValueWidth valueWidth = (UCPTrieValueWidth)trie->valueWidth; + UCPTrieValueWidth valueWidth = static_cast<UCPTrieValueWidth>(trie->valueWidth); if (start >= trie->highStart) { if (pValue != nullptr) { int32_t di = trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET; @@ -304,7 +304,7 @@ UChar32 getRange(const void *t, UChar32 start, i1 += UCPTRIE_SMALL_INDEX_LENGTH; } i3Block = trie->index[ - (int32_t)trie->index[i1] + ((c >> UCPTRIE_SHIFT_2) & UCPTRIE_INDEX_2_MASK)]; + static_cast<int32_t>(trie->index[i1]) + ((c >> UCPTRIE_SHIFT_2) & UCPTRIE_INDEX_2_MASK)]; if (i3Block == prevI3Block && (c - start) >= UCPTRIE_CP_PER_INDEX_2_ENTRY) { // The index-3 block is the same as the previous one, and filled with value. U_ASSERT((c & (UCPTRIE_CP_PER_INDEX_2_ENTRY - 1)) == 0); @@ -341,7 +341,7 @@ UChar32 getRange(const void *t, UChar32 start, // 18-bit indexes stored in groups of 9 entries per 8 indexes. int32_t group = (i3Block & 0x7fff) + (i3 & ~7) + (i3 >> 3); int32_t gi = i3 & 7; - block = ((int32_t)index[group++] << (2 + (2 * gi))) & 0x30000; + block = (static_cast<int32_t>(index[group++]) << (2 + (2 * gi))) & 0x30000; block |= index[group + gi]; } if (block == prevBlock && (c - start) >= dataBlockLength) { diff --git a/thirdparty/icu4c/common/ucurr.cpp b/thirdparty/icu4c/common/ucurr.cpp index dbad1e5014..b74a80a676 100644 --- a/thirdparty/icu4c/common/ucurr.cpp +++ b/thirdparty/icu4c/common/ucurr.cpp @@ -130,7 +130,7 @@ private: const icu::UnicodeString * EquivIterator::next() { - const icu::UnicodeString* _next = (const icu::UnicodeString*) _hash.get(*_current); + const icu::UnicodeString* _next = static_cast<const icu::UnicodeString*>(_hash.get(*_current)); if (_next == nullptr) { U_ASSERT(_current == _start); return nullptr; @@ -260,7 +260,7 @@ currSymbolsEquiv_cleanup() */ static void U_CALLCONV deleteIsoCodeEntry(void *obj) { - IsoCodeEntry *entry = (IsoCodeEntry*)obj; + IsoCodeEntry* entry = static_cast<IsoCodeEntry*>(obj); uprv_free(entry); } @@ -269,7 +269,7 @@ deleteIsoCodeEntry(void *obj) { */ static void U_CALLCONV deleteUnicode(void *obj) { - icu::UnicodeString *entry = (icu::UnicodeString*)obj; + icu::UnicodeString* entry = static_cast<icu::UnicodeString*>(obj); delete entry; } @@ -306,10 +306,9 @@ _findMetaData(const char16_t* currency, UErrorCode& ec) { // move out of the root locale file later; if it does, update this // code.] UResourceBundle* currencyData = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &ec); - UResourceBundle* currencyMeta = ures_getByKey(currencyData, CURRENCY_META, currencyData, &ec); + LocalUResourceBundlePointer currencyMeta(ures_getByKey(currencyData, CURRENCY_META, currencyData, &ec)); if (U_FAILURE(ec)) { - ures_close(currencyMeta); // Config/build error; return hard-coded defaults return LAST_RESORT_DATA; } @@ -317,32 +316,25 @@ _findMetaData(const char16_t* currency, UErrorCode& ec) { // Look up our currency, or if that's not available, then DEFAULT char buf[ISO_CURRENCY_CODE_LENGTH+1]; UErrorCode ec2 = U_ZERO_ERROR; // local error code: soft failure - UResourceBundle* rb = ures_getByKey(currencyMeta, myUCharsToChars(buf, currency), nullptr, &ec2); + LocalUResourceBundlePointer rb(ures_getByKey(currencyMeta.getAlias(), myUCharsToChars(buf, currency), nullptr, &ec2)); if (U_FAILURE(ec2)) { - ures_close(rb); - rb = ures_getByKey(currencyMeta,DEFAULT_META, nullptr, &ec); + rb.adoptInstead(ures_getByKey(currencyMeta.getAlias(),DEFAULT_META, nullptr, &ec)); if (U_FAILURE(ec)) { - ures_close(currencyMeta); - ures_close(rb); // Config/build error; return hard-coded defaults return LAST_RESORT_DATA; } } int32_t len; - const int32_t *data = ures_getIntVector(rb, &len, &ec); + const int32_t *data = ures_getIntVector(rb.getAlias(), &len, &ec); if (U_FAILURE(ec) || len != 4) { // Config/build error; return hard-coded defaults if (U_SUCCESS(ec)) { ec = U_INVALID_FORMAT_ERROR; } - ures_close(currencyMeta); - ures_close(rb); return LAST_RESORT_DATA; } - ures_close(currencyMeta); - ures_close(rb); return data; } @@ -380,8 +372,8 @@ struct CReg : public icu::UMemory { CReg(const char16_t* _iso, const char* _id) : next(nullptr) { - int32_t len = (int32_t)uprv_strlen(_id); - if (len > (int32_t)(sizeof(id)-1)) { + int32_t len = static_cast<int32_t>(uprv_strlen(_id)); + if (len > static_cast<int32_t>(sizeof(id) - 1)) { len = (sizeof(id)-1); } uprv_strncpy(id, _id, len); @@ -565,14 +557,14 @@ ucurr_forLocale(const char* locale, localStatus = U_ZERO_ERROR; UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus); UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); - UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus); + LocalUResourceBundlePointer countryArray(ures_getByKey(rb, id.data(), cm, &localStatus)); // https://unicode-org.atlassian.net/browse/ICU-21997 // Prefer to use currencies that are legal tender. if (U_SUCCESS(localStatus)) { - int32_t arrayLength = ures_getSize(countryArray); + int32_t arrayLength = ures_getSize(countryArray.getAlias()); for (int32_t i = 0; i < arrayLength; ++i) { LocalUResourceBundlePointer currencyReq( - ures_getByIndex(countryArray, i, nullptr, &localStatus)); + ures_getByIndex(countryArray.getAlias(), i, nullptr, &localStatus)); // The currency is legal tender if it is *not* marked with tender{"false"}. UErrorCode tenderStatus = localStatus; const char16_t *tender = @@ -592,7 +584,6 @@ ucurr_forLocale(const char* locale, localStatus = U_MISSING_RESOURCE_ERROR; } } - ures_close(countryArray); } if ((U_FAILURE(localStatus)) && strchr(id.data(), '_') != nullptr) { @@ -805,21 +796,19 @@ ucurr_getPluralName(const char16_t* currency, rb = ures_getByKey(rb, CURRENCYPLURALS, rb, &ec2); // Fetch resource with multi-level resource inheritance fallback - rb = ures_getByKeyWithFallback(rb, buf, rb, &ec2); + LocalUResourceBundlePointer curr(ures_getByKeyWithFallback(rb, buf, rb, &ec2)); - s = ures_getStringByKeyWithFallback(rb, pluralCount, len, &ec2); + s = ures_getStringByKeyWithFallback(curr.getAlias(), pluralCount, len, &ec2); if (U_FAILURE(ec2)) { // fall back to "other" ec2 = U_ZERO_ERROR; - s = ures_getStringByKeyWithFallback(rb, "other", len, &ec2); + s = ures_getStringByKeyWithFallback(curr.getAlias(), "other", len, &ec2); if (U_FAILURE(ec2)) { - ures_close(rb); // fall back to long name in Currencies return ucurr_getName(currency, locale, UCURR_LONG_NAME, isChoiceFormat, len, ec); } } - ures_close(rb); // If we've succeeded we're done. Otherwise, try to fallback. // If that fails (because we are already at root) then exit. @@ -866,8 +855,8 @@ typedef struct { // Comparison function used in quick sort. static int U_CALLCONV currencyNameComparator(const void* a, const void* b) { - const CurrencyNameStruct* currName_1 = (const CurrencyNameStruct*)a; - const CurrencyNameStruct* currName_2 = (const CurrencyNameStruct*)b; + const CurrencyNameStruct* currName_1 = static_cast<const CurrencyNameStruct*>(a); + const CurrencyNameStruct* currName_2 = static_cast<const CurrencyNameStruct*>(b); for (int32_t i = 0; i < MIN(currName_1->currencyNameLen, currName_2->currencyNameLen); ++i) { @@ -911,34 +900,29 @@ getCurrencyNameCount(const char* loc, int32_t* total_currency_name_count, int32_ for (;;) { UErrorCode ec2 = U_ZERO_ERROR; // TODO: ures_openDirect? - UResourceBundle* rb = ures_open(U_ICUDATA_CURR, locale.data(), &ec2); - UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, nullptr, &ec2); - int32_t n = ures_getSize(curr); + LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_CURR, locale.data(), &ec2)); + LocalUResourceBundlePointer curr(ures_getByKey(rb.getAlias(), CURRENCIES, nullptr, &ec2)); + int32_t n = ures_getSize(curr.getAlias()); for (int32_t i=0; i<n; ++i) { - UResourceBundle* names = ures_getByIndex(curr, i, nullptr, &ec2); + LocalUResourceBundlePointer names(ures_getByIndex(curr.getAlias(), i, nullptr, &ec2)); int32_t len; - s = ures_getStringByIndex(names, UCURR_SYMBOL_NAME, &len, &ec2); + s = ures_getStringByIndex(names.getAlias(), UCURR_SYMBOL_NAME, &len, &ec2); ++(*total_currency_symbol_count); // currency symbol if (currencySymbolsEquiv != nullptr) { *total_currency_symbol_count += countEquivalent(*currencySymbolsEquiv, UnicodeString(true, s, len)); } ++(*total_currency_symbol_count); // iso code ++(*total_currency_name_count); // long name - ures_close(names); } // currency plurals UErrorCode ec3 = U_ZERO_ERROR; - UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, nullptr, &ec3); - n = ures_getSize(curr_p); + LocalUResourceBundlePointer curr_p(ures_getByKey(rb.getAlias(), CURRENCYPLURALS, nullptr, &ec3)); + n = ures_getSize(curr_p.getAlias()); for (int32_t i=0; i<n; ++i) { - UResourceBundle* names = ures_getByIndex(curr_p, i, nullptr, &ec3); - *total_currency_name_count += ures_getSize(names); - ures_close(names); + LocalUResourceBundlePointer names(ures_getByIndex(curr_p.getAlias(), i, nullptr, &ec3)); + *total_currency_name_count += ures_getSize(names.getAlias()); } - ures_close(curr_p); - ures_close(curr); - ures_close(rb); if (!fallback(locale)) { break; @@ -953,7 +937,10 @@ toUpperCase(const char16_t* source, int32_t len, const char* locale) { int32_t destLen = u_strToUpper(dest, 0, source, len, locale, &ec); ec = U_ZERO_ERROR; - dest = (char16_t*)uprv_malloc(sizeof(char16_t) * MAX(destLen, len)); + dest = static_cast<char16_t*>(uprv_malloc(sizeof(char16_t) * MAX(destLen, len))); + if (dest == nullptr) { + return nullptr; + } u_strToUpper(dest, destLen, source, len, locale, &ec); if (U_FAILURE(ec)) { u_memcpy(dest, source, len); @@ -962,6 +949,7 @@ toUpperCase(const char16_t* source, int32_t len, const char* locale) { } +static void deleteCurrencyNames(CurrencyNameStruct* currencyNames, int32_t count); // Collect all available currency names associated with the given locale // (enable fallback chain). // Read currenc names defined in resource bundle "Currencies" and @@ -975,6 +963,11 @@ collectCurrencyNames(const char* locale, CurrencyNameStruct** currencySymbols, int32_t* total_currency_symbol_count, UErrorCode& ec) { + if (U_FAILURE(ec)) { + *currencyNames = *currencySymbols = nullptr; + *total_currency_name_count = *total_currency_symbol_count = 0; + return; + } U_NAMESPACE_USE const icu::Hashtable *currencySymbolsEquiv = getCurrSymbolsEquiv(); // Look up the Currencies resource for the given locale. @@ -983,21 +976,32 @@ collectCurrencyNames(const char* locale, CharString loc = ulocimp_getName(locale, ec2); if (U_FAILURE(ec2)) { ec = U_ILLEGAL_ARGUMENT_ERROR; + *currencyNames = *currencySymbols = nullptr; + *total_currency_name_count = *total_currency_symbol_count = 0; + return; } // Get maximum currency name count first. getCurrencyNameCount(loc.data(), total_currency_name_count, total_currency_symbol_count); - *currencyNames = (CurrencyNameStruct*)uprv_malloc - (sizeof(CurrencyNameStruct) * (*total_currency_name_count)); - *currencySymbols = (CurrencyNameStruct*)uprv_malloc - (sizeof(CurrencyNameStruct) * (*total_currency_symbol_count)); - - if(currencyNames == nullptr || currencySymbols == nullptr) { - ec = U_MEMORY_ALLOCATION_ERROR; + *currencyNames = static_cast<CurrencyNameStruct*>( + uprv_malloc(sizeof(CurrencyNameStruct) * (*total_currency_name_count))); + if(*currencyNames == nullptr) { + *currencySymbols = nullptr; + *total_currency_name_count = *total_currency_symbol_count = 0; + ec = U_MEMORY_ALLOCATION_ERROR; + return; } + *currencySymbols = static_cast<CurrencyNameStruct*>( + uprv_malloc(sizeof(CurrencyNameStruct) * (*total_currency_symbol_count))); - if (U_FAILURE(ec)) return; + if(*currencySymbols == nullptr) { + uprv_free(*currencyNames); + *currencyNames = nullptr; + *total_currency_name_count = *total_currency_symbol_count = 0; + ec = U_MEMORY_ALLOCATION_ERROR; + return; + } const char16_t* s = nullptr; // currency name char* iso = nullptr; // currency ISO code @@ -1009,113 +1013,91 @@ collectCurrencyNames(const char* locale, UErrorCode ec4 = U_ZERO_ERROR; // Using hash to remove duplicates caused by locale fallback - UHashtable* currencyIsoCodes = uhash_open(uhash_hashChars, uhash_compareChars, nullptr, &ec3); - UHashtable* currencyPluralIsoCodes = uhash_open(uhash_hashChars, uhash_compareChars, nullptr, &ec4); + LocalUHashtablePointer currencyIsoCodes(uhash_open(uhash_hashChars, uhash_compareChars, nullptr, &ec3)); + LocalUHashtablePointer currencyPluralIsoCodes(uhash_open(uhash_hashChars, uhash_compareChars, nullptr, &ec4)); for (int32_t localeLevel = 0; ; ++localeLevel) { ec2 = U_ZERO_ERROR; // TODO: ures_openDirect - UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc.data(), &ec2); - UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, nullptr, &ec2); - int32_t n = ures_getSize(curr); + LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_CURR, loc.data(), &ec2)); + LocalUResourceBundlePointer curr(ures_getByKey(rb.getAlias(), CURRENCIES, nullptr, &ec2)); + int32_t n = ures_getSize(curr.getAlias()); for (int32_t i=0; i<n; ++i) { - UResourceBundle* names = ures_getByIndex(curr, i, nullptr, &ec2); + LocalUResourceBundlePointer names(ures_getByIndex(curr.getAlias(), i, nullptr, &ec2)); int32_t len; - s = ures_getStringByIndex(names, UCURR_SYMBOL_NAME, &len, &ec2); + s = ures_getStringByIndex(names.getAlias(), UCURR_SYMBOL_NAME, &len, &ec2); // TODO: uhash_put wont change key/value? - iso = (char*)ures_getKey(names); - if (localeLevel == 0) { - uhash_put(currencyIsoCodes, iso, iso, &ec3); - } else { - if (uhash_get(currencyIsoCodes, iso) != nullptr) { - ures_close(names); - continue; - } else { - uhash_put(currencyIsoCodes, iso, iso, &ec3); - } + iso = const_cast<char*>(ures_getKey(names.getAlias())); + if (localeLevel != 0 && uhash_get(currencyIsoCodes.getAlias(), iso) != nullptr) { + continue; } + uhash_put(currencyIsoCodes.getAlias(), iso, iso, &ec3); // Add currency symbol. - (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso; - (*currencySymbols)[*total_currency_symbol_count].currencyName = (char16_t*)s; - (*currencySymbols)[*total_currency_symbol_count].flag = 0; - (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = len; + (*currencySymbols)[(*total_currency_symbol_count)++] = {iso, const_cast<char16_t*>(s), len, 0}; + // Add equivalent symbols if (currencySymbolsEquiv != nullptr) { UnicodeString str(true, s, len); icu::EquivIterator iter(*currencySymbolsEquiv, str); const UnicodeString *symbol; while ((symbol = iter.next()) != nullptr) { - (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso; - (*currencySymbols)[*total_currency_symbol_count].currencyName = - const_cast<char16_t*>(symbol->getBuffer()); - (*currencySymbols)[*total_currency_symbol_count].flag = 0; - (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = symbol->length(); + (*currencySymbols)[(*total_currency_symbol_count)++] + = {iso, const_cast<char16_t*>(symbol->getBuffer()), symbol->length(), 0}; } } // Add currency long name. - s = ures_getStringByIndex(names, UCURR_LONG_NAME, &len, &ec2); - (*currencyNames)[*total_currency_name_count].IsoCode = iso; + s = ures_getStringByIndex(names.getAlias(), UCURR_LONG_NAME, &len, &ec2); char16_t* upperName = toUpperCase(s, len, locale); - (*currencyNames)[*total_currency_name_count].currencyName = upperName; - (*currencyNames)[*total_currency_name_count].flag = NEED_TO_BE_DELETED; - (*currencyNames)[(*total_currency_name_count)++].currencyNameLen = len; + if (upperName == nullptr) { + ec = U_MEMORY_ALLOCATION_ERROR; + goto error; + } + (*currencyNames)[(*total_currency_name_count)++] = {iso, upperName, len, NEED_TO_BE_DELETED}; // put (iso, 3, and iso) in to array // Add currency ISO code. - (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso; - (*currencySymbols)[*total_currency_symbol_count].currencyName = (char16_t*)uprv_malloc(sizeof(char16_t)*3); + char16_t* isoCode = static_cast<char16_t*>(uprv_malloc(sizeof(char16_t) * 3)); + if (isoCode == nullptr) { + ec = U_MEMORY_ALLOCATION_ERROR; + goto error; + } // Must convert iso[] into Unicode - u_charsToUChars(iso, (*currencySymbols)[*total_currency_symbol_count].currencyName, 3); - (*currencySymbols)[*total_currency_symbol_count].flag = NEED_TO_BE_DELETED; - (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = 3; - - ures_close(names); + u_charsToUChars(iso, isoCode, 3); + (*currencySymbols)[(*total_currency_symbol_count)++] = {iso, isoCode, 3, NEED_TO_BE_DELETED}; } // currency plurals UErrorCode ec5 = U_ZERO_ERROR; - UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, nullptr, &ec5); - n = ures_getSize(curr_p); + LocalUResourceBundlePointer curr_p(ures_getByKey(rb.getAlias(), CURRENCYPLURALS, nullptr, &ec5)); + n = ures_getSize(curr_p.getAlias()); for (int32_t i=0; i<n; ++i) { - UResourceBundle* names = ures_getByIndex(curr_p, i, nullptr, &ec5); - iso = (char*)ures_getKey(names); + LocalUResourceBundlePointer names(ures_getByIndex(curr_p.getAlias(), i, nullptr, &ec5)); + iso = const_cast<char*>(ures_getKey(names.getAlias())); // Using hash to remove duplicated ISO codes in fallback chain. - if (localeLevel == 0) { - uhash_put(currencyPluralIsoCodes, iso, iso, &ec4); - } else { - if (uhash_get(currencyPluralIsoCodes, iso) != nullptr) { - ures_close(names); - continue; - } else { - uhash_put(currencyPluralIsoCodes, iso, iso, &ec4); - } + if (localeLevel != 0 && uhash_get(currencyPluralIsoCodes.getAlias(), iso) != nullptr) { + continue; } - int32_t num = ures_getSize(names); + uhash_put(currencyPluralIsoCodes.getAlias(), iso, iso, &ec4); + int32_t num = ures_getSize(names.getAlias()); int32_t len; for (int32_t j = 0; j < num; ++j) { // TODO: remove duplicates between singular name and // currency long name? - s = ures_getStringByIndex(names, j, &len, &ec5); - (*currencyNames)[*total_currency_name_count].IsoCode = iso; + s = ures_getStringByIndex(names.getAlias(), j, &len, &ec5); char16_t* upperName = toUpperCase(s, len, locale); - (*currencyNames)[*total_currency_name_count].currencyName = upperName; - (*currencyNames)[*total_currency_name_count].flag = NEED_TO_BE_DELETED; - (*currencyNames)[(*total_currency_name_count)++].currencyNameLen = len; + if (upperName == nullptr) { + ec = U_MEMORY_ALLOCATION_ERROR; + goto error; + } + (*currencyNames)[(*total_currency_name_count)++] = {iso, upperName, len, NEED_TO_BE_DELETED}; } - ures_close(names); } - ures_close(curr_p); - ures_close(curr); - ures_close(rb); if (!fallback(loc)) { break; } } - uhash_close(currencyIsoCodes); - uhash_close(currencyPluralIsoCodes); - // quick sort the struct qsort(*currencyNames, *total_currency_name_count, sizeof(CurrencyNameStruct), currencyNameComparator); @@ -1147,11 +1129,17 @@ collectCurrencyNames(const char* locale, // fail on hashtable errors if (U_FAILURE(ec3)) { ec = ec3; - return; - } - if (U_FAILURE(ec4)) { + } else if (U_FAILURE(ec4)) { ec = ec4; - return; + } + + error: + // clean up if we got error + if (U_FAILURE(ec)) { + deleteCurrencyNames(*currencyNames, *total_currency_name_count); + deleteCurrencyNames(*currencySymbols, *total_currency_symbol_count); + *currencyNames = *currencySymbols = nullptr; + *total_currency_name_count = *total_currency_symbol_count = 0; } } @@ -1485,7 +1473,13 @@ getCacheEntry(const char* locale, UErrorCode& ec) { deleteCacheEntry(cacheEntry); } } - cacheEntry = (CurrencyNameCacheEntry*)uprv_malloc(sizeof(CurrencyNameCacheEntry)); + cacheEntry = static_cast<CurrencyNameCacheEntry*>(uprv_malloc(sizeof(CurrencyNameCacheEntry))); + if (cacheEntry == nullptr) { + deleteCurrencyNames(currencyNames, total_currency_name_count); + deleteCurrencyNames(currencySymbols, total_currency_symbol_count); + ec = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } currCache[currentCacheEntryIndex] = cacheEntry; uprv_strcpy(cacheEntry->locale, locale); cacheEntry->currencyNames = currencyNames; @@ -2030,6 +2024,7 @@ static const struct CurrencyList { {"ZRN", UCURR_COMMON|UCURR_DEPRECATED}, {"ZRZ", UCURR_COMMON|UCURR_DEPRECATED}, {"ZWD", UCURR_COMMON|UCURR_DEPRECATED}, + {"ZWG", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"ZWL", UCURR_COMMON|UCURR_DEPRECATED}, {"ZWR", UCURR_COMMON|UCURR_DEPRECATED}, { nullptr, 0 } // Leave here to denote the end of the list. @@ -2095,18 +2090,18 @@ ucurr_createCurrencyList(UHashtable *isoCodes, UErrorCode* status){ // Look up the CurrencyMap element in the root bundle. UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus); - UResourceBundle *currencyMapArray = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); + LocalUResourceBundlePointer currencyMapArray(ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus)); if (U_SUCCESS(localStatus)) { - // process each entry in currency map - for (int32_t i=0; i<ures_getSize(currencyMapArray); i++) { + // process each entry in currency map + for (int32_t i=0; i<ures_getSize(currencyMapArray.getAlias()); i++) { // get the currency resource - UResourceBundle *currencyArray = ures_getByIndex(currencyMapArray, i, nullptr, &localStatus); - // process each currency + LocalUResourceBundlePointer currencyArray(ures_getByIndex(currencyMapArray.getAlias(), i, nullptr, &localStatus)); + // process each currency if (U_SUCCESS(localStatus)) { - for (int32_t j=0; j<ures_getSize(currencyArray); j++) { + for (int32_t j=0; j<ures_getSize(currencyArray.getAlias()); j++) { // get the currency resource - UResourceBundle *currencyRes = ures_getByIndex(currencyArray, j, nullptr, &localStatus); + LocalUResourceBundlePointer currencyRes(ures_getByIndex(currencyArray.getAlias(), j, nullptr, &localStatus)); IsoCodeEntry *entry = (IsoCodeEntry*)uprv_malloc(sizeof(IsoCodeEntry)); if (entry == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -2115,41 +2110,36 @@ ucurr_createCurrencyList(UHashtable *isoCodes, UErrorCode* status){ // get the ISO code int32_t isoLength = 0; - UResourceBundle *idRes = ures_getByKey(currencyRes, "id", nullptr, &localStatus); - if (idRes == nullptr) { + LocalUResourceBundlePointer idRes(ures_getByKey(currencyRes.getAlias(), "id", nullptr, &localStatus)); + if (idRes.isNull()) { continue; } - const char16_t *isoCode = ures_getString(idRes, &isoLength, &localStatus); + const char16_t *isoCode = ures_getString(idRes.getAlias(), &isoLength, &localStatus); // get from date UDate fromDate = U_DATE_MIN; - UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", nullptr, &localStatus); + LocalUResourceBundlePointer fromRes(ures_getByKey(currencyRes.getAlias(), "from", nullptr, &localStatus)); if (U_SUCCESS(localStatus)) { int32_t fromLength = 0; - const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus); + const int32_t *fromArray = ures_getIntVector(fromRes.getAlias(), &fromLength, &localStatus); int64_t currDate64 = ((uint64_t)fromArray[0]) << 32; currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF)); fromDate = (UDate)currDate64; } - ures_close(fromRes); // get to date UDate toDate = U_DATE_MAX; localStatus = U_ZERO_ERROR; - UResourceBundle *toRes = ures_getByKey(currencyRes, "to", nullptr, &localStatus); + LocalUResourceBundlePointer toRes(ures_getByKey(currencyRes.getAlias(), "to", nullptr, &localStatus)); if (U_SUCCESS(localStatus)) { int32_t toLength = 0; - const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus); + const int32_t *toArray = ures_getIntVector(toRes.getAlias(), &toLength, &localStatus); int64_t currDate64 = (uint64_t)toArray[0] << 32; currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF)); toDate = (UDate)currDate64; } - ures_close(toRes); - - ures_close(idRes); - ures_close(currencyRes); entry->isoCode = isoCode; entry->from = fromDate; @@ -2161,13 +2151,10 @@ ucurr_createCurrencyList(UHashtable *isoCodes, UErrorCode* status){ } else { *status = localStatus; } - ures_close(currencyArray); } } else { *status = localStatus; } - - ures_close(currencyMapArray); } static const UEnumeration gEnumCurrencyList = { @@ -2186,19 +2173,18 @@ static void U_CALLCONV initIsoCodes(UErrorCode &status) { U_ASSERT(gIsoCodes == nullptr); ucln_common_registerCleanup(UCLN_COMMON_CURRENCY, currency_cleanup); - UHashtable *isoCodes = uhash_open(uhash_hashUChars, uhash_compareUChars, nullptr, &status); + LocalUHashtablePointer isoCodes(uhash_open(uhash_hashUChars, uhash_compareUChars, nullptr, &status)); if (U_FAILURE(status)) { return; } - uhash_setValueDeleter(isoCodes, deleteIsoCodeEntry); + uhash_setValueDeleter(isoCodes.getAlias(), deleteIsoCodeEntry); - ucurr_createCurrencyList(isoCodes, &status); + ucurr_createCurrencyList(isoCodes.getAlias(), &status); if (U_FAILURE(status)) { - uhash_close(isoCodes); return; } - gIsoCodes = isoCodes; // Note: gIsoCodes is const. Once set up here it is never altered, - // and read only access is safe without synchronization. + gIsoCodes = isoCodes.orphan(); // Note: gIsoCodes is const. Once set up here it is never altered, + // and read only access is safe without synchronization. } static void populateCurrSymbolsEquiv(icu::Hashtable *hash, UErrorCode &status) { @@ -2320,30 +2306,30 @@ ucurr_countCurrencies(const char* locale, UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); // Using the id derived from the local, get the currency data - UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus); + LocalUResourceBundlePointer countryArray(ures_getByKey(rb, id.data(), cm, &localStatus)); // process each currency to see which one is valid for the given date if (U_SUCCESS(localStatus)) { - for (int32_t i=0; i<ures_getSize(countryArray); i++) + for (int32_t i=0; i<ures_getSize(countryArray.getAlias()); i++) { // get the currency resource - UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, nullptr, &localStatus); + LocalUResourceBundlePointer currencyRes(ures_getByIndex(countryArray.getAlias(), i, nullptr, &localStatus)); // get the from date int32_t fromLength = 0; - UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", nullptr, &localStatus); - const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus); + LocalUResourceBundlePointer fromRes(ures_getByKey(currencyRes.getAlias(), "from", nullptr, &localStatus)); + const int32_t *fromArray = ures_getIntVector(fromRes.getAlias(), &fromLength, &localStatus); int64_t currDate64 = (int64_t)((uint64_t)(fromArray[0]) << 32); currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF)); UDate fromDate = (UDate)currDate64; - if (ures_getSize(currencyRes)> 2) + if (ures_getSize(currencyRes.getAlias())> 2) { int32_t toLength = 0; - UResourceBundle *toRes = ures_getByKey(currencyRes, "to", nullptr, &localStatus); - const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus); + LocalUResourceBundlePointer toRes(ures_getByKey(currencyRes.getAlias(), "to", nullptr, &localStatus)); + const int32_t *toArray = ures_getIntVector(toRes.getAlias(), &toLength, &localStatus); currDate64 = (int64_t)toArray[0] << 32; currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF)); @@ -2353,8 +2339,6 @@ ucurr_countCurrencies(const char* locale, { currCount++; } - - ures_close(toRes); } else { @@ -2363,16 +2347,9 @@ ucurr_countCurrencies(const char* locale, currCount++; } } - - // close open resources - ures_close(currencyRes); - ures_close(fromRes); - } // end For loop } // end if (U_SUCCESS(localStatus)) - ures_close(countryArray); - // Check for errors if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) { @@ -2386,7 +2363,6 @@ ucurr_countCurrencies(const char* locale, // no errors return currCount; } - } // If we got here, either error code is invalid or @@ -2433,39 +2409,38 @@ ucurr_forLocaleAndDate(const char* locale, UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); // Using the id derived from the local, get the currency data - UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus); + LocalUResourceBundlePointer countryArray(ures_getByKey(rb, id.data(), cm, &localStatus)); // process each currency to see which one is valid for the given date bool matchFound = false; if (U_SUCCESS(localStatus)) { - if ((index <= 0) || (index> ures_getSize(countryArray))) + if ((index <= 0) || (index> ures_getSize(countryArray.getAlias()))) { // requested index is out of bounds - ures_close(countryArray); return 0; } - for (int32_t i=0; i<ures_getSize(countryArray); i++) + for (int32_t i=0; i<ures_getSize(countryArray.getAlias()); i++) { // get the currency resource - UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, nullptr, &localStatus); - s = ures_getStringByKey(currencyRes, "id", &resLen, &localStatus); + LocalUResourceBundlePointer currencyRes(ures_getByIndex(countryArray.getAlias(), i, nullptr, &localStatus)); + s = ures_getStringByKey(currencyRes.getAlias(), "id", &resLen, &localStatus); // get the from date int32_t fromLength = 0; - UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", nullptr, &localStatus); - const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus); + LocalUResourceBundlePointer fromRes(ures_getByKey(currencyRes.getAlias(), "from", nullptr, &localStatus)); + const int32_t *fromArray = ures_getIntVector(fromRes.getAlias(), &fromLength, &localStatus); int64_t currDate64 = (int64_t)((uint64_t)fromArray[0] << 32); currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF)); UDate fromDate = (UDate)currDate64; - if (ures_getSize(currencyRes)> 2) + if (ures_getSize(currencyRes.getAlias()) > 2) { int32_t toLength = 0; - UResourceBundle *toRes = ures_getByKey(currencyRes, "to", nullptr, &localStatus); - const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus); + LocalUResourceBundlePointer toRes(ures_getByKey(currencyRes.getAlias(), "to", nullptr, &localStatus)); + const int32_t *toArray = ures_getIntVector(toRes.getAlias(), &toLength, &localStatus); currDate64 = (int64_t)toArray[0] << 32; currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF)); @@ -2479,8 +2454,6 @@ ucurr_forLocaleAndDate(const char* locale, matchFound = true; } } - - ures_close(toRes); } else { @@ -2493,11 +2466,6 @@ ucurr_forLocaleAndDate(const char* locale, } } } - - // close open resources - ures_close(currencyRes); - ures_close(fromRes); - // check for loop exit if (matchFound) { @@ -2507,8 +2475,6 @@ ucurr_forLocaleAndDate(const char* locale, } // end For loop } - ures_close(countryArray); - // Check for errors if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) { @@ -2578,20 +2544,16 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, memcpy(en, &defaultKeywordValues, sizeof(UEnumeration)); en->context = values; - UResourceBundle *bundle = ures_openDirect(U_ICUDATA_CURR, "supplementalData", status); - ures_getByKey(bundle, "CurrencyMap", bundle, status); - UResourceBundle bundlekey, regbndl, curbndl, to; - ures_initStackObject(&bundlekey); - ures_initStackObject(®bndl); - ures_initStackObject(&curbndl); - ures_initStackObject(&to); + UResourceBundle* rb = ures_openDirect(U_ICUDATA_CURR, "supplementalData", status); + LocalUResourceBundlePointer bundle(ures_getByKey(rb, "CurrencyMap", rb, status)); + StackUResourceBundle bundlekey, regbndl, curbndl, to; - while (U_SUCCESS(*status) && ures_hasNext(bundle)) { - ures_getNextResource(bundle, &bundlekey, status); + while (U_SUCCESS(*status) && ures_hasNext(bundle.getAlias())) { + ures_getNextResource(bundle.getAlias(), bundlekey.getAlias(), status); if (U_FAILURE(*status)) { break; } - const char *region = ures_getKey(&bundlekey); + const char *region = ures_getKey(bundlekey.getAlias()); UBool isPrefRegion = prefRegion == region; if (!isPrefRegion && commonlyUsed) { // With commonlyUsed=true, we do not put @@ -2599,29 +2561,29 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, // result list. continue; } - ures_getByKey(bundle, region, ®bndl, status); + ures_getByKey(bundle.getAlias(), region, regbndl.getAlias(), status); if (U_FAILURE(*status)) { break; } - while (U_SUCCESS(*status) && ures_hasNext(®bndl)) { - ures_getNextResource(®bndl, &curbndl, status); - if (ures_getType(&curbndl) != URES_TABLE) { + while (U_SUCCESS(*status) && ures_hasNext(regbndl.getAlias())) { + ures_getNextResource(regbndl.getAlias(), curbndl.getAlias(), status); + if (ures_getType(curbndl.getAlias()) != URES_TABLE) { // Currently, an empty ARRAY is mixed in. continue; } char *curID = (char *)uprv_malloc(sizeof(char) * ULOC_KEYWORDS_CAPACITY); - int32_t curIDLength = ULOC_KEYWORDS_CAPACITY; if (curID == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; break; } + int32_t curIDLength = ULOC_KEYWORDS_CAPACITY; #if U_CHARSET_FAMILY==U_ASCII_FAMILY - ures_getUTF8StringByKey(&curbndl, "id", curID, &curIDLength, true, status); + ures_getUTF8StringByKey(curbndl.getAlias(), "id", curID, &curIDLength, true, status); /* optimize - use the utf-8 string */ #else { - const char16_t* defString = ures_getStringByKey(&curbndl, "id", &curIDLength, status); + const char16_t* defString = ures_getStringByKey(curbndl.getAlias(), "id", &curIDLength, status); if(U_SUCCESS(*status)) { if(curIDLength+1 > ULOC_KEYWORDS_CAPACITY) { *status = U_BUFFER_OVERFLOW_ERROR; @@ -2636,7 +2598,7 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, break; } UBool hasTo = false; - ures_getByKey(&curbndl, "to", &to, status); + ures_getByKey(curbndl.getAlias(), "to", to.getAlias(), status); if (U_FAILURE(*status)) { // Do nothing here... *status = U_ZERO_ERROR; @@ -2669,6 +2631,10 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, while ((value = (char *)ulist_getNext(otherValues)) != nullptr) { if (!ulist_containsString(values, value, (int32_t)uprv_strlen(value))) { char *tmpValue = (char *)uprv_malloc(sizeof(char) * ULOC_KEYWORDS_CAPACITY); + if (tmpValue == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; + break; + } uprv_memcpy(tmpValue, value, uprv_strlen(value) + 1); ulist_addItemEndList(values, tmpValue, true, status); if (U_FAILURE(*status)) { @@ -2677,7 +2643,6 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, } } } - ulist_resetList((UList *)(en->context)); } else { ulist_deleteList(values); @@ -2685,14 +2650,7 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, values = nullptr; en = nullptr; } - ures_close(&to); - ures_close(&curbndl); - ures_close(®bndl); - ures_close(&bundlekey); - ures_close(bundle); - ulist_deleteList(otherValues); - return en; } @@ -2703,19 +2661,18 @@ ucurr_getNumericCode(const char16_t* currency) { if (currency && u_strlen(currency) == ISO_CURRENCY_CODE_LENGTH) { UErrorCode status = U_ZERO_ERROR; - UResourceBundle *bundle = ures_openDirect(nullptr, "currencyNumericCodes", &status); - ures_getByKey(bundle, "codeMap", bundle, &status); + UResourceBundle* bundle = ures_openDirect(nullptr, "currencyNumericCodes", &status); + LocalUResourceBundlePointer codeMap(ures_getByKey(bundle, "codeMap", bundle, &status)); if (U_SUCCESS(status)) { char alphaCode[ISO_CURRENCY_CODE_LENGTH+1]; myUCharsToChars(alphaCode, currency); T_CString_toUpperCase(alphaCode); - ures_getByKey(bundle, alphaCode, bundle, &status); - int tmpCode = ures_getInt(bundle, &status); + ures_getByKey(codeMap.getAlias(), alphaCode, codeMap.getAlias(), &status); + int tmpCode = ures_getInt(codeMap.getAlias(), &status); if (U_SUCCESS(status)) { code = tmpCode; } } - ures_close(bundle); } return code; } diff --git a/thirdparty/icu4c/common/udata.cpp b/thirdparty/icu4c/common/udata.cpp index 4c2ba57303..68b6227290 100644 --- a/thirdparty/icu4c/common/udata.cpp +++ b/thirdparty/icu4c/common/udata.cpp @@ -274,7 +274,7 @@ typedef struct DataCacheElement { * here for each entry. */ static void U_CALLCONV DataCacheElement_deleter(void *pDCEl) { - DataCacheElement *p = (DataCacheElement *)pDCEl; + DataCacheElement* p = static_cast<DataCacheElement*>(pDCEl); udata_close(p->item); /* unmaps storage */ uprv_free(p->name); /* delete the hash key string. */ uprv_free(pDCEl); /* delete 'this' */ @@ -316,7 +316,7 @@ static UDataMemory *udata_findCachedData(const char *path, UErrorCode &err) baseName = findBasename(path); /* Cache remembers only the base name, not the full path. */ umtx_lock(nullptr); - el = (DataCacheElement *)uhash_get(htable, baseName); + el = static_cast<DataCacheElement*>(uhash_get(htable, baseName)); umtx_unlock(nullptr); if (el != nullptr) { retVal = el->item; @@ -344,7 +344,7 @@ static UDataMemory *udata_cacheDataItem(const char *path, UDataMemory *item, UEr /* Create a new DataCacheElement - the thingy we store in the hash table - * and copy the supplied path and UDataMemoryItems into it. */ - newElement = (DataCacheElement *)uprv_malloc(sizeof(DataCacheElement)); + newElement = static_cast<DataCacheElement*>(uprv_malloc(sizeof(DataCacheElement))); if (newElement == nullptr) { *pErr = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -357,8 +357,8 @@ static UDataMemory *udata_cacheDataItem(const char *path, UDataMemory *item, UEr UDatamemory_assign(newElement->item, item); baseName = findBasename(path); - nameLen = (int32_t)uprv_strlen(baseName); - newElement->name = (char *)uprv_malloc(nameLen+1); + nameLen = static_cast<int32_t>(uprv_strlen(baseName)); + newElement->name = static_cast<char*>(uprv_malloc(nameLen + 1)); if (newElement->name == nullptr) { *pErr = U_MEMORY_ALLOCATION_ERROR; uprv_free(newElement->item); @@ -370,7 +370,7 @@ static UDataMemory *udata_cacheDataItem(const char *path, UDataMemory *item, UEr /* Stick the new DataCacheElement into the hash table. */ umtx_lock(nullptr); - oldValue = (DataCacheElement *)uhash_get(htable, path); + oldValue = static_cast<DataCacheElement*>(uhash_get(htable, path)); if (oldValue != nullptr) { subErr = U_USING_DEFAULT_WARNING; } @@ -469,13 +469,13 @@ UDataPathIterator::UDataPathIterator(const char *inPath, const char *pkg, /** Item **/ basename = findBasename(item); - basenameLen = (int32_t)uprv_strlen(basename); + basenameLen = static_cast<int32_t>(uprv_strlen(basename)); /** Item path **/ if(basename == item) { nextPath = path; } else { - itemPath.append(item, (int32_t)(basename-item), *pErrorCode); + itemPath.append(item, static_cast<int32_t>(basename - item), *pErrorCode); nextPath = itemPath.data(); } #ifdef UDATA_DEBUG @@ -531,16 +531,16 @@ const char *UDataPathIterator::next(UErrorCode *pErrorCode) if(nextPath == itemPath.data()) { /* we were processing item's path. */ nextPath = path; /* start with regular path next tm. */ - pathLen = (int32_t)uprv_strlen(currentPath); + pathLen = static_cast<int32_t>(uprv_strlen(currentPath)); } else { /* fix up next for next time */ nextPath = uprv_strchr(currentPath, U_PATH_SEP_CHAR); if(nextPath == nullptr) { /* segment: entire path */ - pathLen = (int32_t)uprv_strlen(currentPath); + pathLen = static_cast<int32_t>(uprv_strlen(currentPath)); } else { /* segment: until next segment */ - pathLen = (int32_t)(nextPath - currentPath); + pathLen = static_cast<int32_t>(nextPath - currentPath); /* skip divider */ nextPath ++; } @@ -777,17 +777,6 @@ openCommonData(const char *path, /* Path from OpenChoice? */ return nullptr; } -#if defined(OS390_STUBDATA) && defined(OS390BATCH) - if (!UDataMemory_isLoaded(&tData)) { - char ourPathBuffer[1024]; - /* One more chance, for extendCommonData() */ - uprv_strncpy(ourPathBuffer, path, 1019); - ourPathBuffer[1019]=0; - uprv_strcat(ourPathBuffer, ".dat"); - uprv_mapFile(&tData, ourPathBuffer, pErrorCode); - } -#endif - if (U_FAILURE(*pErrorCode)) { return nullptr; } @@ -1231,7 +1220,7 @@ doOpenChoice(const char *path, const char *type, const char *name, if(isICUData) { pkgName.append(U_ICUDATA_NAME, *pErrorCode); } else { - pkgName.append(path, (int32_t)(treeChar-path), *pErrorCode); + pkgName.append(path, static_cast<int32_t>(treeChar - path), *pErrorCode); if (first == nullptr) { /* This user data has no path, but there is a tree name. diff --git a/thirdparty/icu4c/common/udataswp.cpp b/thirdparty/icu4c/common/udataswp.cpp index 0f194f47e8..09adf9510c 100644 --- a/thirdparty/icu4c/common/udataswp.cpp +++ b/thirdparty/icu4c/common/udataswp.cpp @@ -47,12 +47,12 @@ uprv_swapArray16(const UDataSwapper *ds, } /* setup and swapping */ - p=(const uint16_t *)inData; - q=(uint16_t *)outData; + p = static_cast<const uint16_t*>(inData); + q = static_cast<uint16_t*>(outData); count=length/2; while(count>0) { x=*p++; - *q++=(uint16_t)((x<<8)|(x>>8)); + *q++ = static_cast<uint16_t>((x << 8) | (x >> 8)); --count; } @@ -95,12 +95,12 @@ uprv_swapArray32(const UDataSwapper *ds, } /* setup and swapping */ - p=(const uint32_t *)inData; - q=(uint32_t *)outData; + p = static_cast<const uint32_t*>(inData); + q = static_cast<uint32_t*>(outData); count=length/4; while(count>0) { x=*p++; - *q++=(uint32_t)((x<<24)|((x<<8)&0xff0000)|((x>>8)&0xff00)|(x>>24)); + *q++ = (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | (x >> 24); --count; } @@ -142,8 +142,8 @@ uprv_swapArray64(const UDataSwapper *ds, } /* setup and swapping */ - p=(const uint64_t *)inData; - q=(uint64_t *)outData; + p = static_cast<const uint64_t*>(inData); + q = static_cast<uint64_t*>(outData); count=length/8; while(count>0) { uint64_t x=*p++; @@ -176,7 +176,7 @@ uprv_copyArray64(const UDataSwapper *ds, static uint16_t U_CALLCONV uprv_readSwapUInt16(uint16_t x) { - return (uint16_t)((x<<8)|(x>>8)); + return static_cast<uint16_t>((x << 8) | (x >> 8)); } static uint16_t U_CALLCONV @@ -186,7 +186,7 @@ uprv_readDirectUInt16(uint16_t x) { static uint32_t U_CALLCONV uprv_readSwapUInt32(uint32_t x) { - return (uint32_t)((x<<24)|((x<<8)&0xff0000)|((x>>8)&0xff00)|(x>>24)); + return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | (x >> 24); } static uint32_t U_CALLCONV @@ -196,7 +196,7 @@ uprv_readDirectUInt32(uint32_t x) { static void U_CALLCONV uprv_writeSwapUInt16(uint16_t *p, uint16_t x) { - *p=(uint16_t)((x<<8)|(x>>8)); + *p = static_cast<uint16_t>((x << 8) | (x >> 8)); } static void U_CALLCONV @@ -206,7 +206,7 @@ uprv_writeDirectUInt16(uint16_t *p, uint16_t x) { static void U_CALLCONV uprv_writeSwapUInt32(uint32_t *p, uint32_t x) { - *p=(uint32_t)((x<<24)|((x<<8)&0xff0000)|((x>>8)&0xff00)|(x>>24)); + *p = (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | (x >> 24); } static void U_CALLCONV diff --git a/thirdparty/icu4c/common/uenum.cpp b/thirdparty/icu4c/common/uenum.cpp index 7aab58c44c..b4a5071ae7 100644 --- a/thirdparty/icu4c/common/uenum.cpp +++ b/thirdparty/icu4c/common/uenum.cpp @@ -34,14 +34,14 @@ static const int32_t PAD = 8; static void* _getBuffer(UEnumeration* en, int32_t capacity) { if (en->baseContext != nullptr) { - if (((_UEnumBuffer*) en->baseContext)->len < capacity) { + if (static_cast<_UEnumBuffer*>(en->baseContext)->len < capacity) { capacity += PAD; en->baseContext = uprv_realloc(en->baseContext, sizeof(int32_t) + capacity); if (en->baseContext == nullptr) { return nullptr; } - ((_UEnumBuffer*) en->baseContext)->len = capacity; + static_cast<_UEnumBuffer*>(en->baseContext)->len = capacity; } } else { capacity += PAD; @@ -49,10 +49,10 @@ static void* _getBuffer(UEnumeration* en, int32_t capacity) { if (en->baseContext == nullptr) { return nullptr; } - ((_UEnumBuffer*) en->baseContext)->len = capacity; + static_cast<_UEnumBuffer*>(en->baseContext)->len = capacity; } - return (void*) & ((_UEnumBuffer*) en->baseContext)->data; + return static_cast<void*>(&static_cast<_UEnumBuffer*>(en->baseContext)->data); } U_CAPI void U_EXPORT2 diff --git a/thirdparty/icu4c/common/uhash.cpp b/thirdparty/icu4c/common/uhash.cpp index 4d92dfa93f..02dc3d0478 100644 --- a/thirdparty/icu4c/common/uhash.cpp +++ b/thirdparty/icu4c/common/uhash.cpp @@ -12,6 +12,8 @@ ****************************************************************************** */ +#include <string_view> + #include "uhash.h" #include "unicode/ustring.h" #include "cstring.h" @@ -224,8 +226,8 @@ _uhash_allocate(UHashtable *hash, hash->primeIndex = static_cast<int8_t>(primeIndex); hash->length = PRIMES[primeIndex]; - p = hash->elements = (UHashElement*) - uprv_malloc(sizeof(UHashElement) * hash->length); + p = hash->elements = static_cast<UHashElement*>( + uprv_malloc(sizeof(UHashElement) * hash->length)); if (hash->elements == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -244,8 +246,8 @@ _uhash_allocate(UHashtable *hash, } hash->count = 0; - hash->lowWaterMark = (int32_t)(hash->length * hash->lowWaterRatio); - hash->highWaterMark = (int32_t)(hash->length * hash->highWaterRatio); + hash->lowWaterMark = static_cast<int32_t>(hash->length * hash->lowWaterRatio); + hash->highWaterMark = static_cast<int32_t>(hash->length * hash->highWaterRatio); } static UHashtable* @@ -287,7 +289,7 @@ _uhash_create(UHashFunction *keyHash, if (U_FAILURE(*status)) return nullptr; - result = (UHashtable*) uprv_malloc(sizeof(UHashtable)); + result = static_cast<UHashtable*>(uprv_malloc(sizeof(UHashtable))); if (result == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -944,6 +946,12 @@ uhash_hashIChars(const UHashTok key) { return s == nullptr ? 0 : ustr_hashICharsN(s, static_cast<int32_t>(uprv_strlen(s))); } +U_CAPI int32_t U_EXPORT2 +uhash_hashIStringView(const UHashTok key) { + const std::string_view* s = static_cast<std::string_view*>(key.pointer); + return s == nullptr ? 0 : ustr_hashICharsN(s->data(), static_cast<int32_t>(s->size())); +} + U_CAPI UBool U_EXPORT2 uhash_equals(const UHashtable* hash1, const UHashtable* hash2){ int32_t count1, count2, pos, i; @@ -1014,7 +1022,7 @@ uhash_compareUChars(const UHashTok key1, const UHashTok key2) { ++p1; ++p2; } - return (UBool)(*p1 == *p2); + return *p1 == *p2; } U_CAPI UBool U_EXPORT2 @@ -1031,7 +1039,7 @@ uhash_compareChars(const UHashTok key1, const UHashTok key2) { ++p1; ++p2; } - return (UBool)(*p1 == *p2); + return *p1 == *p2; } U_CAPI UBool U_EXPORT2 @@ -1048,7 +1056,30 @@ uhash_compareIChars(const UHashTok key1, const UHashTok key2) { ++p1; ++p2; } - return (UBool)(*p1 == *p2); + return *p1 == *p2; +} + +U_CAPI UBool U_EXPORT2 +uhash_compareIStringView(const UHashTok key1, const UHashTok key2) { + const std::string_view* p1 = static_cast<std::string_view*>(key1.pointer); + const std::string_view* p2 = static_cast<std::string_view*>(key2.pointer); + if (p1 == p2) { + return true; + } + if (p1 == nullptr || p2 == nullptr) { + return false; + } + const std::string_view& v1 = *p1; + const std::string_view& v2 = *p2; + if (v1.size() != v2.size()) { + return false; + } + for (size_t i = 0; i < v1.size(); ++i) { + if (uprv_tolower(v1[i]) != uprv_tolower(v2[i])) { + return false; + } + } + return true; } /******************************************************************** @@ -1062,5 +1093,5 @@ uhash_hashLong(const UHashTok key) { U_CAPI UBool U_EXPORT2 uhash_compareLong(const UHashTok key1, const UHashTok key2) { - return (UBool)(key1.integer == key2.integer); + return key1.integer == key2.integer; } diff --git a/thirdparty/icu4c/common/uhash.h b/thirdparty/icu4c/common/uhash.h index 2ce296f0ec..d381670b87 100644 --- a/thirdparty/icu4c/common/uhash.h +++ b/thirdparty/icu4c/common/uhash.h @@ -695,6 +695,15 @@ U_CAPI int32_t U_EXPORT2 uhash_hashIChars(const UHashTok key); /** + * Generate a case-insensitive hash code for a std::string_view. + * Use together with uhash_compareIStringView. + * @param key A pointer to the std::string_view to hash. + * @return A hash code for the key. + */ +U_CAPI int32_t U_EXPORT2 +uhash_hashIStringView(const UHashTok key); + +/** * Comparator for null-terminated UChar* strings. Use together with * uhash_hashUChars. * @param key1 The string for comparison @@ -724,6 +733,16 @@ uhash_compareChars(const UHashTok key1, const UHashTok key2); U_CAPI UBool U_EXPORT2 uhash_compareIChars(const UHashTok key1, const UHashTok key2); +/** + * Case-insensitive comparator for std::string_view. + * Use together with uhash_hashIStringView. + * @param key1 A pointer to the std::string_view for comparison + * @param key2 A pointer to the std::string_view for comparison + * @return true if key1 and key2 are equal, return false otherwise. + */ +U_CAPI UBool U_EXPORT2 +uhash_compareIStringView(const UHashTok key1, const UHashTok key2); + /******************************************************************** * UnicodeString Support Functions ********************************************************************/ diff --git a/thirdparty/icu4c/common/uidna.cpp b/thirdparty/icu4c/common/uidna.cpp index 949d128f93..48b3d0eb70 100644 --- a/thirdparty/icu4c/common/uidna.cpp +++ b/thirdparty/icu4c/common/uidna.cpp @@ -107,7 +107,7 @@ compareCaseInsensitiveASCII(const char16_t* s1, int32_t s1Len, /* Case-insensitive comparison */ if(c1!=c2) { - rc=(int32_t)toASCIILower(c1)-(int32_t)toASCIILower(c2); + rc = static_cast<int32_t>(toASCIILower(c1)) - static_cast<int32_t>(toASCIILower(c2)); if(rc!=0) { lengthResult=rc; break; @@ -219,7 +219,7 @@ _internal_toASCII(const char16_t* src, int32_t srcLength, int32_t j=0; //get the options - UBool useSTD3ASCIIRules = (UBool)((options & UIDNA_USE_STD3_RULES) != 0); + UBool useSTD3ASCIIRules = static_cast<UBool>((options & UIDNA_USE_STD3_RULES) != 0); int32_t failPos = -1; @@ -228,7 +228,7 @@ _internal_toASCII(const char16_t* src, int32_t srcLength, } if(srcLength > b1Capacity){ - b1 = (char16_t*) uprv_malloc(srcLength * U_SIZEOF_UCHAR); + b1 = static_cast<char16_t*>(uprv_malloc(srcLength * U_SIZEOF_UCHAR)); if(b1==nullptr){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; @@ -256,7 +256,7 @@ _internal_toASCII(const char16_t* src, int32_t srcLength, if(b1 != b1Stack){ uprv_free(b1); } - b1 = (char16_t*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); + b1 = static_cast<char16_t*>(uprv_malloc(b1Len * U_SIZEOF_UCHAR)); if(b1==nullptr){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; @@ -338,7 +338,7 @@ _internal_toASCII(const char16_t* src, int32_t srcLength, if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ - b2 = (char16_t*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); + b2 = static_cast<char16_t*>(uprv_malloc(b2Len * U_SIZEOF_UCHAR)); if(b2 == nullptr){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; @@ -458,7 +458,7 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength, if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ - b1 = (char16_t*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); + b1 = static_cast<char16_t*>(uprv_malloc(b1Len * U_SIZEOF_UCHAR)); if(b1==nullptr){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; @@ -475,7 +475,7 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength, }else{ //just point src to b1 - b1 = (char16_t*) src; + b1 = const_cast<char16_t*>(src); b1Len = srcLength; } @@ -498,7 +498,7 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength, if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ - b2 = (char16_t*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); + b2 = static_cast<char16_t*>(uprv_malloc(b2Len * U_SIZEOF_UCHAR)); if(b2==nullptr){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; @@ -516,7 +516,7 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength, if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ - b3 = (char16_t*) uprv_malloc(b3Len * U_SIZEOF_UCHAR); + b3 = static_cast<char16_t*>(uprv_malloc(b3Len * U_SIZEOF_UCHAR)); if(b3==nullptr){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; @@ -585,6 +585,9 @@ CLEANUP: if(b2 != b2Stack){ uprv_free(b2); } + if(b3 != b3Stack){ + uprv_free(b3); + } uprv_free(caseFlags); // The RFC states that @@ -689,9 +692,9 @@ uidna_IDNToASCII( const char16_t *src, int32_t srcLength, } //initialize pointers - char16_t *delimiter = (char16_t*)src; - char16_t *labelStart = (char16_t*)src; - char16_t *currentDest = (char16_t*) dest; + char16_t* delimiter = const_cast<char16_t*>(src); + char16_t* labelStart = const_cast<char16_t*>(src); + char16_t* currentDest = dest; int32_t remainingLen = srcLength; int32_t remainingDestCapacity = destCapacity; int32_t labelLen = 0, labelReqLength = 0; @@ -782,9 +785,9 @@ uidna_IDNToUnicode( const char16_t* src, int32_t srcLength, } //initialize pointers - char16_t *delimiter = (char16_t*)src; - char16_t *labelStart = (char16_t*)src; - char16_t *currentDest = (char16_t*) dest; + char16_t* delimiter = const_cast<char16_t*>(src); + char16_t* labelStart = const_cast<char16_t*>(src); + char16_t* currentDest = dest; int32_t remainingLen = srcLength; int32_t remainingDestCapacity = destCapacity; int32_t labelLen = 0, labelReqLength = 0; diff --git a/thirdparty/icu4c/common/uinvchar.cpp b/thirdparty/icu4c/common/uinvchar.cpp index 096a8e28d1..2ffef7b580 100644 --- a/thirdparty/icu4c/common/uinvchar.cpp +++ b/thirdparty/icu4c/common/uinvchar.cpp @@ -446,7 +446,7 @@ uprv_copyEbcdic(const UDataSwapper *ds, return length; } -U_CFUNC UBool +U_CAPI UBool uprv_isEbcdicAtSign(char c) { static const uint8_t ebcdicAtSigns[] = { 0x7C, 0x44, 0x66, 0x80, 0xAC, 0xAE, 0xAF, 0xB5, 0xEC, 0xEF, 0x00 }; diff --git a/thirdparty/icu4c/common/uinvchar.h b/thirdparty/icu4c/common/uinvchar.h index 9b7a9bd114..3e031ccc5a 100644 --- a/thirdparty/icu4c/common/uinvchar.h +++ b/thirdparty/icu4c/common/uinvchar.h @@ -120,7 +120,7 @@ U_NAMESPACE_END * EBCDIC machine won't be compiled the same way on other EBCDIC based machines. * @internal */ -U_CFUNC UBool +U_CAPI UBool uprv_isEbcdicAtSign(char c); /** diff --git a/thirdparty/icu4c/common/uloc.cpp b/thirdparty/icu4c/common/uloc.cpp index 88fe7eaadc..51887c97c3 100644 --- a/thirdparty/icu4c/common/uloc.cpp +++ b/thirdparty/icu4c/common/uloc.cpp @@ -30,7 +30,9 @@ l = lang, C = ctry, M = charmap, V = variant */ +#include <algorithm> #include <optional> +#include <string_view> #include "unicode/bytestream.h" #include "unicode/errorcode.h" @@ -551,17 +553,17 @@ namespace { * @param status return status (keyword too long) * @return the keyword name */ -CharString locale_canonKeywordName(const char* keywordName, UErrorCode& status) +CharString locale_canonKeywordName(std::string_view keywordName, UErrorCode& status) { if (U_FAILURE(status)) { return {}; } CharString result; - for (; *keywordName != 0; keywordName++) { - if (!UPRV_ISALPHANUM(*keywordName)) { + for (char c : keywordName) { + if (!UPRV_ISALPHANUM(c)) { status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */ return {}; } - result.append(uprv_tolower(*keywordName), status); + result.append(uprv_tolower(c), status); } if (result.isEmpty()) { status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name */ @@ -580,8 +582,8 @@ typedef struct { int32_t U_CALLCONV compareKeywordStructs(const void * /*context*/, const void *left, const void *right) { - const char* leftString = ((const KeywordStruct *)left)->keyword; - const char* rightString = ((const KeywordStruct *)right)->keyword; + const char* leftString = static_cast<const KeywordStruct*>(left)->keyword; + const char* rightString = static_cast<const KeywordStruct*>(right)->keyword; return uprv_strcmp(leftString, rightString); } @@ -686,10 +688,10 @@ ulocimp_getKeywords(const char* localeID, while(*(pos - i - 1) == ' ') { i++; } - keywordList[numKeywords].valueLen = (int32_t)(pos - equalSign - i); + keywordList[numKeywords].valueLen = static_cast<int32_t>(pos - equalSign - i); pos++; } else { - i = (int32_t)uprv_strlen(equalSign); + i = static_cast<int32_t>(uprv_strlen(equalSign)); while(i && equalSign[i-1] == ' ') { i--; } @@ -733,6 +735,11 @@ uloc_getKeywordValue(const char* localeID, char* buffer, int32_t bufferCapacity, UErrorCode* status) { + if (U_FAILURE(*status)) { return 0; } + if (keywordName == nullptr || *keywordName == '\0') { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } return ByteSinkUtil::viaByteSinkToTerminatedChars( buffer, bufferCapacity, [&](ByteSink& sink, UErrorCode& status) { @@ -743,7 +750,7 @@ uloc_getKeywordValue(const char* localeID, U_EXPORT CharString ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, UErrorCode& status) { return ByteSinkUtil::viaByteSinkToCharString( @@ -755,13 +762,13 @@ ulocimp_getKeywordValue(const char* localeID, U_EXPORT void ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, icu::ByteSink& sink, UErrorCode& status) { if (U_FAILURE(status)) { return; } - if (localeID == nullptr || keywordName == nullptr || keywordName[0] == 0) { + if (localeID == nullptr || keywordName.empty()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } @@ -865,6 +872,11 @@ uloc_setKeywordValue(const char* keywordName, { if (U_FAILURE(*status)) { return 0; } + if (keywordName == nullptr || *keywordName == 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + if (bufferCapacity <= 1) { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; @@ -883,7 +895,11 @@ uloc_setKeywordValue(const char* keywordName, CheckedArrayByteSink sink(keywords == nullptr ? buffer + bufLen : keywords, bufferCapacity - baseLen - 1); int32_t reslen = ulocimp_setKeywordValue( - keywords, keywordName, keywordValue, sink, *status); + keywords == nullptr ? std::string_view() : keywords, + keywordName, + keywordValue == nullptr ? std::string_view() : keywordValue, + sink, + *status); if (U_FAILURE(*status)) { return *status == U_BUFFER_OVERFLOW_ERROR ? reslen + baseLen : 0; @@ -898,24 +914,29 @@ uloc_setKeywordValue(const char* keywordName, } U_EXPORT void -ulocimp_setKeywordValue(const char* keywordName, - const char* keywordValue, +ulocimp_setKeywordValue(std::string_view keywordName, + std::string_view keywordValue, CharString& localeID, UErrorCode& status) { if (U_FAILURE(status)) { return; } - // This is safe because CharString::truncate() doesn't actually erase any - // data, but simply sets the position for where new data will be written. - const char* keywords = locale_getKeywordsStart(localeID.data()); - if (keywords != nullptr) localeID.truncate(keywords - localeID.data()); + std::string_view keywords; + if (const char* start = locale_getKeywordsStart(localeID.data()); start != nullptr) { + // This is safe because CharString::truncate() doesn't actually erase any + // data, but simply sets the position for where new data will be written. + int32_t size = start - localeID.data(); + keywords = localeID.toStringPiece(); + keywords.remove_prefix(size); + localeID.truncate(size); + } CharStringByteSink sink(&localeID); ulocimp_setKeywordValue(keywords, keywordName, keywordValue, sink, status); } U_EXPORT int32_t -ulocimp_setKeywordValue(const char* keywords, - const char* keywordName, - const char* keywordValue, +ulocimp_setKeywordValue(std::string_view keywords, + std::string_view keywordName, + std::string_view keywordValue, ByteSink& sink, UErrorCode& status) { @@ -924,9 +945,6 @@ ulocimp_setKeywordValue(const char* keywords, /* TODO: sorting. removal. */ int32_t needLen = 0; int32_t rc; - const char* nextSeparator = nullptr; - const char* nextEqualsign = nullptr; - const char* keywordStart = nullptr; CharString updatedKeysAndValues; bool handledInputKeyAndValue = false; char keyValuePrefix = '@'; @@ -934,7 +952,7 @@ ulocimp_setKeywordValue(const char* keywords, if (status == U_STRING_NOT_TERMINATED_WARNING) { status = U_ZERO_ERROR; } - if (keywordName == nullptr || keywordName[0] == 0) { + if (keywordName.empty()) { status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } @@ -944,21 +962,19 @@ ulocimp_setKeywordValue(const char* keywords, } CharString canonKeywordValue; - if(keywordValue) { - while (*keywordValue != 0) { - if (!UPRV_ISALPHANUM(*keywordValue) && !UPRV_OK_VALUE_PUNCTUATION(*keywordValue)) { - status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */ - return 0; - } - /* Should we force lowercase in value to set? */ - canonKeywordValue.append(*keywordValue++, status); + for (char c : keywordValue) { + if (!UPRV_ISALPHANUM(c) && !UPRV_OK_VALUE_PUNCTUATION(c)) { + status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */ + return 0; } + /* Should we force lowercase in value to set? */ + canonKeywordValue.append(c, status); } if (U_FAILURE(status)) { return 0; } - if (keywords == nullptr || keywords[1] == '\0') { + if (keywords.size() <= 1) { if (canonKeywordValue.isEmpty()) { /* no keywords = nothing to remove */ U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING); return 0; @@ -984,23 +1000,20 @@ ulocimp_setKeywordValue(const char* keywords, return needLen; } /* end shortcut - no @ */ - keywordStart = keywords; /* search for keyword */ - while(keywordStart) { - const char* keyValueTail; - + for (size_t keywordStart = 0; keywordStart != std::string_view::npos;) { keywordStart++; /* skip @ or ; */ - nextEqualsign = uprv_strchr(keywordStart, '='); - if (!nextEqualsign) { + size_t nextEqualsign = keywords.find('=', keywordStart); + if (nextEqualsign == std::string_view::npos) { status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */ return 0; } /* strip leading & trailing spaces (TC decided to tolerate these) */ - while(*keywordStart == ' ') { + while (keywordStart < keywords.size() && keywords[keywordStart] == ' ') { keywordStart++; } - keyValueTail = nextEqualsign; - while (keyValueTail > keywordStart && *(keyValueTail-1) == ' ') { + size_t keyValueTail = nextEqualsign; + while (keyValueTail > keywordStart && keywords[keyValueTail - 1] == ' ') { keyValueTail--; } /* now keyValueTail points to first char after the keyName */ @@ -1011,26 +1024,26 @@ ulocimp_setKeywordValue(const char* keywords, } CharString localeKeywordName; while (keywordStart < keyValueTail) { - if (!UPRV_ISALPHANUM(*keywordStart)) { + if (!UPRV_ISALPHANUM(keywords[keywordStart])) { status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */ return 0; } - localeKeywordName.append(uprv_tolower(*keywordStart++), status); + localeKeywordName.append(uprv_tolower(keywords[keywordStart++]), status); } if (U_FAILURE(status)) { return 0; } - nextSeparator = uprv_strchr(nextEqualsign, ';'); + size_t nextSeparator = keywords.find(';', nextEqualsign); /* start processing the value part */ nextEqualsign++; /* skip '=' */ /* First strip leading & trailing spaces (TC decided to tolerate these) */ - while(*nextEqualsign == ' ') { + while (nextEqualsign < keywords.size() && keywords[nextEqualsign] == ' ') { nextEqualsign++; } - keyValueTail = (nextSeparator)? nextSeparator: nextEqualsign + uprv_strlen(nextEqualsign); - while(keyValueTail > nextEqualsign && *(keyValueTail-1) == ' ') { + keyValueTail = nextSeparator == std::string_view::npos ? keywords.size() : nextSeparator; + while (keyValueTail > nextEqualsign && keywords[keyValueTail - 1] == ' ') { keyValueTail--; } if (nextEqualsign == keyValueTail) { @@ -1065,9 +1078,10 @@ ulocimp_setKeywordValue(const char* keywords, keyValuePrefix = ';'; /* for any subsequent key-value pair */ updatedKeysAndValues.append(localeKeywordName, status); updatedKeysAndValues.append('=', status); - updatedKeysAndValues.append(nextEqualsign, static_cast<int32_t>(keyValueTail-nextEqualsign), status); + updatedKeysAndValues.append(keywords.data() + nextEqualsign, + static_cast<int32_t>(keyValueTail - nextEqualsign), status); } - if (!nextSeparator && !canonKeywordValue.isEmpty() && !handledInputKeyAndValue) { + if (nextSeparator == std::string_view::npos && !canonKeywordValue.isEmpty() && !handledInputKeyAndValue) { /* append new entry at the end, it sorts later than existing entries */ updatedKeysAndValues.append(keyValuePrefix, status); /* skip keyValuePrefix update, no subsequent key-value pair */ @@ -1091,7 +1105,7 @@ ulocimp_setKeywordValue(const char* keywords, /* if input key/value specified removal of a keyword not present in locale, or * there was an error in CharString.append, leave original locale alone. */ U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING); - return (int32_t)uprv_strlen(keywords); + return static_cast<int32_t>(keywords.size()); } needLen = updatedKeysAndValues.length(); @@ -1155,7 +1169,7 @@ std::optional<int16_t> _findIndex(const char* const* list, const char* key) while (pass++ < 2) { while (*list) { if (uprv_strcmp(key, *list) == 0) { - return (int16_t)(list - anchor); + return static_cast<int16_t>(list - anchor); } list++; } @@ -1241,7 +1255,7 @@ _getLanguage(const char* localeID, std::optional<int16_t> offset = _findIndex(LANGUAGES_3, buffer); if (offset.has_value()) { const char* const alias = LANGUAGES[*offset]; - sink->Append(alias, (int32_t)uprv_strlen(alias)); + sink->Append(alias, static_cast<int32_t>(uprv_strlen(alias))); return; } } @@ -1322,7 +1336,7 @@ _getRegion(const char* localeID, std::optional<int16_t> offset = _findIndex(COUNTRIES_3, buffer); if (offset.has_value()) { const char* const alias = COUNTRIES[*offset]; - sink->Append(alias, (int32_t)uprv_strlen(alias)); + sink->Append(alias, static_cast<int32_t>(uprv_strlen(alias))); return; } } @@ -1370,7 +1384,7 @@ _getVariant(const char* localeID, needSeparator = false; } if (sink != nullptr) { - char c = (char)uprv_toupper(localeID[index]); + char c = uprv_toupper(localeID[index]); if (c == '-') c = '_'; sink->Append(&c, 1); } @@ -1399,7 +1413,7 @@ _getVariant(const char* localeID, needSeparator = false; } if (sink != nullptr) { - char c = (char)uprv_toupper(localeID[index]); + char c = uprv_toupper(localeID[index]); if (c == '-' || c == ',') c = '_'; sink->Append(&c, 1); } @@ -1955,7 +1969,7 @@ ulocimp_getParent(const char* localeID, lastUnderscore=uprv_strrchr(localeID, '_'); if(lastUnderscore!=nullptr) { - i=(int32_t)(lastUnderscore-localeID); + i = static_cast<int32_t>(lastUnderscore - localeID); } else { i=0; } @@ -2218,7 +2232,7 @@ uloc_getLCID(const char* localeID) CharString collVal = ulocimp_getKeywordValue(localeID, "collation", status); if (U_SUCCESS(status) && !collVal.isEmpty()) { CharString tmpLocaleID = ulocimp_getBaseName(localeID, status); - ulocimp_setKeywordValue("collation", collVal.data(), tmpLocaleID, status); + ulocimp_setKeywordValue("collation", collVal.toStringPiece(), tmpLocaleID, status); if (U_SUCCESS(status)) { return uprv_convertToLCID(langID.data(), tmpLocaleID.data(), &status); } @@ -2285,8 +2299,17 @@ uloc_getISOCountries() U_CAPI const char* U_EXPORT2 uloc_toUnicodeLocaleKey(const char* keyword) { - const char* bcpKey = ulocimp_toBcpKey(keyword); - if (bcpKey == nullptr && ultag_isUnicodeLocaleKey(keyword, -1)) { + if (keyword == nullptr || *keyword == '\0') { return nullptr; } + std::optional<std::string_view> result = ulocimp_toBcpKeyWithFallback(keyword); + return result.has_value() ? result->data() : nullptr; // Known to be NUL terminated. +} + +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpKeyWithFallback(std::string_view keyword) +{ + std::optional<std::string_view> bcpKey = ulocimp_toBcpKey(keyword); + if (!bcpKey.has_value() && + ultag_isUnicodeLocaleKey(keyword.data(), static_cast<int32_t>(keyword.size()))) { // unknown keyword, but syntax is fine.. return keyword; } @@ -2296,8 +2319,18 @@ uloc_toUnicodeLocaleKey(const char* keyword) U_CAPI const char* U_EXPORT2 uloc_toUnicodeLocaleType(const char* keyword, const char* value) { - const char* bcpType = ulocimp_toBcpType(keyword, value, nullptr, nullptr); - if (bcpType == nullptr && ultag_isUnicodeLocaleType(value, -1)) { + if (keyword == nullptr || *keyword == '\0' || + value == nullptr || *value == '\0') { return nullptr; } + std::optional<std::string_view> result = ulocimp_toBcpTypeWithFallback(keyword, value); + return result.has_value() ? result->data() : nullptr; // Known to be NUL terminated. +} + +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpTypeWithFallback(std::string_view keyword, std::string_view value) +{ + std::optional<std::string_view> bcpType = ulocimp_toBcpType(keyword, value); + if (!bcpType.has_value() && + ultag_isUnicodeLocaleType(value.data(), static_cast<int32_t>(value.size()))) { // unknown keyword, but syntax is fine.. return value; } @@ -2307,37 +2340,28 @@ uloc_toUnicodeLocaleType(const char* keyword, const char* value) namespace { bool -isWellFormedLegacyKey(const char* legacyKey) +isWellFormedLegacyKey(std::string_view key) { - const char* p = legacyKey; - while (*p) { - if (!UPRV_ISALPHANUM(*p)) { - return false; - } - p++; - } - return true; + return std::all_of(key.begin(), key.end(), UPRV_ISALPHANUM); } bool -isWellFormedLegacyType(const char* legacyType) +isWellFormedLegacyType(std::string_view legacyType) { - const char* p = legacyType; int32_t alphaNumLen = 0; - while (*p) { - if (*p == '_' || *p == '/' || *p == '-') { + for (char c : legacyType) { + if (c == '_' || c == '/' || c == '-') { if (alphaNumLen == 0) { return false; } alphaNumLen = 0; - } else if (UPRV_ISALPHANUM(*p)) { + } else if (UPRV_ISALPHANUM(c)) { alphaNumLen++; } else { return false; } - p++; } - return (alphaNumLen != 0); + return alphaNumLen != 0; } } // namespace @@ -2345,8 +2369,16 @@ isWellFormedLegacyType(const char* legacyType) U_CAPI const char* U_EXPORT2 uloc_toLegacyKey(const char* keyword) { - const char* legacyKey = ulocimp_toLegacyKey(keyword); - if (legacyKey == nullptr) { + if (keyword == nullptr || *keyword == '\0') { return nullptr; } + std::optional<std::string_view> result = ulocimp_toLegacyKeyWithFallback(keyword); + return result.has_value() ? result->data() : nullptr; // Known to be NUL terminated. +} + +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyKeyWithFallback(std::string_view keyword) +{ + std::optional<std::string_view> legacyKey = ulocimp_toLegacyKey(keyword); + if (!legacyKey.has_value() && isWellFormedLegacyKey(keyword)) { // Checks if the specified locale key is well-formed with the legacy locale syntax. // // Note: @@ -2354,9 +2386,7 @@ uloc_toLegacyKey(const char* keyword) // * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier and // * http://www.unicode.org/reports/tr35/#Old_Locale_Extension_Syntax // Keys can only consist of [0-9a-zA-Z]. - if (isWellFormedLegacyKey(keyword)) { - return keyword; - } + return keyword; } return legacyKey; } @@ -2364,8 +2394,17 @@ uloc_toLegacyKey(const char* keyword) U_CAPI const char* U_EXPORT2 uloc_toLegacyType(const char* keyword, const char* value) { - const char* legacyType = ulocimp_toLegacyType(keyword, value, nullptr, nullptr); - if (legacyType == nullptr) { + if (keyword == nullptr || *keyword == '\0' || + value == nullptr || *value == '\0') { return nullptr; } + std::optional<std::string_view> result = ulocimp_toLegacyTypeWithFallback(keyword, value); + return result.has_value() ? result->data() : nullptr; // Known to be NUL terminated. +} + +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyTypeWithFallback(std::string_view keyword, std::string_view value) +{ + std::optional<std::string_view> legacyType = ulocimp_toLegacyType(keyword, value); + if (!legacyType.has_value() && isWellFormedLegacyType(value)) { // Checks if the specified locale type is well-formed with the legacy locale syntax. // // Note: @@ -2374,9 +2413,7 @@ uloc_toLegacyType(const char* keyword, const char* value) // * http://www.unicode.org/reports/tr35/#Old_Locale_Extension_Syntax // Values (types) can only consist of [0-9a-zA-Z], plus for legacy values // we allow [/_-+] in the middle (e.g. "Etc/GMT+1", "Asia/Tel_Aviv") - if (isWellFormedLegacyType(value)) { - return value; - } + return value; } return legacyType; } diff --git a/thirdparty/icu4c/common/uloc_keytype.cpp b/thirdparty/icu4c/common/uloc_keytype.cpp index 38694d4a18..9dc392126e 100644 --- a/thirdparty/icu4c/common/uloc_keytype.cpp +++ b/thirdparty/icu4c/common/uloc_keytype.cpp @@ -7,6 +7,8 @@ ********************************************************************** */ #include <algorithm> +#include <optional> +#include <string_view> #include "unicode/utypes.h" #include "unicode/unistr.h" @@ -18,6 +20,7 @@ #include "uassert.h" #include "ucln_cmn.h" #include "uhash.h" +#include "ulocimp.h" #include "umutex.h" #include "uresimp.h" #include "uvector.h" @@ -35,20 +38,25 @@ typedef enum { } SpecialType; struct LocExtKeyData : public icu::UMemory { - const char* legacyId; - const char* bcpId; + std::string_view legacyId; + std::string_view bcpId; icu::LocalUHashtablePointer typeMap; uint32_t specialTypes; }; struct LocExtType : public icu::UMemory { - const char* legacyId; - const char* bcpId; + std::string_view legacyId; + std::string_view bcpId; +}; + +struct TypeAlias : public icu::UMemory { + std::string_view from; }; static icu::MemoryPool<icu::CharString>* gKeyTypeStringPool = nullptr; static icu::MemoryPool<LocExtKeyData>* gLocExtKeyDataEntries = nullptr; static icu::MemoryPool<LocExtType>* gLocExtTypeEntries = nullptr; +static icu::MemoryPool<TypeAlias>* gTypeAliasEntries = nullptr; U_CDECL_BEGIN @@ -65,6 +73,9 @@ uloc_key_type_cleanup() { delete gLocExtTypeEntries; gLocExtTypeEntries = nullptr; + delete gTypeAliasEntries; + gTypeAliasEntries = nullptr; + delete gKeyTypeStringPool; gKeyTypeStringPool = nullptr; @@ -81,7 +92,7 @@ initFromResourceBundle(UErrorCode& sts) { U_NAMESPACE_USE ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KEY_TYPE, uloc_key_type_cleanup); - gLocExtKeyMap = uhash_open(uhash_hashIChars, uhash_compareIChars, nullptr, &sts); + gLocExtKeyMap = uhash_open(uhash_hashIStringView, uhash_compareIStringView, nullptr, &sts); LocalUResourceBundlePointer keyTypeDataRes(ures_openDirect(nullptr, "keyTypeData", &sts)); LocalUResourceBundlePointer keyMapRes(ures_getByKey(keyTypeDataRes.getAlias(), "keyMap", nullptr, &sts)); @@ -112,6 +123,11 @@ initFromResourceBundle(UErrorCode& sts) { sts = U_MEMORY_ALLOCATION_ERROR; return; } + gTypeAliasEntries = new icu::MemoryPool<TypeAlias>; + if (gTypeAliasEntries == nullptr) { + sts = U_MEMORY_ALLOCATION_ERROR; + return; + } // iterate through keyMap resource LocalUResourceBundlePointer keyMapEntry; @@ -144,7 +160,7 @@ initFromResourceBundle(UErrorCode& sts) { bool isTZ = uprv_strcmp(legacyKeyId, "timezone") == 0; - UHashtable* typeDataMap = uhash_open(uhash_hashIChars, uhash_compareIChars, nullptr, &sts); + UHashtable* typeDataMap = uhash_open(uhash_hashIStringView, uhash_compareIStringView, nullptr, &sts); if (U_FAILURE(sts)) { break; } @@ -253,10 +269,10 @@ initFromResourceBundle(UErrorCode& sts) { t->bcpId = bcpTypeId; t->legacyId = legacyTypeId; - uhash_put(typeDataMap, (void*)legacyTypeId, t, &sts); + uhash_put(typeDataMap, &t->legacyId, t, &sts); if (bcpTypeId != legacyTypeId) { // different type value - uhash_put(typeDataMap, (void*)bcpTypeId, t, &sts); + uhash_put(typeDataMap, &t->bcpId, t, &sts); } if (U_FAILURE(sts)) { break; @@ -275,8 +291,14 @@ initFromResourceBundle(UErrorCode& sts) { break; } // check if this is an alias of canonical legacy type - if (uprv_compareInvWithUChar(nullptr, legacyTypeId, -1, to, toLen) == 0) { + if (uprv_compareInvWithUChar( + nullptr, + t->legacyId.data(), + static_cast<int32_t>(t->legacyId.size()), + to, + toLen) == 0) { const char* from = ures_getKey(typeAliasDataEntry.getAlias()); + TypeAlias* alias = gTypeAliasEntries->create(TypeAlias{{}, from}); if (isTZ) { // replace colon with slash if necessary if (uprv_strchr(from, ':') != nullptr) { @@ -293,10 +315,10 @@ initFromResourceBundle(UErrorCode& sts) { fromBuf->data(), fromBuf->data() + fromBuf->length(), ':', '/'); - from = fromBuf->data(); + alias->from = fromBuf->toStringPiece(); } } - uhash_put(typeDataMap, (void*)from, t, &sts); + uhash_put(typeDataMap, &alias->from, t, &sts); } } if (U_FAILURE(sts)) { @@ -316,9 +338,15 @@ initFromResourceBundle(UErrorCode& sts) { break; } // check if this is an alias of bcp type - if (uprv_compareInvWithUChar(nullptr, bcpTypeId, -1, to, toLen) == 0) { + if (uprv_compareInvWithUChar( + nullptr, + t->bcpId.data(), + static_cast<int32_t>(t->bcpId.size()), + to, + toLen) == 0) { const char* from = ures_getKey(bcpTypeAliasDataEntry.getAlias()); - uhash_put(typeDataMap, (void*)from, t, &sts); + TypeAlias* alias = gTypeAliasEntries->create(TypeAlias{{}, from}); + uhash_put(typeDataMap, &alias->from, t, &sts); } } if (U_FAILURE(sts)) { @@ -341,10 +369,10 @@ initFromResourceBundle(UErrorCode& sts) { keyData->specialTypes = specialTypes; keyData->typeMap.adoptInstead(typeDataMap); - uhash_put(gLocExtKeyMap, (void*)legacyKeyId, keyData, &sts); + uhash_put(gLocExtKeyMap, &keyData->legacyId, keyData, &sts); if (legacyKeyId != bcpKeyId) { // different key value - uhash_put(gLocExtKeyMap, (void*)bcpKeyId, keyData, &sts); + uhash_put(gLocExtKeyMap, &keyData->bcpId, keyData, &sts); } if (U_FAILURE(sts)) { break; @@ -363,110 +391,96 @@ init() { } bool -isSpecialTypeCodepoints(const char* val) { +isSpecialTypeCodepoints(std::string_view val) { int32_t subtagLen = 0; - const char* p = val; - while (*p) { - if (*p == '-') { + for (char c : val) { + if (c == '-') { if (subtagLen < 4 || subtagLen > 6) { return false; } subtagLen = 0; - } else if ((*p >= '0' && *p <= '9') || - (*p >= 'A' && *p <= 'F') || // A-F/a-f are contiguous - (*p >= 'a' && *p <= 'f')) { // also in EBCDIC + } else if ((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F') || // A-F/a-f are contiguous + (c >= 'a' && c <= 'f')) { // also in EBCDIC subtagLen++; } else { return false; } - p++; } - return (subtagLen >= 4 && subtagLen <= 6); + return subtagLen >= 4 && subtagLen <= 6; } bool -isSpecialTypeReorderCode(const char* val) { +isSpecialTypeReorderCode(std::string_view val) { int32_t subtagLen = 0; - const char* p = val; - while (*p) { - if (*p == '-') { + for (char c : val) { + if (c == '-') { if (subtagLen < 3 || subtagLen > 8) { return false; } subtagLen = 0; - } else if (uprv_isASCIILetter(*p)) { + } else if (uprv_isASCIILetter(c)) { subtagLen++; } else { return false; } - p++; } - return (subtagLen >=3 && subtagLen <=8); + return subtagLen >= 3 && subtagLen <= 8; } bool -isSpecialTypeRgKeyValue(const char* val) { +isSpecialTypeRgKeyValue(std::string_view val) { int32_t subtagLen = 0; - const char* p = val; - while (*p) { - if ( (subtagLen < 2 && uprv_isASCIILetter(*p)) || - (subtagLen >= 2 && (*p == 'Z' || *p == 'z')) ) { + for (char c : val) { + if ((subtagLen < 2 && uprv_isASCIILetter(c)) || + (subtagLen >= 2 && (c == 'Z' || c == 'z'))) { subtagLen++; } else { return false; } - p++; } - return (subtagLen == 6); + return subtagLen == 6; } } // namespace -U_EXPORT const char* -ulocimp_toBcpKey(const char* key) { +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpKey(std::string_view key) { if (!init()) { - return nullptr; + return std::nullopt; } - LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key); + LocExtKeyData* keyData = static_cast<LocExtKeyData*>(uhash_get(gLocExtKeyMap, &key)); if (keyData != nullptr) { return keyData->bcpId; } - return nullptr; + + return std::nullopt; } -U_EXPORT const char* -ulocimp_toLegacyKey(const char* key) { +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyKey(std::string_view key) { if (!init()) { - return nullptr; + return std::nullopt; } - LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key); + LocExtKeyData* keyData = static_cast<LocExtKeyData*>(uhash_get(gLocExtKeyMap, &key)); if (keyData != nullptr) { return keyData->legacyId; } - return nullptr; -} -U_EXPORT const char* -ulocimp_toBcpType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType) { - if (isKnownKey != nullptr) { - *isKnownKey = false; - } - if (isSpecialType != nullptr) { - *isSpecialType = false; - } + return std::nullopt; +} +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpType(std::string_view key, std::string_view type) { if (!init()) { - return nullptr; + return std::nullopt; } - LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key); + LocExtKeyData* keyData = static_cast<LocExtKeyData*>(uhash_get(gLocExtKeyMap, &key)); if (keyData != nullptr) { - if (isKnownKey != nullptr) { - *isKnownKey = true; - } - LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap.getAlias(), type); + LocExtType* t = static_cast<LocExtType*>(uhash_get(keyData->typeMap.getAlias(), &type)); if (t != nullptr) { return t->bcpId; } @@ -482,36 +496,24 @@ ulocimp_toBcpType(const char* key, const char* type, bool* isKnownKey, bool* isS matched = isSpecialTypeRgKeyValue(type); } if (matched) { - if (isSpecialType != nullptr) { - *isSpecialType = true; - } return type; } } } - return nullptr; -} + return std::nullopt; +} -U_EXPORT const char* -ulocimp_toLegacyType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType) { - if (isKnownKey != nullptr) { - *isKnownKey = false; - } - if (isSpecialType != nullptr) { - *isSpecialType = false; - } +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyType(std::string_view key, std::string_view type) { if (!init()) { - return nullptr; + return std::nullopt; } - LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key); + LocExtKeyData* keyData = static_cast<LocExtKeyData*>(uhash_get(gLocExtKeyMap, &key)); if (keyData != nullptr) { - if (isKnownKey != nullptr) { - *isKnownKey = true; - } - LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap.getAlias(), type); + LocExtType* t = static_cast<LocExtType*>(uhash_get(keyData->typeMap.getAlias(), &type)); if (t != nullptr) { return t->legacyId; } @@ -527,12 +529,10 @@ ulocimp_toLegacyType(const char* key, const char* type, bool* isKnownKey, bool* matched = isSpecialTypeRgKeyValue(type); } if (matched) { - if (isSpecialType != nullptr) { - *isSpecialType = true; - } return type; } } } - return nullptr; + + return std::nullopt; } diff --git a/thirdparty/icu4c/common/uloc_tag.cpp b/thirdparty/icu4c/common/uloc_tag.cpp index f5ab0c36a6..7b3b1e73a3 100644 --- a/thirdparty/icu4c/common/uloc_tag.cpp +++ b/thirdparty/icu4c/common/uloc_tag.cpp @@ -7,6 +7,8 @@ ********************************************************************** */ +#include <optional> +#include <string_view> #include <utility> #include "unicode/bytestream.h" @@ -415,7 +417,7 @@ _isAlphaNumericString(const char* s, int32_t len) { bool _isAlphaNumericStringLimitedLength(const char* s, int32_t len, int32_t min, int32_t max) { if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len >= min && len <= max && _isAlphaNumericString(s, len)) { return true; @@ -433,7 +435,7 @@ ultag_isLanguageSubtag(const char* s, int32_t len) { * See ICU-20372 */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len >= 2 && len <= 8 && _isAlphaString(s, len)) { return true; @@ -450,7 +452,7 @@ _isExtlangSubtag(const char* s, int32_t len) { * *2("-" 3ALPHA) ; permanently reserved */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len == 3 && _isAlphaString(s, len)) { return true; @@ -466,7 +468,7 @@ ultag_isScriptSubtag(const char* s, int32_t len) { * script = 4ALPHA ; ISO 15924 code */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len == 4 && _isAlphaString(s, len)) { return true; @@ -481,7 +483,7 @@ ultag_isRegionSubtag(const char* s, int32_t len) { * / 3DIGIT ; UN M.49 code */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len == 2 && _isAlphaString(s, len)) { return true; @@ -501,7 +503,7 @@ _isVariantSubtag(const char* s, int32_t len) { * / (DIGIT 3alphanum) */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (_isAlphaNumericStringLimitedLength(s, len, 5, 8)) { return true; @@ -518,7 +520,7 @@ _isSepListOf(bool (*test)(const char*, int32_t), const char* s, int32_t len) { const char *pSubtag = nullptr; if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } while ((p - s) < len) { @@ -526,7 +528,7 @@ _isSepListOf(bool (*test)(const char*, int32_t), const char* s, int32_t len) { if (pSubtag == nullptr) { return false; } - if (!test(pSubtag, (int32_t)(p - pSubtag))) { + if (!test(pSubtag, static_cast<int32_t>(p - pSubtag))) { return false; } pSubtag = nullptr; @@ -538,7 +540,7 @@ _isSepListOf(bool (*test)(const char*, int32_t), const char* s, int32_t len) { if (pSubtag == nullptr) { return false; } - return test(pSubtag, (int32_t)(p - pSubtag)); + return test(pSubtag, static_cast<int32_t>(p - pSubtag)); } } // namespace @@ -572,7 +574,7 @@ _isExtensionSingleton(const char* s, int32_t len) { * / %x79-7A ; y - z */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len == 1 && (ISALPHA(*s) || ISNUMERIC(*s)) && (uprv_tolower(*s) != PRIVATEUSE)) { return true; @@ -631,7 +633,7 @@ ultag_isUnicodeLocaleKey(const char* s, int32_t len) { * key = alphanum alpha ; */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len == 2 && (ISALPHA(*s) || ISNUMERIC(*s)) && ISALPHA(s[1])) { return true; @@ -664,7 +666,7 @@ _isTKey(const char* s, int32_t len) * tkey = alpha digit ; */ if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } if (len == 2 && ISALPHA(*s) && ISNUMERIC(*(s + 1))) { return true; @@ -718,7 +720,7 @@ _isTransformedExtensionSubtag(int32_t& state, const char* s, int32_t len) if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } switch (state) { case kStart: @@ -822,7 +824,7 @@ _isStatefulSepListOf(bool (*test)(int32_t&, const char*, int32_t), const char* s int32_t subtagLen = 0; if (len < 0) { - len = (int32_t)uprv_strlen(s); + len = static_cast<int32_t>(uprv_strlen(s)); } for (p = s; len > 0; p++, len--) { @@ -966,8 +968,8 @@ _addExtensionToList(ExtensionListEntry **first, ExtensionListEntry *ext, bool lo /* special handling for locale to bcp conversion */ int32_t len, curlen; - len = (int32_t)uprv_strlen(ext->key); - curlen = (int32_t)uprv_strlen(cur->key); + len = static_cast<int32_t>(uprv_strlen(ext->key)); + curlen = static_cast<int32_t>(uprv_strlen(cur->key)); if (len == 1 && curlen == 1) { if (*(ext->key) == *(cur->key)) { @@ -1074,10 +1076,10 @@ _appendLanguageToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str // ones in DEPRECATEDLANGS[]. Get out of loop on coming // across the 1st 3-letter subtag, if the input is a 2-letter code. // to avoid continuing to try when there's no match. - if (buf.length() < (int32_t)uprv_strlen(DEPRECATEDLANGS[i])) break; + if (buf.length() < static_cast<int32_t>(uprv_strlen(DEPRECATEDLANGS[i]))) break; if (uprv_compareInvCharsAsAscii(buf.data(), DEPRECATEDLANGS[i]) == 0) { const char* const resolved = DEPRECATEDLANGS[i + 1]; - sink.Append(resolved, (int32_t)uprv_strlen(resolved)); + sink.Append(resolved, static_cast<int32_t>(uprv_strlen(resolved))); return; } } @@ -1144,7 +1146,7 @@ _appendRegionToLanguageTag(const char* localeID, icu::ByteSink& sink, bool stric for (int32_t i = 0; i < UPRV_LENGTHOF(DEPRECATEDREGIONS); i += 2) { if (uprv_compareInvCharsAsAscii(buf.data(), DEPRECATEDREGIONS[i]) == 0) { const char* const resolved = DEPRECATEDREGIONS[i + 1]; - sink.Append(resolved, (int32_t)uprv_strlen(resolved)); + sink.Append(resolved, static_cast<int32_t>(uprv_strlen(resolved))); return; } } @@ -1208,7 +1210,7 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str /* validate */ if (_isVariantSubtag(pVar, -1)) { - if (uprv_strcmp(pVar,POSIX_VALUE) || buf.length() != (int32_t)uprv_strlen(POSIX_VALUE)) { + if (uprv_strcmp(pVar, POSIX_VALUE) || buf.length() != static_cast<int32_t>(uprv_strlen(POSIX_VALUE))) { /* emit the variant to the list */ icu::LocalPointer<VariantListEntry> var(new VariantListEntry, status); if (U_FAILURE(status)) { @@ -1254,7 +1256,7 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str VariantListEntry* var = varFirst; while (var != nullptr) { sink.Append("-", 1); - varLen = (int32_t)uprv_strlen(var->variant); + varLen = static_cast<int32_t>(uprv_strlen(var->variant)); sink.Append(var->variant, varLen); var = var->next; } @@ -1323,7 +1325,7 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str continue; } - keylen = (int32_t)uprv_strlen(key); + keylen = static_cast<int32_t>(uprv_strlen(key)); isBcpUExt = (keylen > 1); /* special keyword used for representing Unicode locale attributes */ @@ -1374,27 +1376,28 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str bcpValue = nullptr; } } else if (isBcpUExt) { - bcpKey = uloc_toUnicodeLocaleKey(key); - if (bcpKey == nullptr) { + std::optional<std::string_view> optBcpKey = ulocimp_toBcpKeyWithFallback(key); + if (!optBcpKey.has_value()) { if (strict) { status = U_ILLEGAL_ARGUMENT_ERROR; break; } continue; } + bcpKey = optBcpKey->data(); - /* we've checked buf is null-terminated above */ - bcpValue = uloc_toUnicodeLocaleType(key, buf.data()); - if (bcpValue == nullptr) { + std::optional<std::string_view> optBcpValue = + ulocimp_toBcpTypeWithFallback(key, buf.toStringPiece()); + if (!optBcpValue.has_value()) { if (strict) { status = U_ILLEGAL_ARGUMENT_ERROR; break; } continue; } - if (bcpValue == buf.data()) { + if (optBcpValue->data() == buf.data()) { /* - When uloc_toUnicodeLocaleType(key, buf) returns the + When ulocimp_toBcpTypeWithFallback(key, buf) returns the input value as is, the value is well-formed, but has no known mapping. This implementation normalizes the value to lower case @@ -1412,6 +1415,8 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str T_CString_toLowerCase(extBuf->data()); bcpValue = extBuf->data(); + } else { + bcpValue = optBcpValue->data(); } } else { if (*key == PRIVATEUSE) { @@ -1669,33 +1674,28 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT const char *pKey = nullptr; /* LDML key */ const char *pType = nullptr; /* LDML type */ - char bcpKeyBuf[3]; /* BCP key length is always 2 for now */ - U_ASSERT(pBcpKey != nullptr); - if (bcpKeyLen >= (int32_t)sizeof(bcpKeyBuf)) { + /* BCP key length is always 2 for now */ + if (bcpKeyLen != 2) { /* the BCP key is invalid */ status = U_ILLEGAL_ARGUMENT_ERROR; return; } - U_ASSERT(bcpKeyLen <= 2); - - uprv_strncpy(bcpKeyBuf, pBcpKey, bcpKeyLen); - bcpKeyBuf[bcpKeyLen] = 0; /* u extension key to LDML key */ - pKey = uloc_toLegacyKey(bcpKeyBuf); - if (pKey == nullptr) { + std::optional<std::string_view> legacyKey = ulocimp_toLegacyKeyWithFallback( + {pBcpKey, static_cast<std::string_view::size_type>(bcpKeyLen)}); + if (!legacyKey.has_value()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } - if (pKey == bcpKeyBuf) { + if (legacyKey->data() == pBcpKey) { /* The key returned by toLegacyKey points to the input buffer. We normalize the result key to lower case. */ - T_CString_toLowerCase(bcpKeyBuf); - icu::CharString* key = kwdBuf.create(bcpKeyBuf, bcpKeyLen, status); + icu::CharString* key = kwdBuf.create(pBcpKey, bcpKeyLen, status); if (key == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; @@ -1703,36 +1703,37 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT if (U_FAILURE(status)) { return; } + T_CString_toLowerCase(key->data()); pKey = key->data(); + } else { + pKey = legacyKey->data(); } if (pBcpType) { - icu::CharString bcpTypeBuf(pBcpType, bcpTypeLen, status); - if (U_FAILURE(status)) { - return; - } - /* BCP type to locale type */ - pType = uloc_toLegacyType(pKey, bcpTypeBuf.data()); - if (pType == nullptr) { + std::optional<std::string_view> legacyType = ulocimp_toLegacyTypeWithFallback( + pKey, {pBcpType, static_cast<std::string_view::size_type>(bcpTypeLen)}); + if (!legacyType.has_value()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } - if (pType == bcpTypeBuf.data()) { + if (legacyType->data() == pBcpType) { /* The type returned by toLegacyType points to the input buffer. We normalize the result type to lower case. */ - /* normalize to lower case */ - T_CString_toLowerCase(bcpTypeBuf.data()); - if (icu::CharString* type = - kwdBuf.create(std::move(bcpTypeBuf), status)) { - if (U_FAILURE(status)) { return; } - pType = type->data(); - } else { + icu::CharString* type = kwdBuf.create(pBcpType, bcpTypeLen, status); + if (type == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } + if (U_FAILURE(status)) { + return; + } + T_CString_toLowerCase(type->data()); + pType = type->data(); + } else { + pType = legacyType->data(); } } else { /* typeless - default type value is "yes" */ @@ -1822,7 +1823,7 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) if (U_SUCCESS(status)) { type = ultag_getPrivateUse(langtag); - if ((int32_t)uprv_strlen(type) > 0) { + if (static_cast<int32_t>(uprv_strlen(type)) > 0) { /* add private use as a keyword */ kwd = extPool.create(); if (kwd == nullptr) { @@ -1840,7 +1841,7 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) /* If a POSIX variant was in the extensions, write it out before writing the keywords. */ if (U_SUCCESS(status) && posixVariant) { - len = (int32_t) uprv_strlen(_POSIX); + len = static_cast<int32_t>(uprv_strlen(_POSIX)); sink.Append(_POSIX, len); } @@ -1857,12 +1858,12 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) } /* key */ - len = (int32_t)uprv_strlen(kwd->key); + len = static_cast<int32_t>(uprv_strlen(kwd->key)); sink.Append(kwd->key, len); sink.Append("=", 1); /* type */ - len = (int32_t)uprv_strlen(kwd->value); + len = static_cast<int32_t>(uprv_strlen(kwd->value)); sink.Append(kwd->value, len); kwd = kwd->next; @@ -1932,7 +1933,7 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool s firstValue = false; } - int32_t len = (int32_t)uprv_strlen(pPriv); + int32_t len = static_cast<int32_t>(uprv_strlen(pPriv)); sink.Append(pPriv, len); } } @@ -1994,11 +1995,11 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta } if (tagLen < 0) { - tagLen = (int32_t)uprv_strlen(tag); + tagLen = static_cast<int32_t>(uprv_strlen(tag)); } /* copy the entire string */ - tagBuf = (char*)uprv_malloc(tagLen + 1); + tagBuf = static_cast<char*>(uprv_malloc(tagLen + 1)); if (tagBuf == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -2011,7 +2012,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta /* create a ULanguageTag */ icu::LocalULanguageTagPointer t( - (ULanguageTag*)uprv_malloc(sizeof(ULanguageTag))); + static_cast<ULanguageTag*>(uprv_malloc(sizeof(ULanguageTag)))); if (t.isNull()) { uprv_free(tagBuf); status = U_MEMORY_ALLOCATION_ERROR; @@ -2050,7 +2051,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta uprv_free(tagBuf); // Change t->buf after the free and before return to avoid the second double free in // the destructor of t when t is out of scope. - t->buf = tagBuf = (char*)uprv_malloc(newTagLength + 1); + t->buf = tagBuf = static_cast<char*>(uprv_malloc(newTagLength + 1)); if (tagBuf == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -2133,7 +2134,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta } else { pNext = pSep + 1; } - subtagLen = (int32_t)(pSep - pSubtag); + subtagLen = static_cast<int32_t>(pSep - pSubtag); if (next & LANG) { if (ultag_isLanguageSubtag(pSubtag, subtagLen)) { @@ -2321,7 +2322,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta } else { pNext = pSep + 1; } - subtagLen = (int32_t)(pSep - pSubtag); + subtagLen = static_cast<int32_t>(pSep - pSubtag); if (uprv_strncmp(pSubtag, PRIVUSE_VARIANT_PREFIX, uprv_strlen(PRIVUSE_VARIANT_PREFIX)) == 0) { *pSep = 0; @@ -2373,7 +2374,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta } if (parsedLen != nullptr) { - *parsedLen = (int32_t)(pLastGoodPosition - t->buf + parsedLenDelta); + *parsedLen = static_cast<int32_t>(pLastGoodPosition - t->buf + parsedLenDelta); } return t.orphan(); @@ -2698,7 +2699,7 @@ ulocimp_forLanguageTag(const char* langtag, /* language */ subtag = ultag_getExtlangSize(lt.getAlias()) > 0 ? ultag_getExtlang(lt.getAlias(), 0) : ultag_getLanguage(lt.getAlias()); if (uprv_compareInvCharsAsAscii(subtag, LANG_UND) != 0) { - len = (int32_t)uprv_strlen(subtag); + len = static_cast<int32_t>(uprv_strlen(subtag)); if (len > 0) { sink.Append(subtag, len); isEmpty = false; @@ -2707,7 +2708,7 @@ ulocimp_forLanguageTag(const char* langtag, /* script */ subtag = ultag_getScript(lt.getAlias()); - len = (int32_t)uprv_strlen(subtag); + len = static_cast<int32_t>(uprv_strlen(subtag)); if (len > 0) { sink.Append("_", 1); isEmpty = false; @@ -2720,7 +2721,7 @@ ulocimp_forLanguageTag(const char* langtag, /* region */ subtag = ultag_getRegion(lt.getAlias()); - len = (int32_t)uprv_strlen(subtag); + len = static_cast<int32_t>(uprv_strlen(subtag)); if (len > 0) { sink.Append("_", 1); isEmpty = false; diff --git a/thirdparty/icu4c/common/ulocale.cpp b/thirdparty/icu4c/common/ulocale.cpp index aaa17954a3..f2f81bc971 100644 --- a/thirdparty/icu4c/common/ulocale.cpp +++ b/thirdparty/icu4c/common/ulocale.cpp @@ -21,7 +21,10 @@ U_NAMESPACE_USE ULocale* ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err) { if (U_FAILURE(*err)) { return nullptr; } - CharString str(length < 0 ? StringPiece(localeID) : StringPiece(localeID, length), *err); + if (length < 0) { + return EXTERNAL(icu::Locale::createFromName(localeID).clone()); + } + CharString str(localeID, length, *err); // Make a NUL terminated copy. if (U_FAILURE(*err)) { return nullptr; } return EXTERNAL(icu::Locale::createFromName(str.data()).clone()); } diff --git a/thirdparty/icu4c/common/ulocbuilder.cpp b/thirdparty/icu4c/common/ulocbuilder.cpp index 3b46647362..b8b6ce8c18 100644 --- a/thirdparty/icu4c/common/ulocbuilder.cpp +++ b/thirdparty/icu4c/common/ulocbuilder.cpp @@ -119,7 +119,7 @@ int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder, } icu::Locale l = INTERNAL(builder)->build(*err); if (U_FAILURE(*err)) { return 0; } - int32_t length = (int32_t)(uprv_strlen(l.getName())); + int32_t length = static_cast<int32_t>(uprv_strlen(l.getName())); if (0 < length && length <= bufferCapacity) { uprv_memcpy(buffer, l.getName(), length); } diff --git a/thirdparty/icu4c/common/ulocimp.h b/thirdparty/icu4c/common/ulocimp.h index 7fb6406288..1887e2a849 100644 --- a/thirdparty/icu4c/common/ulocimp.h +++ b/thirdparty/icu4c/common/ulocimp.h @@ -11,6 +11,8 @@ #define ULOCIMP_H #include <cstddef> +#include <optional> +#include <string_view> #include "unicode/bytestream.h" #include "unicode/uloc.h" @@ -53,6 +55,18 @@ uloc_getCurrentCountryID(const char* oldID); U_CFUNC const char* uloc_getCurrentLanguageID(const char* oldID); +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpKeyWithFallback(std::string_view keyword); + +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpTypeWithFallback(std::string_view keyword, std::string_view value); + +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyKeyWithFallback(std::string_view keyword); + +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyTypeWithFallback(std::string_view keyword, std::string_view value); + U_EXPORT icu::CharString ulocimp_getKeywords(const char* localeID, char prev, @@ -95,12 +109,12 @@ ulocimp_canonicalize(const char* localeID, U_EXPORT icu::CharString ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, UErrorCode& status); U_EXPORT void ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, icu::ByteSink& sink, UErrorCode& status); @@ -117,15 +131,15 @@ U_EXPORT icu::CharString ulocimp_getVariant(const char* localeID, UErrorCode& status); U_EXPORT void -ulocimp_setKeywordValue(const char* keywordName, - const char* keywordValue, +ulocimp_setKeywordValue(std::string_view keywordName, + std::string_view keywordValue, icu::CharString& localeID, UErrorCode& status); U_EXPORT int32_t -ulocimp_setKeywordValue(const char* keywords, - const char* keywordName, - const char* keywordValue, +ulocimp_setKeywordValue(std::string_view keywords, + std::string_view keywordName, + std::string_view keywordValue, icu::ByteSink& sink, UErrorCode& status); @@ -391,17 +405,17 @@ ultag_isVariantSubtags(const char* s, int32_t len); const char* ultag_getTKeyStart(const char* localeID); -U_EXPORT const char* -ulocimp_toBcpKey(const char* key); +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpKey(std::string_view key); -U_EXPORT const char* -ulocimp_toLegacyKey(const char* key); +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyKey(std::string_view key); -U_EXPORT const char* -ulocimp_toBcpType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType); +U_EXPORT std::optional<std::string_view> +ulocimp_toBcpType(std::string_view key, std::string_view type); -U_EXPORT const char* -ulocimp_toLegacyType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType); +U_EXPORT std::optional<std::string_view> +ulocimp_toLegacyType(std::string_view key, std::string_view type); /* Function for testing purpose */ U_EXPORT const char* const* @@ -411,4 +425,19 @@ ulocimp_getKnownCanonicalizedLocaleForTest(int32_t& length); U_EXPORT bool ulocimp_isCanonicalizedLocaleForTest(const char* localeName); +#ifdef __cplusplus +U_NAMESPACE_BEGIN +class U_COMMON_API RegionValidateMap : public UObject { + public: + RegionValidateMap(); + virtual ~RegionValidateMap(); + bool isSet(const char* region) const; + bool equals(const RegionValidateMap& that) const; + protected: + int32_t value(const char* region) const; + uint32_t map[22]; // 26x26/32 = 22; +}; +U_NAMESPACE_END +#endif /* __cplusplus */ + #endif diff --git a/thirdparty/icu4c/common/umapfile.cpp b/thirdparty/icu4c/common/umapfile.cpp index 8dddf0e78d..b58ac37f4d 100644 --- a/thirdparty/icu4c/common/umapfile.cpp +++ b/thirdparty/icu4c/common/umapfile.cpp @@ -63,7 +63,7 @@ typedef HANDLE MemoryMap; # define IS_MAP(map) ((map)!=nullptr) -#elif MAP_IMPLEMENTATION==MAP_POSIX || MAP_IMPLEMENTATION==MAP_390DLL +#elif MAP_IMPLEMENTATION==MAP_POSIX typedef size_t MemoryMap; # define IS_MAP(map) ((map)!=0) @@ -76,18 +76,6 @@ typedef HANDLE MemoryMap; # ifndef MAP_FAILED # define MAP_FAILED ((void*)-1) # endif - -# if MAP_IMPLEMENTATION==MAP_390DLL - /* No memory mapping for 390 batch mode. Fake it using dll loading. */ -# include <dll.h> -# include "cstring.h" -# include "cmemory.h" -# include "unicode/udata.h" -# define LIB_PREFIX "lib" -# define LIB_SUFFIX ".dll" - /* This is inconvenient until we figure out what to do with U_ICUDATA_NAME in utypes.h */ -# define U_ICUDATA_ENTRY_NAME "icudt" U_ICU_VERSION_SHORT U_LIB_SUFFIX_C_NAME_STRING "_dat" -# endif #elif MAP_IMPLEMENTATION==MAP_STDIO # include <stdio.h> # include "cmemory.h" @@ -339,192 +327,6 @@ typedef HANDLE MemoryMap; pData->pHeader = nullptr; } } - - -#elif MAP_IMPLEMENTATION==MAP_390DLL - /* 390 specific Library Loading. - * This is the only platform left that dynamically loads an ICU Data Library. - * All other platforms use .data files when dynamic loading is required, but - * this turn out to be awkward to support in 390 batch mode. - * - * The idea here is to hide the fact that 390 is using dll loading from the - * rest of ICU, and make it look like there is file loading happening. - * - */ - - static char *strcpy_returnEnd(char *dest, const char *src) - { - while((*dest=*src)!=0) { - ++dest; - ++src; - } - return dest; - } - - /*------------------------------------------------------------------------------ - * - * computeDirPath given a user-supplied path of an item to be opened, - * compute and return - * - the full directory path to be used - * when opening the file. - * - Pointer to null at end of above returned path - * - * Parameters: - * path: input path. Buffer is not altered. - * pathBuffer: Output buffer. Any contents are overwritten. - * - * Returns: - * Pointer to null termination in returned pathBuffer. - * - * TODO: This works the way ICU historically has, but the - * whole data fallback search path is so complicated that - * probably almost no one will ever really understand it, - * the potential for confusion is large. (It's not just - * this one function, but the whole scheme.) - * - *------------------------------------------------------------------------------*/ - static char *uprv_computeDirPath(const char *path, char *pathBuffer) - { - char *finalSlash; /* Ptr to last dir separator in input path, or null if none. */ - int32_t pathLen; /* Length of the returned directory path */ - - finalSlash = 0; - if (path != 0) { - finalSlash = uprv_strrchr(path, U_FILE_SEP_CHAR); - } - - *pathBuffer = 0; - if (finalSlash == 0) { - /* No user-supplied path. - * Copy the ICU_DATA path to the path buffer and return that*/ - const char *icuDataDir; - icuDataDir=u_getDataDirectory(); - if(icuDataDir!=nullptr && *icuDataDir!=0) { - return strcpy_returnEnd(pathBuffer, icuDataDir); - } else { - /* there is no icuDataDir either. Just return the empty pathBuffer. */ - return pathBuffer; - } - } - - /* User supplied path did contain a directory portion. - * Copy it to the output path buffer */ - pathLen = (int32_t)(finalSlash - path + 1); - uprv_memcpy(pathBuffer, path, pathLen); - *(pathBuffer+pathLen) = 0; - return pathBuffer+pathLen; - } - - -# define DATA_TYPE "dat" - - U_CFUNC UBool uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) { - const char *inBasename; - char *basename; - char pathBuffer[1024]; - const DataHeader *pHeader; - dllhandle *handle; - void *val=0; - - if (U_FAILURE(*status)) { - return false; - } - - inBasename=uprv_strrchr(path, U_FILE_SEP_CHAR); - if(inBasename==nullptr) { - inBasename = path; - } else { - inBasename++; - } - basename=uprv_computeDirPath(path, pathBuffer); - if(uprv_strcmp(inBasename, U_ICUDATA_NAME".dat") != 0) { - /* must mmap file... for build */ - int fd; - int length; - struct stat mystat; - void *data; - UDataMemory_init(pData); /* Clear the output struct. */ - - /* determine the length of the file */ - if(stat(path, &mystat)!=0 || mystat.st_size<=0) { - return false; - } - length=mystat.st_size; - - /* open the file */ - fd=open(path, O_RDONLY); - if(fd==-1) { - return false; - } - - /* get a view of the mapping */ - data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); /* no longer needed */ - if(data==MAP_FAILED) { - // Possibly check the errorno value for ENOMEM, and report U_MEMORY_ALLOCATION_ERROR? - return false; - } - pData->map = (char *)data + length; - pData->pHeader=(const DataHeader *)data; - pData->mapAddr = data; - return true; - } - -# ifdef OS390BATCH - /* ### hack: we still need to get u_getDataDirectory() fixed - for OS/390 (batch mode - always return "//"? ) - and this here straightened out with LIB_PREFIX and LIB_SUFFIX (both empty?!) - This is probably due to the strange file system on OS/390. It's more like - a database with short entry names than a typical file system. */ - /* U_ICUDATA_NAME should always have the correct name */ - /* BUT FOR BATCH MODE IT IS AN EXCEPTION BECAUSE */ - /* THE FIRST THREE LETTERS ARE PREASSIGNED TO THE */ - /* PROJECT!!!!! */ - uprv_strcpy(pathBuffer, "IXMI" U_ICU_VERSION_SHORT "DA"); -# else - /* set up the library name */ - uprv_strcpy(basename, LIB_PREFIX U_LIBICUDATA_NAME U_ICU_VERSION_SHORT LIB_SUFFIX); -# endif - -# ifdef UDATA_DEBUG - fprintf(stderr, "dllload: %s ", pathBuffer); -# endif - - handle=dllload(pathBuffer); - -# ifdef UDATA_DEBUG - fprintf(stderr, " -> %08X\n", handle ); -# endif - - if(handle != nullptr) { - /* we have a data DLL - what kind of lookup do we need here? */ - /* try to find the Table of Contents */ - UDataMemory_init(pData); /* Clear the output struct. */ - val=dllqueryvar((dllhandle*)handle, U_ICUDATA_ENTRY_NAME); - if(val == 0) { - /* failed... so keep looking */ - return false; - } -# ifdef UDATA_DEBUG - fprintf(stderr, "dllqueryvar(%08X, %s) -> %08X\n", handle, U_ICUDATA_ENTRY_NAME, val); -# endif - - pData->pHeader=(const DataHeader *)val; - return true; - } else { - return false; /* no handle */ - } - } - - U_CFUNC void uprv_unmapFile(UDataMemory *pData) { - if(pData!=nullptr && pData->map!=nullptr) { - uprv_free(pData->map); - pData->map = nullptr; - pData->mapAddr = nullptr; - pData->pHeader = nullptr; - } - } - #else # error MAP_IMPLEMENTATION is set incorrectly #endif diff --git a/thirdparty/icu4c/common/umapfile.h b/thirdparty/icu4c/common/umapfile.h index 042e71374c..bacd10e70d 100644 --- a/thirdparty/icu4c/common/umapfile.h +++ b/thirdparty/icu4c/common/umapfile.h @@ -37,19 +37,13 @@ U_CFUNC void uprv_unmapFile(UDataMemory *pData); #define MAP_WIN32 1 #define MAP_POSIX 2 #define MAP_STDIO 3 -#define MAP_390DLL 4 #if UCONFIG_NO_FILE_IO # define MAP_IMPLEMENTATION MAP_NONE #elif U_PLATFORM_USES_ONLY_WIN32_API # define MAP_IMPLEMENTATION MAP_WIN32 #elif U_HAVE_MMAP || U_PLATFORM == U_PF_OS390 -# if U_PLATFORM == U_PF_OS390 && defined (OS390_STUBDATA) - /* No memory mapping for 390 batch mode. Fake it using dll loading. */ -# define MAP_IMPLEMENTATION MAP_390DLL -# else -# define MAP_IMPLEMENTATION MAP_POSIX -# endif +# define MAP_IMPLEMENTATION MAP_POSIX #else /* unknown platform, no memory map implementation: use stdio.h and uprv_malloc() instead */ # define MAP_IMPLEMENTATION MAP_STDIO #endif diff --git a/thirdparty/icu4c/common/umutablecptrie.cpp b/thirdparty/icu4c/common/umutablecptrie.cpp index cdbe27080b..40ea57f149 100644 --- a/thirdparty/icu4c/common/umutablecptrie.cpp +++ b/thirdparty/icu4c/common/umutablecptrie.cpp @@ -45,10 +45,10 @@ constexpr uint8_t MIXED = 1; constexpr uint8_t SAME_AS = 2; /** Start with allocation of 16k data entries. */ -constexpr int32_t INITIAL_DATA_LENGTH = ((int32_t)1 << 14); +constexpr int32_t INITIAL_DATA_LENGTH = static_cast<int32_t>(1) << 14; /** Grow about 8x each time. */ -constexpr int32_t MEDIUM_DATA_LENGTH = ((int32_t)1 << 17); +constexpr int32_t MEDIUM_DATA_LENGTH = static_cast<int32_t>(1) << 17; /** * Maximum length of the build-time data array. @@ -135,8 +135,8 @@ MutableCodePointTrie::MutableCodePointTrie(uint32_t iniValue, uint32_t errValue, #endif { if (U_FAILURE(errorCode)) { return; } - index = (uint32_t *)uprv_malloc(BMP_I_LIMIT * 4); - data = (uint32_t *)uprv_malloc(INITIAL_DATA_LENGTH * 4); + index = static_cast<uint32_t*>(uprv_malloc(BMP_I_LIMIT * 4)); + data = static_cast<uint32_t*>(uprv_malloc(INITIAL_DATA_LENGTH * 4)); if (index == nullptr || data == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; @@ -157,8 +157,8 @@ MutableCodePointTrie::MutableCodePointTrie(const MutableCodePointTrie &other, UE { if (U_FAILURE(errorCode)) { return; } int32_t iCapacity = highStart <= BMP_LIMIT ? BMP_I_LIMIT : I_LIMIT; - index = (uint32_t *)uprv_malloc(iCapacity * 4); - data = (uint32_t *)uprv_malloc(other.dataCapacity * 4); + index = static_cast<uint32_t*>(uprv_malloc(iCapacity * 4)); + data = static_cast<uint32_t*>(uprv_malloc(other.dataCapacity * 4)); if (index == nullptr || data == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; @@ -268,7 +268,7 @@ void MutableCodePointTrie::clear() { } uint32_t MutableCodePointTrie::get(UChar32 c) const { - if ((uint32_t)c > MAX_UNICODE) { + if (static_cast<uint32_t>(c) > MAX_UNICODE) { return errorValue; } if (c >= highStart) { @@ -295,7 +295,7 @@ inline uint32_t maybeFilterValue(uint32_t value, uint32_t initialValue, uint32_t UChar32 MutableCodePointTrie::getRange( UChar32 start, UCPMapValueFilter *filter, const void *context, uint32_t *pValue) const { - if ((uint32_t)start > MAX_UNICODE) { + if (static_cast<uint32_t>(start) > MAX_UNICODE) { return U_SENTINEL; } if (start >= highStart) { @@ -387,7 +387,7 @@ bool MutableCodePointTrie::ensureHighStart(UChar32 c) { int32_t i = highStart >> UCPTRIE_SHIFT_3; int32_t iLimit = c >> UCPTRIE_SHIFT_3; if (iLimit > indexCapacity) { - uint32_t *newIndex = (uint32_t *)uprv_malloc(I_LIMIT * 4); + uint32_t* newIndex = static_cast<uint32_t*>(uprv_malloc(I_LIMIT * 4)); if (newIndex == nullptr) { return false; } uprv_memcpy(newIndex, index, i * 4); uprv_free(index); @@ -418,7 +418,7 @@ int32_t MutableCodePointTrie::allocDataBlock(int32_t blockLength) { // or the code writes more values than should be possible. return -1; } - uint32_t *newData = (uint32_t *)uprv_malloc(capacity * 4); + uint32_t* newData = static_cast<uint32_t*>(uprv_malloc(capacity * 4)); if (newData == nullptr) { return -1; } @@ -468,7 +468,7 @@ void MutableCodePointTrie::set(UChar32 c, uint32_t value, UErrorCode &errorCode) if (U_FAILURE(errorCode)) { return; } - if ((uint32_t)c > MAX_UNICODE) { + if (static_cast<uint32_t>(c) > MAX_UNICODE) { errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } @@ -495,7 +495,7 @@ void MutableCodePointTrie::setRange(UChar32 start, UChar32 end, uint32_t value, if (U_FAILURE(errorCode)) { return; } - if ((uint32_t)start > MAX_UNICODE || (uint32_t)end > MAX_UNICODE || start > end) { + if (static_cast<uint32_t>(start) > MAX_UNICODE || static_cast<uint32_t>(end) > MAX_UNICODE || start > end) { errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } @@ -792,7 +792,7 @@ public: } if (newLength > capacity) { uprv_free(table); - table = (uint32_t *)uprv_malloc(newLength * 4); + table = static_cast<uint32_t*>(uprv_malloc(newLength * 4)); if (table == nullptr) { return false; } @@ -1207,8 +1207,8 @@ int32_t MutableCodePointTrie::compactIndex(int32_t fastILimit, MixedBlocks &mixe int32_t i3FirstNull = -1; for (int32_t i = 0, j = 0; i < fastILimit; ++j) { uint32_t i3 = index[i]; - fastIndex[j] = (uint16_t)i3; - if (i3 == (uint32_t)dataNullOffset) { + fastIndex[j] = static_cast<uint16_t>(i3); + if (i3 == static_cast<uint32_t>(dataNullOffset)) { if (i3FirstNull < 0) { i3FirstNull = j; } else if (index3NullOffset < 0 && @@ -1257,7 +1257,7 @@ int32_t MutableCodePointTrie::compactIndex(int32_t fastILimit, MixedBlocks &mixe do { uint32_t i3 = index[j]; oredI3 |= i3; - if (i3 != (uint32_t)dataNullOffset) { + if (i3 != static_cast<uint32_t>(dataNullOffset)) { isNull = false; } } while (++j < jLimit); @@ -1299,7 +1299,7 @@ int32_t MutableCodePointTrie::compactIndex(int32_t fastILimit, MixedBlocks &mixe // Index table: Fast index, index-1, index-3, index-2. // +1 for possible index table padding. int32_t index16Capacity = fastIndexLength + index1Length + index3Capacity + index2Capacity + 1; - index16 = (uint16_t *)uprv_malloc(index16Capacity * 2); + index16 = static_cast<uint16_t*>(uprv_malloc(index16Capacity * 2)); if (index16 == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return 0; @@ -1531,7 +1531,7 @@ int32_t MutableCodePointTrie::compactTrie(int32_t fastILimit, UErrorCode &errorC errorCode = U_MEMORY_ALLOCATION_ERROR; return 0; } - uint32_t *newData = (uint32_t *)uprv_malloc(newDataCapacity * 4); + uint32_t* newData = static_cast<uint32_t*>(uprv_malloc(newDataCapacity * 4)); if (newData == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return 0; @@ -1654,7 +1654,7 @@ UCPTrie *MutableCodePointTrie::build(UCPTrieType type, UCPTrieValueWidth valueWi length += sizeof(UCPTrie); U_ASSERT((length & 3) == 0); - uint8_t *bytes = (uint8_t *)uprv_malloc(length); + uint8_t* bytes = static_cast<uint8_t*>(uprv_malloc(length)); if (bytes == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; clear(); @@ -1679,13 +1679,13 @@ UCPTrie *MutableCodePointTrie::build(UCPTrieType type, UCPTrieValueWidth valueWi bytes += sizeof(UCPTrie); // Fill the index and data arrays. - uint16_t *dest16 = (uint16_t *)bytes; + uint16_t* dest16 = reinterpret_cast<uint16_t*>(bytes); trie->index = dest16; if (highStart <= fastLimit) { // Condense only the fast index from the mutable-trie index. for (int32_t i = 0, j = 0; j < indexLength; i += SMALL_DATA_BLOCKS_PER_BMP_BLOCK, ++j) { - *dest16++ = (uint16_t)index[i]; // dest16[j] + *dest16++ = static_cast<uint16_t>(index[i]); // dest16[j] } } else { uprv_memcpy(dest16, index16, indexLength * 2); @@ -1700,19 +1700,19 @@ UCPTrie *MutableCodePointTrie::build(UCPTrieType type, UCPTrieValueWidth valueWi // Write 16-bit data values. trie->data.ptr16 = dest16; for (int32_t i = dataLength; i > 0; --i) { - *dest16++ = (uint16_t)*p++; + *dest16++ = static_cast<uint16_t>(*p++); } break; case UCPTRIE_VALUE_BITS_32: // Write 32-bit data values. - trie->data.ptr32 = (uint32_t *)bytes; + trie->data.ptr32 = reinterpret_cast<uint32_t*>(bytes); uprv_memcpy(bytes, p, (size_t)dataLength * 4); break; case UCPTRIE_VALUE_BITS_8: // Write 8-bit data values. trie->data.ptr8 = bytes; for (int32_t i = dataLength; i > 0; --i) { - *bytes++ = (uint8_t)*p++; + *bytes++ = static_cast<uint8_t>(*p++); } break; default: diff --git a/thirdparty/icu4c/common/unames.cpp b/thirdparty/icu4c/common/unames.cpp index 1b3192bf25..71b2baff6c 100644 --- a/thirdparty/icu4c/common/unames.cpp +++ b/thirdparty/icu4c/common/unames.cpp @@ -180,7 +180,7 @@ static UBool U_CALLCONV isAcceptable(void * /*context*/, const char * /*type*/, const char * /*name*/, const UDataInfo *pInfo) { - return (UBool)( + return pInfo->size>=20 && pInfo->isBigEndian==U_IS_BIG_ENDIAN && pInfo->charsetFamily==U_CHARSET_FAMILY && @@ -188,7 +188,7 @@ isAcceptable(void * /*context*/, pInfo->dataFormat[1]==0x6e && pInfo->dataFormat[2]==0x61 && pInfo->dataFormat[3]==0x6d && - pInfo->formatVersion[0]==1); + pInfo->formatVersion[0]==1; } static void U_CALLCONV @@ -238,9 +238,9 @@ static uint16_t expandName(UCharNames *names, const uint8_t *name, uint16_t nameLength, UCharNameChoice nameChoice, char *buffer, uint16_t bufferLength) { - uint16_t *tokens=(uint16_t *)names+8; + uint16_t* tokens = reinterpret_cast<uint16_t*>(names) + 8; uint16_t token, tokenCount=*tokens++, bufferPos=0; - uint8_t *tokenStrings=(uint8_t *)names+names->tokenStringOffset; + uint8_t* tokenStrings = reinterpret_cast<uint8_t*>(names) + names->tokenStringOffset; uint8_t c; if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) { @@ -248,7 +248,7 @@ expandName(UCharNames *names, * skip the modern name if it is not requested _and_ * if the semicolon byte value is a character, not a token number */ - if((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) { + if (static_cast<uint8_t>(';') >= tokenCount || tokens[static_cast<uint8_t>(';')] == static_cast<uint16_t>(-1)) { int fieldIndex= nameChoice==U_ISO_COMMENT ? 2 : nameChoice; do { while(nameLength>0) { @@ -283,12 +283,12 @@ expandName(UCharNames *names, } } else { token=tokens[c]; - if(token==(uint16_t)(-2)) { + if (token == static_cast<uint16_t>(-2)) { /* this is a lead byte for a double-byte token */ token=tokens[c<<8|*name++]; --nameLength; } - if(token==(uint16_t)(-1)) { + if (token == static_cast<uint16_t>(-1)) { if(c!=';') { /* explicit letter */ WRITE_CHAR(buffer, bufferLength, bufferPos, c); @@ -297,7 +297,7 @@ expandName(UCharNames *names, extended names and there was no 2.0 name but there is a 1.0 name. */ if(!bufferPos && nameChoice == U_EXTENDED_CHAR_NAME) { - if ((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) { + if (static_cast<uint8_t>(';') >= tokenCount || tokens[static_cast<uint8_t>(';')] == static_cast<uint16_t>(-1)) { continue; } } @@ -331,9 +331,9 @@ static UBool compareName(UCharNames *names, const uint8_t *name, uint16_t nameLength, UCharNameChoice nameChoice, const char *otherName) { - uint16_t *tokens=(uint16_t *)names+8; + uint16_t* tokens = reinterpret_cast<uint16_t*>(names) + 8; uint16_t token, tokenCount=*tokens++; - uint8_t *tokenStrings=(uint8_t *)names+names->tokenStringOffset; + uint8_t* tokenStrings = reinterpret_cast<uint8_t*>(names) + names->tokenStringOffset; uint8_t c; const char *origOtherName = otherName; @@ -342,7 +342,7 @@ compareName(UCharNames *names, * skip the modern name if it is not requested _and_ * if the semicolon byte value is a character, not a token number */ - if((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) { + if (static_cast<uint8_t>(';') >= tokenCount || tokens[static_cast<uint8_t>(';')] == static_cast<uint16_t>(-1)) { int fieldIndex= nameChoice==U_ISO_COMMENT ? 2 : nameChoice; do { while(nameLength>0) { @@ -370,7 +370,7 @@ compareName(UCharNames *names, if(c>=tokenCount) { if(c!=';') { /* implicit letter */ - if((char)c!=*otherName++) { + if (static_cast<char>(c) != *otherName++) { return false; } } else { @@ -379,15 +379,15 @@ compareName(UCharNames *names, } } else { token=tokens[c]; - if(token==(uint16_t)(-2)) { + if (token == static_cast<uint16_t>(-2)) { /* this is a lead byte for a double-byte token */ token=tokens[c<<8|*name++]; --nameLength; } - if(token==(uint16_t)(-1)) { + if (token == static_cast<uint16_t>(-1)) { if(c!=';') { /* explicit letter */ - if((char)c!=*otherName++) { + if (static_cast<char>(c) != *otherName++) { return false; } } else { @@ -395,7 +395,7 @@ compareName(UCharNames *names, extended names and there was no 2.0 name but there is a 1.0 name. */ if(otherName == origOtherName && nameChoice == U_EXTENDED_CHAR_NAME) { - if ((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) { + if (static_cast<uint8_t>(';') >= tokenCount || tokens[static_cast<uint8_t>(';')] == static_cast<uint16_t>(-1)) { continue; } } @@ -406,7 +406,7 @@ compareName(UCharNames *names, /* write token word */ uint8_t *tokenString=tokenStrings+token; while((c=*tokenString++)!=0) { - if((char)c!=*otherName++) { + if (static_cast<char>(c) != *otherName++) { return false; } } @@ -415,7 +415,7 @@ compareName(UCharNames *names, } /* complete match? */ - return (UBool)(*otherName==0); + return *otherName == 0; } static uint8_t getCharCat(UChar32 cp) { @@ -462,7 +462,7 @@ static uint16_t getExtName(uint32_t code, char *buffer, uint16_t bufferLength) { if (ndigits < 4) ndigits = 4; for (cp = code, i = ndigits; (cp || i > 0) && bufferLength; cp >>= 4, bufferLength--) { - uint8_t v = (uint8_t)(cp & 0xf); + uint8_t v = static_cast<uint8_t>(cp & 0xf); buffer[--i] = (v < 10 ? '0' + v : 'A' + v - 10); } buffer += ndigits; @@ -482,14 +482,14 @@ static uint16_t getExtName(uint32_t code, char *buffer, uint16_t bufferLength) { static const uint16_t * getGroup(UCharNames *names, uint32_t code) { const uint16_t *groups=GET_GROUPS(names); - uint16_t groupMSB=(uint16_t)(code>>GROUP_SHIFT), + uint16_t groupMSB = static_cast<uint16_t>(code >> GROUP_SHIFT), start=0, limit=*groups++, number; /* binary search for the group of names that contains the one for code */ while(start<limit-1) { - number=(uint16_t)((start+limit)/2); + number = static_cast<uint16_t>((start + limit) / 2); if(groupMSB<groups[number*GROUP_LENGTH+GROUP_MSB]) { limit=number; } else { @@ -525,14 +525,14 @@ expandGroupLengths(const uint8_t *s, /* read even nibble - MSBs of lengthByte */ if(length>=12) { /* double-nibble length spread across two bytes */ - length=(uint16_t)(((length&0x3)<<4|lengthByte>>4)+12); + length = static_cast<uint16_t>(((length & 0x3) << 4 | lengthByte >> 4) + 12); lengthByte&=0xf; } else if((lengthByte /* &0xf0 */)>=0xc0) { /* double-nibble length spread across this one byte */ - length=(uint16_t)((lengthByte&0x3f)+12); + length = static_cast<uint16_t>((lengthByte & 0x3f) + 12); } else { /* single-nibble length in MSBs */ - length=(uint16_t)(lengthByte>>4); + length = static_cast<uint16_t>(lengthByte >> 4); lengthByte&=0xf; } @@ -568,7 +568,7 @@ expandGroupName(UCharNames *names, const uint16_t *group, uint16_t lineNumber, UCharNameChoice nameChoice, char *buffer, uint16_t bufferLength) { uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2]; - const uint8_t *s=(uint8_t *)names+names->groupStringOffset+GET_GROUP_OFFSET(group); + const uint8_t* s = reinterpret_cast<uint8_t*>(names) + names->groupStringOffset + GET_GROUP_OFFSET(group); s=expandGroupLengths(s, offsets, lengths); return expandName(names, s+offsets[lineNumber], lengths[lineNumber], nameChoice, buffer, bufferLength); @@ -578,8 +578,8 @@ static uint16_t getName(UCharNames *names, uint32_t code, UCharNameChoice nameChoice, char *buffer, uint16_t bufferLength) { const uint16_t *group=getGroup(names, code); - if((uint16_t)(code>>GROUP_SHIFT)==group[GROUP_MSB]) { - return expandGroupName(names, group, (uint16_t)(code&GROUP_MASK), nameChoice, + if (static_cast<uint16_t>(code >> GROUP_SHIFT) == group[GROUP_MSB]) { + return expandGroupName(names, group, static_cast<uint16_t>(code & GROUP_MASK), nameChoice, buffer, bufferLength); } else { /* group not found */ @@ -601,7 +601,7 @@ enumGroupNames(UCharNames *names, const uint16_t *group, UEnumCharNamesFn *fn, void *context, UCharNameChoice nameChoice) { uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2]; - const uint8_t *s=(uint8_t *)names+names->groupStringOffset+GET_GROUP_OFFSET(group); + const uint8_t* s = reinterpret_cast<uint8_t*>(names) + names->groupStringOffset + GET_GROUP_OFFSET(group); s=expandGroupLengths(s, offsets, lengths); if(fn!=DO_FIND_NAME) { @@ -622,10 +622,10 @@ enumGroupNames(UCharNames *names, const uint16_t *group, ++start; } } else { - const char *otherName=((FindName *)context)->otherName; + const char* otherName = static_cast<FindName*>(context)->otherName; while(start<=end) { if(compareName(names, s+offsets[start&GROUP_MASK], lengths[start&GROUP_MASK], nameChoice, otherName)) { - ((FindName *)context)->code=start; + static_cast<FindName*>(context)->code = start; return false; } ++start; @@ -671,15 +671,15 @@ enumNames(UCharNames *names, uint16_t startGroupMSB, endGroupMSB, groupCount; const uint16_t *group, *groupLimit; - startGroupMSB=(uint16_t)(start>>GROUP_SHIFT); - endGroupMSB=(uint16_t)((limit-1)>>GROUP_SHIFT); + startGroupMSB = static_cast<uint16_t>(start >> GROUP_SHIFT); + endGroupMSB = static_cast<uint16_t>((limit - 1) >> GROUP_SHIFT); /* find the group that contains start, or the highest before it */ group=getGroup(names, start); if(startGroupMSB<group[GROUP_MSB] && nameChoice==U_EXTENDED_CHAR_NAME) { /* enumerate synthetic names between start and the group start */ - UChar32 extLimit=((UChar32)group[GROUP_MSB]<<GROUP_SHIFT); + UChar32 extLimit = static_cast<UChar32>(group[GROUP_MSB]) << GROUP_SHIFT; if(extLimit>limit) { extLimit=limit; } @@ -703,7 +703,7 @@ enumNames(UCharNames *names, /* enumerate characters in the partial start group */ if((start&GROUP_MASK)!=0) { if(!enumGroupNames(names, group, - start, ((UChar32)startGroupMSB<<GROUP_SHIFT)+LINES_PER_GROUP-1, + start, (static_cast<UChar32>(startGroupMSB) << GROUP_SHIFT) + LINES_PER_GROUP - 1, fn, context, nameChoice)) { return false; } @@ -727,7 +727,7 @@ enumNames(UCharNames *names, /* enumerate entire groups between the start- and end-groups */ while(group<groupLimit && group[GROUP_MSB]<endGroupMSB) { const uint16_t *nextGroup; - start=(UChar32)group[GROUP_MSB]<<GROUP_SHIFT; + start = static_cast<UChar32>(group[GROUP_MSB]) << GROUP_SHIFT; if(!enumGroupNames(names, group, start, start+LINES_PER_GROUP-1, fn, context, nameChoice)) { return false; } @@ -790,14 +790,14 @@ writeFactorSuffix(const uint16_t *factors, uint16_t count, --count; for(i=count; i>0; --i) { factor=factors[i]; - indexes[i]=(uint16_t)(code%factor); + indexes[i] = static_cast<uint16_t>(code % factor); code/=factor; } /* * we don't need to calculate the last modulus because start<=code<=end * guarantees here that code<=factors[0] */ - indexes[0]=(uint16_t)code; + indexes[0] = static_cast<uint16_t>(code); /* write each element */ for(;;) { @@ -826,7 +826,7 @@ writeFactorSuffix(const uint16_t *factors, uint16_t count, } /* skip the rest of the strings for this factors[i] */ - factor=(uint16_t)(factors[i]-indexes[i]-1); + factor = static_cast<uint16_t>(factors[i] - indexes[i] - 1); while(factor>0) { while(*s++!=0) {} --factor; @@ -865,7 +865,7 @@ getAlgName(AlgorithmicRange *range, uint32_t code, UCharNameChoice nameChoice, switch(range->type) { case 0: { /* name = prefix hex-digits */ - const char *s=(const char *)(range+1); + const char* s = reinterpret_cast<const char*>(range + 1); char c; uint16_t i, count; @@ -885,7 +885,7 @@ getAlgName(AlgorithmicRange *range, uint32_t code, UCharNameChoice nameChoice, for(i=count; i>0;) { if(--i<bufferLength) { - c=(char)(code&0xf); + c = static_cast<char>(code & 0xf); if(c<10) { c+='0'; } else { @@ -902,9 +902,9 @@ getAlgName(AlgorithmicRange *range, uint32_t code, UCharNameChoice nameChoice, case 1: { /* name = prefix factorized-elements */ uint16_t indexes[8]; - const uint16_t *factors=(const uint16_t *)(range+1); + const uint16_t* factors = reinterpret_cast<const uint16_t*>(range + 1); uint16_t count=range->variant; - const char *s=(const char *)(factors+count); + const char* s = reinterpret_cast<const char*>(factors + count); char c; /* copy prefix */ @@ -950,7 +950,7 @@ enumAlgNames(AlgorithmicRange *range, char c; /* get the full name of the start character */ - length=getAlgName(range, (uint32_t)start, nameChoice, buffer, sizeof(buffer)); + length = getAlgName(range, static_cast<uint32_t>(start), nameChoice, buffer, sizeof(buffer)); if(length<=0) { return true; } @@ -973,7 +973,7 @@ enumAlgNames(AlgorithmicRange *range, for (;;) { c=*--s; if(('0'<=c && c<'9') || ('A'<=c && c<'F')) { - *s=(char)(c+1); + *s = static_cast<char>(c + 1); break; } else if(c=='9') { *s='A'; @@ -992,9 +992,9 @@ enumAlgNames(AlgorithmicRange *range, case 1: { uint16_t indexes[8]; const char *elementBases[8], *elements[8]; - const uint16_t *factors=(const uint16_t *)(range+1); + const uint16_t* factors = reinterpret_cast<const uint16_t*>(range + 1); uint16_t count=range->variant; - const char *s=(const char *)(factors+count); + const char* s = reinterpret_cast<const char*>(factors + count); char *suffix, *t; uint16_t prefixLength, i, idx; @@ -1011,10 +1011,10 @@ enumAlgNames(AlgorithmicRange *range, } /* append the suffix of the start character */ - length=(uint16_t)(prefixLength+writeFactorSuffix(factors, count, - s, (uint32_t)start-range->start, + length = static_cast<uint16_t>(prefixLength + writeFactorSuffix(factors, count, + s, static_cast<uint32_t>(start) - range->start, indexes, elementBases, elements, - suffix, (uint16_t)(sizeof(buffer)-prefixLength))); + suffix, static_cast<uint16_t>(sizeof(buffer) - prefixLength))); /* call the enumerator function with this first character */ if(!fn(context, start, nameChoice, buffer, length)) { @@ -1026,7 +1026,7 @@ enumAlgNames(AlgorithmicRange *range, /* increment the indexes in lexical order bound by the factors */ i=count; for (;;) { - idx=(uint16_t)(indexes[--i]+1); + idx = static_cast<uint16_t>(indexes[--i] + 1); if(idx<factors[i]) { /* skip one index and its element string */ indexes[i]=idx; @@ -1085,14 +1085,14 @@ findAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *oth switch(range->type) { case 0: { /* name = prefix hex-digits */ - const char *s=(const char *)(range+1); + const char* s = reinterpret_cast<const char*>(range + 1); char c; uint16_t i, count; /* compare prefix */ while((c=*s++)!=0) { - if((char)c!=*otherName++) { + if (c != *otherName++) { return 0xffff; } } @@ -1112,7 +1112,7 @@ findAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *oth } /* does it fit into the range? */ - if(*otherName==0 && range->start<=(uint32_t)code && (uint32_t)code<=range->end) { + if (*otherName == 0 && range->start <= static_cast<uint32_t>(code) && static_cast<uint32_t>(code) <= range->end) { return code; } break; @@ -1121,9 +1121,9 @@ findAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *oth char buffer[64]; uint16_t indexes[8]; const char *elementBases[8], *elements[8]; - const uint16_t *factors=(const uint16_t *)(range+1); + const uint16_t* factors = reinterpret_cast<const uint16_t*>(range + 1); uint16_t count=range->variant; - const char *s=(const char *)(factors+count), *t; + const char *s = reinterpret_cast<const char*>(factors + count), *t; UChar32 start, limit; uint16_t i, idx; @@ -1133,13 +1133,13 @@ findAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *oth /* compare prefix */ while((c=*s++)!=0) { - if((char)c!=*otherName++) { + if (c != *otherName++) { return 0xffff; } } - start=(UChar32)range->start; - limit=(UChar32)(range->end+1); + start = static_cast<UChar32>(range->start); + limit = static_cast<UChar32>(range->end + 1); /* initialize the suffix elements for enumeration; indexes should all be set to 0 */ writeFactorSuffix(factors, count, s, 0, @@ -1155,7 +1155,7 @@ findAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *oth /* increment the indexes in lexical order bound by the factors */ i=count; for (;;) { - idx=(uint16_t)(indexes[--i]+1); + idx = static_cast<uint16_t>(indexes[--i] + 1); if(idx<factors[i]) { /* skip one index and its element string */ indexes[i]=idx; @@ -1220,27 +1220,27 @@ calcAlgNameSetsLengths(int32_t maxNameLength) { int32_t length; /* enumerate algorithmic ranges */ - p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset); + p = reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(uCharNames) + uCharNames->algNamesOffset); rangeCount=*p; - range=(AlgorithmicRange *)(p+1); + range = reinterpret_cast<AlgorithmicRange*>(p + 1); while(rangeCount>0) { switch(range->type) { case 0: /* name = prefix + (range->variant times) hex-digits */ /* prefix */ - length=calcStringSetLength(gNameSet, (const char *)(range+1))+range->variant; + length = calcStringSetLength(gNameSet, reinterpret_cast<const char*>(range + 1)) + range->variant; if(length>maxNameLength) { maxNameLength=length; } break; case 1: { /* name = prefix factorized-elements */ - const uint16_t *factors=(const uint16_t *)(range+1); + const uint16_t* factors = reinterpret_cast<const uint16_t*>(range + 1); const char *s; int32_t i, count=range->variant, factor, factorLength, maxFactorLength; /* prefix length */ - s=(const char *)(factors+count); + s = reinterpret_cast<const char*>(factors + count); length=calcStringSetLength(gNameSet, s); s+=length+1; /* start of factor suffixes */ @@ -1267,7 +1267,7 @@ calcAlgNameSetsLengths(int32_t maxNameLength) { break; } - range=(AlgorithmicRange *)((uint8_t *)range+range->size); + range = reinterpret_cast<AlgorithmicRange*>(reinterpret_cast<uint8_t*>(range) + range->size); --rangeCount; } return maxNameLength; @@ -1301,19 +1301,19 @@ calcNameSetLength(const uint16_t *tokens, uint16_t tokenCount, const uint8_t *to int32_t length=0, tokenLength; uint16_t c, token; - while(line!=lineLimit && (c=*line++)!=(uint8_t)';') { + while (line != lineLimit && (c = *line++) != static_cast<uint8_t>(';')) { if(c>=tokenCount) { /* implicit letter */ SET_ADD(set, c); ++length; } else { token=tokens[c]; - if(token==(uint16_t)(-2)) { + if (token == static_cast<uint16_t>(-2)) { /* this is a lead byte for a double-byte token */ c=c<<8|*line++; token=tokens[c]; } - if(token==(uint16_t)(-1)) { + if (token == static_cast<uint16_t>(-1)) { /* explicit letter */ SET_ADD(set, c); ++length; @@ -1323,11 +1323,11 @@ calcNameSetLength(const uint16_t *tokens, uint16_t tokenCount, const uint8_t *to /* use cached token length */ tokenLength=tokenLengths[c]; if(tokenLength==0) { - tokenLength=calcStringSetLength(set, (const char *)tokenStrings+token); - tokenLengths[c]=(int8_t)tokenLength; + tokenLength = calcStringSetLength(set, reinterpret_cast<const char*>(tokenStrings) + token); + tokenLengths[c] = static_cast<int8_t>(tokenLength); } } else { - tokenLength=calcStringSetLength(set, (const char *)tokenStrings+token); + tokenLength = calcStringSetLength(set, reinterpret_cast<const char*>(tokenStrings) + token); } length+=tokenLength; } @@ -1342,9 +1342,9 @@ static void calcGroupNameSetsLengths(int32_t maxNameLength) { uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2]; - uint16_t *tokens=(uint16_t *)uCharNames+8; + uint16_t* tokens = reinterpret_cast<uint16_t*>(uCharNames) + 8; uint16_t tokenCount=*tokens++; - uint8_t *tokenStrings=(uint8_t *)uCharNames+uCharNames->tokenStringOffset; + uint8_t* tokenStrings = reinterpret_cast<uint8_t*>(uCharNames) + uCharNames->tokenStringOffset; int8_t *tokenLengths; @@ -1353,7 +1353,7 @@ calcGroupNameSetsLengths(int32_t maxNameLength) { int32_t groupCount, lineNumber, length; - tokenLengths=(int8_t *)uprv_malloc(tokenCount); + tokenLengths = static_cast<int8_t*>(uprv_malloc(tokenCount)); if(tokenLengths!=nullptr) { uprv_memset(tokenLengths, 0, tokenCount); } @@ -1363,7 +1363,7 @@ calcGroupNameSetsLengths(int32_t maxNameLength) { /* enumerate all groups */ while(groupCount>0) { - s=(uint8_t *)uCharNames+uCharNames->groupStringOffset+GET_GROUP_OFFSET(group); + s = reinterpret_cast<uint8_t*>(uCharNames) + uCharNames->groupStringOffset + GET_GROUP_OFFSET(group); s=expandGroupLengths(s, offsets, lengths); /* enumerate all lines in each group */ @@ -1424,7 +1424,7 @@ calcNameSetsLengths(UErrorCode *pErrorCode) { } /* set hex digits, used in various names, and <>-, used in extended names */ - for(i=0; i<(int32_t)sizeof(extChars)-1; ++i) { + for (i = 0; i < static_cast<int32_t>(sizeof(extChars)) - 1; ++i) { SET_ADD(gNameSet, extChars[i]); } @@ -1732,7 +1732,7 @@ charSetToUSet(uint32_t cset[8], const USetAdder *sa) { length=0; for(i=0; i<256; ++i) { if(SET_CONTAINS(cset, i)) { - cs[length++]=(char)i; + cs[length++] = static_cast<char>(i); } } @@ -1785,7 +1785,7 @@ makeTokenMap(const UDataSwapper *ds, if(ds->inCharset==ds->outCharset) { /* Same charset family: identity permutation */ for(i=0; i<256; ++i) { - map[i]=(uint8_t)i; + map[i] = static_cast<uint8_t>(i); } } else { uprv_memset(map, 0, 256); @@ -1799,7 +1799,7 @@ makeTokenMap(const UDataSwapper *ds, for(i=1; i<tokenCount; ++i) { if(tokens[i]==-1) { /* convert the direct byte character */ - c1=(uint8_t)i; + c1 = static_cast<uint8_t>(i); ds->swapInvChars(ds, &c1, 1, &c2, pErrorCode); if(U_FAILURE(*pErrorCode)) { udata_printError(ds, "unames/makeTokenMap() finds variant character 0x%02x used (input charset family %d)\n", @@ -1821,7 +1821,7 @@ makeTokenMap(const UDataSwapper *ds, while(usedOutChar[j]) { ++j; } - map[i]=(uint8_t)j++; + map[i] = static_cast<uint8_t>(j++); } } diff --git a/thirdparty/icu4c/common/unicode/brkiter.h b/thirdparty/icu4c/common/unicode/brkiter.h index bd96629285..30c59c4a94 100644 --- a/thirdparty/icu4c/common/unicode/brkiter.h +++ b/thirdparty/icu4c/common/unicode/brkiter.h @@ -219,7 +219,7 @@ public: * boundaries have been returned. * @stable ICU 2.0 */ - DONE = (int32_t)-1 + DONE = static_cast<int32_t>(-1) }; /** diff --git a/thirdparty/icu4c/common/unicode/bytestream.h b/thirdparty/icu4c/common/unicode/bytestream.h index 997746e428..bea41461bc 100644 --- a/thirdparty/icu4c/common/unicode/bytestream.h +++ b/thirdparty/icu4c/common/unicode/bytestream.h @@ -281,7 +281,7 @@ class StringByteSink : public ByteSink { */ StringByteSink(StringClass* dest, int32_t initialAppendCapacity) : dest_(dest) { if (initialAppendCapacity > 0 && - (uint32_t)initialAppendCapacity > (dest->capacity() - dest->length())) { + static_cast<uint32_t>(initialAppendCapacity) > dest->capacity() - dest->length()) { dest->reserve(dest->length() + initialAppendCapacity); } } diff --git a/thirdparty/icu4c/common/unicode/bytestrie.h b/thirdparty/icu4c/common/unicode/bytestrie.h index 1719a6bb83..c07dfada94 100644 --- a/thirdparty/icu4c/common/unicode/bytestrie.h +++ b/thirdparty/icu4c/common/unicode/bytestrie.h @@ -109,7 +109,7 @@ public: */ uint64_t getState64() const { return (static_cast<uint64_t>(remainingMatchLength_ + 2) << kState64RemainingShift) | - (uint64_t)(pos_ - bytes_); + static_cast<uint64_t>(pos_ - bytes_); } /** @@ -439,7 +439,7 @@ private: } static inline UStringTrieResult valueResult(int32_t node) { - return (UStringTrieResult)(USTRINGTRIE_INTERMEDIATE_VALUE-(node&kValueIsFinal)); + return static_cast<UStringTrieResult>(USTRINGTRIE_INTERMEDIATE_VALUE - (node & kValueIsFinal)); } // Handles a branch node for both next(byte) and next(string). diff --git a/thirdparty/icu4c/common/unicode/char16ptr.h b/thirdparty/icu4c/common/unicode/char16ptr.h index de8182c7ad..daf35cd43b 100644 --- a/thirdparty/icu4c/common/unicode/char16ptr.h +++ b/thirdparty/icu4c/common/unicode/char16ptr.h @@ -12,6 +12,7 @@ #if U_SHOW_CPLUSPLUS_API #include <cstddef> +#include <string_view> /** * \file @@ -306,6 +307,76 @@ inline OldUChar *toOldUCharPtr(char16_t *p) { return reinterpret_cast<OldUChar *>(p); } +#ifndef U_FORCE_HIDE_INTERNAL_API +/** + * Is T convertible to a std::u16string_view or some other 16-bit string view? + * @internal + */ +template<typename T> +constexpr bool ConvertibleToU16StringView = + std::is_convertible_v<T, std::u16string_view> +#if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000) + || std::is_convertible_v<T, std::basic_string_view<uint16_t>> +#endif +#if U_SIZEOF_WCHAR_T==2 + || std::is_convertible_v<T, std::wstring_view> +#endif + ; + +namespace internal { +/** + * Pass-through overload. + * @internal + */ +inline std::u16string_view toU16StringView(std::u16string_view sv) { return sv; } + +#if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000) +/** + * Basically undefined behavior but sometimes necessary conversion + * from std::basic_string_view<uint16_t> to std::u16string_view. + * @internal + */ +inline std::u16string_view toU16StringView(std::basic_string_view<uint16_t> sv) { + return { ConstChar16Ptr(sv.data()), sv.length() }; +} +#endif + +#if U_SIZEOF_WCHAR_T==2 +/** + * Basically undefined behavior but sometimes necessary conversion + * from std::wstring_view to std::u16string_view. + * @internal + */ +inline std::u16string_view toU16StringView(std::wstring_view sv) { + return { ConstChar16Ptr(sv.data()), sv.length() }; +} +#endif + +/** + * Pass-through overload. + * @internal + */ +template <typename T, + typename = typename std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>>> +inline std::u16string_view toU16StringViewNullable(const T& text) { + return toU16StringView(text); +} + +/** + * In case of nullptr, return an empty view. + * @internal + */ +template <typename T, + typename = typename std::enable_if_t<std::is_pointer_v<std::remove_reference_t<T>>>, + typename = void> +inline std::u16string_view toU16StringViewNullable(const T& text) { + if (text == nullptr) return {}; // For backward compatibility. + return toU16StringView(text); +} + +} // internal +#endif // U_FORCE_HIDE_INTERNAL_API + U_NAMESPACE_END #endif /* U_SHOW_CPLUSPLUS_API */ diff --git a/thirdparty/icu4c/common/unicode/docmain.h b/thirdparty/icu4c/common/unicode/docmain.h index fa4dbbc052..676e868e7c 100644 --- a/thirdparty/icu4c/common/unicode/docmain.h +++ b/thirdparty/icu4c/common/unicode/docmain.h @@ -138,6 +138,11 @@ * <td>icu::DateFormat</td> * </tr> * <tr> + * <td>Relative Date and Time Formatting</td> + * <td>ureldatefmt.h</td> + * <td>icu::RelativeDateTimeFormatter</td> + * </tr> + * <tr> * <td>Message Formatting</td> * <td>umsg.h</td> * <td>icu::MessageFormat</td> diff --git a/thirdparty/icu4c/common/unicode/edits.h b/thirdparty/icu4c/common/unicode/edits.h index dda9d3ca75..bc3c943822 100644 --- a/thirdparty/icu4c/common/unicode/edits.h +++ b/thirdparty/icu4c/common/unicode/edits.h @@ -508,7 +508,7 @@ private: Edits ©Array(const Edits &other); Edits &moveArray(Edits &src) noexcept; - void setLastUnit(int32_t last) { array[length - 1] = (uint16_t)last; } + void setLastUnit(int32_t last) { array[length - 1] = static_cast<uint16_t>(last); } int32_t lastUnit() const { return length > 0 ? array[length - 1] : 0xffff; } void append(int32_t r); diff --git a/thirdparty/icu4c/common/unicode/idna.h b/thirdparty/icu4c/common/unicode/idna.h index 1c57205bae..1e36fa771f 100644 --- a/thirdparty/icu4c/common/unicode/idna.h +++ b/thirdparty/icu4c/common/unicode/idna.h @@ -70,6 +70,7 @@ public: * The worker functions use transitional processing, including deviation mappings, * unless UIDNA_NONTRANSITIONAL_TO_ASCII or UIDNA_NONTRANSITIONAL_TO_UNICODE * is used in which case the deviation characters are passed through without change. + * <b>Unicode 15.1 UTS #46 deprecated transitional processing.</b> * * Disallowed characters are mapped to U+FFFD. * @@ -82,6 +83,8 @@ public: * letters, digits, hyphen (LDH) and dot/full stop are disallowed and mapped to U+FFFD. * * @param options Bit set to modify the processing and error checking. + * These should include UIDNA_DEFAULT, or + * UIDNA_NONTRANSITIONAL_TO_ASCII | UIDNA_NONTRANSITIONAL_TO_UNICODE. * See option bit set values in uidna.h. * @param errorCode Standard ICU error code. Its input value must * pass the U_SUCCESS() test, or else the function returns diff --git a/thirdparty/icu4c/common/unicode/locid.h b/thirdparty/icu4c/common/unicode/locid.h index 60282d623d..e1afd598cf 100644 --- a/thirdparty/icu4c/common/unicode/locid.h +++ b/thirdparty/icu4c/common/unicode/locid.h @@ -727,7 +727,9 @@ public: * * @stable ICU 49 */ - void setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status); + void setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status) { + setKeywordValue(StringPiece{keywordName}, StringPiece{keywordValue}, status); + } /** * Sets or removes the value for a keyword. diff --git a/thirdparty/icu4c/common/unicode/messagepattern.h b/thirdparty/icu4c/common/unicode/messagepattern.h index 55b09bfbd4..db36ede727 100644 --- a/thirdparty/icu4c/common/unicode/messagepattern.h +++ b/thirdparty/icu4c/common/unicode/messagepattern.h @@ -775,7 +775,7 @@ public: UMessagePatternArgType getArgType() const { UMessagePatternPartType msgType=getType(); if(msgType ==UMSGPAT_PART_TYPE_ARG_START || msgType ==UMSGPAT_PART_TYPE_ARG_LIMIT) { - return (UMessagePatternArgType)value; + return static_cast<UMessagePatternArgType>(value); } else { return UMSGPAT_ARG_TYPE_NONE; } @@ -821,6 +821,7 @@ public: static const int32_t MAX_LENGTH=0xffff; static const int32_t MAX_VALUE=0x7fff; + static const int32_t MAX_NESTED_LEVELS=0x03ff; // Some fields are not final because they are modified during pattern parsing. // After pattern parsing, the parts are effectively immutable. diff --git a/thirdparty/icu4c/common/unicode/normalizer2.h b/thirdparty/icu4c/common/unicode/normalizer2.h index 6856ff8720..01271623f3 100644 --- a/thirdparty/icu4c/common/unicode/normalizer2.h +++ b/thirdparty/icu4c/common/unicode/normalizer2.h @@ -163,7 +163,6 @@ public: static const Normalizer2 * getNFKCCasefoldInstance(UErrorCode &errorCode); -#ifndef U_HIDE_DRAFT_API /** * Returns a Normalizer2 instance for a variant of Unicode toNFKC_Casefold() normalization * which is equivalent to applying the NFKC_Simple_Casefold mappings and then NFC. @@ -176,11 +175,10 @@ public: * immediately. Check for U_FAILURE() on output or use with * function chaining. (See User Guide for details.) * @return the requested Normalizer2, if successful - * @draft ICU 74 + * @stable ICU 74 */ static const Normalizer2 * getNFKCSimpleCasefoldInstance(UErrorCode &errorCode); -#endif // U_HIDE_DRAFT_API /** * Returns a Normalizer2 instance which uses the specified data file diff --git a/thirdparty/icu4c/common/unicode/platform.h b/thirdparty/icu4c/common/unicode/platform.h index 7aca76c67d..b2fcb21ef1 100644 --- a/thirdparty/icu4c/common/unicode/platform.h +++ b/thirdparty/icu4c/common/unicode/platform.h @@ -132,6 +132,8 @@ #define U_PF_BROWSER_NATIVE_CLIENT 4020 /** Android is based on Linux. @internal */ #define U_PF_ANDROID 4050 +/** Haiku is a POSIX-ish platform. @internal */ +#define U_PF_HAIKU 4080 /** Fuchsia is a POSIX-ish platform. @internal */ #define U_PF_FUCHSIA 4100 /* Maximum value for Linux-based platform is 4499 */ @@ -154,6 +156,8 @@ # define U_PLATFORM U_PF_MINGW #elif defined(__CYGWIN__) # define U_PLATFORM U_PF_CYGWIN + /* Cygwin uchar.h doesn't exist until Cygwin 3.5. */ +# include <cygwin/version.h> #elif defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) # define U_PLATFORM U_PF_WINDOWS #elif defined(__ANDROID__) @@ -200,6 +204,8 @@ # define U_PLATFORM U_PF_OS390 #elif defined(__OS400__) || defined(__TOS_OS400__) # define U_PLATFORM U_PF_OS400 +#elif defined(__HAIKU__) +# define U_PLATFORM U_PF_HAIKU #elif defined(__EMSCRIPTEN__) # define U_PLATFORM U_PF_EMSCRIPTEN #else @@ -235,7 +241,7 @@ /** * \def U_PLATFORM_USES_ONLY_WIN32_API * Defines whether the platform uses only the Win32 API. - * Set to 1 for Windows/MSVC and MinGW but not Cygwin. + * Set to 1 for Windows/MSVC, ClangCL and MinGW but not Cygwin. * @internal */ #ifdef U_PLATFORM_USES_ONLY_WIN32_API @@ -250,7 +256,7 @@ /** * \def U_PLATFORM_HAS_WIN32_API * Defines whether the Win32 API is available on the platform. - * Set to 1 for Windows/MSVC, MinGW and Cygwin. + * Set to 1 for Windows/MSVC, ClangCL, MinGW and Cygwin. * @internal */ #ifdef U_PLATFORM_HAS_WIN32_API @@ -722,12 +728,16 @@ /* * Notes: * C++11 and C11 require support for UTF-16 literals - * Doesn't work on Mac C11 (see workaround in ptypes.h). + * Doesn't work on Mac C11 (see workaround in ptypes.h) + * or Cygwin less than 3.5. */ -# if defined(__cplusplus) || !U_PLATFORM_IS_DARWIN_BASED +# if defined(__cplusplus) # define U_HAVE_CHAR16_T 1 -# else +# elif U_PLATFORM_IS_DARWIN_BASED || (U_PLATFORM == U_PF_CYGWIN && CYGWIN_VERSION_DLL_MAJOR < 3005) # define U_HAVE_CHAR16_T 0 +# else + // conformant C11 +# define U_HAVE_CHAR16_T 1 # endif #endif @@ -735,7 +745,9 @@ * @{ * \def U_DECLARE_UTF16 * Do not use this macro because it is not defined on all platforms. - * Use the UNICODE_STRING or U_STRING_DECL macros instead. + * In C++, use std::u16string_view literals, see the UNICODE_STRING docs. + * In C, use u"UTF-16 literals". + * See also the public U_STRING_DECL macro. * @internal */ #ifdef U_DECLARE_UTF16 @@ -766,7 +778,7 @@ #elif defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(__dllexport__) && \ UPRV_HAS_DECLSPEC_ATTRIBUTE(__dllimport__)) # define U_EXPORT __declspec(dllexport) -#elif defined(__GNUC__) +#elif defined(__GNUC__) || defined(__open_xl__) # define U_EXPORT __attribute__((visibility("default"))) #elif (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x550) \ || (defined(__SUNPRO_C) && __SUNPRO_C >= 0x550) @@ -805,7 +817,7 @@ */ #ifdef U_HIDDEN /* Use the predefined value. */ -#elif defined(__GNUC__) +#elif defined(__GNUC__) || defined(__open_xl__) # define U_HIDDEN __attribute__((visibility("hidden"))) #else # define U_HIDDEN diff --git a/thirdparty/icu4c/common/unicode/simpleformatter.h b/thirdparty/icu4c/common/unicode/simpleformatter.h index 33bdd6d48f..62c75d08bb 100644 --- a/thirdparty/icu4c/common/unicode/simpleformatter.h +++ b/thirdparty/icu4c/common/unicode/simpleformatter.h @@ -63,7 +63,7 @@ public: * Default constructor. * @stable ICU 57 */ - SimpleFormatter() : compiledPattern((char16_t)0) {} + SimpleFormatter() : compiledPattern(static_cast<char16_t>(0)) {} /** * Constructs a formatter from the pattern string. diff --git a/thirdparty/icu4c/common/unicode/stringpiece.h b/thirdparty/icu4c/common/unicode/stringpiece.h index 6f2a50eafc..74919d7222 100644 --- a/thirdparty/icu4c/common/unicode/stringpiece.h +++ b/thirdparty/icu4c/common/unicode/stringpiece.h @@ -32,6 +32,7 @@ #if U_SHOW_CPLUSPLUS_API #include <cstddef> +#include <string_view> #include <type_traits> #include "unicode/uobject.h" @@ -176,6 +177,16 @@ class U_COMMON_API StringPiece : public UMemory { */ StringPiece(const StringPiece& x, int32_t pos, int32_t len); +#ifndef U_HIDE_INTERNAL_API + /** + * Converts to a std::string_view(). + * @internal + */ + inline operator std::string_view() const { + return {data(), static_cast<std::string_view::size_type>(size())}; + } +#endif // U_HIDE_INTERNAL_API + /** * Returns the string pointer. May be nullptr if it is empty. * diff --git a/thirdparty/icu4c/common/unicode/stringtriebuilder.h b/thirdparty/icu4c/common/unicode/stringtriebuilder.h index 429d7883f1..62108dfe3e 100644 --- a/thirdparty/icu4c/common/unicode/stringtriebuilder.h +++ b/thirdparty/icu4c/common/unicode/stringtriebuilder.h @@ -346,7 +346,7 @@ protected: virtual void write(StringTrieBuilder &builder) override; // Adds a unit with a final value. void add(int32_t c, int32_t value) { - units[length]=(char16_t)c; + units[length] = static_cast<char16_t>(c); equal[length]=nullptr; values[length]=value; ++length; @@ -354,7 +354,7 @@ protected: } // Adds a unit which leads to another match node. void add(int32_t c, Node *node) { - units[length]=(char16_t)c; + units[length] = static_cast<char16_t>(c); equal[length]=node; values[length]=0; ++length; diff --git a/thirdparty/icu4c/common/unicode/ucasemap.h b/thirdparty/icu4c/common/unicode/ucasemap.h index d1c1b483ab..4b623e6910 100644 --- a/thirdparty/icu4c/common/unicode/ucasemap.h +++ b/thirdparty/icu4c/common/unicode/ucasemap.h @@ -202,8 +202,8 @@ ucasemap_setBreakIterator(UCaseMap *csm, UBreakIterator *iterToAdopt, UErrorCode * * The titlecase break iterator can be provided to customize for arbitrary * styles, using rules and dictionaries beyond the standard iterators. - * The standard titlecase iterator for the root locale implements the - * algorithm of Unicode TR 21. + * If the break iterator passed in is null, the default Unicode algorithm + * will be used to determine the titlecase positions. * * This function uses only the setText(), first() and next() methods of the * provided break iterator. @@ -312,8 +312,8 @@ ucasemap_utf8ToUpper(const UCaseMap *csm, * * The titlecase break iterator can be provided to customize for arbitrary * styles, using rules and dictionaries beyond the standard iterators. - * The standard titlecase iterator for the root locale implements the - * algorithm of Unicode TR 21. + * If the break iterator passed in is null, the default Unicode algorithm + * will be used to determine the titlecase positions. * * This function uses only the setUText(), first(), next() and close() methods of the * provided break iterator. diff --git a/thirdparty/icu4c/common/unicode/uchar.h b/thirdparty/icu4c/common/unicode/uchar.h index 4572230d9f..0daa7dd214 100644 --- a/thirdparty/icu4c/common/unicode/uchar.h +++ b/thirdparty/icu4c/common/unicode/uchar.h @@ -54,14 +54,14 @@ U_CDECL_BEGIN /*==========================================================================*/ /** * Unicode version number, default for the current ICU version. - * The actual Unicode Character Database (UCD) data is stored in uprops.dat + * The actual Unicode Character Database (UCD) data is stored in uprops.icu * and may be generated from UCD files from a different Unicode version. * Call u_getUnicodeVersion to get the actual Unicode version of the data. * * @see u_getUnicodeVersion * @stable ICU 2.0 */ -#define U_UNICODE_VERSION "15.1" +#define U_UNICODE_VERSION "16.0" /** * \file @@ -533,33 +533,39 @@ typedef enum UProperty { * @stable ICU 70 */ UCHAR_RGI_EMOJI=71, -#ifndef U_HIDE_DRAFT_API /** * Binary property IDS_Unary_Operator. * For programmatic determination of Ideographic Description Sequences. * - * @draft ICU 74 + * @stable ICU 74 */ UCHAR_IDS_UNARY_OPERATOR=72, /** * Binary property ID_Compat_Math_Start. * Used in mathematical identifier profile in UAX #31. - * @draft ICU 74 + * @stable ICU 74 */ UCHAR_ID_COMPAT_MATH_START=73, /** * Binary property ID_Compat_Math_Continue. * Used in mathematical identifier profile in UAX #31. - * @draft ICU 74 + * @stable ICU 74 */ UCHAR_ID_COMPAT_MATH_CONTINUE=74, +#ifndef U_HIDE_DRAFT_API + /** + * Binary property Modifier_Combining_Mark. + * Used by the AMTRA algorithm in UAX #53. + * @draft ICU 76 + */ + UCHAR_MODIFIER_COMBINING_MARK=75, #endif // U_HIDE_DRAFT_API #ifndef U_HIDE_DEPRECATED_API /** * One more than the last constant for binary Unicode properties. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UCHAR_BINARY_LIMIT=75, + UCHAR_BINARY_LIMIT=76, #endif // U_HIDE_DEPRECATED_API /** Enumerated property Bidi_Class. @@ -677,13 +683,19 @@ typedef enum UProperty { * @draft ICU 75 */ UCHAR_IDENTIFIER_STATUS=0x1019, + /** + * Enumerated property Indic_Conjunct_Break. + * Used in the grapheme cluster break algorithm in UAX #29. + * @draft ICU 76 + */ + UCHAR_INDIC_CONJUNCT_BREAK=0x101A, #endif // U_HIDE_DRAFT_API #ifndef U_HIDE_DEPRECATED_API /** * One more than the last constant for enumerated/integer Unicode properties. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UCHAR_INT_LIMIT=0x101A, + UCHAR_INT_LIMIT=0x101B, #endif // U_HIDE_DEPRECATED_API /** Bitmask property General_Category_Mask. @@ -1952,6 +1964,29 @@ enum UBlockCode { /** @stable ICU 74 */ UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_I = 328, /*[2EBF0]*/ + // New blocks in Unicode 16.0 + + /** @stable ICU 76 */ + UBLOCK_EGYPTIAN_HIEROGLYPHS_EXTENDED_A = 329, /*[13460]*/ + /** @stable ICU 76 */ + UBLOCK_GARAY = 330, /*[10D40]*/ + /** @stable ICU 76 */ + UBLOCK_GURUNG_KHEMA = 331, /*[16100]*/ + /** @stable ICU 76 */ + UBLOCK_KIRAT_RAI = 332, /*[16D40]*/ + /** @stable ICU 76 */ + UBLOCK_MYANMAR_EXTENDED_C = 333, /*[116D0]*/ + /** @stable ICU 76 */ + UBLOCK_OL_ONAL = 334, /*[1E5D0]*/ + /** @stable ICU 76 */ + UBLOCK_SUNUWAR = 335, /*[11BC0]*/ + /** @stable ICU 76 */ + UBLOCK_SYMBOLS_FOR_LEGACY_COMPUTING_SUPPLEMENT = 336, /*[1CC00]*/ + /** @stable ICU 76 */ + UBLOCK_TODHRI = 337, /*[105C0]*/ + /** @stable ICU 76 */ + UBLOCK_TULU_TIGALARI = 338, /*[11380]*/ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UBlockCode value. @@ -1959,7 +1994,7 @@ enum UBlockCode { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UBLOCK_COUNT = 329, + UBLOCK_COUNT = 339, #endif // U_HIDE_DEPRECATED_API /** @stable ICU 2.0 */ @@ -2254,6 +2289,8 @@ typedef enum UJoiningGroup { U_JG_THIN_YEH, /**< @stable ICU 70 */ U_JG_VERTICAL_TAIL, /**< @stable ICU 70 */ + U_JG_KASHMIRI_YEH, /**< @stable ICU 76 */ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UJoiningGroup value. @@ -2702,8 +2739,35 @@ typedef enum UIndicSyllabicCategory { U_INSC_VOWEL_DEPENDENT, /** @stable ICU 63 */ U_INSC_VOWEL_INDEPENDENT, + /** @stable ICU 76 */ + U_INSC_REORDERING_KILLER, } UIndicSyllabicCategory; +#ifndef U_HIDE_DRAFT_API +/** + * Indic Conjunct Break constants. + * + * @see UCHAR_INDIC_CONJUNCT_BREAK + * @draft ICU 76 + */ +typedef enum UIndicConjunctBreak { + /* + * Note: UIndicConjunctBreak constants are parsed by preparseucd.py. + * It matches lines like + * U_INCB_<Unicode Indic_Conjunct_Break value name> + */ + + /** @draft ICU 76 */ + U_INCB_NONE, + /** @draft ICU 76 */ + U_INCB_CONSONANT, + /** @draft ICU 76 */ + U_INCB_EXTEND, + /** @draft ICU 76 */ + U_INCB_LINKER, +} UIndicConjunctBreak; +#endif // U_HIDE_DRAFT_API + /** * Vertical Orientation constants. * diff --git a/thirdparty/icu4c/common/unicode/ucharstrie.h b/thirdparty/icu4c/common/unicode/ucharstrie.h index fa1b55616c..ca4b469470 100644 --- a/thirdparty/icu4c/common/unicode/ucharstrie.h +++ b/thirdparty/icu4c/common/unicode/ucharstrie.h @@ -107,7 +107,7 @@ public: */ uint64_t getState64() const { return (static_cast<uint64_t>(remainingMatchLength_ + 2) << kState64RemainingShift) | - (uint64_t)(pos_ - uchars_); + static_cast<uint64_t>(pos_ - uchars_); } /** @@ -493,7 +493,7 @@ private: } static inline UStringTrieResult valueResult(int32_t node) { - return (UStringTrieResult)(USTRINGTRIE_INTERMEDIATE_VALUE-(node>>15)); + return static_cast<UStringTrieResult>(USTRINGTRIE_INTERMEDIATE_VALUE - (node >> 15)); } // Handles a branch node for both next(uchar) and next(string). diff --git a/thirdparty/icu4c/common/unicode/uidna.h b/thirdparty/icu4c/common/unicode/uidna.h index 24a81ceadd..362a2dcbe6 100644 --- a/thirdparty/icu4c/common/unicode/uidna.h +++ b/thirdparty/icu4c/common/unicode/uidna.h @@ -49,11 +49,19 @@ */ enum { /** - * Default options value: None of the other options are set. + * Default options value: UTS #46 nontransitional processing. * For use in static worker and factory methods. + * + * Since ICU 76, this is the same as + * UIDNA_NONTRANSITIONAL_TO_ASCII | UIDNA_NONTRANSITIONAL_TO_UNICODE, + * corresponding to Unicode 15.1 UTS #46 deprecating transitional processing. + * (These options are ignored by the IDNA2003 implementation.) + * + * Before ICU 76, this constant did not set any of the options. + * * @stable ICU 2.6 */ - UIDNA_DEFAULT=0, + UIDNA_DEFAULT=0x30, #ifndef U_HIDE_DEPRECATED_API /** * Option to allow unassigned code points in domain names and labels. @@ -91,19 +99,27 @@ enum { /** * IDNA option for nontransitional processing in ToASCII(). * For use in static worker and factory methods. + * * <p>By default, ToASCII() uses transitional processing. + * Unicode 15.1 UTS #46 deprecated transitional processing. + * * <p>This option is ignored by the IDNA2003 implementation. * (This is only relevant for compatibility of newer IDNA implementations with IDNA2003.) * @stable ICU 4.6 + * @see UIDNA_DEFAULT */ UIDNA_NONTRANSITIONAL_TO_ASCII=0x10, /** * IDNA option for nontransitional processing in ToUnicode(). * For use in static worker and factory methods. + * * <p>By default, ToUnicode() uses transitional processing. + * Unicode 15.1 UTS #46 deprecated transitional processing. + * * <p>This option is ignored by the IDNA2003 implementation. * (This is only relevant for compatibility of newer IDNA implementations with IDNA2003.) * @stable ICU 4.6 + * @see UIDNA_DEFAULT */ UIDNA_NONTRANSITIONAL_TO_UNICODE=0x20, /** @@ -134,6 +150,8 @@ typedef struct UIDNA UIDNA; /**< C typedef for struct UIDNA. @stable ICU 4.6 */ * For details about the UTS #46 implementation see the IDNA C++ class in idna.h. * * @param options Bit set to modify the processing and error checking. + * These should include UIDNA_DEFAULT, or + * UIDNA_NONTRANSITIONAL_TO_ASCII | UIDNA_NONTRANSITIONAL_TO_UNICODE. * See option bit set values in uidna.h. * @param pErrorCode Standard ICU error code. Its input value must * pass the U_SUCCESS() test, or else the function returns diff --git a/thirdparty/icu4c/common/unicode/ulocale.h b/thirdparty/icu4c/common/unicode/ulocale.h index 33e92844bc..1b3af3a5f2 100644 --- a/thirdparty/icu4c/common/unicode/ulocale.h +++ b/thirdparty/icu4c/common/unicode/ulocale.h @@ -13,16 +13,15 @@ * \brief C API: Locale ID functionality similar to C++ class Locale */ -#ifndef U_HIDE_DRAFT_API /** * Opaque C service object type for the locale API - * @draft ICU 74 + * @stable ICU 74 */ struct ULocale; /** * C typedef for struct ULocale. - * @draft ICU 74 + * @stable ICU 74 */ typedef struct ULocale ULocale; @@ -37,7 +36,7 @@ typedef struct ULocale ULocale; * @param err the error code * @return the locale. * - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI ULocale* U_EXPORT2 ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err); @@ -53,7 +52,7 @@ ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err); * @param err the error code * @return the locale. * - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI ULocale* U_EXPORT2 ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err); @@ -62,7 +61,7 @@ ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err); * Close the locale and destroy it's internal states. * * @param locale the locale - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocale_close(ULocale* locale); @@ -72,7 +71,7 @@ ulocale_close(ULocale* locale); * * @param locale the locale * @return the language code of the locale. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI const char* U_EXPORT2 ulocale_getLanguage(const ULocale* locale); @@ -82,7 +81,7 @@ ulocale_getLanguage(const ULocale* locale); * * @param locale the locale * @return A pointer to the script. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI const char* U_EXPORT2 ulocale_getScript(const ULocale* locale); @@ -92,7 +91,7 @@ ulocale_getScript(const ULocale* locale); * * @param locale the locale * @return A pointer to the region. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI const char* U_EXPORT2 ulocale_getRegion(const ULocale* locale); @@ -102,7 +101,7 @@ ulocale_getRegion(const ULocale* locale); * * @param locale the locale * @return A pointer to the variant. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI const char* U_EXPORT2 ulocale_getVariant(const ULocale* locale); @@ -115,7 +114,7 @@ ulocale_getVariant(const ULocale* locale); * * @param locale the locale * @return A pointer to "name". - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI const char* U_EXPORT2 ulocale_getLocaleID(const ULocale* locale); @@ -126,7 +125,7 @@ ulocale_getLocaleID(const ULocale* locale); * * @param locale the locale * @return A pointer to "base name". - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI const char* U_EXPORT2 ulocale_getBaseName(const ULocale* locale); @@ -136,7 +135,7 @@ ulocale_getBaseName(const ULocale* locale); * * @param locale the locale * @return false if it is a real locale, true if it is a bogus locale - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI bool U_EXPORT2 ulocale_isBogus(const ULocale* locale); @@ -148,7 +147,7 @@ ulocale_isBogus(const ULocale* locale); * @param err the error code * @return pointer to UEnumeration, or nullptr if there are no keywords. * Client must call uenum_close() to dispose the returned value. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI UEnumeration* U_EXPORT2 ulocale_getKeywords(const ULocale* locale, UErrorCode *err); @@ -160,7 +159,7 @@ ulocale_getKeywords(const ULocale* locale, UErrorCode *err); * @param err the error code * @return pointer to UEnumeration, or nullptr if there are no keywords. * Client must call uenum_close() to dispose the returned value. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI UEnumeration* U_EXPORT2 ulocale_getUnicodeKeywords(const ULocale* locale, UErrorCode *err); @@ -178,7 +177,7 @@ ulocale_getUnicodeKeywords(const ULocale* locale, UErrorCode *err); * @param valueBuffer The buffer to receive the value. * @param valueBufferCapacity The capacity of receiving valueBuffer. * @param err the error code - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI int32_t U_EXPORT2 ulocale_getKeywordValue( @@ -198,7 +197,7 @@ ulocale_getKeywordValue( * @param valueBuffer The buffer to receive the Unicode value. * @param valueBufferCapacity The capacity of receiving valueBuffer. * @param err the error code - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI int32_t U_EXPORT2 ulocale_getUnicodeKeywordValue( @@ -216,7 +215,7 @@ U_NAMESPACE_BEGIN * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 74 + * @stable ICU 74 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalULocalePointer, ULocale, ulocale_close); @@ -224,6 +223,4 @@ U_NAMESPACE_END #endif /* U_SHOW_CPLUSPLUS_API */ -#endif /* U_HIDE_DRAFT_API */ - #endif /*_ULOCALE */ diff --git a/thirdparty/icu4c/common/unicode/ulocbuilder.h b/thirdparty/icu4c/common/unicode/ulocbuilder.h index 9b147292f4..ce61995bde 100644 --- a/thirdparty/icu4c/common/unicode/ulocbuilder.h +++ b/thirdparty/icu4c/common/unicode/ulocbuilder.h @@ -12,17 +12,15 @@ * \brief C API: Builder API for Locale */ -#ifndef U_HIDE_DRAFT_API - /** * Opaque C service object type for the locale builder API - * @draft ICU 74 + * @stable ICU 74 */ struct ULocaleBuilder; /** * C typedef for struct ULocaleBuilder. - * @draft ICU 74 + * @stable ICU 74 */ typedef struct ULocaleBuilder ULocaleBuilder; @@ -62,7 +60,7 @@ typedef struct ULocaleBuilder ULocaleBuilder; * UErrorCode, then track the error of the validation of the input parameter * into the internal UErrorCode. * - * @draft ICU 74 + * @stable ICU 74 */ /** @@ -71,7 +69,7 @@ typedef struct ULocaleBuilder ULocaleBuilder; * empty string. The created builder should be destroyed by calling * ulocbld_close(); * - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI ULocaleBuilder* U_EXPORT2 ulocbld_open(void); @@ -79,7 +77,7 @@ ulocbld_open(void); /** * Close the builder and destroy it's internal states. * @param builder the builder - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_close(ULocaleBuilder* builder); @@ -97,7 +95,7 @@ ulocbld_close(ULocaleBuilder* builder); * @param length the length of the locale; if negative, then the locale need to be * null terminated, * - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t length); @@ -113,7 +111,7 @@ ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t length); * @param locale the locale, a ULocale* pointer. The builder adopts the locale * after the call and the client must not delete it. * - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale); @@ -136,7 +134,7 @@ ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale); * the length is non-negative) * @param length the length of the tag; if negative, then the tag need to be * null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setLanguageTag(ULocaleBuilder* builder, const char* tag, int32_t length); @@ -156,7 +154,7 @@ ulocbld_setLanguageTag(ULocaleBuilder* builder, const char* tag, int32_t length) * the length is non-negative) * @param length the length of the language; if negative, then the language need to be * null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setLanguage(ULocaleBuilder* builder, const char* language, int32_t length); @@ -177,7 +175,7 @@ ulocbld_setLanguage(ULocaleBuilder* builder, const char* language, int32_t lengt * the length is non-negative) * @param length the length of the script; if negative, then the script need to be * null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setScript(ULocaleBuilder* builder, const char* script, int32_t length); @@ -201,7 +199,7 @@ ulocbld_setScript(ULocaleBuilder* builder, const char* script, int32_t length); * the length is non-negative) * @param length the length of the region; if negative, then the region need to be * null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setRegion(ULocaleBuilder* builder, const char* region, int32_t length); @@ -227,7 +225,7 @@ ulocbld_setRegion(ULocaleBuilder* builder, const char* region, int32_t length); * the length is non-negative) * @param length the length of the variant; if negative, then the variant need to be * null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setVariant(ULocaleBuilder* builder, const char* variant, int32_t length); @@ -253,7 +251,7 @@ ulocbld_setVariant(ULocaleBuilder* builder, const char* variant, int32_t length) * the length is non-negative) * @param length the length of the value; if negative, then the value need to be * null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setExtension(ULocaleBuilder* builder, char key, const char* value, int32_t length); @@ -282,7 +280,7 @@ ulocbld_setExtension(ULocaleBuilder* builder, char key, const char* value, int32 * @param typeLength the length of the type; if negative, then the type need to * be null terminated, * @return This builder. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_setUnicodeLocaleKeyword(ULocaleBuilder* builder, @@ -299,7 +297,7 @@ ulocbld_setUnicodeLocaleKeyword(ULocaleBuilder* builder, * terminated when the length is non-negative) * @param length the length of the attribute; if negative, then the attribute * need to be null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_addUnicodeLocaleAttribute( @@ -318,7 +316,7 @@ ulocbld_addUnicodeLocaleAttribute( * terminated when the length is non-negative) * @param length the length of the attribute; if negative, then the attribute * need to be null terminated, - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_removeUnicodeLocaleAttribute( @@ -329,7 +327,7 @@ ulocbld_removeUnicodeLocaleAttribute( * <p>This method clears the internal UErrorCode. * * @param builder the builder - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_clear(ULocaleBuilder* builder); @@ -339,7 +337,7 @@ ulocbld_clear(ULocaleBuilder* builder); * Language, script, region and variant are unchanged. * * @param builder the builder - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI void U_EXPORT2 ulocbld_clearExtensions(ULocaleBuilder* builder); @@ -358,7 +356,7 @@ ulocbld_clearExtensions(ULocaleBuilder* builder); * @param localeCapacity the size of the locale buffer to store the locale id * @param err the error code * @return the length of the locale id in buffer - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI int32_t U_EXPORT2 ulocbld_buildLocaleID(ULocaleBuilder* builder, char* locale, @@ -377,7 +375,7 @@ ulocbld_buildLocaleID(ULocaleBuilder* builder, char* locale, * @param err the error code. * @return the locale, a ULocale* pointer. The created ULocale must be * destroyed by calling {@link ulocale_close}. - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI ULocale* U_EXPORT2 ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err); @@ -397,7 +395,7 @@ ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err); * tag * @param err the error code * @return the length of the language tag in buffer - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI int32_t U_EXPORT2 ulocbld_buildLanguageTag(ULocaleBuilder* builder, char* language, @@ -412,7 +410,7 @@ ulocbld_buildLanguageTag(ULocaleBuilder* builder, char* language, * Unchanged if there is no such error or if outErrorCode * already contained an error. * @return true if U_FAILURE(*outErrorCode) - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI UBool U_EXPORT2 ulocbld_copyErrorTo(const ULocaleBuilder* builder, UErrorCode *outErrorCode); @@ -428,7 +426,7 @@ U_NAMESPACE_BEGIN * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 74 + * @stable ICU 74 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalULocaleBuilderPointer, ULocaleBuilder, ulocbld_close); @@ -436,6 +434,4 @@ U_NAMESPACE_END #endif /* U_SHOW_CPLUSPLUS_API */ -#endif /* U_HIDE_DRAFT_API */ - #endif // __ULOCBUILDER_H__ diff --git a/thirdparty/icu4c/common/unicode/uniset.h b/thirdparty/icu4c/common/unicode/uniset.h index 127e4ce063..d070fd631a 100644 --- a/thirdparty/icu4c/common/unicode/uniset.h +++ b/thirdparty/icu4c/common/unicode/uniset.h @@ -313,7 +313,7 @@ private: char16_t *pat = nullptr; int32_t patLen = 0; - UVector* strings = nullptr; // maintained in sorted order + UVector* strings_ = nullptr; // maintained in sorted order UnicodeSetStringSpan *stringSpan = nullptr; /** @@ -1102,6 +1102,118 @@ public: */ UChar32 charAt(int32_t index) const; +#ifndef U_HIDE_DRAFT_API + /** + * Returns a C++ "range" for iterating over the code points of this set. + * + * \code + * UnicodeSet set(u"[abcçカ🚴]", errorCode); + * for (UChar32 c : set.codePoints()) { + * printf("set.codePoint U+%04lx\n", (long)c); + * } + * \endcode + * + * @return a "range" object for iterating over the code points of this set. + * @draft ICU 76 + * @see ranges + * @see strings + * @see begin + * @see end + */ + inline U_HEADER_NESTED_NAMESPACE::USetCodePoints codePoints() const { + return U_HEADER_NESTED_NAMESPACE::USetCodePoints(toUSet()); + } + + /** + * Returns a C++ "range" for iterating over the code point ranges of this set. + * + * \code + * UnicodeSet set(u"[abcçカ🚴]", errorCode); + * for (auto [start, end] : set.ranges()) { + * printf("set.range U+%04lx..U+%04lx\n", (long)start, (long)end); + * } + * for (auto range : set.ranges()) { + * for (UChar32 c : range) { + * printf("set.range.c U+%04lx\n", (long)c); + * } + * } + * \endcode + * + * @return a "range" object for iterating over the code point ranges of this set. + * @draft ICU 76 + * @see codePoints + * @see strings + * @see begin + * @see end + */ + inline U_HEADER_NESTED_NAMESPACE::USetRanges ranges() const { + return U_HEADER_NESTED_NAMESPACE::USetRanges(toUSet()); + } + + /** + * Returns a C++ "range" for iterating over the empty and multi-character strings of this set. + * Returns each string as a std::u16string_view without copying its contents. + * + * \code + * UnicodeSet set(u"[abcçカ🚴{}{abc}{de}]", errorCode); + * for (auto s : set.strings()) { + * UnicodeString us(s); + * std::string u8; + * printf("set.string length %ld \"%s\"\n", (long)s.length(), us.toUTF8String(u8).c_str()); + * } + * \endcode + * + * @return a "range" object for iterating over the strings of this set. + * @draft ICU 76 + * @see codePoints + * @see ranges + * @see begin + * @see end + */ + inline U_HEADER_NESTED_NAMESPACE::USetStrings strings() const { + return U_HEADER_NESTED_NAMESPACE::USetStrings(toUSet()); + } + + /** + * Returns a C++ iterator for iterating over all of the elements of this set. + * Convenient all-in one iteration, but creates a UnicodeString for each + * code point or string. + * (Similar to how Java UnicodeSet *is an* Iterable<String>.) + * + * Code points are returned first, then empty and multi-character strings. + * + * \code + * UnicodeSet set(u"[abcçカ🚴{}{abc}{de}]", errorCode); + * for (auto el : set) { + * std::string u8; + * printf("set.string length %ld \"%s\"\n", (long)el.length(), el.toUTF8String(u8).c_str()); + * } + * \endcode + * + * @return an all-elements iterator. + * @draft ICU 76 + * @see end + * @see codePoints + * @see ranges + * @see strings + */ + inline U_HEADER_NESTED_NAMESPACE::USetElementIterator begin() const { + return U_HEADER_NESTED_NAMESPACE::USetElements(toUSet()).begin(); + } + + /** + * @return an exclusive-end sentinel for iterating over all of the elements of this set. + * @draft ICU 76 + * @see begin + * @see codePoints + * @see ranges + * @see strings + */ + inline U_HEADER_NESTED_NAMESPACE::USetElementIterator end() const { + return U_HEADER_NESTED_NAMESPACE::USetElements(toUSet()).end(); + } +#endif // U_HIDE_DRAFT_API + /** * Adds the specified range to this set if it is not already * present. If this set already contains the specified range, @@ -1731,7 +1843,7 @@ inline bool UnicodeSet::operator!=(const UnicodeSet& o) const { } inline UBool UnicodeSet::isFrozen() const { - return (UBool)(bmpSet!=nullptr || stringSpan!=nullptr); + return bmpSet != nullptr || stringSpan != nullptr; } inline UBool UnicodeSet::containsSome(UChar32 start, UChar32 end) const { @@ -1747,7 +1859,7 @@ inline UBool UnicodeSet::containsSome(const UnicodeString& s) const { } inline UBool UnicodeSet::isBogus() const { - return (UBool)(fFlags & kIsBogus); + return fFlags & kIsBogus; } inline UnicodeSet *UnicodeSet::fromUSet(USet *uset) { diff --git a/thirdparty/icu4c/common/unicode/unistr.h b/thirdparty/icu4c/common/unicode/unistr.h index a41e6358fa..39d789fd6e 100644 --- a/thirdparty/icu4c/common/unicode/unistr.h +++ b/thirdparty/icu4c/common/unicode/unistr.h @@ -33,6 +33,7 @@ #if U_SHOW_CPLUSPLUS_API #include <cstddef> +#include <string_view> #include "unicode/char16ptr.h" #include "unicode/rep.h" #include "unicode/std_string.h" @@ -97,16 +98,19 @@ class UnicodeStringAppendable; // unicode/appendable.h #define US_INV icu::UnicodeString::kInvariant /** - * Unicode String literals in C++. + * \def UNICODE_STRING + * Obsolete macro approximating UnicodeString literals. * - * Note: these macros are not recommended for new code. - * Prior to the availability of C++11 and u"unicode string literals", - * these macros were provided for portability and efficiency when + * Prior to the availability of C++11 and u"UTF-16 string literals", + * this macro was provided for portability and efficiency when * initializing UnicodeStrings from literals. * - * They work only for strings that contain "invariant characters", i.e., - * only latin letters, digits, and some punctuation. - * See utypes.h for details. + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode * * The string parameter must be a C string literal. * The length of the string, not including the terminating @@ -121,16 +125,12 @@ class UnicodeStringAppendable; // unicode/appendable.h /** * Unicode String literals in C++. - * Dependent on the platform properties, different UnicodeString - * constructors should be used to create a UnicodeString object from - * a string literal. - * The macros are defined for improved performance. - * They work only for strings that contain "invariant characters", i.e., - * only latin letters, digits, and some punctuation. - * See utypes.h for details. + * Obsolete macro approximating UnicodeString literals. + * See UNICODE_STRING. * * The string parameter must be a C string literal. * @stable ICU 2.0 + * @see UNICODE_STRING */ #define UNICODE_STRING_SIMPLE(cs) UNICODE_STRING(cs, -1) @@ -327,6 +327,30 @@ public: */ inline bool operator== (const UnicodeString& text) const; +#ifndef U_HIDE_DRAFT_API + /** + * Equality operator. Performs only bitwise comparison with `text` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view. + * + * For performance, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str = ...; + * if (str == u"literal") { ... } + * \endcode + * @param text The string view to compare to this string. + * @return true if `text` contains the same characters as this one, false otherwise. + * @draft ICU 76 + */ + template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> + inline bool operator==(const S &text) const { + std::u16string_view sv(internal::toU16StringView(text)); + uint32_t len; // unsigned to avoid a compiler warning + return !isBogus() && (len = length()) == sv.length() && doEquals(sv.data(), len); + } +#endif // U_HIDE_DRAFT_API + /** * Inequality operator. Performs only bitwise comparison. * @param text The UnicodeString to compare to this one. @@ -336,6 +360,30 @@ public: */ inline bool operator!= (const UnicodeString& text) const; +#ifndef U_HIDE_DRAFT_API + /** + * Inequality operator. Performs only bitwise comparison with `text` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view. + * + * For performance, you can use std::u16string_view literals with compile-time + * length determination: + * \code + * #include <string_view> + * using namespace std::string_view_literals; + * UnicodeString str = ...; + * if (str != u"literal"sv) { ... } + * \endcode + * @param text The string view to compare to this string. + * @return false if `text` contains the same characters as this one, true otherwise. + * @draft ICU 76 + */ + template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> + inline bool operator!=(const S &text) const { + return !operator==(text); + } +#endif // U_HIDE_DRAFT_API + /** * Greater than operator. Performs only bitwise comparison. * @param text The UnicodeString to compare to this one. @@ -1897,6 +1945,24 @@ public: */ UnicodeString &fastCopyFrom(const UnicodeString &src); +#ifndef U_HIDE_DRAFT_API + /** + * Assignment operator. Replaces the characters in this UnicodeString + * with a copy of the characters from the `src` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view. + * + * @param src The string view containing the characters to copy. + * @return a reference to this + * @draft ICU 76 + */ + template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> + inline UnicodeString &operator=(const S &src) { + unBogus(); + return doReplace(0, length(), internal::toU16StringView(src)); + } +#endif // U_HIDE_DRAFT_API + /** * Move assignment operator; might leave src in bogus state. * This string will have the same contents and state that the source string had. @@ -2146,6 +2212,23 @@ public: */ inline UnicodeString& operator+= (const UnicodeString& srcText); +#ifndef U_HIDE_DRAFT_API + /** + * Append operator. Appends the characters in `src` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view, + * to the UnicodeString object. + * + * @param src the source for the new characters + * @return a reference to this + * @draft ICU 76 + */ + template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> + inline UnicodeString& operator+=(const S &src) { + return doAppend(internal::toU16StringView(src)); + } +#endif // U_HIDE_DRAFT_API + /** * Append the characters * in `srcText` in the range @@ -2191,8 +2274,8 @@ public: int32_t srcLength); /** - * Append the characters in `srcChars` to the UnicodeString object - * at offset `start`. `srcChars` is not modified. + * Append the characters in `srcChars` to the UnicodeString object. + * `srcChars` is not modified. * @param srcChars the source for the new characters * @param srcLength the number of Unicode characters in `srcChars`; * can be -1 if `srcChars` is NUL-terminated @@ -2202,6 +2285,23 @@ public: inline UnicodeString& append(ConstChar16Ptr srcChars, int32_t srcLength); +#ifndef U_HIDE_DRAFT_API + /** + * Appends the characters in `src` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view, + * to the UnicodeString object. + * + * @param src the source for the new characters + * @return a reference to this + * @draft ICU 76 + */ + template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> + inline UnicodeString& append(const S &src) { + return doAppend(internal::toU16StringView(src)); + } +#endif // U_HIDE_DRAFT_API + /** * Append the code unit `srcChar` to the UnicodeString object. * @param srcChar the code unit to append @@ -2556,7 +2656,7 @@ public: * @stable ICU 2.0 */ inline UnicodeString& remove(int32_t start, - int32_t length = (int32_t)INT32_MAX); + int32_t length = static_cast<int32_t>(INT32_MAX)); /** * Remove the characters in the range @@ -2567,7 +2667,7 @@ public: * @stable ICU 2.0 */ inline UnicodeString& removeBetween(int32_t start, - int32_t limit = (int32_t)INT32_MAX); + int32_t limit = static_cast<int32_t>(INT32_MAX)); /** * Retain only the characters in the range @@ -2693,8 +2793,8 @@ public: * styles, using rules and dictionaries beyond the standard iterators. * It may be more efficient to always provide an iterator to avoid * opening and closing one for each string. - * The standard titlecase iterator for the root locale implements the - * algorithm of Unicode TR 21. + * If the break iterator passed in is null, the default Unicode algorithm + * will be used to determine the titlecase positions. * * This function uses only the setText(), first() and next() methods of the * provided break iterator. @@ -2721,8 +2821,8 @@ public: * styles, using rules and dictionaries beyond the standard iterators. * It may be more efficient to always provide an iterator to avoid * opening and closing one for each string. - * The standard titlecase iterator for the root locale implements the - * algorithm of Unicode TR 21. + * If the break iterator passed in is null, the default Unicode algorithm + * will be used to determine the titlecase positions. * * This function uses only the setText(), first() and next() methods of the * provided break iterator. @@ -2750,8 +2850,8 @@ public: * styles, using rules and dictionaries beyond the standard iterators. * It may be more efficient to always provide an iterator to avoid * opening and closing one for each string. - * The standard titlecase iterator for the root locale implements the - * algorithm of Unicode TR 21. + * If the break iterator passed in is null, the default Unicode algorithm + * will be used to determine the titlecase positions. * * This function uses only the setText(), first() and next() methods of the * provided break iterator. @@ -2925,6 +3025,37 @@ public: */ const char16_t *getTerminatedBuffer(); +#ifndef U_HIDE_DRAFT_API + /** + * Converts to a std::u16string_view. + * + * @return a string view of the contents of this string + * @draft ICU 76 + */ + inline operator std::u16string_view() const { + return {getBuffer(), static_cast<std::u16string_view::size_type>(length())}; + } + +#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN) + /** + * Converts to a std::wstring_view. + * + * Note: This should remain draft until C++ standard plans + * about char16_t vs. wchar_t become clearer. + * + * @return a string view of the contents of this string + * @draft ICU 76 + */ + inline operator std::wstring_view() const { + const char16_t *p = getBuffer(); +#ifdef U_ALIASING_BARRIER + U_ALIASING_BARRIER(p); +#endif + return { reinterpret_cast<const wchar_t *>(p), (std::wstring_view::size_type)length() }; + } +#endif // U_SIZEOF_WCHAR_T +#endif // U_HIDE_DRAFT_API + //======================================== // Constructors //======================================== @@ -2969,19 +3100,32 @@ public: */ UNISTR_FROM_CHAR_EXPLICIT UnicodeString(UChar32 ch); +#ifdef U_HIDE_DRAFT_API /** * char16_t* constructor. * * It is recommended to mark this constructor "explicit" by * `-DUNISTR_FROM_STRING_EXPLICIT=explicit` * on the compiler command line or similar. + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * * @param text The characters to place in the UnicodeString. `text` * must be NUL (U+0000) terminated. * @stable ICU 2.0 */ - UNISTR_FROM_STRING_EXPLICIT UnicodeString(const char16_t *text); + UNISTR_FROM_STRING_EXPLICIT UnicodeString(const char16_t *text) : + UnicodeString(text, -1) {} +#endif // U_HIDE_DRAFT_API -#if !U_CHAR16_IS_TYPEDEF +#if !U_CHAR16_IS_TYPEDEF && \ + (defined(U_HIDE_DRAFT_API) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 180000)) /** * uint16_t * constructor. * Delegates to UnicodeString(const char16_t *). @@ -2989,14 +3133,23 @@ public: * It is recommended to mark this constructor "explicit" by * `-DUNISTR_FROM_STRING_EXPLICIT=explicit` * on the compiler command line or similar. + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * * @param text NUL-terminated UTF-16 string * @stable ICU 59 */ UNISTR_FROM_STRING_EXPLICIT UnicodeString(const uint16_t *text) : - UnicodeString(ConstChar16Ptr(text)) {} + UnicodeString(ConstChar16Ptr(text), -1) {} #endif -#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN) +#if defined(U_HIDE_DRAFT_API) && (U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)) /** * wchar_t * constructor. * (Only defined if U_SIZEOF_WCHAR_T==2.) @@ -3005,11 +3158,20 @@ public: * It is recommended to mark this constructor "explicit" by * `-DUNISTR_FROM_STRING_EXPLICIT=explicit` * on the compiler command line or similar. + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * * @param text NUL-terminated UTF-16 string * @stable ICU 59 */ UNISTR_FROM_STRING_EXPLICIT UnicodeString(const wchar_t *text) : - UnicodeString(ConstChar16Ptr(text)) {} + UnicodeString(ConstChar16Ptr(text), -1) {} #endif /** @@ -3026,6 +3188,15 @@ public: /** * char16_t* constructor. + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * * @param text The characters to place in the UnicodeString. * @param textLength The number of Unicode characters in `text` * to copy. @@ -3038,6 +3209,15 @@ public: /** * uint16_t * constructor. * Delegates to UnicodeString(const char16_t *, int32_t). + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * * @param text UTF-16 string * @param textLength string length * @stable ICU 59 @@ -3051,7 +3231,16 @@ public: * wchar_t * constructor. * (Only defined if U_SIZEOF_WCHAR_T==2.) * Delegates to UnicodeString(const char16_t *, int32_t). - * @param text NUL-terminated UTF-16 string + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * + * @param text UTF-16 string * @param textLength string length * @stable ICU 59 */ @@ -3068,6 +3257,26 @@ public: */ inline UnicodeString(const std::nullptr_t text, int32_t textLength); +#ifndef U_HIDE_DRAFT_API + /** + * Constructor from `text` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view. + * The string is bogus if the string view is too long. + * + * If you need a UnicodeString but need not copy the string view contents, + * then you can call the UnicodeString::readOnlyAlias() function instead of this constructor. + * + * @param text UTF-16 string + * @draft ICU 76 + */ + template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> + UNISTR_FROM_STRING_EXPLICIT UnicodeString(const S &text) { + fUnion.fFields.fLengthAndFlags = kShortString; + doAppend(internal::toU16StringViewNullable(text)); + } +#endif // U_HIDE_DRAFT_API + /** * Readonly-aliasing char16_t* constructor. * The text will be used for the UnicodeString object, but @@ -3082,6 +3291,14 @@ public: * When using fastCopyFrom(), the text will be aliased again, * so that both strings then alias the same readonly-text. * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString alias = UnicodeString::readOnlyAlias(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * * @param isTerminated specifies if `text` is `NUL`-terminated. * This must be true if `textLength==-1`. * @param text The characters to alias for the UnicodeString. @@ -3160,8 +3377,14 @@ public: * * For ASCII (really "invariant character") strings it is more efficient to use * the constructor that takes a US_INV (for its enum EInvariant). - * For ASCII (invariant-character) string literals, see UNICODE_STRING and - * UNICODE_STRING_SIMPLE. + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode * * It is recommended to mark this constructor "explicit" by * `-DUNISTR_FROM_STRING_EXPLICIT=explicit` @@ -3169,8 +3392,6 @@ public: * @param codepageData an array of bytes, null-terminated, * in the platform's default codepage. * @stable ICU 2.0 - * @see UNICODE_STRING - * @see UNICODE_STRING_SIMPLE */ UNISTR_FROM_STRING_EXPLICIT UnicodeString(const char *codepageData); @@ -3270,6 +3491,15 @@ public: * // use ustr ... * } * \endcode + * + * Note, for string literals: + * Since C++17 and ICU 76, you can use UTF-16 string literals with compile-time + * length determination: + * \code + * UnicodeString str(u"literal"); + * if (str == u"other literal") { ... } + * \endcode + * * @param src String using only invariant characters. * @param textLength Length of src, or -1 if NUL-terminated. * @param inv Signature-distinguishing parameter, use US_INV. @@ -3343,6 +3573,58 @@ public: */ virtual ~UnicodeString(); +#ifndef U_HIDE_DRAFT_API + /** + * Readonly-aliasing factory method. + * Aliases the same buffer as the input `text` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view. + * The string is bogus if the string view is too long. + * + * The text will be used for the UnicodeString object, but + * it will not be released when the UnicodeString is destroyed. + * This has copy-on-write semantics: + * When the string is modified, then the buffer is first copied into + * newly allocated memory. + * The aliased buffer is never modified. + * + * In an assignment to another UnicodeString, when using the copy constructor + * or the assignment operator, the text will be copied. + * When using fastCopyFrom(), the text will be aliased again, + * so that both strings then alias the same readonly-text. + * + * @param text The string view to alias for the UnicodeString. + * @draft ICU 76 + */ + template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> + static inline UnicodeString readOnlyAlias(const S &text) { + return readOnlyAliasFromU16StringView(internal::toU16StringView(text)); + } + + /** + * Readonly-aliasing factory method. + * Aliases the same buffer as the input `text`. + * + * The text will be used for the UnicodeString object, but + * it will not be released when the UnicodeString is destroyed. + * This has copy-on-write semantics: + * When the string is modified, then the buffer is first copied into + * newly allocated memory. + * The aliased buffer is never modified. + * + * In an assignment to another UnicodeString, when using the copy constructor + * or the assignment operator, the text will be copied. + * When using fastCopyFrom(), the text will be aliased again, + * so that both strings then alias the same readonly-text. + * + * @param text The UnicodeString to alias. + * @draft ICU 76 + */ + static inline UnicodeString readOnlyAlias(const UnicodeString &text) { + return readOnlyAliasFromUnicodeString(text); + } +#endif // U_HIDE_DRAFT_API + /** * Create a UnicodeString from a UTF-8 string. * Illegal input is replaced with U+FFFD. Otherwise, errors result in a bogus string. @@ -3470,6 +3752,9 @@ protected: virtual UChar32 getChar32At(int32_t offset) const override; private: + static UnicodeString readOnlyAliasFromU16StringView(std::u16string_view text); + static UnicodeString readOnlyAliasFromUnicodeString(const UnicodeString &text); + // For char* constructors. Could be made public. UnicodeString &setToUTF8(StringPiece utf8); // For extract(char*). @@ -3485,7 +3770,10 @@ private: * Internal string contents comparison, called by operator==. * Requires: this & text not bogus and have same lengths. */ - UBool doEquals(const UnicodeString &text, int32_t len) const; + inline UBool doEquals(const UnicodeString &text, int32_t len) const { + return doEquals(text.getArrayStart(), len); + } + UBool doEquals(const char16_t *text, int32_t len) const; inline UBool doEqualsSubstring(int32_t start, @@ -3580,9 +3868,11 @@ private: const char16_t *srcChars, int32_t srcStart, int32_t srcLength); + UnicodeString& doReplace(int32_t start, int32_t length, std::u16string_view src); UnicodeString& doAppend(const UnicodeString& src, int32_t srcStart, int32_t srcLength); UnicodeString& doAppend(const char16_t *srcChars, int32_t srcStart, int32_t srcLength); + UnicodeString& doAppend(std::u16string_view src); UnicodeString& doReverse(int32_t start, int32_t length); @@ -3711,7 +4001,7 @@ private: * Must be at least U16_MAX_LENGTH for the single-code point constructor to work. * @see UNISTR_OBJECT_SIZE */ - US_STACKBUF_SIZE=(int32_t)(UNISTR_OBJECT_SIZE-sizeof(void *)-2)/U_SIZEOF_UCHAR, + US_STACKBUF_SIZE = static_cast<int32_t>(UNISTR_OBJECT_SIZE - sizeof(void*) - 2) / U_SIZEOF_UCHAR, kInvalidUChar=0xffff, // U+FFFF returned by charAt(invalid index) kInvalidHashCode=0, // invalid hash code kEmptyHashCode=1, // hash code for empty string @@ -3802,7 +4092,7 @@ private: }; /** - * Create a new UnicodeString with the concatenation of two others. + * Creates a new UnicodeString from the concatenation of two others. * * @param s1 The first string to be copied to the new one. * @param s2 The second string to be copied to the new one, after s1. @@ -3812,6 +4102,29 @@ private: U_COMMON_API UnicodeString U_EXPORT2 operator+ (const UnicodeString &s1, const UnicodeString &s2); +#ifndef U_HIDE_DRAFT_API +/** + * Creates a new UnicodeString from the concatenation of a UnicodeString and `s2` + * which is, or which is implicitly convertible to, + * a std::u16string_view or (if U_SIZEOF_WCHAR_T==2) std::wstring_view. + * + * @param s1 The string to be copied to the new one. + * @param s2 The string view to be copied to the new string, after s1. + * @return UnicodeString(s1).append(s2) + * @draft ICU 76 + */ +template<typename S, typename = std::enable_if_t<ConvertibleToU16StringView<S>>> +inline UnicodeString operator+(const UnicodeString &s1, const S &s2) { + return unistr_internalConcat(s1, internal::toU16StringView(s2)); +} +#endif // U_HIDE_DRAFT_API + +#ifndef U_FORCE_HIDE_INTERNAL_API +/** @internal */ +U_COMMON_API UnicodeString U_EXPORT2 +unistr_internalConcat(const UnicodeString &s1, std::u16string_view s2); +#endif + //======================================== // Inline members //======================================== @@ -3914,18 +4227,18 @@ UnicodeString::hashCode() const inline UBool UnicodeString::isBogus() const -{ return (UBool)(fUnion.fFields.fLengthAndFlags & kIsBogus); } +{ return fUnion.fFields.fLengthAndFlags & kIsBogus; } inline UBool UnicodeString::isWritable() const -{ return (UBool)!(fUnion.fFields.fLengthAndFlags&(kOpenGetBuffer|kIsBogus)); } +{ return !(fUnion.fFields.fLengthAndFlags & (kOpenGetBuffer | kIsBogus)); } inline UBool UnicodeString::isBufferWritable() const { - return (UBool)( + return !(fUnion.fFields.fLengthAndFlags&(kOpenGetBuffer|kIsBogus|kBufferIsReadonly)) && - (!(fUnion.fFields.fLengthAndFlags&kRefCounted) || refCount()==1)); + (!(fUnion.fFields.fLengthAndFlags&kRefCounted) || refCount()==1); } inline const char16_t * @@ -3950,7 +4263,7 @@ UnicodeString::doCompare(int32_t start, int32_t srcLength) const { if(srcText.isBogus()) { - return (int8_t)!isBogus(); // 0 if both are bogus, 1 otherwise + return static_cast<int8_t>(!isBogus()); // 0 if both are bogus, 1 otherwise } else { srcText.pinIndices(srcStart, srcLength); return doCompare(start, thisLength, srcText.getArrayStart(), srcStart, srcLength); @@ -4057,7 +4370,7 @@ UnicodeString::doCompareCodePointOrder(int32_t start, int32_t srcLength) const { if(srcText.isBogus()) { - return (int8_t)!isBogus(); // 0 if both are bogus, 1 otherwise + return static_cast<int8_t>(!isBogus()); // 0 if both are bogus, 1 otherwise } else { srcText.pinIndices(srcStart, srcLength); return doCompareCodePointOrder(start, thisLength, srcText.getArrayStart(), srcStart, srcLength); @@ -4119,7 +4432,7 @@ UnicodeString::doCaseCompare(int32_t start, uint32_t options) const { if(srcText.isBogus()) { - return (int8_t)!isBogus(); // 0 if both are bogus, 1 otherwise + return static_cast<int8_t>(!isBogus()); // 0 if both are bogus, 1 otherwise } else { srcText.pinIndices(srcStart, srcLength); return doCaseCompare(start, thisLength, srcText.getArrayStart(), srcStart, srcLength, options); @@ -4531,7 +4844,7 @@ UnicodeString::tempSubStringBetween(int32_t start, int32_t limit) const { inline char16_t UnicodeString::doCharAt(int32_t offset) const { - if((uint32_t)offset < (uint32_t)length()) { + if (static_cast<uint32_t>(offset) < static_cast<uint32_t>(length())) { return getArrayStart()[offset]; } else { return kInvalidUChar; @@ -4564,7 +4877,7 @@ inline void UnicodeString::setShortLength(int32_t len) { // requires 0 <= len <= kMaxShortLength fUnion.fFields.fLengthAndFlags = - (int16_t)((fUnion.fFields.fLengthAndFlags & kAllStorageFlags) | (len << kLengthShift)); + static_cast<int16_t>((fUnion.fFields.fLengthAndFlags & kAllStorageFlags) | (len << kLengthShift)); } inline void @@ -4758,7 +5071,7 @@ UnicodeString::truncate(int32_t targetLength) // truncate(0) of a bogus string makes the string empty and non-bogus unBogus(); return false; - } else if((uint32_t)targetLength < (uint32_t)length()) { + } else if (static_cast<uint32_t>(targetLength) < static_cast<uint32_t>(length())) { setLength(targetLength); return true; } else { diff --git a/thirdparty/icu4c/common/unicode/unorm2.h b/thirdparty/icu4c/common/unicode/unorm2.h index 3844041f17..48f614d74f 100644 --- a/thirdparty/icu4c/common/unicode/unorm2.h +++ b/thirdparty/icu4c/common/unicode/unorm2.h @@ -197,7 +197,6 @@ unorm2_getNFKDInstance(UErrorCode *pErrorCode); U_CAPI const UNormalizer2 * U_EXPORT2 unorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode); -#ifndef U_HIDE_DRAFT_API /** * Returns a UNormalizer2 instance for a variant of Unicode toNFKC_Casefold() normalization * which is equivalent to applying the NFKC_Simple_Casefold mappings and then NFC. @@ -210,11 +209,10 @@ unorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode); * immediately. Check for U_FAILURE() on output or use with * function chaining. (See User Guide for details.) * @return the requested Normalizer2, if successful - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI const UNormalizer2 * U_EXPORT2 unorm2_getNFKCSimpleCasefoldInstance(UErrorCode *pErrorCode); -#endif // U_HIDE_DRAFT_API /** * Returns a UNormalizer2 instance which uses the specified data file diff --git a/thirdparty/icu4c/common/unicode/urename.h b/thirdparty/icu4c/common/unicode/urename.h index c94592ec03..e39c779e81 100644 --- a/thirdparty/icu4c/common/unicode/urename.h +++ b/thirdparty/icu4c/common/unicode/urename.h @@ -490,6 +490,7 @@ #define ubiditransform_close U_ICU_ENTRY_POINT_RENAME(ubiditransform_close) #define ubiditransform_open U_ICU_ENTRY_POINT_RENAME(ubiditransform_open) #define ubiditransform_transform U_ICU_ENTRY_POINT_RENAME(ubiditransform_transform) +#define ublock_addPropertyStarts U_ICU_ENTRY_POINT_RENAME(ublock_addPropertyStarts) #define ublock_getCode U_ICU_ENTRY_POINT_RENAME(ublock_getCode) #define ubrk_clone U_ICU_ENTRY_POINT_RENAME(ubrk_clone) #define ubrk_close U_ICU_ENTRY_POINT_RENAME(ubrk_close) @@ -991,6 +992,7 @@ #define uhash_compareCaselessUnicodeString U_ICU_ENTRY_POINT_RENAME(uhash_compareCaselessUnicodeString) #define uhash_compareChars U_ICU_ENTRY_POINT_RENAME(uhash_compareChars) #define uhash_compareIChars U_ICU_ENTRY_POINT_RENAME(uhash_compareIChars) +#define uhash_compareIStringView U_ICU_ENTRY_POINT_RENAME(uhash_compareIStringView) #define uhash_compareLong U_ICU_ENTRY_POINT_RENAME(uhash_compareLong) #define uhash_compareScriptSet U_ICU_ENTRY_POINT_RENAME(uhash_compareScriptSet) #define uhash_compareUChars U_ICU_ENTRY_POINT_RENAME(uhash_compareUChars) @@ -1008,6 +1010,7 @@ #define uhash_hashCaselessUnicodeString U_ICU_ENTRY_POINT_RENAME(uhash_hashCaselessUnicodeString) #define uhash_hashChars U_ICU_ENTRY_POINT_RENAME(uhash_hashChars) #define uhash_hashIChars U_ICU_ENTRY_POINT_RENAME(uhash_hashIChars) +#define uhash_hashIStringView U_ICU_ENTRY_POINT_RENAME(uhash_hashIStringView) #define uhash_hashLong U_ICU_ENTRY_POINT_RENAME(uhash_hashLong) #define uhash_hashScriptSet U_ICU_ENTRY_POINT_RENAME(uhash_hashScriptSet) #define uhash_hashUChars U_ICU_ENTRY_POINT_RENAME(uhash_hashUChars) @@ -1209,10 +1212,14 @@ #define ulocimp_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_minimizeSubtags) #define ulocimp_setKeywordValue U_ICU_ENTRY_POINT_RENAME(ulocimp_setKeywordValue) #define ulocimp_toBcpKey U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpKey) +#define ulocimp_toBcpKeyWithFallback U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpKeyWithFallback) #define ulocimp_toBcpType U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpType) +#define ulocimp_toBcpTypeWithFallback U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpTypeWithFallback) #define ulocimp_toLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_toLanguageTag) #define ulocimp_toLegacyKey U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyKey) +#define ulocimp_toLegacyKeyWithFallback U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyKeyWithFallback) #define ulocimp_toLegacyType U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyType) +#define ulocimp_toLegacyTypeWithFallback U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyTypeWithFallback) #define ultag_getTKeyStart U_ICU_ENTRY_POINT_RENAME(ultag_getTKeyStart) #define ultag_isExtensionSubtags U_ICU_ENTRY_POINT_RENAME(ultag_isExtensionSubtags) #define ultag_isLanguageSubtag U_ICU_ENTRY_POINT_RENAME(ultag_isLanguageSubtag) @@ -1773,6 +1780,8 @@ #define uset_getSerializedRange U_ICU_ENTRY_POINT_RENAME(uset_getSerializedRange) #define uset_getSerializedRangeCount U_ICU_ENTRY_POINT_RENAME(uset_getSerializedRangeCount) #define uset_getSerializedSet U_ICU_ENTRY_POINT_RENAME(uset_getSerializedSet) +#define uset_getString U_ICU_ENTRY_POINT_RENAME(uset_getString) +#define uset_getStringCount U_ICU_ENTRY_POINT_RENAME(uset_getStringCount) #define uset_hasStrings U_ICU_ENTRY_POINT_RENAME(uset_hasStrings) #define uset_indexOf U_ICU_ENTRY_POINT_RENAME(uset_indexOf) #define uset_isEmpty U_ICU_ENTRY_POINT_RENAME(uset_isEmpty) @@ -1811,7 +1820,6 @@ #define usnum_setMinimumIntegerDigits U_ICU_ENTRY_POINT_RENAME(usnum_setMinimumIntegerDigits) #define usnum_setSign U_ICU_ENTRY_POINT_RENAME(usnum_setSign) #define usnum_setToInt64 U_ICU_ENTRY_POINT_RENAME(usnum_setToInt64) -#define usnum_truncateStart U_ICU_ENTRY_POINT_RENAME(usnum_truncateStart) #define usnumf_close U_ICU_ENTRY_POINT_RENAME(usnumf_close) #define usnumf_format U_ICU_ENTRY_POINT_RENAME(usnumf_format) #define usnumf_formatInt64 U_ICU_ENTRY_POINT_RENAME(usnumf_formatInt64) diff --git a/thirdparty/icu4c/common/unicode/uscript.h b/thirdparty/icu4c/common/unicode/uscript.h index 2c9cee1bfa..d983c40901 100644 --- a/thirdparty/icu4c/common/unicode/uscript.h +++ b/thirdparty/icu4c/common/unicode/uscript.h @@ -503,6 +503,21 @@ typedef enum UScriptCode { /** @stable ICU 75 */ USCRIPT_ARABIC_NASTALIQ = 200, /* Aran */ + /** @stable ICU 76 */ + USCRIPT_GARAY = 201, /* Gara */ + /** @stable ICU 76 */ + USCRIPT_GURUNG_KHEMA = 202, /* Gukh */ + /** @stable ICU 76 */ + USCRIPT_KIRAT_RAI = 203, /* Krai */ + /** @stable ICU 76 */ + USCRIPT_OL_ONAL = 204, /* Onao */ + /** @stable ICU 76 */ + USCRIPT_SUNUWAR = 205, /* Sunu */ + /** @stable ICU 76 */ + USCRIPT_TODHRI = 206, /* Todr */ + /** @stable ICU 76 */ + USCRIPT_TULU_TIGALARI = 207, /* Tutg */ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UScriptCode value. @@ -510,7 +525,7 @@ typedef enum UScriptCode { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - USCRIPT_CODE_LIMIT = 201 + USCRIPT_CODE_LIMIT = 208 #endif // U_HIDE_DEPRECATED_API } UScriptCode; diff --git a/thirdparty/icu4c/common/unicode/uset.h b/thirdparty/icu4c/common/unicode/uset.h index cce95ce921..c8f9b5592d 100644 --- a/thirdparty/icu4c/common/unicode/uset.h +++ b/thirdparty/icu4c/common/unicode/uset.h @@ -33,7 +33,10 @@ #include "unicode/uchar.h" #if U_SHOW_CPLUSPLUS_API +#include <string_view> +#include "unicode/char16ptr.h" #include "unicode/localpointer.h" +#include "unicode/unistr.h" #endif // U_SHOW_CPLUSPLUS_API #ifndef USET_DEFINED @@ -955,7 +958,7 @@ uset_charAt(const USet* set, int32_t charIndex); /** * Returns the number of characters and strings contained in this set. - * The last (uset_getItemCount() - uset_getRangeCount()) items are strings. + * The last uset_getStringCount() == (uset_getItemCount() - uset_getRangeCount()) items are strings. * * This is slower than uset_getRangeCount() and uset_getItemCount() because * it counts the code points of all ranges. @@ -965,6 +968,8 @@ uset_charAt(const USet* set, int32_t charIndex); * contained in set * @stable ICU 2.4 * @see uset_getRangeCount + * @see uset_getStringCount + * @see uset_getItemCount */ U_CAPI int32_t U_EXPORT2 uset_size(const USet* set); @@ -975,11 +980,42 @@ uset_size(const USet* set); * @stable ICU 70 * @see uset_getItemCount * @see uset_getItem + * @see uset_getStringCount * @see uset_size */ U_CAPI int32_t U_EXPORT2 uset_getRangeCount(const USet *set); +#ifndef U_HIDE_DRAFT_API + +/** + * @param set the set + * @return the number of strings in this set. + * @draft ICU 76 + * @see uset_getRangeCount + * @see uset_getItemCount + * @see uset_size + */ +U_CAPI int32_t U_EXPORT2 +uset_getStringCount(const USet *set); + +/** + * Returns the index-th string (empty or multi-character) in the set. + * The string may not be NUL-terminated. + * The output length must be used, and the caller must not read more than that many UChars. + * + * @param set the set + * @param index the string index, 0 .. uset_getStringCount() - 1 + * @param pLength the output string length; must not be NULL + * @return the pointer to the string; NULL if the index is out of range or pLength is NULL + * @draft ICU 76 + * @see uset_getStringCount + */ +U_CAPI const UChar* U_EXPORT2 +uset_getString(const USet *set, int32_t index, int32_t *pLength); + +#endif // U_HIDE_DRAFT_API + /** * Returns the number of items in this set. An item is either a range * of characters or a single multicharacter string. @@ -987,6 +1023,8 @@ uset_getRangeCount(const USet *set); * @return a non-negative integer counting the character ranges * and/or strings contained in set * @stable ICU 2.4 + * @see uset_getRangeCount + * @see uset_getStringCount */ U_CAPI int32_t U_EXPORT2 uset_getItemCount(const USet* set); @@ -1001,6 +1039,7 @@ uset_getItemCount(const USet* set); * If <code>itemIndex</code> is at least uset_getRangeCount() and less than uset_getItemCount(), then * this function copies the string into <code>str[strCapacity]</code> and * returns the length of the string (0 for the empty string). + * See uset_getString() for a function that does not copy the string contents. * * If <code>itemIndex</code> is out of range, then this function returns -1. * @@ -1018,6 +1057,7 @@ uset_getItemCount(const USet* set); * @return the length of the string (0 or >= 2), or 0 if the item is a range, * or -1 if the itemIndex is out of range * @stable ICU 2.4 + * @see uset_getString */ U_CAPI int32_t U_EXPORT2 uset_getItem(const USet* set, int32_t itemIndex, @@ -1285,4 +1325,574 @@ U_CAPI UBool U_EXPORT2 uset_getSerializedRange(const USerializedSet* set, int32_t rangeIndex, UChar32* pStart, UChar32* pEnd); -#endif +#if U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API +#ifndef U_HIDE_DRAFT_API + +namespace U_HEADER_ONLY_NAMESPACE { + +// Note: Not U_COMMON_API, and not a subclass of UMemory, because this is a header-only class, +// not intended to be used via export from the ICU DLL. + +/** + * Iterator returned by USetCodePoints. + * @draft ICU 76 + */ +class USetCodePointIterator { +public: + /** @draft ICU 76 */ + USetCodePointIterator(const USetCodePointIterator &other) = default; + + /** @draft ICU 76 */ + bool operator==(const USetCodePointIterator &other) const { + // No need to compare rangeCount & end given private constructor + // and assuming we don't compare iterators across the set being modified. + // And comparing rangeIndex is redundant with comparing c. + // We might even skip comparing uset. + // Unless we want operator==() to be "correct" for more than iteration. + return uset == other.uset && c == other.c; + } + + /** @draft ICU 76 */ + bool operator!=(const USetCodePointIterator &other) const { return !operator==(other); } + + /** @draft ICU 76 */ + UChar32 operator*() const { return c; } + + /** + * Pre-increment. + * @draft ICU 76 + */ + USetCodePointIterator &operator++() { + if (c < end) { + ++c; + } else if (rangeIndex < rangeCount) { + UErrorCode errorCode = U_ZERO_ERROR; + int32_t result = uset_getItem(uset, rangeIndex, &c, &end, nullptr, 0, &errorCode); + if (U_SUCCESS(errorCode) && result == 0) { + ++rangeIndex; + } else { + c = end = U_SENTINEL; + } + } else { + c = end = U_SENTINEL; + } + return *this; + } + + /** + * Post-increment. + * @draft ICU 76 + */ + USetCodePointIterator operator++(int) { + USetCodePointIterator result(*this); + operator++(); + return result; + } + +private: + friend class USetCodePoints; + + USetCodePointIterator(const USet *uset, int32_t rangeIndex, int32_t rangeCount) + : uset(uset), rangeIndex(rangeIndex), rangeCount(rangeCount), + c(U_SENTINEL), end(U_SENTINEL) { + // Fetch the first range. + operator++(); + } + + const USet *uset; + int32_t rangeIndex; + int32_t rangeCount; + UChar32 c, end; +}; + +/** + * C++ "range" for iterating over the code points of a USet. + * + * \code + * using U_HEADER_NESTED_NAMESPACE::USetCodePoints; + * LocalUSetPointer uset(uset_openPattern(u"[abcçカ🚴]", -1, &errorCode)); + * for (UChar32 c : USetCodePoints(uset.getAlias())) { + * printf("uset.codePoint U+%04lx\n", (long)c); + * } + * \endcode + * + * C++ UnicodeSet has member functions for iteration, including codePoints(). + * + * @draft ICU 76 + * @see USetRanges + * @see USetStrings + * @see USetElements + */ +class USetCodePoints { +public: + /** + * Constructs a C++ "range" object over the code points of the USet. + * @draft ICU 76 + */ + USetCodePoints(const USet *uset) : uset(uset), rangeCount(uset_getRangeCount(uset)) {} + + /** @draft ICU 76 */ + USetCodePoints(const USetCodePoints &other) = default; + + /** @draft ICU 76 */ + USetCodePointIterator begin() const { + return USetCodePointIterator(uset, 0, rangeCount); + } + + /** @draft ICU 76 */ + USetCodePointIterator end() const { + return USetCodePointIterator(uset, rangeCount, rangeCount); + } + +private: + const USet *uset; + int32_t rangeCount; +}; + +/** + * A contiguous range of code points in a USet/UnicodeSet. + * Returned by USetRangeIterator which is returned by USetRanges. + * Both the rangeStart and rangeEnd are in the range. + * (end() returns an iterator corresponding to rangeEnd+1.) + * @draft ICU 76 + */ +struct CodePointRange { + /** @draft ICU 76 */ + struct iterator { + /** @draft ICU 76 */ + iterator(UChar32 c) : c(c) {} + + /** @draft ICU 76 */ + bool operator==(const iterator &other) const { return c == other.c; } + /** @draft ICU 76 */ + bool operator!=(const iterator &other) const { return !operator==(other); } + + /** @draft ICU 76 */ + UChar32 operator*() const { return c; } + + /** + * Pre-increment. + * @draft ICU 76 + */ + iterator &operator++() { + ++c; + return *this; + } + + /** + * Post-increment. + * @draft ICU 76 + */ + iterator operator++(int) { + return c++; + } + + /** + * The current code point in the range. + * @draft ICU 76 + */ + UChar32 c; + }; + + /** @draft ICU 76 */ + CodePointRange(UChar32 start, UChar32 end) : rangeStart(start), rangeEnd(end) {} + /** @draft ICU 76 */ + CodePointRange(const CodePointRange &other) = default; + /** @draft ICU 76 */ + size_t size() const { return (rangeEnd + 1) - rangeStart; } + /** @draft ICU 76 */ + iterator begin() const { return rangeStart; } + /** @draft ICU 76 */ + iterator end() const { return rangeEnd + 1; } + + /** + * Start of a USet/UnicodeSet range of code points. + * @draft ICU 76 + */ + UChar32 rangeStart; + /** + * Inclusive end of a USet/UnicodeSet range of code points. + * @draft ICU 76 + */ + UChar32 rangeEnd; +}; + +/** + * Iterator returned by USetRanges. + * @draft ICU 76 + */ +class USetRangeIterator { +public: + /** @draft ICU 76 */ + USetRangeIterator(const USetRangeIterator &other) = default; + + /** @draft ICU 76 */ + bool operator==(const USetRangeIterator &other) const { + // No need to compare rangeCount given private constructor + // and assuming we don't compare iterators across the set being modified. + // We might even skip comparing uset. + // Unless we want operator==() to be "correct" for more than iteration. + return uset == other.uset && rangeIndex == other.rangeIndex; + } + + /** @draft ICU 76 */ + bool operator!=(const USetRangeIterator &other) const { return !operator==(other); } + + /** @draft ICU 76 */ + CodePointRange operator*() const { + if (rangeIndex < rangeCount) { + UChar32 start, end; + UErrorCode errorCode = U_ZERO_ERROR; + int32_t result = uset_getItem(uset, rangeIndex, &start, &end, nullptr, 0, &errorCode); + if (U_SUCCESS(errorCode) && result == 0) { + return CodePointRange(start, end); + } + } + return CodePointRange(U_SENTINEL, U_SENTINEL); + } + + /** + * Pre-increment. + * @draft ICU 76 + */ + USetRangeIterator &operator++() { + ++rangeIndex; + return *this; + } + + /** + * Post-increment. + * @draft ICU 76 + */ + USetRangeIterator operator++(int) { + USetRangeIterator result(*this); + ++rangeIndex; + return result; + } + +private: + friend class USetRanges; + + USetRangeIterator(const USet *uset, int32_t rangeIndex, int32_t rangeCount) + : uset(uset), rangeIndex(rangeIndex), rangeCount(rangeCount) {} + + const USet *uset; + int32_t rangeIndex; + int32_t rangeCount; +}; + +/** + * C++ "range" for iterating over the code point ranges of a USet. + * + * \code + * using U_HEADER_NESTED_NAMESPACE::USetRanges; + * LocalUSetPointer uset(uset_openPattern(u"[abcçカ🚴]", -1, &errorCode)); + * for (auto [start, end] : USetRanges(uset.getAlias())) { + * printf("uset.range U+%04lx..U+%04lx\n", (long)start, (long)end); + * } + * for (auto range : USetRanges(uset.getAlias())) { + * for (UChar32 c : range) { + * printf("uset.range.c U+%04lx\n", (long)c); + * } + * } + * \endcode + * + * C++ UnicodeSet has member functions for iteration, including ranges(). + * + * @draft ICU 76 + * @see USetCodePoints + * @see USetStrings + * @see USetElements + */ +class USetRanges { +public: + /** + * Constructs a C++ "range" object over the code point ranges of the USet. + * @draft ICU 76 + */ + USetRanges(const USet *uset) : uset(uset), rangeCount(uset_getRangeCount(uset)) {} + + /** @draft ICU 76 */ + USetRanges(const USetRanges &other) = default; + + /** @draft ICU 76 */ + USetRangeIterator begin() const { + return USetRangeIterator(uset, 0, rangeCount); + } + + /** @draft ICU 76 */ + USetRangeIterator end() const { + return USetRangeIterator(uset, rangeCount, rangeCount); + } + +private: + const USet *uset; + int32_t rangeCount; +}; + +/** + * Iterator returned by USetStrings. + * @draft ICU 76 + */ +class USetStringIterator { +public: + /** @draft ICU 76 */ + USetStringIterator(const USetStringIterator &other) = default; + + /** @draft ICU 76 */ + bool operator==(const USetStringIterator &other) const { + // No need to compare count given private constructor + // and assuming we don't compare iterators across the set being modified. + // We might even skip comparing uset. + // Unless we want operator==() to be "correct" for more than iteration. + return uset == other.uset && index == other.index; + } + + /** @draft ICU 76 */ + bool operator!=(const USetStringIterator &other) const { return !operator==(other); } + + /** @draft ICU 76 */ + std::u16string_view operator*() const { + if (index < count) { + int32_t length; + const UChar *uchars = uset_getString(uset, index, &length); + // assert uchars != nullptr; + return {ConstChar16Ptr(uchars), static_cast<uint32_t>(length)}; + } + return {}; + } + + /** + * Pre-increment. + * @draft ICU 76 + */ + USetStringIterator &operator++() { + ++index; + return *this; + } + + /** + * Post-increment. + * @draft ICU 76 + */ + USetStringIterator operator++(int) { + USetStringIterator result(*this); + ++index; + return result; + } + +private: + friend class USetStrings; + + USetStringIterator(const USet *uset, int32_t index, int32_t count) + : uset(uset), index(index), count(count) {} + + const USet *uset; + int32_t index; + int32_t count; +}; + +/** + * C++ "range" for iterating over the empty and multi-character strings of a USet. + * + * \code + * using U_HEADER_NESTED_NAMESPACE::USetStrings; + * LocalUSetPointer uset(uset_openPattern(u"[abcçカ🚴{}{abc}{de}]", -1, &errorCode)); + * for (auto s : USetStrings(uset.getAlias())) { + * UnicodeString us(s); + * std::string u8; + * printf("uset.string length %ld \"%s\"\n", (long)s.length(), us.toUTF8String(u8).c_str()); + * } + * \endcode + * + * C++ UnicodeSet has member functions for iteration, including strings(). + * + * @draft ICU 76 + * @see USetCodePoints + * @see USetRanges + * @see USetElements + */ +class USetStrings { +public: + /** + * Constructs a C++ "range" object over the strings of the USet. + * @draft ICU 76 + */ + USetStrings(const USet *uset) : uset(uset), count(uset_getStringCount(uset)) {} + + /** @draft ICU 76 */ + USetStrings(const USetStrings &other) = default; + + /** @draft ICU 76 */ + USetStringIterator begin() const { + return USetStringIterator(uset, 0, count); + } + + /** @draft ICU 76 */ + USetStringIterator end() const { + return USetStringIterator(uset, count, count); + } + +private: + const USet *uset; + int32_t count; +}; + +/** + * Iterator returned by USetElements. + * @draft ICU 76 + */ +class USetElementIterator { +public: + /** @draft ICU 76 */ + USetElementIterator(const USetElementIterator &other) = default; + + /** @draft ICU 76 */ + bool operator==(const USetElementIterator &other) const { + // No need to compare rangeCount & end given private constructor + // and assuming we don't compare iterators across the set being modified. + // We might even skip comparing uset. + // Unless we want operator==() to be "correct" for more than iteration. + return uset == other.uset && c == other.c && index == other.index; + } + + /** @draft ICU 76 */ + bool operator!=(const USetElementIterator &other) const { return !operator==(other); } + + /** @draft ICU 76 */ + UnicodeString operator*() const { + if (c >= 0) { + return UnicodeString(c); + } else if (index < totalCount) { + int32_t length; + const UChar *uchars = uset_getString(uset, index - rangeCount, &length); + // assert uchars != nullptr; + return UnicodeString(uchars, length); + } else { + return UnicodeString(); + } + } + + /** + * Pre-increment. + * @draft ICU 76 + */ + USetElementIterator &operator++() { + if (c < end) { + ++c; + } else if (index < rangeCount) { + UErrorCode errorCode = U_ZERO_ERROR; + int32_t result = uset_getItem(uset, index, &c, &end, nullptr, 0, &errorCode); + if (U_SUCCESS(errorCode) && result == 0) { + ++index; + } else { + c = end = U_SENTINEL; + } + } else if (c >= 0) { + // assert index == rangeCount; + // Switch from the last range to the first string. + c = end = U_SENTINEL; + } else { + ++index; + } + return *this; + } + + /** + * Post-increment. + * @draft ICU 76 + */ + USetElementIterator operator++(int) { + USetElementIterator result(*this); + operator++(); + return result; + } + +private: + friend class USetElements; + + USetElementIterator(const USet *uset, int32_t index, int32_t rangeCount, int32_t totalCount) + : uset(uset), index(index), rangeCount(rangeCount), totalCount(totalCount), + c(U_SENTINEL), end(U_SENTINEL) { + if (index < rangeCount) { + // Fetch the first range. + operator++(); + } + // Otherwise don't move beyond the (index - rangeCount)-th string. + } + + const USet *uset; + int32_t index; + /** Number of UnicodeSet/USet code point ranges. */ + int32_t rangeCount; + /** + * Number of code point ranges plus number of strings. + * index starts from 0, counts ranges while less than rangeCount, + * then counts strings while at least rangeCount and less than totalCount. + * + * Note that totalCount is the same as uset_getItemCount(), but usually + * smaller than the number of elements returned by this iterator + * because we return each code point of each range. + */ + int32_t totalCount; + UChar32 c, end; +}; + +/** + * A C++ "range" for iterating over all of the elements of a USet. + * Convenient all-in one iteration, but creates a UnicodeString for each + * code point or string. + * + * Code points are returned first, then empty and multi-character strings. + * + * \code + * using U_HEADER_NESTED_NAMESPACE::USetElements; + * LocalUSetPointer uset(uset_openPattern(u"[abcçカ🚴{}{abc}{de}]", -1, &errorCode)); + * for (auto el : USetElements(uset.getAlias())) { + * std::string u8; + * printf("uset.string length %ld \"%s\"\n", (long)el.length(), el.toUTF8String(u8).c_str()); + * } + * \endcode + * + * C++ UnicodeSet has member functions for iteration, including begin() and end(). + * + * @return an all-elements iterator. + * @draft ICU 76 + * @see USetCodePoints + * @see USetRanges + * @see USetStrings + */ +class USetElements { +public: + /** + * Constructs a C++ "range" object over all of the elements of the USet. + * @draft ICU 76 + */ + USetElements(const USet *uset) + : uset(uset), rangeCount(uset_getRangeCount(uset)), + stringCount(uset_getStringCount(uset)) {} + + /** @draft ICU 76 */ + USetElements(const USetElements &other) = default; + + /** @draft ICU 76 */ + USetElementIterator begin() const { + return USetElementIterator(uset, 0, rangeCount, rangeCount + stringCount); + } + + /** @draft ICU 76 */ + USetElementIterator end() const { + return USetElementIterator(uset, rangeCount + stringCount, rangeCount, rangeCount + stringCount); + } + +private: + const USet *uset; + int32_t rangeCount, stringCount; +}; + +} // namespace U_HEADER_ONLY_NAMESPACE + +#endif // U_HIDE_DRAFT_API +#endif // U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API + +#endif // __USET_H__ diff --git a/thirdparty/icu4c/common/unicode/ustring.h b/thirdparty/icu4c/common/unicode/ustring.h index 03c697c722..a3d08254d6 100644 --- a/thirdparty/icu4c/common/unicode/ustring.h +++ b/thirdparty/icu4c/common/unicode/ustring.h @@ -1107,8 +1107,8 @@ u_strToLower(UChar *dest, int32_t destCapacity, * styles, using rules and dictionaries beyond the standard iterators. * It may be more efficient to always provide an iterator to avoid * opening and closing one for each string. - * The standard titlecase iterator for the root locale implements the - * algorithm of Unicode TR 21. + * If the break iterator passed in is null, the default Unicode algorithm + * will be used to determine the titlecase positions. * * This function uses only the setText(), first() and next() methods of the * provided break iterator. diff --git a/thirdparty/icu4c/common/unicode/utypes.h b/thirdparty/icu4c/common/unicode/utypes.h index 6c7cc51345..0151ebd470 100644 --- a/thirdparty/icu4c/common/unicode/utypes.h +++ b/thirdparty/icu4c/common/unicode/utypes.h @@ -54,22 +54,37 @@ * integer and other types. */ +/** @{ API visibility control */ /** * \def U_SHOW_CPLUSPLUS_API + * When defined to 1 (=default) and compiled with a C++ compiler, both C and C++ APIs are visible. + * Otherwise, only C APIs are visible; this is for C++ users who want to + * restrict their usage to binary stable C APIs exported by ICU DLLs. + * @internal + */ +/** + * \def U_SHOW_CPLUSPLUS_HEADER_API + * When defined to 1 (=default) and compiled with a C++ compiler, C++ header-only APIs are visible. + * This is for C++ users who restrict their usage to binary stable C APIs exported by ICU DLLs + * (U_SHOW_CPLUSPLUS_API=0) + * but who still want to use C++ header-only APIs which do not rely on ICU DLL exports. * @internal */ #ifdef __cplusplus # ifndef U_SHOW_CPLUSPLUS_API # define U_SHOW_CPLUSPLUS_API 1 # endif +# ifndef U_SHOW_CPLUSPLUS_HEADER_API +# define U_SHOW_CPLUSPLUS_HEADER_API 1 +# endif #else # undef U_SHOW_CPLUSPLUS_API # define U_SHOW_CPLUSPLUS_API 0 +# undef U_SHOW_CPLUSPLUS_HEADER_API +# define U_SHOW_CPLUSPLUS_HEADER_API 0 #endif -/** @{ API visibility control */ - /** * \def U_HIDE_DRAFT_API * Define this to 1 to request that draft API be "hidden" @@ -582,14 +597,13 @@ typedef enum UErrorCode { U_MF_MISSING_SELECTOR_ANNOTATION_ERROR, /**< A selector expression evaluates to an unannotated operand. @internal ICU 75 technology preview @deprecated This API is for technology preview only. */ U_MF_DUPLICATE_DECLARATION_ERROR, /**< The same variable is declared in more than one .local or .input declaration. @internal ICU 75 technology preview @deprecated This API is for technology preview only. */ U_MF_OPERAND_MISMATCH_ERROR, /**< An operand provided to a function does not have the required form for that function @internal ICU 75 technology preview @deprecated This API is for technology preview only. */ - U_MF_UNSUPPORTED_STATEMENT_ERROR, /**< A message includes a reserved statement. @internal ICU 75 technology preview @deprecated This API is for technology preview only. */ - U_MF_UNSUPPORTED_EXPRESSION_ERROR, /**< A message includes syntax reserved for future standardization or private implementation use. @internal ICU 75 technology preview @deprecated This API is for technology preview only. */ + U_MF_DUPLICATE_VARIANT_ERROR, /**< A message includes a variant with the same key list as another variant. @internal ICU 76 technology preview @deprecated This API is for technology preview only. */ #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal formatting API error code. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - U_FMT_PARSE_ERROR_LIMIT = 0x10121, + U_FMT_PARSE_ERROR_LIMIT = 0x10120, #endif // U_HIDE_DEPRECATED_API /* @@ -713,13 +727,13 @@ typedef enum UErrorCode { * @stable ICU 2.0 */ static - inline UBool U_SUCCESS(UErrorCode code) { return (UBool)(code<=U_ZERO_ERROR); } + inline UBool U_SUCCESS(UErrorCode code) { return code <= U_ZERO_ERROR; } /** * Does the error code indicate a failure? * @stable ICU 2.0 */ static - inline UBool U_FAILURE(UErrorCode code) { return (UBool)(code>U_ZERO_ERROR); } + inline UBool U_FAILURE(UErrorCode code) { return code > U_ZERO_ERROR; } #else /** * Does the error code indicate success? diff --git a/thirdparty/icu4c/common/unicode/uvernum.h b/thirdparty/icu4c/common/unicode/uvernum.h index eb7c50f385..a3cb882623 100644 --- a/thirdparty/icu4c/common/unicode/uvernum.h +++ b/thirdparty/icu4c/common/unicode/uvernum.h @@ -53,7 +53,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 75 +#define U_ICU_VERSION_MAJOR_NUM 76 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU @@ -79,7 +79,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _75 +#define U_ICU_VERSION_SUFFIX _76 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -132,7 +132,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "75.1" +#define U_ICU_VERSION "76.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -145,13 +145,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "75" +#define U_ICU_VERSION_SHORT "76" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "75.1" +#define U_ICU_DATA_VERSION "76.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/thirdparty/icu4c/common/unicode/uversion.h b/thirdparty/icu4c/common/unicode/uversion.h index 113568df8c..25d73a3aeb 100644 --- a/thirdparty/icu4c/common/unicode/uversion.h +++ b/thirdparty/icu4c/common/unicode/uversion.h @@ -124,6 +124,49 @@ typedef uint8_t UVersionInfo[U_MAX_VERSION_LENGTH]; # if U_USING_ICU_NAMESPACE U_NAMESPACE_USE # endif + +#ifndef U_HIDE_DRAFT_API +/** + * \def U_HEADER_NESTED_NAMESPACE + * Nested namespace used inside U_ICU_NAMESPACE for header-only APIs. + * Different when used inside ICU to prevent public use of internal instantiations: + * "header" when compiling calling code; "internal" when compiling ICU library code. + * + * When compiling for Windows, where DLL exports of APIs are explicit, + * this is always "header". Header-only types are not marked for export, + * which on Windows already avoids callers linking with library instantiations. + * + * @draft ICU 76 + * @see U_HEADER_ONLY_NAMESPACE + */ + +/** + * \def U_HEADER_ONLY_NAMESPACE + * Namespace used for header-only APIs. + * Different when used inside ICU to prevent public use of internal instantiations. + * "U_ICU_NAMESPACE::header" or "U_ICU_NAMESPACE::internal", + * see U_HEADER_NESTED_NAMESPACE for details. + * + * @draft ICU 76 + */ + +// The first test is the same as for defining U_EXPORT for Windows. +#if defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(__dllexport__) && \ + UPRV_HAS_DECLSPEC_ATTRIBUTE(__dllimport__)) +# define U_HEADER_NESTED_NAMESPACE header +#elif defined(U_COMBINED_IMPLEMENTATION) || defined(U_COMMON_IMPLEMENTATION) || \ + defined(U_I18N_IMPLEMENTATION) || defined(U_IO_IMPLEMENTATION) || \ + defined(U_LAYOUTEX_IMPLEMENTATION) || defined(U_TOOLUTIL_IMPLEMENTATION) +# define U_HEADER_NESTED_NAMESPACE internal +#else +# define U_HEADER_NESTED_NAMESPACE header +#endif + +#define U_HEADER_ONLY_NAMESPACE U_ICU_NAMESPACE::U_HEADER_NESTED_NAMESPACE + +namespace U_HEADER_ONLY_NAMESPACE {} +#endif // U_HIDE_DRAFT_API + #endif /* __cplusplus */ /*===========================================================================*/ diff --git a/thirdparty/icu4c/common/unifiedcache.cpp b/thirdparty/icu4c/common/unifiedcache.cpp index 1284c03813..68af4e04c1 100644 --- a/thirdparty/icu4c/common/unifiedcache.cpp +++ b/thirdparty/icu4c/common/unifiedcache.cpp @@ -47,20 +47,20 @@ U_NAMESPACE_BEGIN int32_t U_EXPORT2 ucache_hashKeys(const UHashTok key) { - const CacheKeyBase *ckey = (const CacheKeyBase *) key.pointer; + const CacheKeyBase* ckey = static_cast<const CacheKeyBase*>(key.pointer); return ckey->hashCode(); } UBool U_EXPORT2 ucache_compareKeys(const UHashTok key1, const UHashTok key2) { - const CacheKeyBase *p1 = (const CacheKeyBase *) key1.pointer; - const CacheKeyBase *p2 = (const CacheKeyBase *) key2.pointer; + const CacheKeyBase* p1 = static_cast<const CacheKeyBase*>(key1.pointer); + const CacheKeyBase* p2 = static_cast<const CacheKeyBase*>(key2.pointer); return *p1 == *p2; } void U_EXPORT2 ucache_deleteKey(void *obj) { - CacheKeyBase *p = (CacheKeyBase *) obj; + CacheKeyBase* p = static_cast<CacheKeyBase*>(obj); delete p; } @@ -253,7 +253,7 @@ UBool UnifiedCache::_flush(UBool all) const { } if (all || _isEvictable(element)) { const SharedObject *sharedObject = - (const SharedObject *) element->value.pointer; + static_cast<const SharedObject*>(element->value.pointer); U_ASSERT(sharedObject->cachePtr == this); uhash_removeElement(fHashtable, element); removeSoftRef(sharedObject); // Deletes the sharedObject when softRefCount goes to zero. @@ -269,7 +269,7 @@ int32_t UnifiedCache::_computeCountOfItemsToEvict() const { int32_t unusedLimitByPercentage = fNumValuesInUse * fMaxPercentageOfInUse / 100; int32_t unusedLimit = std::max(unusedLimitByPercentage, fMaxUnused); - int32_t countOfItemsToEvict = std::max(0, evictableItems - unusedLimit); + int32_t countOfItemsToEvict = std::max<int32_t>(0, evictableItems - unusedLimit); return countOfItemsToEvict; } @@ -285,7 +285,7 @@ void UnifiedCache::_runEvictionSlice() const { } if (_isEvictable(element)) { const SharedObject *sharedObject = - (const SharedObject *) element->value.pointer; + static_cast<const SharedObject*>(element->value.pointer); uhash_removeElement(fHashtable, element); removeSoftRef(sharedObject); // Deletes sharedObject when SoftRefCount goes to zero. ++fAutoEvictedCount; @@ -416,8 +416,8 @@ void UnifiedCache::_put( const SharedObject *value, const UErrorCode status) const { U_ASSERT(_inProgress(element)); - const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer; - const SharedObject *oldValue = (const SharedObject *) element->value.pointer; + const CacheKeyBase* theKey = static_cast<const CacheKeyBase*>(element->key.pointer); + const SharedObject* oldValue = static_cast<const SharedObject*>(element->value.pointer); theKey->fCreationStatus = status; if (value->softRefCount == 0) { _registerPrimary(theKey, value); @@ -437,7 +437,7 @@ void UnifiedCache::_fetch( const UHashElement *element, const SharedObject *&value, UErrorCode &status) const { - const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer; + const CacheKeyBase* theKey = static_cast<const CacheKeyBase*>(element->key.pointer); status = theKey->fCreationStatus; // Since we have the cache lock, calling regular SharedObject add/removeRef @@ -465,9 +465,8 @@ UBool UnifiedCache::_inProgress( UBool UnifiedCache::_isEvictable(const UHashElement *element) const { - const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer; - const SharedObject *theValue = - (const SharedObject *) element->value.pointer; + const CacheKeyBase* theKey = static_cast<const CacheKeyBase*>(element->key.pointer); + const SharedObject* theValue = static_cast<const SharedObject*>(element->value.pointer); // Entries that are under construction are never evictable if (_inProgress(theValue, theKey->fCreationStatus)) { diff --git a/thirdparty/icu4c/common/uniset.cpp b/thirdparty/icu4c/common/uniset.cpp index 71f57fc12d..2d6610cb35 100644 --- a/thirdparty/icu4c/common/uniset.cpp +++ b/thirdparty/icu4c/common/uniset.cpp @@ -108,25 +108,25 @@ static inline void _dbgdt(UnicodeSet* set) { //---------------------------------------------------------------- static void U_CALLCONV cloneUnicodeString(UElement *dst, UElement *src) { - dst->pointer = new UnicodeString(*(UnicodeString*)src->pointer); + dst->pointer = new UnicodeString(*static_cast<UnicodeString*>(src->pointer)); } static int32_t U_CALLCONV compareUnicodeString(UElement t1, UElement t2) { - const UnicodeString &a = *(const UnicodeString*)t1.pointer; - const UnicodeString &b = *(const UnicodeString*)t2.pointer; + const UnicodeString& a = *static_cast<const UnicodeString*>(t1.pointer); + const UnicodeString& b = *static_cast<const UnicodeString*>(t2.pointer); return a.compare(b); } UBool UnicodeSet::hasStrings() const { - return strings != nullptr && !strings->isEmpty(); + return strings_ != nullptr && !strings_->isEmpty(); } int32_t UnicodeSet::stringsSize() const { - return strings == nullptr ? 0 : strings->size(); + return strings_ == nullptr ? 0 : strings_->size(); } UBool UnicodeSet::stringsContains(const UnicodeString &s) const { - return strings != nullptr && strings->contains((void*) &s); + return strings_ != nullptr && strings_->contains((void*) &s); } //---------------------------------------------------------------- @@ -171,7 +171,7 @@ UnicodeSet::UnicodeSet(const UnicodeSet& o, UBool /* asThawed */) : UnicodeFilte if (o.hasStrings()) { UErrorCode status = U_ZERO_ERROR; if (!allocateStrings(status) || - (strings->assign(*o.strings, cloneUnicodeString, status), U_FAILURE(status))) { + (strings_->assign(*o.strings_, cloneUnicodeString, status), U_FAILURE(status))) { setToBogus(); return; } @@ -195,7 +195,7 @@ UnicodeSet::~UnicodeSet() { if (buffer != stackList) { uprv_free(buffer); } - delete strings; + delete strings_; delete stringSpan; releasePattern(); } @@ -233,16 +233,16 @@ UnicodeSet& UnicodeSet::copyFrom(const UnicodeSet& o, UBool asThawed) { } if (o.hasStrings()) { UErrorCode status = U_ZERO_ERROR; - if ((strings == nullptr && !allocateStrings(status)) || - (strings->assign(*o.strings, cloneUnicodeString, status), U_FAILURE(status))) { + if ((strings_ == nullptr && !allocateStrings(status)) || + (strings_->assign(*o.strings_, cloneUnicodeString, status), U_FAILURE(status))) { setToBogus(); return *this; } } else if (hasStrings()) { - strings->removeAllElements(); + strings_->removeAllElements(); } if (o.stringSpan != nullptr && !asThawed) { - stringSpan = new UnicodeSetStringSpan(*o.stringSpan, *strings); + stringSpan = new UnicodeSetStringSpan(*o.stringSpan, *strings_); if (stringSpan == nullptr) { // Check for memory allocation error. setToBogus(); return *this; @@ -284,7 +284,7 @@ bool UnicodeSet::operator==(const UnicodeSet& o) const { if (list[i] != o.list[i]) return false; } if (hasStrings() != o.hasStrings()) { return false; } - if (hasStrings() && *strings != *o.strings) return false; + if (hasStrings() && *strings_ != *o.strings_) return false; return true; } @@ -355,7 +355,7 @@ UBool UnicodeSet::contains(UChar32 c) const { return false; } int32_t i = findCodePoint(c); - return (UBool)(i & 1); // return true if odd + return i & 1; // return true if odd } /** @@ -430,7 +430,7 @@ UBool UnicodeSet::contains(const UnicodeString& s) const { if (cp < 0) { return stringsContains(s); } else { - return contains((UChar32) cp); + return contains(static_cast<UChar32>(cp)); } } @@ -450,7 +450,7 @@ UBool UnicodeSet::containsAll(const UnicodeSet& c) const { return false; } } - return !c.hasStrings() || (strings != nullptr && strings->containsAll(*c.strings)); + return !c.hasStrings() || (strings_ != nullptr && strings_->containsAll(*c.strings_)); } /** @@ -460,8 +460,7 @@ UBool UnicodeSet::containsAll(const UnicodeSet& c) const { * @return true if the test condition is met */ UBool UnicodeSet::containsAll(const UnicodeString& s) const { - return (UBool)(span(s.getBuffer(), s.length(), USET_SPAN_CONTAINED) == - s.length()); + return span(s.getBuffer(), s.length(), USET_SPAN_CONTAINED) == s.length(); } /** @@ -496,7 +495,7 @@ UBool UnicodeSet::containsNone(const UnicodeSet& c) const { return false; } } - return strings == nullptr || !c.hasStrings() || strings->containsNone(*c.strings); + return strings_ == nullptr || !c.hasStrings() || strings_->containsNone(*c.strings_); } /** @@ -506,8 +505,7 @@ UBool UnicodeSet::containsNone(const UnicodeSet& c) const { * @return true if the test condition is met */ UBool UnicodeSet::containsNone(const UnicodeString& s) const { - return (UBool)(span(s.getBuffer(), s.length(), USET_SPAN_NOT_CONTAINED) == - s.length()); + return span(s.getBuffer(), s.length(), USET_SPAN_NOT_CONTAINED) == s.length(); } /** @@ -538,8 +536,8 @@ UBool UnicodeSet::matchesIndexValue(uint8_t v) const { } } if (hasStrings()) { - for (i=0; i<strings->size(); ++i) { - const UnicodeString& s = *(const UnicodeString*)strings->elementAt(i); + for (i=0; i<strings_->size(); ++i) { + const UnicodeString& s = *static_cast<const UnicodeString*>(strings_->elementAt(i)); if (s.isEmpty()) { continue; // skip the empty string } @@ -588,8 +586,8 @@ UMatchDegree UnicodeSet::matches(const Replaceable& text, // return the longest match. int32_t highWaterLength = 0; - for (i=0; i<strings->size(); ++i) { - const UnicodeString& trial = *(const UnicodeString*)strings->elementAt(i); + for (i=0; i<strings_->size(); ++i) { + const UnicodeString& trial = *static_cast<const UnicodeString*>(strings_->elementAt(i)); if (trial.isEmpty()) { continue; // skip the empty string } @@ -731,12 +729,12 @@ UChar32 UnicodeSet::charAt(int32_t index) const { UChar32 start = list[i++]; int32_t count = list[i++] - start; if (index < count) { - return (UChar32)(start + index); + return static_cast<UChar32>(start + index); } index -= count; } } - return (UChar32)-1; + return static_cast<UChar32>(-1); } /** @@ -958,21 +956,21 @@ UnicodeSet& UnicodeSet::add(const UnicodeString& s) { releasePattern(); } } else { - add((UChar32)cp); + add(static_cast<UChar32>(cp)); } return *this; } /** - * Adds the given string, in order, to 'strings'. The given string - * must have been checked by the caller to not already be in 'strings'. + * Adds the given string, in order, to 'strings_'. The given string + * must have been checked by the caller to not already be in 'strings_'. */ void UnicodeSet::_add(const UnicodeString& s) { if (isFrozen() || isBogus()) { return; } UErrorCode ec = U_ZERO_ERROR; - if (strings == nullptr && !allocateStrings(ec)) { + if (strings_ == nullptr && !allocateStrings(ec)) { setToBogus(); return; } @@ -981,7 +979,7 @@ void UnicodeSet::_add(const UnicodeString& s) { setToBogus(); return; } - strings->sortedInsert(t, compareUnicodeString, ec); + strings_->sortedInsert(t, compareUnicodeString, ec); if (U_FAILURE(ec)) { setToBogus(); } @@ -1060,7 +1058,7 @@ UnicodeSet& UnicodeSet::removeAll(const UnicodeString& s) { UnicodeSet& UnicodeSet::removeAllStrings() { if (!isFrozen() && hasStrings()) { - strings->removeAllElements(); + strings_->removeAllElements(); releasePattern(); } return *this; @@ -1178,11 +1176,11 @@ UnicodeSet& UnicodeSet::remove(const UnicodeString& s) { if (isFrozen() || isBogus()) return *this; int32_t cp = getSingleCP(s); if (cp < 0) { - if (strings != nullptr && strings->removeElement((void*) &s)) { + if (strings_ != nullptr && strings_->removeElement((void*) &s)) { releasePattern(); } } else { - remove((UChar32)cp, (UChar32)cp); + remove(static_cast<UChar32>(cp), static_cast<UChar32>(cp)); } return *this; } @@ -1250,13 +1248,13 @@ UnicodeSet& UnicodeSet::complement(const UnicodeString& s) { int32_t cp = getSingleCP(s); if (cp < 0) { if (stringsContains(s)) { - strings->removeElement((void*) &s); + strings_->removeElement((void*) &s); } else { _add(s); } releasePattern(); } else { - complement((UChar32)cp, (UChar32)cp); + complement(static_cast<UChar32>(cp), static_cast<UChar32>(cp)); } return *this; } @@ -1277,9 +1275,9 @@ UnicodeSet& UnicodeSet::addAll(const UnicodeSet& c) { } // Add strings in order - if ( c.strings!=nullptr ) { - for (int32_t i=0; i<c.strings->size(); ++i) { - const UnicodeString* s = (const UnicodeString*)c.strings->elementAt(i); + if ( c.strings_!=nullptr ) { + for (int32_t i=0; i<c.strings_->size(); ++i) { + const UnicodeString* s = static_cast<const UnicodeString*>(c.strings_->elementAt(i)); if (!stringsContains(*s)) { _add(*s); } @@ -1304,9 +1302,9 @@ UnicodeSet& UnicodeSet::retainAll(const UnicodeSet& c) { retain(c.list, c.len, 0); if (hasStrings()) { if (!c.hasStrings()) { - strings->removeAllElements(); + strings_->removeAllElements(); } else { - strings->retainAll(*c.strings); + strings_->retainAll(*c.strings_); } } return *this; @@ -1327,7 +1325,7 @@ UnicodeSet& UnicodeSet::removeAll(const UnicodeSet& c) { } retain(c.list, c.len, 2); if (hasStrings() && c.hasStrings()) { - strings->removeAll(*c.strings); + strings_->removeAll(*c.strings_); } return *this; } @@ -1346,11 +1344,11 @@ UnicodeSet& UnicodeSet::complementAll(const UnicodeSet& c) { } exclusiveOr(c.list, c.len, 0); - if (c.strings != nullptr) { - for (int32_t i=0; i<c.strings->size(); ++i) { - void* e = c.strings->elementAt(i); - if (strings == nullptr || !strings->removeElement(e)) { - _add(*(const UnicodeString*)e); + if (c.strings_ != nullptr) { + for (int32_t i=0; i<c.strings_->size(); ++i) { + void* e = c.strings_->elementAt(i); + if (strings_ == nullptr || !strings_->removeElement(e)) { + _add(*static_cast<const UnicodeString*>(e)); } } } @@ -1368,8 +1366,8 @@ UnicodeSet& UnicodeSet::clear() { list[0] = UNICODESET_HIGH; len = 1; releasePattern(); - if (strings != nullptr) { - strings->removeAllElements(); + if (strings_ != nullptr) { + strings_->removeAllElements(); } // Remove bogus fFlags = 0; @@ -1407,7 +1405,7 @@ UChar32 UnicodeSet::getRangeEnd(int32_t index) const { } const UnicodeString* UnicodeSet::getString(int32_t index) const { - return (const UnicodeString*) strings->elementAt(index); + return static_cast<const UnicodeString*>(strings_->elementAt(index)); } /** @@ -1433,7 +1431,7 @@ UnicodeSet& UnicodeSet::compact() { capacity = INITIAL_CAPACITY; } else if ((len + 7) < capacity) { // If we have more than a little unused capacity, shrink it to len. - UChar32* temp = (UChar32*) uprv_realloc(list, sizeof(UChar32) * len); + UChar32* temp = static_cast<UChar32*>(uprv_realloc(list, sizeof(UChar32) * len)); if (temp) { list = temp; capacity = len; @@ -1441,9 +1439,9 @@ UnicodeSet& UnicodeSet::compact() { // else what the heck happened?! We allocated less memory! // Oh well. We'll keep our original array. } - if (strings != nullptr && strings->isEmpty()) { - delete strings; - strings = nullptr; + if (strings_ != nullptr && strings_->isEmpty()) { + delete strings_; + strings_ = nullptr; } return *this; } @@ -1492,8 +1490,8 @@ UnicodeSet::UnicodeSet(const uint16_t data[], int32_t dataLen, ESerialization se } // copy smp for(i=bmpLength;i<newLength;i++) { - list[i] = ((UChar32)data[headerSize+bmpLength+(i-bmpLength)*2+0] << 16) + - ((UChar32)data[headerSize+bmpLength+(i-bmpLength)*2+1]); + list[i] = (static_cast<UChar32>(data[headerSize + bmpLength + (i - bmpLength) * 2 + 0]) << 16) + + static_cast<UChar32>(data[headerSize + bmpLength + (i - bmpLength) * 2 + 1]); #ifdef DEBUG_SERIALIZE printf("<<32@%d+[%d] %lX\n", headerSize+bmpLength+i, i, list[i]); #endif @@ -1568,10 +1566,10 @@ int32_t UnicodeSet::serialize(uint16_t *dest, int32_t destCapacity, UErrorCode& #ifdef DEBUG_SERIALIZE printf("writeHdr\n"); #endif - *dest=(uint16_t)length; + *dest = static_cast<uint16_t>(length); if (length>bmpLength) { *dest|=0x8000; - *++dest=(uint16_t)bmpLength; + *++dest = static_cast<uint16_t>(bmpLength); } ++dest; @@ -1581,7 +1579,7 @@ int32_t UnicodeSet::serialize(uint16_t *dest, int32_t destCapacity, UErrorCode& #ifdef DEBUG_SERIALIZE printf("writebmp: %x\n", (int)*p); #endif - *dest++=(uint16_t)*p++; + *dest++ = static_cast<uint16_t>(*p++); } /* write the supplementary part of the array */ @@ -1589,8 +1587,8 @@ int32_t UnicodeSet::serialize(uint16_t *dest, int32_t destCapacity, UErrorCode& #ifdef DEBUG_SERIALIZE printf("write32: %x\n", (int)*p); #endif - *dest++=(uint16_t)(*p>>16); - *dest++=(uint16_t)*p++; + *dest++ = static_cast<uint16_t>(*p >> 16); + *dest++ = static_cast<uint16_t>(*p++); } } else { ec=U_BUFFER_OVERFLOW_ERROR; @@ -1609,15 +1607,15 @@ UBool UnicodeSet::allocateStrings(UErrorCode &status) { if (U_FAILURE(status)) { return false; } - strings = new UVector(uprv_deleteUObject, + strings_ = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, 1, status); - if (strings == nullptr) { // Check for memory allocation error. + if (strings_ == nullptr) { // Check for memory allocation error. status = U_MEMORY_ALLOCATION_ERROR; return false; } if (U_FAILURE(status)) { - delete strings; - strings = nullptr; + delete strings_; + strings_ = nullptr; return false; } return true; @@ -1646,7 +1644,7 @@ bool UnicodeSet::ensureCapacity(int32_t newLen) { return true; } int32_t newCapacity = nextCapacity(newLen); - UChar32* temp = (UChar32*) uprv_malloc(newCapacity * sizeof(UChar32)); + UChar32* temp = static_cast<UChar32*>(uprv_malloc(newCapacity * sizeof(UChar32))); if (temp == nullptr) { setToBogus(); // set the object to bogus state if an OOM failure occurred. return false; @@ -1669,7 +1667,7 @@ bool UnicodeSet::ensureBufferCapacity(int32_t newLen) { return true; } int32_t newCapacity = nextCapacity(newLen); - UChar32* temp = (UChar32*) uprv_malloc(newCapacity * sizeof(UChar32)); + UChar32* temp = static_cast<UChar32*>(uprv_malloc(newCapacity * sizeof(UChar32))); if (temp == nullptr) { setToBogus(); return false; @@ -2133,11 +2131,11 @@ UnicodeString& UnicodeSet::_generatePattern(UnicodeString& result, } } - if (strings != nullptr) { - for (int32_t i = 0; i<strings->size(); ++i) { + if (strings_ != nullptr) { + for (int32_t i = 0; i<strings_->size(); ++i) { result.append(u'{'); _appendToPat(result, - *(const UnicodeString*) strings->elementAt(i), + *static_cast<const UnicodeString*>(strings_->elementAt(i)), escapeUnprintable); result.append(u'}'); } @@ -2161,7 +2159,7 @@ void UnicodeSet::releasePattern() { */ void UnicodeSet::setPattern(const char16_t *newPat, int32_t newPatLen) { releasePattern(); - pat = (char16_t *)uprv_malloc((newPatLen + 1) * sizeof(char16_t)); + pat = static_cast<char16_t*>(uprv_malloc((newPatLen + 1) * sizeof(char16_t))); if (pat) { patLen = newPatLen; u_memcpy(pat, newPat, patLen); @@ -2177,7 +2175,7 @@ UnicodeSet *UnicodeSet::freeze() { // Optimize contains() and span() and similar functions. if (hasStrings()) { - stringSpan = new UnicodeSetStringSpan(*this, *strings, UnicodeSetStringSpan::ALL); + stringSpan = new UnicodeSetStringSpan(*this, *strings_, UnicodeSetStringSpan::ALL); if (stringSpan == nullptr) { setToBogus(); return this; @@ -2204,7 +2202,7 @@ UnicodeSet *UnicodeSet::freeze() { int32_t UnicodeSet::span(const char16_t *s, int32_t length, USetSpanCondition spanCondition) const { if(length>0 && bmpSet!=nullptr) { - return (int32_t)(bmpSet->span(s, s+length, spanCondition)-s); + return static_cast<int32_t>(bmpSet->span(s, s + length, spanCondition) - s); } if(length<0) { length=u_strlen(s); @@ -2218,7 +2216,7 @@ int32_t UnicodeSet::span(const char16_t *s, int32_t length, USetSpanCondition sp uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ? UnicodeSetStringSpan::FWD_UTF16_NOT_CONTAINED : UnicodeSetStringSpan::FWD_UTF16_CONTAINED; - UnicodeSetStringSpan strSpan(*this, *strings, which); + UnicodeSetStringSpan strSpan(*this, *strings_, which); if(strSpan.needsStringSpanUTF16()) { return strSpan.span(s, length, spanCondition); } @@ -2241,7 +2239,7 @@ int32_t UnicodeSet::span(const char16_t *s, int32_t length, USetSpanCondition sp int32_t UnicodeSet::spanBack(const char16_t *s, int32_t length, USetSpanCondition spanCondition) const { if(length>0 && bmpSet!=nullptr) { - return (int32_t)(bmpSet->spanBack(s, s+length, spanCondition)-s); + return static_cast<int32_t>(bmpSet->spanBack(s, s + length, spanCondition) - s); } if(length<0) { length=u_strlen(s); @@ -2255,7 +2253,7 @@ int32_t UnicodeSet::spanBack(const char16_t *s, int32_t length, USetSpanConditio uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ? UnicodeSetStringSpan::BACK_UTF16_NOT_CONTAINED : UnicodeSetStringSpan::BACK_UTF16_CONTAINED; - UnicodeSetStringSpan strSpan(*this, *strings, which); + UnicodeSetStringSpan strSpan(*this, *strings_, which); if(strSpan.needsStringSpanUTF16()) { return strSpan.spanBack(s, length, spanCondition); } @@ -2278,24 +2276,24 @@ int32_t UnicodeSet::spanBack(const char16_t *s, int32_t length, USetSpanConditio int32_t UnicodeSet::spanUTF8(const char *s, int32_t length, USetSpanCondition spanCondition) const { if(length>0 && bmpSet!=nullptr) { - const uint8_t *s0=(const uint8_t *)s; - return (int32_t)(bmpSet->spanUTF8(s0, length, spanCondition)-s0); + const uint8_t* s0 = reinterpret_cast<const uint8_t*>(s); + return static_cast<int32_t>(bmpSet->spanUTF8(s0, length, spanCondition) - s0); } if(length<0) { - length=(int32_t)uprv_strlen(s); + length = static_cast<int32_t>(uprv_strlen(s)); } if(length==0) { return 0; } if(stringSpan!=nullptr) { - return stringSpan->spanUTF8((const uint8_t *)s, length, spanCondition); + return stringSpan->spanUTF8(reinterpret_cast<const uint8_t*>(s), length, spanCondition); } else if(hasStrings()) { uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ? UnicodeSetStringSpan::FWD_UTF8_NOT_CONTAINED : UnicodeSetStringSpan::FWD_UTF8_CONTAINED; - UnicodeSetStringSpan strSpan(*this, *strings, which); + UnicodeSetStringSpan strSpan(*this, *strings_, which); if(strSpan.needsStringSpanUTF8()) { - return strSpan.spanUTF8((const uint8_t *)s, length, spanCondition); + return strSpan.spanUTF8(reinterpret_cast<const uint8_t*>(s), length, spanCondition); } } @@ -2316,24 +2314,24 @@ int32_t UnicodeSet::spanUTF8(const char *s, int32_t length, USetSpanCondition sp int32_t UnicodeSet::spanBackUTF8(const char *s, int32_t length, USetSpanCondition spanCondition) const { if(length>0 && bmpSet!=nullptr) { - const uint8_t *s0=(const uint8_t *)s; + const uint8_t* s0 = reinterpret_cast<const uint8_t*>(s); return bmpSet->spanBackUTF8(s0, length, spanCondition); } if(length<0) { - length=(int32_t)uprv_strlen(s); + length = static_cast<int32_t>(uprv_strlen(s)); } if(length==0) { return 0; } if(stringSpan!=nullptr) { - return stringSpan->spanBackUTF8((const uint8_t *)s, length, spanCondition); + return stringSpan->spanBackUTF8(reinterpret_cast<const uint8_t*>(s), length, spanCondition); } else if(hasStrings()) { uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ? UnicodeSetStringSpan::BACK_UTF8_NOT_CONTAINED : UnicodeSetStringSpan::BACK_UTF8_CONTAINED; - UnicodeSetStringSpan strSpan(*this, *strings, which); + UnicodeSetStringSpan strSpan(*this, *strings_, which); if(strSpan.needsStringSpanUTF8()) { - return strSpan.spanBackUTF8((const uint8_t *)s, length, spanCondition); + return strSpan.spanBackUTF8(reinterpret_cast<const uint8_t*>(s), length, spanCondition); } } diff --git a/thirdparty/icu4c/common/uniset_closure.cpp b/thirdparty/icu4c/common/uniset_closure.cpp index 173a5cbaae..ae777c5fac 100644 --- a/thirdparty/icu4c/common/uniset_closure.cpp +++ b/thirdparty/icu4c/common/uniset_closure.cpp @@ -116,17 +116,17 @@ UnicodeSet& UnicodeSet::applyPattern(const UnicodeString& pattern, // Does not use uset.h to reduce code dependencies static void U_CALLCONV _set_add(USet *set, UChar32 c) { - ((UnicodeSet *)set)->add(c); + reinterpret_cast<UnicodeSet*>(set)->add(c); } static void U_CALLCONV _set_addRange(USet *set, UChar32 start, UChar32 end) { - ((UnicodeSet *)set)->add(start, end); + reinterpret_cast<UnicodeSet*>(set)->add(start, end); } static void U_CALLCONV _set_addString(USet *set, const char16_t *str, int32_t length) { - ((UnicodeSet *)set)->add(UnicodeString((UBool)(length<0), str, length)); + reinterpret_cast<UnicodeSet*>(set)->add(UnicodeString(static_cast<UBool>(length < 0), str, length)); } //---------------------------------------------------------------- @@ -143,7 +143,7 @@ addCaseMapping(UnicodeSet &set, int32_t result, const char16_t *full, UnicodeStr set.add(result); } else { // add a string case mapping from full with length result - str.setTo((UBool)false, full, result); + str.setTo(static_cast<UBool>(false), full, result); set.add(str); } } @@ -242,7 +242,7 @@ void UnicodeSet::closeOverCaseInsensitive(bool simple) { // therefore, start with no strings and add only those needed. // Do this before processing code points, because they may add strings. if (!simple && foldSet.hasStrings()) { - foldSet.strings->removeAllElements(); + foldSet.strings_->removeAllElements(); } USetAdder sa = { @@ -276,8 +276,8 @@ void UnicodeSet::closeOverCaseInsensitive(bool simple) { } if (hasStrings()) { UnicodeString str; - for (int32_t j=0; j<strings->size(); ++j) { - const UnicodeString *pStr = (const UnicodeString *) strings->elementAt(j); + for (int32_t j=0; j<strings_->size(); ++j) { + const UnicodeString* pStr = static_cast<const UnicodeString*>(strings_->elementAt(j)); if (simple) { if (scfString(*pStr, str)) { foldSet.remove(*pStr).add(str); @@ -334,8 +334,8 @@ void UnicodeSet::closeOverAddCaseMappings() { BreakIterator *bi = BreakIterator::createWordInstance(root, status); if (U_SUCCESS(status)) { #endif - for (int32_t j=0; j<strings->size(); ++j) { - const UnicodeString *pStr = (const UnicodeString *) strings->elementAt(j); + for (int32_t j=0; j<strings_->size(); ++j) { + const UnicodeString* pStr = static_cast<const UnicodeString*>(strings_->elementAt(j)); (str = *pStr).toLower(root); foldSet.add(str); #if !UCONFIG_NO_BREAK_ITERATION diff --git a/thirdparty/icu4c/common/uniset_props.cpp b/thirdparty/icu4c/common/uniset_props.cpp index e6f880c9f2..532b17f506 100644 --- a/thirdparty/icu4c/common/uniset_props.cpp +++ b/thirdparty/icu4c/common/uniset_props.cpp @@ -47,14 +47,17 @@ U_NAMESPACE_USE +namespace { + // Special property set IDs -static const char ANY[] = "ANY"; // [\u0000-\U0010FFFF] -static const char ASCII[] = "ASCII"; // [\u0000-\u007F] -static const char ASSIGNED[] = "Assigned"; // [:^Cn:] +constexpr char ANY[] = "ANY"; // [\u0000-\U0010FFFF] +constexpr char ASCII[] = "ASCII"; // [\u0000-\u007F] +constexpr char ASSIGNED[] = "Assigned"; // [:^Cn:] // Unicode name property alias -#define NAME_PROP "na" -#define NAME_PROP_LENGTH 2 +constexpr char16_t NAME_PROP[] = u"na"; + +} // namespace // Cached sets ------------------------------------------------------------- *** @@ -83,7 +86,7 @@ namespace { // Cache some sets for other services -------------------------------------- *** void U_CALLCONV createUni32Set(UErrorCode &errorCode) { U_ASSERT(uni32Singleton == nullptr); - uni32Singleton = new UnicodeSet(UNICODE_STRING_SIMPLE("[:age=3.2:]"), errorCode); + uni32Singleton = new UnicodeSet(UnicodeString(u"[:age=3.2:]"), errorCode); if(uni32Singleton==nullptr) { errorCode=U_MEMORY_ALLOCATION_ERROR; } else { @@ -209,7 +212,7 @@ UnicodeSet::applyPatternIgnoreSpace(const UnicodeString& pattern, */ UBool UnicodeSet::resemblesPattern(const UnicodeString& pattern, int32_t pos) { return ((pos+1) < pattern.length() && - pattern.charAt(pos) == (char16_t)91/*[*/) || + pattern.charAt(pos) == static_cast<char16_t>(91)/*[*/) || resemblesPropertyPattern(pattern, pos); } @@ -471,7 +474,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, case u'-': if (op == 0) { if (lastItem != 0) { - op = (char16_t) c; + op = static_cast<char16_t>(c); continue; } else { // Treat final trailing '-' as a literal @@ -490,7 +493,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, return; case u'&': if (lastItem == 2 && op == 0) { - op = (char16_t) c; + op = static_cast<char16_t>(c); continue; } // syntaxError(chars, "'&' not after set"); @@ -561,7 +564,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, } add(U_ETHER); usePat = true; - patLocal.append((char16_t) SymbolTable::SYMBOL_REF); + patLocal.append(static_cast<char16_t>(SymbolTable::SYMBOL_REF)); patLocal.append(u']'); mode = 2; continue; @@ -658,11 +661,11 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, namespace { UBool numericValueFilter(UChar32 ch, void* context) { - return u_getNumericValue(ch) == *(double*)context; + return u_getNumericValue(ch) == *static_cast<double*>(context); } UBool generalCategoryMaskFilter(UChar32 ch, void* context) { - int32_t value = *(int32_t*)context; + int32_t value = *static_cast<int32_t*>(context); return (U_GET_GC_MASK((UChar32) ch) & value) != 0; } @@ -670,7 +673,7 @@ UBool versionFilter(UChar32 ch, void* context) { static const UVersionInfo none = { 0, 0, 0, 0 }; UVersionInfo v; u_charAge(ch, v); - UVersionInfo* version = (UVersionInfo*)context; + UVersionInfo* version = static_cast<UVersionInfo*>(context); return uprv_memcmp(&v, &none, sizeof(v)) > 0 && uprv_memcmp(&v, version, sizeof(v)) <= 0; } @@ -680,16 +683,16 @@ typedef struct { } IntPropertyContext; UBool intPropertyFilter(UChar32 ch, void* context) { - IntPropertyContext* c = (IntPropertyContext*)context; - return u_getIntPropertyValue((UChar32) ch, c->prop) == c->value; + IntPropertyContext* c = static_cast<IntPropertyContext*>(context); + return u_getIntPropertyValue(ch, c->prop) == c->value; } UBool scriptExtensionsFilter(UChar32 ch, void* context) { - return uscript_hasScript(ch, *(UScriptCode*)context); + return uscript_hasScript(ch, *static_cast<UScriptCode*>(context)); } UBool idTypeFilter(UChar32 ch, void* context) { - return u_hasIDType(ch, *(UIdentifierType*)context); + return u_hasIDType(ch, *static_cast<UIdentifierType*>(context)); } } // namespace @@ -738,7 +741,7 @@ void UnicodeSet::applyFilter(UnicodeSet::Filter filter, } } if (startHasProperty >= 0) { - add((UChar32)startHasProperty, (UChar32)0x10FFFF); + add(startHasProperty, static_cast<UChar32>(0x10FFFF)); } if (isBogus() && U_SUCCESS(status)) { // We likely ran out of memory. AHHH! @@ -784,11 +787,11 @@ UnicodeSet::applyIntPropertyValue(UProperty prop, int32_t value, UErrorCode& ec) applyFilter(generalCategoryMaskFilter, &value, inclusions, ec); } else if (prop == UCHAR_SCRIPT_EXTENSIONS) { const UnicodeSet* inclusions = CharacterProperties::getInclusionsForProperty(prop, ec); - UScriptCode script = (UScriptCode)value; + UScriptCode script = static_cast<UScriptCode>(value); applyFilter(scriptExtensionsFilter, &script, inclusions, ec); } else if (prop == UCHAR_IDENTIFIER_TYPE) { const UnicodeSet* inclusions = CharacterProperties::getInclusionsForProperty(prop, ec); - UIdentifierType idType = (UIdentifierType)value; + UIdentifierType idType = static_cast<UIdentifierType>(value); applyFilter(idTypeFilter, &idType, inclusions, ec); } else if (0 <= prop && prop < UCHAR_BINARY_LIMIT) { if (value == 0 || value == 1) { @@ -862,7 +865,7 @@ UnicodeSet::applyPropertyAlias(const UnicodeString& prop, // We catch NaN here because comparing it with both 0 and 255 will be false // (as are all comparisons with NaN). if (*end != 0 || !(0 <= val && val <= 255) || - (v = (int32_t)val) != val) { + (v = static_cast<int32_t>(val)) != val) { // non-integral value or outside 0..255, or trailing junk FAIL(ec); } @@ -1105,7 +1108,7 @@ UnicodeSet& UnicodeSet::applyPropertyPattern(const UnicodeString& pattern, // support args of (UProperty, char*) then we can remove // NAME_PROP and make this a little more efficient. valueName = propName; - propName = UnicodeString(NAME_PROP, NAME_PROP_LENGTH, US_INV); + propName = NAME_PROP; } } diff --git a/thirdparty/icu4c/common/unisetspan.cpp b/thirdparty/icu4c/common/unisetspan.cpp index b7256d8fd1..209f0a86b5 100644 --- a/thirdparty/icu4c/common/unisetspan.cpp +++ b/thirdparty/icu4c/common/unisetspan.cpp @@ -66,10 +66,10 @@ public: // Call exactly once if the list is to be used. void setMaxLength(int32_t maxLength) { - if(maxLength<=(int32_t)sizeof(staticList)) { - capacity=(int32_t)sizeof(staticList); + if (maxLength <= static_cast<int32_t>(sizeof(staticList))) { + capacity = static_cast<int32_t>(sizeof(staticList)); } else { - UBool *l=(UBool *)uprv_malloc(maxLength); + UBool* l = static_cast<UBool*>(uprv_malloc(maxLength)); if(l!=nullptr) { list=l; capacity=maxLength; @@ -84,7 +84,7 @@ public: } UBool isEmpty() const { - return (UBool)(length==0); + return length == 0; } // Reduce all stored offsets by delta, used when the current position @@ -183,7 +183,7 @@ static int32_t appendUTF8(const char16_t *s, int32_t length, uint8_t *t, int32_t capacity) { UErrorCode errorCode=U_ZERO_ERROR; int32_t length8=0; - u_strToUTF8((char *)t, capacity, &length8, s, length, &errorCode); + u_strToUTF8(reinterpret_cast<char*>(t), capacity, &length8, s, length, &errorCode); if(U_SUCCESS(errorCode)) { return length8; } else { @@ -196,7 +196,7 @@ appendUTF8(const char16_t *s, int32_t length, uint8_t *t, int32_t capacity) { static inline uint8_t makeSpanLengthByte(int32_t spanLength) { // 0xfe==UnicodeSetStringSpan::LONG_SPAN - return spanLength<0xfe ? (uint8_t)spanLength : (uint8_t)0xfe; + return spanLength < 0xfe ? static_cast<uint8_t>(spanLength) : static_cast<uint8_t>(0xfe); } // Construct for all variants of span(), or only for any one variant. @@ -208,7 +208,7 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, utf8Lengths(nullptr), spanLengths(nullptr), utf8(nullptr), utf8Length(0), maxLength16(0), maxLength8(0), - all((UBool)(which==ALL)) { + all(static_cast<UBool>(which == ALL)) { spanSet.retainAll(set); if(which&NOT_CONTAINED) { // Default to the same sets. @@ -228,7 +228,7 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, int32_t i, spanLength; UBool someRelevant=false; for(i=0; i<stringsLength; ++i) { - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); if (length16==0) { @@ -279,10 +279,10 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, allocSize+=stringsLength*4+utf8Length; } } - if(allocSize<=(int32_t)sizeof(staticLengths)) { + if (allocSize <= static_cast<int32_t>(sizeof(staticLengths))) { utf8Lengths=staticLengths; } else { - utf8Lengths=(int32_t *)uprv_malloc(allocSize); + utf8Lengths = static_cast<int32_t*>(uprv_malloc(allocSize)); if(utf8Lengths==nullptr) { maxLength16=maxLength8=0; // Prevent usage by making needsStringSpanUTF16/8() return false. return; // Out of memory. @@ -291,7 +291,7 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, if(all) { // Store span lengths for all span() variants. - spanLengths=(uint8_t *)(utf8Lengths+stringsLength); + spanLengths = reinterpret_cast<uint8_t*>(utf8Lengths + stringsLength); spanBackLengths=spanLengths+stringsLength; spanUTF8Lengths=spanBackLengths+stringsLength; spanBackUTF8Lengths=spanUTF8Lengths+stringsLength; @@ -299,10 +299,10 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, } else { // Store span lengths for only one span() variant. if(which&UTF8) { - spanLengths=(uint8_t *)(utf8Lengths+stringsLength); + spanLengths = reinterpret_cast<uint8_t*>(utf8Lengths + stringsLength); utf8=spanLengths+stringsLength; } else { - spanLengths=(uint8_t *)utf8Lengths; + spanLengths = reinterpret_cast<uint8_t*>(utf8Lengths); } spanBackLengths=spanUTF8Lengths=spanBackUTF8Lengths=spanLengths; } @@ -311,7 +311,7 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, int32_t utf8Count=0; // Count UTF-8 bytes written so far. for(i=0; i<stringsLength; ++i) { - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); spanLength=spanSet.span(s16, length16, USET_SPAN_CONTAINED); @@ -334,15 +334,15 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, int32_t length8=appendUTF8(s16, length16, s8, utf8Length-utf8Count); utf8Count+=utf8Lengths[i]=length8; if(length8==0) { // Irrelevant for UTF-8 because not representable in UTF-8. - spanUTF8Lengths[i]=spanBackUTF8Lengths[i]=(uint8_t)ALL_CP_CONTAINED; + spanUTF8Lengths[i] = spanBackUTF8Lengths[i] = static_cast<uint8_t>(ALL_CP_CONTAINED); } else { // Relevant for UTF-8. if(which&CONTAINED) { if(which&FWD) { - spanLength=spanSet.spanUTF8((const char *)s8, length8, USET_SPAN_CONTAINED); + spanLength = spanSet.spanUTF8(reinterpret_cast<const char*>(s8), length8, USET_SPAN_CONTAINED); spanUTF8Lengths[i]=makeSpanLengthByte(spanLength); } if(which&BACK) { - spanLength=length8-spanSet.spanBackUTF8((const char *)s8, length8, USET_SPAN_CONTAINED); + spanLength = length8 - spanSet.spanBackUTF8(reinterpret_cast<const char*>(s8), length8, USET_SPAN_CONTAINED); spanBackUTF8Lengths[i]=makeSpanLengthByte(spanLength); } } else /* not CONTAINED, not all, but NOT_CONTAINED */ { @@ -378,10 +378,10 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, if(all) { spanLengths[i]=spanBackLengths[i]= spanUTF8Lengths[i]=spanBackUTF8Lengths[i]= - (uint8_t)ALL_CP_CONTAINED; + static_cast<uint8_t>(ALL_CP_CONTAINED); } else { // All spanXYZLengths pointers contain the same address. - spanLengths[i]=(uint8_t)ALL_CP_CONTAINED; + spanLengths[i] = static_cast<uint8_t>(ALL_CP_CONTAINED); } } } @@ -410,17 +410,17 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSetStringSpan &otherStri // UTF-8 lengths, 4 sets of span lengths, UTF-8 strings. int32_t stringsLength=strings.size(); int32_t allocSize=stringsLength*(4+1+1+1+1)+utf8Length; - if(allocSize<=(int32_t)sizeof(staticLengths)) { + if (allocSize <= static_cast<int32_t>(sizeof(staticLengths))) { utf8Lengths=staticLengths; } else { - utf8Lengths=(int32_t *)uprv_malloc(allocSize); + utf8Lengths = static_cast<int32_t*>(uprv_malloc(allocSize)); if(utf8Lengths==nullptr) { maxLength16=maxLength8=0; // Prevent usage by making needsStringSpanUTF16/8() return false. return; // Out of memory. } } - spanLengths=(uint8_t *)(utf8Lengths+stringsLength); + spanLengths = reinterpret_cast<uint8_t*>(utf8Lengths + stringsLength); utf8=spanLengths+stringsLength*4; uprv_memcpy(utf8Lengths, otherStringSpan.utf8Lengths, allocSize); } @@ -658,7 +658,7 @@ int32_t UnicodeSetStringSpan::span(const char16_t *s, int32_t length, USetSpanCo if(overlap==ALL_CP_CONTAINED) { continue; // Irrelevant string. (Also the empty string.) } - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); U_ASSERT(length>0); @@ -698,7 +698,7 @@ int32_t UnicodeSetStringSpan::span(const char16_t *s, int32_t length, USetSpanCo // For longest match, we do need to try to match even an all-contained string // to find the match from the earliest start. - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); if (length16==0) { @@ -826,7 +826,7 @@ int32_t UnicodeSetStringSpan::spanBack(const char16_t *s, int32_t length, USetSp if(overlap==ALL_CP_CONTAINED) { continue; // Irrelevant string. (Also the empty string.) } - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); U_ASSERT(length>0); @@ -868,7 +868,7 @@ int32_t UnicodeSetStringSpan::spanBack(const char16_t *s, int32_t length, USetSp // For longest match, we do need to try to match even an all-contained string // to find the match from the latest end. - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); if (length16==0) { @@ -968,7 +968,7 @@ int32_t UnicodeSetStringSpan::spanUTF8(const uint8_t *s, int32_t length, USetSpa if(spanCondition==USET_SPAN_NOT_CONTAINED) { return spanNotUTF8(s, length); } - int32_t spanLength=spanSet.spanUTF8((const char *)s, length, USET_SPAN_CONTAINED); + int32_t spanLength = spanSet.spanUTF8(reinterpret_cast<const char*>(s), length, USET_SPAN_CONTAINED); if(spanLength==length) { return length; } @@ -1104,7 +1104,7 @@ int32_t UnicodeSetStringSpan::spanUTF8(const uint8_t *s, int32_t length, USetSpa if(offsets.isEmpty()) { // No more strings matched after a previous string match. // Try another code point span from after the last string match. - spanLength=spanSet.spanUTF8((const char *)s+pos, rest, USET_SPAN_CONTAINED); + spanLength = spanSet.spanUTF8(reinterpret_cast<const char*>(s) + pos, rest, USET_SPAN_CONTAINED); if( spanLength==rest || // Reached the end of the string, or spanLength==0 // neither strings nor span progressed. ) { @@ -1145,7 +1145,7 @@ int32_t UnicodeSetStringSpan::spanBackUTF8(const uint8_t *s, int32_t length, USe if(spanCondition==USET_SPAN_NOT_CONTAINED) { return spanNotBackUTF8(s, length); } - int32_t pos=spanSet.spanBackUTF8((const char *)s, length, USET_SPAN_CONTAINED); + int32_t pos = spanSet.spanBackUTF8(reinterpret_cast<const char*>(s), length, USET_SPAN_CONTAINED); if(pos==0) { return 0; } @@ -1284,7 +1284,7 @@ int32_t UnicodeSetStringSpan::spanBackUTF8(const uint8_t *s, int32_t length, USe // No more strings matched before a previous string match. // Try another code point span from before the last string match. int32_t oldPos=pos; - pos=spanSet.spanBackUTF8((const char *)s, oldPos, USET_SPAN_CONTAINED); + pos = spanSet.spanBackUTF8(reinterpret_cast<const char*>(s), oldPos, USET_SPAN_CONTAINED); spanLength=oldPos-pos; if( pos==0 || // Reached the start of the string, or spanLength==0 // neither strings nor span progressed. @@ -1371,7 +1371,7 @@ int32_t UnicodeSetStringSpan::spanNot(const char16_t *s, int32_t length) const { if(spanLengths[i]==ALL_CP_CONTAINED) { continue; // Irrelevant string. (Also the empty string.) } - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); U_ASSERT(length>0); @@ -1415,7 +1415,7 @@ int32_t UnicodeSetStringSpan::spanNotBack(const char16_t *s, int32_t length) con if(spanLengths[i]==ALL_CP_CONTAINED) { continue; // Irrelevant string. (Also the empty string.) } - const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); + const UnicodeString& string = *static_cast<const UnicodeString*>(strings.elementAt(i)); const char16_t *s16=string.getBuffer(); int32_t length16=string.length(); U_ASSERT(length>0); @@ -1442,7 +1442,7 @@ int32_t UnicodeSetStringSpan::spanNotUTF8(const uint8_t *s, int32_t length) cons do { // Span until we find a code point from the set, // or a code point that starts or ends some string. - i=pSpanNotSet->spanUTF8((const char *)s+pos, rest, USET_SPAN_NOT_CONTAINED); + i = pSpanNotSet->spanUTF8(reinterpret_cast<const char*>(s) + pos, rest, USET_SPAN_NOT_CONTAINED); if(i==rest) { return length; // Reached the end of the string. } @@ -1487,7 +1487,7 @@ int32_t UnicodeSetStringSpan::spanNotBackUTF8(const uint8_t *s, int32_t length) do { // Span until we find a code point from the set, // or a code point that starts or ends some string. - pos=pSpanNotSet->spanBackUTF8((const char *)s, pos, USET_SPAN_NOT_CONTAINED); + pos = pSpanNotSet->spanBackUTF8(reinterpret_cast<const char*>(s), pos, USET_SPAN_NOT_CONTAINED); if(pos==0) { return 0; // Reached the start of the string. } diff --git a/thirdparty/icu4c/common/unisetspan.h b/thirdparty/icu4c/common/unisetspan.h index f1dc8e6f74..482782ebf7 100644 --- a/thirdparty/icu4c/common/unisetspan.h +++ b/thirdparty/icu4c/common/unisetspan.h @@ -141,11 +141,11 @@ private: }; UBool UnicodeSetStringSpan::needsStringSpanUTF16() { - return (UBool)(maxLength16!=0); + return maxLength16 != 0; } UBool UnicodeSetStringSpan::needsStringSpanUTF8() { - return (UBool)(maxLength8!=0); + return maxLength8 != 0; } UBool UnicodeSetStringSpan::contains(UChar32 c) const { diff --git a/thirdparty/icu4c/common/unistr.cpp b/thirdparty/icu4c/common/unistr.cpp index ce81138c2c..a720245772 100644 --- a/thirdparty/icu4c/common/unistr.cpp +++ b/thirdparty/icu4c/common/unistr.cpp @@ -20,6 +20,8 @@ ****************************************************************************** */ +#include <string_view> + #include "unicode/utypes.h" #include "unicode/appendable.h" #include "unicode/putil.h" @@ -107,12 +109,34 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeString) UnicodeString U_EXPORT2 operator+ (const UnicodeString &s1, const UnicodeString &s2) { - return - UnicodeString(s1.length()+s2.length()+1, (UChar32)0, 0). - append(s1). - append(s2); + int32_t sumLengths; + if (uprv_add32_overflow(s1.length(), s2.length(), &sumLengths)) { + UnicodeString bogus; + bogus.setToBogus(); + return bogus; + } + if (sumLengths != INT32_MAX) { + ++sumLengths; // space for a terminating NUL if we need one + } + return UnicodeString(sumLengths, static_cast<UChar32>(0), 0).append(s1).append(s2); +} + +U_COMMON_API UnicodeString U_EXPORT2 +unistr_internalConcat(const UnicodeString &s1, std::u16string_view s2) { + int32_t sumLengths; + if (s2.length() > INT32_MAX || + uprv_add32_overflow(s1.length(), static_cast<int32_t>(s2.length()), &sumLengths)) { + UnicodeString bogus; + bogus.setToBogus(); + return bogus; + } + if (sumLengths != INT32_MAX) { + ++sumLengths; // space for a terminating NUL if we need one + } + return UnicodeString(sumLengths, static_cast<UChar32>(0), 0).append(s1).append(s2); } + //======================================== // Reference Counting functions, put at top of file so that optimizing compilers // have a chance to automatically inline. @@ -120,23 +144,23 @@ operator+ (const UnicodeString &s1, const UnicodeString &s2) { void UnicodeString::addRef() { - umtx_atomic_inc((u_atomic_int32_t *)fUnion.fFields.fArray - 1); + umtx_atomic_inc(reinterpret_cast<u_atomic_int32_t*>(fUnion.fFields.fArray) - 1); } int32_t UnicodeString::removeRef() { - return umtx_atomic_dec((u_atomic_int32_t *)fUnion.fFields.fArray - 1); + return umtx_atomic_dec(reinterpret_cast<u_atomic_int32_t*>(fUnion.fFields.fArray) - 1); } int32_t UnicodeString::refCount() const { - return umtx_loadAcquire(*((u_atomic_int32_t *)fUnion.fFields.fArray - 1)); + return umtx_loadAcquire(*(reinterpret_cast<u_atomic_int32_t*>(fUnion.fFields.fArray) - 1)); } void UnicodeString::releaseArray() { if((fUnion.fFields.fLengthAndFlags & kRefCounted) && removeRef() == 0) { - uprv_free((int32_t *)fUnion.fFields.fArray - 1); + uprv_free(reinterpret_cast<int32_t*>(fUnion.fFields.fArray) - 1); } } @@ -150,7 +174,7 @@ UnicodeString::releaseArray() { UnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count) { fUnion.fFields.fLengthAndFlags = 0; - if(count <= 0 || (uint32_t)c > 0x10ffff) { + if (count <= 0 || static_cast<uint32_t>(c) > 0x10ffff) { // just allocate and do not do anything else allocate(capacity); } else if(c <= 0xffff) { @@ -160,7 +184,7 @@ UnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count) { } if(allocate(capacity)) { char16_t *array = getArrayStart(); - char16_t unit = (char16_t)c; + char16_t unit = static_cast<char16_t>(c); for(int32_t i = 0; i < length; ++i) { array[i] = unit; } @@ -206,11 +230,6 @@ UnicodeString::UnicodeString(UChar32 ch) { } } -UnicodeString::UnicodeString(const char16_t *text) { - fUnion.fFields.fLengthAndFlags = kShortString; - doAppend(text, 0, -1); -} - UnicodeString::UnicodeString(const char16_t *text, int32_t textLength) { fUnion.fFields.fLengthAndFlags = kShortString; @@ -256,7 +275,7 @@ UnicodeString::UnicodeString(char16_t *buff, while(p != limit && *p != 0) { ++p; } - buffLength = (int32_t)(p - buff); + buffLength = static_cast<int32_t>(p - buff); } setArray(buff, buffLength, buffCapacity); } @@ -268,7 +287,7 @@ UnicodeString::UnicodeString(const char *src, int32_t length, EInvariant) { // treat as an empty string } else { if(length<0) { - length=(int32_t)uprv_strlen(src); + length = static_cast<int32_t>(uprv_strlen(src)); } if(cloneArrayIfNeeded(length, length, false)) { u_charsToUChars(src, getArrayStart(), length); @@ -279,6 +298,26 @@ UnicodeString::UnicodeString(const char *src, int32_t length, EInvariant) { } } +UnicodeString UnicodeString::readOnlyAliasFromU16StringView(std::u16string_view text) { + UnicodeString result; + if (text.length() <= INT32_MAX) { + result.setTo(false, text.data(), static_cast<int32_t>(text.length())); + } else { + result.setToBogus(); + } + return result; +} + +UnicodeString UnicodeString::readOnlyAliasFromUnicodeString(const UnicodeString &text) { + UnicodeString result; + if (text.isBogus()) { + result.setToBogus(); + } else { + result.setTo(false, text.getBuffer(), text.length()); + } + return result; +} + #if U_CHARSET_IS_UTF8 UnicodeString::UnicodeString(const char *codepageData) { @@ -295,7 +334,7 @@ UnicodeString::UnicodeString(const char *codepageData, int32_t dataLength) { return; } if(dataLength == -1) { - dataLength = (int32_t)uprv_strlen(codepageData); + dataLength = static_cast<int32_t>(uprv_strlen(codepageData)); } setToUTF8(StringPiece(codepageData, dataLength)); } @@ -376,18 +415,18 @@ UnicodeString::allocate(int32_t capacity) { ++capacity; // for the NUL // Switch to size_t which is unsigned so that we can allocate up to 4GB. // Reference counter + UChars. - size_t numBytes = sizeof(int32_t) + (size_t)capacity * U_SIZEOF_UCHAR; + size_t numBytes = sizeof(int32_t) + static_cast<size_t>(capacity) * U_SIZEOF_UCHAR; // Round up to a multiple of 16. numBytes = (numBytes + 15) & ~15; - int32_t *array = (int32_t *) uprv_malloc(numBytes); + int32_t* array = static_cast<int32_t*>(uprv_malloc(numBytes)); if(array != nullptr) { // set initial refCount and point behind the refCount *array++ = 1; numBytes -= sizeof(int32_t); // have fArray point to the first char16_t - fUnion.fFields.fArray = (char16_t *)array; - fUnion.fFields.fCapacity = (int32_t)(numBytes / U_SIZEOF_UCHAR); + fUnion.fFields.fArray = reinterpret_cast<char16_t*>(array); + fUnion.fFields.fCapacity = static_cast<int32_t>(numBytes / U_SIZEOF_UCHAR); fUnion.fFields.fLengthAndFlags = kLongString; return true; } @@ -622,7 +661,7 @@ void UnicodeString::swap(UnicodeString &other) noexcept { //======================================== UnicodeString UnicodeString::unescape() const { - UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with capacity + UnicodeString result(length(), static_cast<UChar32>(0), static_cast<int32_t>(0)); // construct with capacity if (result.isBogus()) { return result; } @@ -656,10 +695,10 @@ UChar32 UnicodeString::unescapeAt(int32_t &offset) const { // Read-only implementation //======================================== UBool -UnicodeString::doEquals(const UnicodeString &text, int32_t len) const { - // Requires: this & text not bogus and have same lengths. +UnicodeString::doEquals(const char16_t *text, int32_t len) const { + // Requires: this not bogus and have same lengths. // Byte-wise comparison works for equality regardless of endianness. - return uprv_memcmp(getArrayStart(), text.getArrayStart(), len * U_SIZEOF_UCHAR) == 0; + return uprv_memcmp(getArrayStart(), text, len * U_SIZEOF_UCHAR) == 0; } UBool @@ -772,9 +811,9 @@ UnicodeString::doCompare( int32_t start, # else // little-endian: compare char16_t units do { - result = ((int32_t)*(chars++) - (int32_t)*(srcChars++)); + result = static_cast<int32_t>(*(chars++)) - static_cast<int32_t>(*(srcChars++)); if(result != 0) { - return (int8_t)(result >> 15 | 1); + return static_cast<int8_t>(result >> 15 | 1); } } while(--minLength > 0); # endif @@ -806,7 +845,7 @@ UnicodeString::doCompareCodePointOrder(int32_t start, int32_t diff = uprv_strCompare(getArrayStart() + start, length, (srcChars!=nullptr)?(srcChars + srcStart):nullptr, srcLength, false, true); /* translate the 32-bit result into an 8-bit one */ if(diff!=0) { - return (int8_t)(diff >> 15 | 1); + return static_cast<int8_t>(diff >> 15 | 1); } else { return 0; } @@ -831,7 +870,7 @@ UChar32 UnicodeString::char32At(int32_t offset) const { int32_t len = length(); - if((uint32_t)offset < (uint32_t)len) { + if (static_cast<uint32_t>(offset) < static_cast<uint32_t>(len)) { const char16_t *array = getArrayStart(); UChar32 c; U16_GET(array, 0, offset, len, c); @@ -843,7 +882,7 @@ UnicodeString::char32At(int32_t offset) const int32_t UnicodeString::getChar32Start(int32_t offset) const { - if((uint32_t)offset < (uint32_t)length()) { + if (static_cast<uint32_t>(offset) < static_cast<uint32_t>(length())) { const char16_t *array = getArrayStart(); U16_SET_CP_START(array, 0, offset); return offset; @@ -855,7 +894,7 @@ UnicodeString::getChar32Start(int32_t offset) const { int32_t UnicodeString::getChar32Limit(int32_t offset) const { int32_t len = length(); - if((uint32_t)offset < (uint32_t)len) { + if (static_cast<uint32_t>(offset) < static_cast<uint32_t>(len)) { const char16_t *array = getArrayStart(); U16_SET_CP_LIMIT(array, 0, offset, len); return offset; @@ -989,7 +1028,7 @@ UnicodeString::extract(int32_t start, int32_t len, if (/*dstSize < 0 || */(dstSize > 0 && target == nullptr)) { return 0; } - return toUTF8(start, len, target, dstSize <= 0x7fffffff ? (int32_t)dstSize : 0x7fffffff); + return toUTF8(start, len, target, dstSize <= 0x7fffffff ? static_cast<int32_t>(dstSize) : 0x7fffffff); } // else see unistr_cnv.cpp @@ -1013,7 +1052,7 @@ UnicodeString::toUTF8(ByteSink &sink) const { int32_t length16 = length(); if(length16 != 0) { char stackBuffer[1024]; - int32_t capacity = (int32_t)sizeof(stackBuffer); + int32_t capacity = static_cast<int32_t>(sizeof(stackBuffer)); UBool utf8IsOwned = false; char *utf8 = sink.GetAppendBuffer(length16 < capacity ? length16 : capacity, 3*length16, @@ -1027,7 +1066,7 @@ UnicodeString::toUTF8(ByteSink &sink) const { nullptr, // Don't care about number of substitutions. &errorCode); if(errorCode == U_BUFFER_OVERFLOW_ERROR) { - utf8 = (char *)uprv_malloc(length8); + utf8 = static_cast<char*>(uprv_malloc(length8)); if(utf8 != nullptr) { utf8IsOwned = true; errorCode = U_ZERO_ERROR; @@ -1089,7 +1128,7 @@ UnicodeString::indexOf(const char16_t *srcChars, if(match == nullptr) { return -1; } else { - return (int32_t)(match - array); + return static_cast<int32_t>(match - array); } } @@ -1107,7 +1146,7 @@ UnicodeString::doIndexOf(char16_t c, if(match == nullptr) { return -1; } else { - return (int32_t)(match - array); + return static_cast<int32_t>(match - array); } } @@ -1124,7 +1163,7 @@ UnicodeString::doIndexOf(UChar32 c, if(match == nullptr) { return -1; } else { - return (int32_t)(match - array); + return static_cast<int32_t>(match - array); } } @@ -1153,7 +1192,7 @@ UnicodeString::lastIndexOf(const char16_t *srcChars, if(match == nullptr) { return -1; } else { - return (int32_t)(match - array); + return static_cast<int32_t>(match - array); } } @@ -1175,7 +1214,7 @@ UnicodeString::doLastIndexOf(char16_t c, if(match == nullptr) { return -1; } else { - return (int32_t)(match - array); + return static_cast<int32_t>(match - array); } } @@ -1192,7 +1231,7 @@ UnicodeString::doLastIndexOf(UChar32 c, if(match == nullptr) { return -1; } else { - return (int32_t)(match - array); + return static_cast<int32_t>(match - array); } } @@ -1329,7 +1368,7 @@ UnicodeString::setTo(UBool isTerminated, textLength = u_strlen(text); } fUnion.fFields.fLengthAndFlags = kReadonlyAlias; - setArray((char16_t *)text, textLength, isTerminated ? textLength + 1 : textLength); + setArray(const_cast<char16_t*>(text), textLength, isTerminated ? textLength + 1 : textLength); return *this; } @@ -1359,7 +1398,7 @@ UnicodeString::setTo(char16_t *buffer, while(p != limit && *p != 0) { ++p; } - buffLength = (int32_t)(p - buffer); + buffLength = static_cast<int32_t>(p - buffer); } releaseArray(); @@ -1574,6 +1613,18 @@ UnicodeString::doReplace(int32_t start, return *this; } +UnicodeString& +UnicodeString::doReplace(int32_t start, int32_t length, std::u16string_view src) { + if (!isWritable()) { + return *this; + } + if (src.length() > INT32_MAX) { + setToBogus(); + return *this; + } + return doReplace(start, length, src.data(), 0, static_cast<int32_t>(src.length())); +} + // Versions of doReplace() only for append() variants. // doReplace() and doAppend() optimize for different cases. @@ -1662,6 +1713,18 @@ UnicodeString::doAppend(const char16_t *srcChars, int32_t srcStart, int32_t srcL return *this; } +UnicodeString& +UnicodeString::doAppend(std::u16string_view src) { + if (!isWritable() || src.empty()) { + return *this; + } + if (src.length() > INT32_MAX) { + setToBogus(); + return *this; + } + return doAppend(src.data(), 0, static_cast<int32_t>(src.length())); +} + /** * Replaceable API */ @@ -1680,7 +1743,7 @@ UnicodeString::copy(int32_t start, int32_t limit, int32_t dest) { if (limit <= start) { return; // Nothing to do; avoid bogus malloc call } - char16_t* text = (char16_t*) uprv_malloc( sizeof(char16_t) * (limit - start) ); + char16_t* text = static_cast<char16_t*>(uprv_malloc(sizeof(char16_t) * (limit - start))); // Check to make sure text is not null. if (text != nullptr) { extractBetween(start, limit, text, 0); @@ -1725,13 +1788,13 @@ UnicodeString::doReverse(int32_t start, int32_t length) { // Before the loop we know left<right because length>=2. do { - hasSupplementary |= (UBool)U16_IS_LEAD(swap = *left); - hasSupplementary |= (UBool)U16_IS_LEAD(*left++ = *right); + hasSupplementary |= static_cast<UBool>(U16_IS_LEAD(swap = *left)); + hasSupplementary |= static_cast<UBool>(U16_IS_LEAD(*left++ = *right)); *right-- = swap; } while(left < right); // Make sure to test the middle code unit of an odd-length string. // Redundant if the length is even. - hasSupplementary |= (UBool)U16_IS_LEAD(*left); + hasSupplementary |= static_cast<UBool>(U16_IS_LEAD(*left)); /* if there are supplementary code points in the reversed range, then re-swap their surrogates */ if(hasSupplementary) { @@ -1834,7 +1897,7 @@ UnicodeString::releaseBuffer(int32_t newLength) { while(p<limit && *p!=0) { ++p; } - newLength=(int32_t)(p-array); + newLength = static_cast<int32_t>(p - array); } else if(newLength>capacity) { newLength=capacity; } @@ -1928,7 +1991,7 @@ UnicodeString::cloneArrayIfNeeded(int32_t newCapacity, // release the old array if(flags & kRefCounted) { // the array is refCounted; decrement and release if 0 - u_atomic_int32_t *pRefCount = ((u_atomic_int32_t *)oldArray - 1); + u_atomic_int32_t* pRefCount = reinterpret_cast<u_atomic_int32_t*>(oldArray) - 1; if(umtx_atomic_dec(pRefCount) == 0) { if (pBufferToDelete == nullptr) { // Note: cast to (void *) is needed with MSVC, where u_atomic_int32_t @@ -1937,7 +2000,7 @@ UnicodeString::cloneArrayIfNeeded(int32_t newCapacity, uprv_free((void *)pRefCount); } else { // the caller requested to delete it himself - *pBufferToDelete = (int32_t *)pRefCount; + *pBufferToDelete = reinterpret_cast<int32_t*>(pRefCount); } } } diff --git a/thirdparty/icu4c/common/unistr_case.cpp b/thirdparty/icu4c/common/unistr_case.cpp index b04d957bdc..40ea6b2f4d 100644 --- a/thirdparty/icu4c/common/unistr_case.cpp +++ b/thirdparty/icu4c/common/unistr_case.cpp @@ -72,7 +72,7 @@ UnicodeString::doCaseCompare(int32_t start, int32_t result=u_strcmpFold(chars, length, srcChars, srcLength, options|U_COMPARE_IGNORE_CASE, &errorCode); if(result!=0) { - return (int8_t)(result >> 24 | 1); + return static_cast<int8_t>(result >> 24 | 1); } } else { // get the srcLength if necessary @@ -80,7 +80,7 @@ UnicodeString::doCaseCompare(int32_t start, srcLength = u_strlen(srcChars + srcStart); } if(length != srcLength) { - return (int8_t)((length - srcLength) >> 24 | 1); + return static_cast<int8_t>((length - srcLength) >> 24 | 1); } } return 0; diff --git a/thirdparty/icu4c/common/unistr_cnv.cpp b/thirdparty/icu4c/common/unistr_cnv.cpp index e300a79ce5..bf52dd5118 100644 --- a/thirdparty/icu4c/common/unistr_cnv.cpp +++ b/thirdparty/icu4c/common/unistr_cnv.cpp @@ -63,7 +63,7 @@ UnicodeString::UnicodeString(const char *codepageData, const char *codepage) { fUnion.fFields.fLengthAndFlags = kShortString; if (codepageData != nullptr) { - doCodepageCreate(codepageData, (int32_t)uprv_strlen(codepageData), codepage); + doCodepageCreate(codepageData, static_cast<int32_t>(uprv_strlen(codepageData)), codepage); } } @@ -89,7 +89,7 @@ UnicodeString::UnicodeString(const char *src, int32_t srcLength, } else { // get input length if(srcLength==-1) { - srcLength=(int32_t)uprv_strlen(src); + srcLength = static_cast<int32_t>(uprv_strlen(src)); } if(srcLength>0) { if (cnv != nullptr) { @@ -151,13 +151,13 @@ UnicodeString::extract(int32_t start, int32_t capacity; if(dstSize < 0x7fffffff) { // Assume that the capacity is real and a limit pointer won't wrap around. - capacity = (int32_t)dstSize; + capacity = static_cast<int32_t>(dstSize); } else { // Pin the capacity so that a limit pointer does not wrap around. - char *targetLimit = (char *)U_MAX_PTR(target); + char* targetLimit = static_cast<char*>(U_MAX_PTR(target)); // U_MAX_PTR(target) returns a targetLimit that is at most 0x7fffffff // greater than target and does not wrap around the top of the address space. - capacity = (int32_t)(targetLimit - target); + capacity = static_cast<int32_t>(targetLimit - target); } // create the converter @@ -267,7 +267,7 @@ UnicodeString::doExtract(int32_t start, int32_t length, destLimit=dest=nullptr; } else if(destCapacity==-1) { // Pin the limit to U_MAX_PTR if the "magic" destCapacity is used. - destLimit=(char*)U_MAX_PTR(dest); + destLimit = static_cast<char*>(U_MAX_PTR(dest)); // for NUL-termination, translate into highest int32_t destCapacity=0x7fffffff; } else { @@ -276,7 +276,7 @@ UnicodeString::doExtract(int32_t start, int32_t length, // perform the conversion ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, &errorCode); - length=(int32_t)(dest-originalDest); + length = static_cast<int32_t>(dest - originalDest); // if an overflow occurs, then get the preflighting length if(errorCode==U_BUFFER_OVERFLOW_ERROR) { @@ -287,7 +287,7 @@ UnicodeString::doExtract(int32_t start, int32_t length, dest=buffer; errorCode=U_ZERO_ERROR; ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, &errorCode); - length+=(int32_t)(dest-buffer); + length += static_cast<int32_t>(dest - buffer); } while(errorCode==U_BUFFER_OVERFLOW_ERROR); } @@ -304,7 +304,7 @@ UnicodeString::doCodepageCreate(const char *codepageData, return; } if(dataLength == -1) { - dataLength = (int32_t)uprv_strlen(codepageData); + dataLength = static_cast<int32_t>(uprv_strlen(codepageData)); } UErrorCode status = U_ZERO_ERROR; @@ -393,7 +393,7 @@ UnicodeString::doCodepageCreate(const char *codepageData, &mySource, mySourceEnd, nullptr, true, &status); // update the conversion parameters - setLength((int32_t)(myTarget - array)); + setLength(static_cast<int32_t>(myTarget - array)); // allocate more space and copy data, if needed if(status == U_BUFFER_OVERFLOW_ERROR) { @@ -405,7 +405,7 @@ UnicodeString::doCodepageCreate(const char *codepageData, // estimate the new size needed, larger than before // try 2 char16_t's per remaining source byte - arraySize = (int32_t)(length() + 2 * (mySourceEnd - mySource)); + arraySize = static_cast<int32_t>(length() + 2 * (mySourceEnd - mySource)); } else { break; } diff --git a/thirdparty/icu4c/common/unormcmp.cpp b/thirdparty/icu4c/common/unormcmp.cpp index 028b28643c..fa8b85cea0 100644 --- a/thirdparty/icu4c/common/unormcmp.cpp +++ b/thirdparty/icu4c/common/unormcmp.cpp @@ -313,7 +313,7 @@ unorm_cmpEquivFold(const char16_t *s1, int32_t length1, */ if( level1==0 && (options&U_COMPARE_IGNORE_CASE) && - (length=ucase_toFullFolding((UChar32)cp1, &p, options))>=0 + (length = ucase_toFullFolding(cp1, &p, options)) >= 0 ) { /* cp1 case-folds to the code point "length" or to p[length] */ if(U_IS_SURROGATE(c1)) { @@ -358,7 +358,7 @@ unorm_cmpEquivFold(const char16_t *s1, int32_t length1, } if( level2==0 && (options&U_COMPARE_IGNORE_CASE) && - (length=ucase_toFullFolding((UChar32)cp2, &p, options))>=0 + (length = ucase_toFullFolding(cp2, &p, options)) >= 0 ) { /* cp2 case-folds to the code point "length" or to p[length] */ if(U_IS_SURROGATE(c2)) { @@ -403,7 +403,7 @@ unorm_cmpEquivFold(const char16_t *s1, int32_t length1, } if( level1<2 && (options&_COMPARE_EQUIV) && - nullptr != (p = nfcImpl->getDecomposition((UChar32)cp1, decomp1, length)) + nullptr != (p = nfcImpl->getDecomposition(cp1, decomp1, length)) ) { /* cp1 decomposes into p[length] */ if(U_IS_SURROGATE(c1)) { @@ -444,7 +444,7 @@ unorm_cmpEquivFold(const char16_t *s1, int32_t length1, } if( level2<2 && (options&_COMPARE_EQUIV) && - nullptr != (p = nfcImpl->getDecomposition((UChar32)cp2, decomp2, length)) + nullptr != (p = nfcImpl->getDecomposition(cp2, decomp2, length)) ) { /* cp2 decomposes into p[length] */ if(U_IS_SURROGATE(c2)) { diff --git a/thirdparty/icu4c/common/uprops.cpp b/thirdparty/icu4c/common/uprops.cpp index c87eeff381..817a1fac0c 100644 --- a/thirdparty/icu4c/common/uprops.cpp +++ b/thirdparty/icu4c/common/uprops.cpp @@ -100,8 +100,8 @@ void U_CALLCONV ulayout_load(UErrorCode &errorCode) { ulayout_isAcceptable, nullptr, &errorCode); if (U_FAILURE(errorCode)) { return; } - const uint8_t *inBytes = (const uint8_t *)udata_getMemory(gLayoutMemory); - const int32_t *inIndexes = (const int32_t *)inBytes; + const uint8_t* inBytes = static_cast<const uint8_t*>(udata_getMemory(gLayoutMemory)); + const int32_t* inIndexes = reinterpret_cast<const int32_t*>(inBytes); int32_t indexesLength = inIndexes[ULAYOUT_IX_INDEXES_LENGTH]; if (indexesLength < 12) { errorCode = U_INVALID_FORMAT_ERROR; // Not enough indexes. @@ -171,7 +171,7 @@ static UBool defaultContains(const BinaryProperty &prop, UChar32 c, UProperty /* } static UBool caseBinaryPropertyContains(const BinaryProperty &/*prop*/, UChar32 c, UProperty which) { - return static_cast<UBool>(ucase_hasBinaryProperty(c, which)); + return ucase_hasBinaryProperty(c, which); } static UBool isBidiControl(const BinaryProperty &/*prop*/, UChar32 c, UProperty /*which*/) { @@ -208,7 +208,7 @@ static UBool isNormInert(const BinaryProperty &, UChar32, UProperty) { static UBool isNormInert(const BinaryProperty &/*prop*/, UChar32 c, UProperty which) { UErrorCode errorCode=U_ZERO_ERROR; const Normalizer2 *norm2=Normalizer2Factory::getInstance( - (UNormalizationMode)(which-UCHAR_NFD_INERT+UNORM_NFD), errorCode); + static_cast<UNormalizationMode>(which - UCHAR_NFD_INERT + UNORM_NFD), errorCode); return U_SUCCESS(errorCode) && norm2->isInert(c); } #endif @@ -242,7 +242,7 @@ static UBool changesWhenCasefolded(const BinaryProperty &/*prop*/, UChar32 c, UP if(c>=0) { /* single code point */ const char16_t *resultString; - return (UBool)(ucase_toFullFolding(c, &resultString, U_FOLD_CASE_DEFAULT)>=0); + return ucase_toFullFolding(c, &resultString, U_FOLD_CASE_DEFAULT) >= 0; } else { /* guess some large but stack-friendly capacity */ char16_t dest[2*UCASE_MAX_STRING_LENGTH]; @@ -250,9 +250,9 @@ static UBool changesWhenCasefolded(const BinaryProperty &/*prop*/, UChar32 c, UP destLength=u_strFoldCase(dest, UPRV_LENGTHOF(dest), nfd.getBuffer(), nfd.length(), U_FOLD_CASE_DEFAULT, &errorCode); - return (UBool)(U_SUCCESS(errorCode) && + return U_SUCCESS(errorCode) && 0!=u_strCompare(nfd.getBuffer(), nfd.length(), - dest, destLength, false)); + dest, destLength, false); } } #endif @@ -359,6 +359,19 @@ static constexpr UChar32 ID_COMPAT_MATH_START[] = { 0x1D7C3 }; +/** Ranges (start/limit pairs) of Modifier_Combining_mark (only), from UCD PropList.txt. */ +static constexpr UChar32 MODIFIER_COMBINING_MARK[] = { + 0x0654, 0x0655 + 1, + 0x0658, 0x0658 + 1, // U+0658 + 0x06DC, 0x06DC + 1, // U+06DC + 0x06E3, 0x06E3 + 1, // U+06E3 + 0x06E7, 0x06E8 + 1, + 0x08CA, 0x08CB + 1, + 0x08CD, 0x08CF + 1, + 0x08D3, 0x08D3 + 1, // U+08D3 + 0x08F3, 0x08F3 + 1 // U+08F3 +}; + static UBool isIDCompatMathStart(const BinaryProperty &/*prop*/, UChar32 c, UProperty /*which*/) { if (c < ID_COMPAT_MATH_START[0]) { return false; } // fastpath for common scripts for (UChar32 startChar : ID_COMPAT_MATH_START) { @@ -375,6 +388,14 @@ static UBool isIDCompatMathContinue(const BinaryProperty &prop, UChar32 c, UProp return isIDCompatMathStart(prop, c, UCHAR_ID_COMPAT_MATH_START); } +static UBool isModifierCombiningMark(const BinaryProperty &/*prop*/, UChar32 c, UProperty /*which*/) { + for (int32_t i = 0; i < UPRV_LENGTHOF(MODIFIER_COMBINING_MARK); i += 2) { + if (c < MODIFIER_COMBINING_MARK[i]) { return false; } // below range start + if (c < MODIFIER_COMBINING_MARK[i + 1]) { return true; } // below range limit + } + return false; +} + static const BinaryProperty binProps[UCHAR_BINARY_LIMIT]={ /* * column and mask values for binary properties from u_getUnicodeProperties(). @@ -459,6 +480,7 @@ static const BinaryProperty binProps[UCHAR_BINARY_LIMIT]={ { UPROPS_SRC_IDSU, 0, isIDSUnaryOperator }, // UCHAR_IDS_UNARY_OPERATOR { UPROPS_SRC_ID_COMPAT_MATH, 0, isIDCompatMathStart }, // UCHAR_ID_COMPAT_MATH_START { UPROPS_SRC_ID_COMPAT_MATH, 0, isIDCompatMathContinue }, // UCHAR_ID_COMPAT_MATH_CONTINUE + { UPROPS_SRC_MCM, 0 , isModifierCombiningMark }, // UCHAR_MODIFIER_COMBINING_MARK }; U_CAPI UBool U_EXPORT2 @@ -521,7 +543,7 @@ struct IntProperty { static int32_t defaultGetValue(const IntProperty &prop, UChar32 c, UProperty /*which*/) { /* systematic, directly stored properties */ - return (int32_t)(u_getUnicodeProperties(c, prop.column)&prop.mask)>>prop.shift; + return static_cast<int32_t>(u_getUnicodeProperties(c, prop.column) & prop.mask) >> prop.shift; } static int32_t defaultGetMaxValue(const IntProperty &prop, UProperty /*which*/) { @@ -533,17 +555,25 @@ static int32_t getMaxValueFromShift(const IntProperty &prop, UProperty /*which*/ } static int32_t getBiDiClass(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { - return (int32_t)u_charDirection(c); + return static_cast<int32_t>(u_charDirection(c)); } static int32_t getBiDiPairedBracketType(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { - return (int32_t)ubidi_getPairedBracketType(c); + return static_cast<int32_t>(ubidi_getPairedBracketType(c)); } static int32_t biDiGetMaxValue(const IntProperty &/*prop*/, UProperty which) { return ubidi_getMaxValue(which); } +static int32_t getBlock(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { + return static_cast<int32_t>(ublock_getCode(c)); +} + +static int32_t blockGetMaxValue(const IntProperty &/*prop*/, UProperty /*which*/) { + return uprv_getMaxValues(UPROPS_MAX_VALUES_OTHER_INDEX) & UPROPS_MAX_BLOCK; +} + #if UCONFIG_NO_NORMALIZATION static int32_t getCombiningClass(const IntProperty &, UChar32, UProperty) { return 0; @@ -555,7 +585,7 @@ static int32_t getCombiningClass(const IntProperty &/*prop*/, UChar32 c, UProper #endif static int32_t getGeneralCategory(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { - return (int32_t)u_charType(c); + return static_cast<int32_t>(u_charType(c)); } static int32_t getJoiningGroup(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { @@ -567,23 +597,26 @@ static int32_t getJoiningType(const IntProperty &/*prop*/, UChar32 c, UProperty } static int32_t getNumericType(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { - int32_t ntv=(int32_t)GET_NUMERIC_TYPE_VALUE(u_getMainProperties(c)); + int32_t ntv = static_cast<int32_t>(GET_NUMERIC_TYPE_VALUE(u_getMainProperties(c))); return UPROPS_NTV_GET_TYPE(ntv); } static int32_t getScript(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { UErrorCode errorCode=U_ZERO_ERROR; - return (int32_t)uscript_getScript(c, &errorCode); + return static_cast<int32_t>(uscript_getScript(c, &errorCode)); } static int32_t scriptGetMaxValue(const IntProperty &/*prop*/, UProperty /*which*/) { - uint32_t scriptX=uprv_getMaxValues(0)&UPROPS_SCRIPT_X_MASK; - return uprops_mergeScriptCodeOrIndex(scriptX); + return uprv_getMaxValues(0)&UPROPS_MAX_SCRIPT; } /* * Map some of the Grapheme Cluster Break values to Hangul Syllable Types. - * Hangul_Syllable_Type is fully redundant with a subset of Grapheme_Cluster_Break. + * Hangul_Syllable_Type used to be fully redundant with a subset of Grapheme_Cluster_Break. + * + * Starting with Unicode 16, this is no longer true for HST=V vs. GCB=V in some cases: + * Some Kirat Rai vowels are given GCB=V for proper grapheme clustering, but + * they are of course not related to Hangul syllables. */ static const UHangulSyllableType gcbToHst[]={ U_HST_NOT_APPLICABLE, /* U_GCB_OTHER */ @@ -603,8 +636,13 @@ static const UHangulSyllableType gcbToHst[]={ }; static int32_t getHangulSyllableType(const IntProperty &/*prop*/, UChar32 c, UProperty /*which*/) { + // Ignore supplementary code points: They all have HST=NA. + // This is a simple way to handle the GCB!=hst cases since Unicode 16 (Kirat Rai vowels). + if(c>0xffff) { + return U_HST_NOT_APPLICABLE; + } /* see comments on gcbToHst[] above */ - int32_t gcb=(int32_t)(u_getUnicodeProperties(c, 2)&UPROPS_GCB_MASK)>>UPROPS_GCB_SHIFT; + int32_t gcb = static_cast<int32_t>(u_getUnicodeProperties(c, 2) & UPROPS_GCB_MASK) >> UPROPS_GCB_SHIFT; if(gcb<UPRV_LENGTHOF(gcbToHst)) { return gcbToHst[gcb]; } else { @@ -618,7 +656,7 @@ static int32_t getNormQuickCheck(const IntProperty &, UChar32, UProperty) { } #else static int32_t getNormQuickCheck(const IntProperty &/*prop*/, UChar32 c, UProperty which) { - return (int32_t)unorm_getQuickCheck(c, (UNormalizationMode)(which-UCHAR_NFD_QUICK_CHECK+UNORM_NFD)); + return static_cast<int32_t>(unorm_getQuickCheck(c, static_cast<UNormalizationMode>(which - UCHAR_NFD_QUICK_CHECK + UNORM_NFD))); } #endif @@ -683,25 +721,25 @@ static const IntProperty intProps[UCHAR_INT_LIMIT-UCHAR_INT_START]={ * For them, column is the UPropertySource value. */ { UPROPS_SRC_BIDI, 0, 0, getBiDiClass, biDiGetMaxValue }, - { 0, UPROPS_BLOCK_MASK, UPROPS_BLOCK_SHIFT, defaultGetValue, defaultGetMaxValue }, + { UPROPS_SRC_BLOCK, 0, 0, getBlock, blockGetMaxValue }, { UPROPS_SRC_NFC, 0, 0xff, getCombiningClass, getMaxValueFromShift }, { 2, UPROPS_DT_MASK, 0, defaultGetValue, defaultGetMaxValue }, { 0, UPROPS_EA_MASK, UPROPS_EA_SHIFT, defaultGetValue, defaultGetMaxValue }, - { UPROPS_SRC_CHAR, 0, (int32_t)U_CHAR_CATEGORY_COUNT-1,getGeneralCategory, getMaxValueFromShift }, + { UPROPS_SRC_CHAR, 0, static_cast<int32_t>(U_CHAR_CATEGORY_COUNT) - 1, getGeneralCategory, getMaxValueFromShift }, { UPROPS_SRC_BIDI, 0, 0, getJoiningGroup, biDiGetMaxValue }, { UPROPS_SRC_BIDI, 0, 0, getJoiningType, biDiGetMaxValue }, { 2, UPROPS_LB_MASK, UPROPS_LB_SHIFT, defaultGetValue, defaultGetMaxValue }, - { UPROPS_SRC_CHAR, 0, (int32_t)U_NT_COUNT-1, getNumericType, getMaxValueFromShift }, + { UPROPS_SRC_CHAR, 0, static_cast<int32_t>(U_NT_COUNT) - 1, getNumericType, getMaxValueFromShift }, { UPROPS_SRC_PROPSVEC, 0, 0, getScript, scriptGetMaxValue }, - { UPROPS_SRC_PROPSVEC, 0, (int32_t)U_HST_COUNT-1, getHangulSyllableType, getMaxValueFromShift }, + { UPROPS_SRC_PROPSVEC, 0, static_cast<int32_t>(U_HST_COUNT) - 1, getHangulSyllableType, getMaxValueFromShift }, // UCHAR_NFD_QUICK_CHECK: max=1=YES -- never "maybe", only "no" or "yes" - { UPROPS_SRC_NFC, 0, (int32_t)UNORM_YES, getNormQuickCheck, getMaxValueFromShift }, + { UPROPS_SRC_NFC, 0, static_cast<int32_t>(UNORM_YES), getNormQuickCheck, getMaxValueFromShift }, // UCHAR_NFKD_QUICK_CHECK: max=1=YES -- never "maybe", only "no" or "yes" - { UPROPS_SRC_NFKC, 0, (int32_t)UNORM_YES, getNormQuickCheck, getMaxValueFromShift }, + { UPROPS_SRC_NFKC, 0, static_cast<int32_t>(UNORM_YES), getNormQuickCheck, getMaxValueFromShift }, // UCHAR_NFC_QUICK_CHECK: max=2=MAYBE - { UPROPS_SRC_NFC, 0, (int32_t)UNORM_MAYBE, getNormQuickCheck, getMaxValueFromShift }, + { UPROPS_SRC_NFC, 0, static_cast<int32_t>(UNORM_MAYBE), getNormQuickCheck, getMaxValueFromShift }, // UCHAR_NFKC_QUICK_CHECK: max=2=MAYBE - { UPROPS_SRC_NFKC, 0, (int32_t)UNORM_MAYBE, getNormQuickCheck, getMaxValueFromShift }, + { UPROPS_SRC_NFKC, 0, static_cast<int32_t>(UNORM_MAYBE), getNormQuickCheck, getMaxValueFromShift }, { UPROPS_SRC_NFC, 0, 0xff, getLeadCombiningClass, getMaxValueFromShift }, { UPROPS_SRC_NFC, 0, 0xff, getTrailCombiningClass, getMaxValueFromShift }, { 2, UPROPS_GCB_MASK, UPROPS_GCB_SHIFT, defaultGetValue, defaultGetMaxValue }, @@ -711,7 +749,8 @@ static const IntProperty intProps[UCHAR_INT_LIMIT-UCHAR_INT_START]={ { UPROPS_SRC_INPC, 0, 0, getInPC, layoutGetMaxValue }, { UPROPS_SRC_INSC, 0, 0, getInSC, layoutGetMaxValue }, { UPROPS_SRC_VO, 0, 0, getVo, layoutGetMaxValue }, - { UPROPS_SRC_PROPSVEC, 0, (int32_t)U_ID_STATUS_ALLOWED, getIDStatusValue, getMaxValueFromShift }, + { UPROPS_SRC_PROPSVEC, 0, static_cast<int32_t>(U_ID_STATUS_ALLOWED), getIDStatusValue, getMaxValueFromShift }, + { 0, UPROPS_INCB_MASK, UPROPS_INCB_SHIFT,defaultGetValue, defaultGetMaxValue }, }; U_CAPI int32_t U_EXPORT2 @@ -829,6 +868,13 @@ uprops_addPropertyStarts(UPropertySource src, const USetAdder *sa, UErrorCode *p } return; } + if (src == UPROPS_SRC_MCM) { + // range limits + for (UChar32 c : MODIFIER_COMBINING_MARK) { + sa->add(sa->set, c); + } + return; + } if (!ulayout_ensureData(*pErrorCode)) { return; } const UCPTrie *trie; switch (src) { diff --git a/thirdparty/icu4c/common/uprops.h b/thirdparty/icu4c/common/uprops.h index 93120017f0..022f64474a 100644 --- a/thirdparty/icu4c/common/uprops.h +++ b/thirdparty/icu4c/common/uprops.h @@ -39,16 +39,18 @@ enum { UPROPS_SCRIPT_EXTENSIONS_INDEX, - UPROPS_RESERVED_INDEX_7, + UPROPS_BLOCK_TRIE_INDEX, UPROPS_RESERVED_INDEX_8, - /* size of the data file (number of 32-bit units after the header) */ + /** size of the data file (number of 32-bit units after the header) */ UPROPS_DATA_TOP_INDEX, - /* maximum values for code values in vector word 0 */ + /** maximum values for code values in vector word 0 */ UPROPS_MAX_VALUES_INDEX=10, - /* maximum values for code values in vector word 2 */ + /** maximum values for code values in vector word 2 */ UPROPS_MAX_VALUES_2_INDEX, + /** maximum values for other code values */ + UPROPS_MAX_VALUES_OTHER_INDEX, UPROPS_INDEX_COUNT=16 }; @@ -117,62 +119,57 @@ enum { /* number of properties vector words */ #define UPROPS_VECTOR_WORDS 3 -/* - * Properties in vector word 0 - * Bits - * 31..24 DerivedAge version major/minor one nibble each - * 23..22 3..1: Bits 21..20 & 7..0 = Script_Extensions index - * 3: Script value from Script_Extensions - * 2: Script=Inherited - * 1: Script=Common - * 0: Script=bits 21..20 & 7..0 - * 21..20 Bits 9..8 of the UScriptCode, or index to Script_Extensions - * 19..17 East Asian Width - * 16.. 8 UBlockCode - * 7.. 0 UScriptCode, or index to Script_Extensions - */ - -/* derived age: one nibble each for major and minor version numbers */ -#define UPROPS_AGE_MASK 0xff000000 -#define UPROPS_AGE_SHIFT 24 - -/* Script_Extensions: mask includes Script */ -#define UPROPS_SCRIPT_X_MASK 0x00f000ff -#define UPROPS_SCRIPT_X_SHIFT 22 - -// The UScriptCode or Script_Extensions index is split across two bit fields. -// (Starting with Unicode 13/ICU 66/2019 due to more varied Script_Extensions.) -// Shift the high bits right by 12 to assemble the full value. -#define UPROPS_SCRIPT_HIGH_MASK 0x00300000 -#define UPROPS_SCRIPT_HIGH_SHIFT 12 -#define UPROPS_MAX_SCRIPT 0x3ff - -#define UPROPS_EA_MASK 0x000e0000 -#define UPROPS_EA_SHIFT 17 - -#define UPROPS_BLOCK_MASK 0x0001ff00 -#define UPROPS_BLOCK_SHIFT 8 - -#define UPROPS_SCRIPT_LOW_MASK 0x000000ff - -/* UPROPS_SCRIPT_X_WITH_COMMON must be the lowest value that involves Script_Extensions. */ -#define UPROPS_SCRIPT_X_WITH_COMMON 0x400000 -#define UPROPS_SCRIPT_X_WITH_INHERITED 0x800000 -#define UPROPS_SCRIPT_X_WITH_OTHER 0xc00000 - #ifdef __cplusplus namespace { -inline uint32_t uprops_mergeScriptCodeOrIndex(uint32_t scriptX) { - return - ((scriptX & UPROPS_SCRIPT_HIGH_MASK) >> UPROPS_SCRIPT_HIGH_SHIFT) | - (scriptX & UPROPS_SCRIPT_LOW_MASK); -} - -} // namespace - -#endif // __cplusplus +// Properties in vector word 0 +// Bits +// 31..26 Age major version (major=0..63) +// 25..24 Age minor version (minor=0..3) +// 23..17 reserved +// 16..15 Indic Conjunct Break +// 14..12 East Asian Width +// 11..10 3..1: Bits 9..0 = Script_Extensions index +// 3: Script value from Script_Extensions +// 2: Script=Inherited +// 1: Script=Common +// 0: Script=bits 9..0 +// 9.. 0 UScriptCode, or index to Script_Extensions + +// *Note*: If we need more than the available bits for new properties, +// then we could move the Age property out of the properties vectors. +// For example, we could store the Age property in its own trie. +// In a small, 8-bit-value-width CodePointTrie, it would be larger than +// the amount of data that we would save in the properties vectors and their trie, +// but the size increase would be a small percentage of the total uprops.icu size. +// It would certainly be a much smaller increase than widening the properties vectors. +// The savings in the properties vectors+trie from pulling out the Age property +// are partly from mediocre correlation between Age and other property values. +// (Adding new characters to existing scripts tends to split property vectors where +// new characters are similar to old ones.) +// See https://github.com/unicode-org/icu/pull/3025 for details. + +inline constexpr uint32_t UPROPS_AGE_MASK = 0xff000000; +inline constexpr int32_t UPROPS_AGE_SHIFT = 24; + +inline constexpr uint8_t UPROPS_AGE_MAJOR_MAX = 63; +inline constexpr uint8_t UPROPS_AGE_MINOR_MAX = 3; + +inline constexpr uint32_t UPROPS_EA_MASK = 0x00007000; +inline constexpr int32_t UPROPS_EA_SHIFT = 12; + +inline constexpr uint32_t UPROPS_INCB_MASK = 0x00018000; +inline constexpr int32_t UPROPS_INCB_SHIFT = 15; + +/** Script_Extensions: mask includes Script */ +inline constexpr uint32_t UPROPS_SCRIPT_X_MASK = 0x00000fff; + +// UPROPS_SCRIPT_X_WITH_COMMON must be the lowest value that involves Script_Extensions. +inline constexpr uint32_t UPROPS_SCRIPT_X_WITH_OTHER = 0xc00; +inline constexpr uint32_t UPROPS_SCRIPT_X_WITH_INHERITED = 0x800; +inline constexpr uint32_t UPROPS_SCRIPT_X_WITH_COMMON = 0x400; +inline constexpr int32_t UPROPS_MAX_SCRIPT = 0x3ff; /* * Properties in vector word 1 @@ -234,8 +231,6 @@ enum { * 4.. 0 Decomposition Type */ -#ifdef __cplusplus - // https://www.unicode.org/reports/tr39/#Identifier_Status_and_Type // The Identifier_Type maps each code point to a *set* of one or more values. // Some can be combined with others, some can only occur alone. @@ -296,6 +291,8 @@ inline constexpr uint8_t uprops_idTypeToEncoded[] = { UPROPS_ID_TYPE_RECOMMENDED }; +} // namespace + #endif // __cplusplus #define UPROPS_LB_MASK 0x03f00000 @@ -312,6 +309,17 @@ inline constexpr uint8_t uprops_idTypeToEncoded[] = { #define UPROPS_DT_MASK 0x0000001f +#ifdef __cplusplus + +namespace { + +// Bits 9..0 in UPROPS_MAX_VALUES_OTHER_INDEX +inline constexpr uint32_t UPROPS_MAX_BLOCK = 0x3ff; + +} // namespace + +#endif // __cplusplus + /** * Gets the main properties value for a code point. * Implemented in uchar.c for uprops.cpp. @@ -385,6 +393,8 @@ enum { ZWNBSP =0xfeff }; +// TODO: Move these two functions into a different header file (new unames.h?) so that uprops.h +// need not be C-compatible any more. /** * Get the maximum length of a (regular/1.0/extended) character name. * @return 0 if no character names available. @@ -438,6 +448,8 @@ enum UPropertySource { UPROPS_SRC_EMOJI, UPROPS_SRC_IDSU, UPROPS_SRC_ID_COMPAT_MATH, + UPROPS_SRC_BLOCK, + UPROPS_SRC_MCM, /** One more than the highest UPropertySource (UPROPS_SRC_) constant. */ UPROPS_SRC_COUNT }; @@ -469,6 +481,13 @@ upropsvec_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode); U_CFUNC void U_EXPORT2 uprops_addPropertyStarts(UPropertySource src, const USetAdder *sa, UErrorCode *pErrorCode); +#ifdef __cplusplus + +U_CFUNC void U_EXPORT2 +ublock_addPropertyStarts(const USetAdder *sa, UErrorCode &errorCode); + +#endif // __cplusplus + /** * Return a set of characters for property enumeration. * For each two consecutive characters (start, limit) in the set, @@ -481,6 +500,8 @@ uprops_addPropertyStarts(UPropertySource src, const USetAdder *sa, UErrorCode *p uprv_getInclusions(const USetAdder *sa, UErrorCode *pErrorCode); */ +// TODO: Move this into a different header file (udataswp.h? new unames.h?) so that uprops.h +// need not be C-compatible any more. /** * Swap the ICU Unicode character names file. See uchar.c. * @internal diff --git a/thirdparty/icu4c/common/uresbund.cpp b/thirdparty/icu4c/common/uresbund.cpp index ea4327b314..3a09cbf3bc 100644 --- a/thirdparty/icu4c/common/uresbund.cpp +++ b/thirdparty/icu4c/common/uresbund.cpp @@ -56,7 +56,7 @@ static UMutex resbMutex; /* INTERNAL: hashes an entry */ static int32_t U_CALLCONV hashEntry(const UHashTok parm) { - UResourceDataEntry *b = (UResourceDataEntry *)parm.pointer; + UResourceDataEntry* b = static_cast<UResourceDataEntry*>(parm.pointer); UHashTok namekey, pathkey; namekey.pointer = b->fName; pathkey.pointer = b->fPath; @@ -65,15 +65,14 @@ static int32_t U_CALLCONV hashEntry(const UHashTok parm) { /* INTERNAL: compares two entries */ static UBool U_CALLCONV compareEntries(const UHashTok p1, const UHashTok p2) { - UResourceDataEntry *b1 = (UResourceDataEntry *)p1.pointer; - UResourceDataEntry *b2 = (UResourceDataEntry *)p2.pointer; + UResourceDataEntry* b1 = static_cast<UResourceDataEntry*>(p1.pointer); + UResourceDataEntry* b2 = static_cast<UResourceDataEntry*>(p2.pointer); UHashTok name1, name2, path1, path2; name1.pointer = b1->fName; name2.pointer = b2->fName; path1.pointer = b1->fPath; path2.pointer = b2->fPath; - return (UBool)(uhash_compareChars(name1, name2) && - uhash_compareChars(path1, path2)); + return uhash_compareChars(name1, name2) && uhash_compareChars(path1, path2); } @@ -403,7 +402,7 @@ static int32_t ures_flushCache() pos = UHASH_FIRST; while ((e = uhash_nextElement(cache, &pos)) != nullptr) { - resB = (UResourceDataEntry *) e->value.pointer; + resB = static_cast<UResourceDataEntry*>(e->value.pointer); /* Deletes only if reference counter == 0 * Don't worry about the children of this node. * Those will eventually get deleted too, if not already. @@ -488,15 +487,15 @@ static void initCache(UErrorCode *status) { /** INTERNAL: sets the name (locale) of the resource bundle to given name */ static void setEntryName(UResourceDataEntry *res, const char *name, UErrorCode *status) { - int32_t len = (int32_t)uprv_strlen(name); + int32_t len = static_cast<int32_t>(uprv_strlen(name)); if(res->fName != nullptr && res->fName != res->fNameBuffer) { uprv_free(res->fName); } - if (len < (int32_t)sizeof(res->fNameBuffer)) { + if (len < static_cast<int32_t>(sizeof(res->fNameBuffer))) { res->fName = res->fNameBuffer; } else { - res->fName = (char *)uprv_malloc(len+1); + res->fName = static_cast<char*>(uprv_malloc(len + 1)); } if(res->fName == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -535,18 +534,18 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE name = localeID; } - find.fName = (char *)name; - find.fPath = (char *)path; + find.fName = const_cast<char*>(name); + find.fPath = const_cast<char*>(path); /* calculate the hash value of the entry */ /*hashkey.pointer = (void *)&find;*/ /*hashValue = hashEntry(hashkey);*/ /* check to see if we already have this entry */ - r = (UResourceDataEntry *)uhash_get(cache, &find); + r = static_cast<UResourceDataEntry*>(uhash_get(cache, &find)); if(r == nullptr) { /* if the entry is not yet in the hash table, we'll try to construct a new one */ - r = (UResourceDataEntry *) uprv_malloc(sizeof(UResourceDataEntry)); + r = static_cast<UResourceDataEntry*>(uprv_malloc(sizeof(UResourceDataEntry))); if(r == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -562,7 +561,7 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE } if(path != nullptr) { - r->fPath = (char *)uprv_strdup(path); + r->fPath = uprv_strdup(path); if(r->fPath == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; uprv_free(r); @@ -589,7 +588,7 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE if (U_SUCCESS(*status)) { const int32_t *poolIndexes = r->fPool->fData.pRoot + 1; if(r->fData.pRoot[1 + URES_INDEX_POOL_CHECKSUM] == poolIndexes[URES_INDEX_POOL_CHECKSUM]) { - r->fData.poolBundleKeys = (const char *)(poolIndexes + (poolIndexes[URES_INDEX_LENGTH] & 0xff)); + r->fData.poolBundleKeys = reinterpret_cast<const char*>(poolIndexes + (poolIndexes[URES_INDEX_LENGTH] & 0xff)); r->fData.poolBundleStrings = r->fPool->fData.p16BitUnits; } else { r->fBogus = *status = U_INVALID_FORMAT_ERROR; @@ -615,7 +614,7 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE { UResourceDataEntry *oldR = nullptr; - if((oldR = (UResourceDataEntry *)uhash_get(cache, r)) == nullptr) { /* if the data is not cached */ + if ((oldR = static_cast<UResourceDataEntry*>(uhash_get(cache, r))) == nullptr) { /* if the data is not cached */ /* just insert it in the cache */ UErrorCode cacheStatus = U_ZERO_ERROR; uhash_put(cache, (void *)r, r, &cacheStatus); @@ -676,8 +675,8 @@ findFirstExisting(const char* path, char* name, const char* defaultLocale, UResO if (U_FAILURE(*status)) { return nullptr; } - *isDefault = (UBool)(uprv_strncmp(name, defaultLocale, uprv_strlen(name)) == 0); - hasRealData = (UBool)(r->fBogus == U_ZERO_ERROR); + *isDefault = static_cast<UBool>(uprv_strncmp(name, defaultLocale, uprv_strlen(name)) == 0); + hasRealData = static_cast<UBool>(r->fBogus == U_ZERO_ERROR); if(!hasRealData) { /* this entry is not real. We will discard it. */ /* However, the parent line for this entry is */ @@ -692,7 +691,7 @@ findFirstExisting(const char* path, char* name, const char* defaultLocale, UResO uprv_strcpy(name, r->fName); /* this is needed for supporting aliases */ } - *isRoot = (UBool)(uprv_strcmp(name, kRootLocaleName) == 0); + *isRoot = static_cast<UBool>(uprv_strcmp(name, kRootLocaleName) == 0); /*Fallback data stuff*/ if (!hasRealData) { @@ -1091,7 +1090,7 @@ static void ures_appendResPath(UResourceBundle *resB, const char* toAdd, int32_t resB->fResPathLen += lenToAdd; if(RES_BUFSIZE <= resB->fResPathLen+1) { if(resB->fResPath == resB->fResBuf) { - resB->fResPath = (char *)uprv_malloc((resB->fResPathLen+1)*sizeof(char)); + resB->fResPath = static_cast<char*>(uprv_malloc((resB->fResPathLen + 1) * sizeof(char))); /* Check that memory was allocated correctly. */ if (resB->fResPath == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -1099,7 +1098,7 @@ static void ures_appendResPath(UResourceBundle *resB, const char* toAdd, int32_t } uprv_strcpy(resB->fResPath, resB->fResBuf); } else { - char *temp = (char *)uprv_realloc(resB->fResPath, (resB->fResPathLen+1)*sizeof(char)); + char* temp = static_cast<char*>(uprv_realloc(resB->fResPath, (resB->fResPathLen + 1) * sizeof(char))); /* Check that memory was reallocated correctly. */ if (temp == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -1348,7 +1347,7 @@ UResourceBundle *getAliasTargetAsResourceBundle( // if the key path wasn't just a single resource ID, clear out // the bundle's key path and re-set it to be equal to keyPath. ures_freeResPath(resB); - ures_appendResPath(resB, keyPath, (int32_t)uprv_strlen(keyPath), status); + ures_appendResPath(resB, keyPath, static_cast<int32_t>(uprv_strlen(keyPath)), status); if(resB->fResPath[resB->fResPathLen-1] != RES_PATH_SEPARATOR) { ures_appendResPath(resB, RES_PATH_SEPARATOR_S, 1, status); } @@ -1407,7 +1406,7 @@ UResourceBundle *init_resb_result( validLocaleDataEntry, containerResPath, recursionDepth, resB, status); } if(resB == nullptr) { - resB = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle)); + resB = static_cast<UResourceBundle*>(uprv_malloc(sizeof(UResourceBundle))); if (resB == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -1449,7 +1448,7 @@ UResourceBundle *init_resb_result( resB, containerResPath, static_cast<int32_t>(uprv_strlen(containerResPath)), status); } if(key != nullptr) { - ures_appendResPath(resB, key, (int32_t)uprv_strlen(key), status); + ures_appendResPath(resB, key, static_cast<int32_t>(uprv_strlen(key)), status); if(resB->fResPath[resB->fResPathLen-1] != RES_PATH_SEPARATOR) { ures_appendResPath(resB, RES_PATH_SEPARATOR_S, 1, status); } @@ -1494,7 +1493,7 @@ UResourceBundle *ures_copyResb(UResourceBundle *r, const UResourceBundle *origin if(original != nullptr) { if(r == nullptr) { isStackObject = false; - r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle)); + r = static_cast<UResourceBundle*>(uprv_malloc(sizeof(UResourceBundle))); /* test for nullptr */ if (r == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -1730,7 +1729,7 @@ U_CAPI UBool U_EXPORT2 ures_hasNext(const UResourceBundle *resB) { if(resB == nullptr) { return false; } - return (UBool)(resB->fIndex < resB->fSize-1); + return resB->fIndex < resB->fSize-1; } U_CAPI const char16_t* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t* len, const char ** key, UErrorCode *status) { @@ -2064,7 +2063,7 @@ static Resource getTableItemByKeyPath(const ResourceData *pResData, Resource tab path.append(key, errorCode); if (U_FAILURE(errorCode)) { return RES_BOGUS; } char *pathPart = path.data(); /* Path from current resource to desired resource */ - UResType type = (UResType)RES_GET_TYPE(resource); /* the current resource type */ + UResType type = static_cast<UResType>(RES_GET_TYPE(resource)); /* the current resource type */ while (*pathPart && resource != RES_BOGUS && URES_IS_CONTAINER(type)) { char *nextPathPart = uprv_strchr(pathPart, RES_PATH_SEPARATOR); if (nextPathPart != nullptr) { @@ -2076,7 +2075,7 @@ static Resource getTableItemByKeyPath(const ResourceData *pResData, Resource tab int32_t t; const char *pathP = pathPart; resource = res_getTableItemByKey(pResData, resource, &t, &pathP); - type = (UResType)RES_GET_TYPE(resource); + type = static_cast<UResType>(RES_GET_TYPE(resource)); pathPart = nextPathPart; } if (*pathPart) { @@ -2737,7 +2736,7 @@ ures_openWithType(UResourceBundle *r, const char* path, const char* localeID, UBool isStackObject; if(r == nullptr) { - r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle)); + r = static_cast<UResourceBundle*>(uprv_malloc(sizeof(UResourceBundle))); if(r == nullptr) { entryClose(entry); *status = U_MEMORY_ALLOCATION_ERROR; @@ -2924,7 +2923,7 @@ typedef struct ULocalesContext { static void U_CALLCONV ures_loc_closeLocales(UEnumeration *enumerator) { - ULocalesContext *ctx = (ULocalesContext *)enumerator->context; + ULocalesContext* ctx = static_cast<ULocalesContext*>(enumerator->context); ures_close(&ctx->curr); ures_close(&ctx->installed); uprv_free(ctx); @@ -2933,7 +2932,7 @@ ures_loc_closeLocales(UEnumeration *enumerator) { static int32_t U_CALLCONV ures_loc_countLocales(UEnumeration *en, UErrorCode * /*status*/) { - ULocalesContext *ctx = (ULocalesContext *)en->context; + ULocalesContext* ctx = static_cast<ULocalesContext*>(en->context); return ures_getSize(&ctx->installed); } @@ -3074,9 +3073,12 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, UErrorCode subStatus = U_ZERO_ERROR; int32_t length = 0; if(U_FAILURE(*status)) return 0; - CharString kwVal = ulocimp_getKeywordValue(locid, keyword, subStatus); - if(kwVal == DEFAULT_TAG) { - kwVal.clear(); + CharString kwVal; + if (keyword != nullptr && *keyword != '\0') { + kwVal = ulocimp_getKeywordValue(locid, keyword, subStatus); + if (kwVal == DEFAULT_TAG) { + kwVal.clear(); + } } CharString base = ulocimp_getBaseName(locid, subStatus); #if defined(URES_TREE_DEBUG) diff --git a/thirdparty/icu4c/common/uresdata.cpp b/thirdparty/icu4c/common/uresdata.cpp index c38e75c65b..11faddf1ad 100644 --- a/thirdparty/icu4c/common/uresdata.cpp +++ b/thirdparty/icu4c/common/uresdata.cpp @@ -140,7 +140,7 @@ isAcceptable(void *context, const char * /*type*/, const char * /*name*/, const UDataInfo *pInfo) { uprv_memcpy(context, pInfo->formatVersion, 4); - return (UBool)( + return pInfo->size>=20 && pInfo->isBigEndian==U_IS_BIG_ENDIAN && pInfo->charsetFamily==U_CHARSET_FAMILY && @@ -149,7 +149,7 @@ isAcceptable(void *context, pInfo->dataFormat[1]==0x65 && pInfo->dataFormat[2]==0x73 && pInfo->dataFormat[3]==0x42 && - (1<=pInfo->formatVersion[0] && pInfo->formatVersion[0]<=3)); + (1<=pInfo->formatVersion[0] && pInfo->formatVersion[0]<=3); } /* semi-public functions ---------------------------------------------------- */ @@ -161,8 +161,8 @@ res_init(ResourceData *pResData, UResType rootType; /* get the root resource */ - pResData->pRoot=(const int32_t *)inBytes; - pResData->rootRes=(Resource)*pResData->pRoot; + pResData->pRoot = static_cast<const int32_t*>(inBytes); + pResData->rootRes = static_cast<Resource>(*pResData->pRoot); pResData->p16BitUnits=&gEmpty16; /* formatVersion 1.1 must have a root item and at least 5 indexes */ @@ -173,7 +173,7 @@ res_init(ResourceData *pResData, } /* currently, we accept only resources that have a Table as their roots */ - rootType=(UResType)RES_GET_TYPE(pResData->rootRes); + rootType = static_cast<UResType>(RES_GET_TYPE(pResData->rootRes)); if(!URES_IS_TABLE(rootType)) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); @@ -207,15 +207,15 @@ res_init(ResourceData *pResData, // In version 2, bits 31..8 were reserved and always 0. // In version 3, they contain bits 23..0 of the poolStringIndexLimit. // Bits 27..24 are in indexes[URES_INDEX_ATTRIBUTES] bits 15..12. - pResData->poolStringIndexLimit=(int32_t)((uint32_t)indexes[URES_INDEX_LENGTH]>>8); + pResData->poolStringIndexLimit = static_cast<int32_t>(static_cast<uint32_t>(indexes[URES_INDEX_LENGTH]) >> 8); } if(indexLength>URES_INDEX_ATTRIBUTES) { int32_t att=indexes[URES_INDEX_ATTRIBUTES]; - pResData->noFallback=(UBool)(att&URES_ATT_NO_FALLBACK); - pResData->isPoolBundle=(UBool)((att&URES_ATT_IS_POOL_BUNDLE)!=0); - pResData->usesPoolBundle=(UBool)((att&URES_ATT_USES_POOL_BUNDLE)!=0); + pResData->noFallback = static_cast<UBool>(att & URES_ATT_NO_FALLBACK); + pResData->isPoolBundle = static_cast<UBool>((att & URES_ATT_IS_POOL_BUNDLE) != 0); + pResData->usesPoolBundle = static_cast<UBool>((att & URES_ATT_USES_POOL_BUNDLE) != 0); pResData->poolStringIndexLimit|=(att&0xf000)<<12; // bits 15..12 -> 27..24 - pResData->poolStringIndex16Limit=(int32_t)((uint32_t)att>>16); + pResData->poolStringIndex16Limit = static_cast<int32_t>(static_cast<uint32_t>(att) >> 16); } if((pResData->isPoolBundle || pResData->usesPoolBundle) && indexLength<=URES_INDEX_POOL_CHECKSUM) { *errorCode=U_INVALID_FORMAT_ERROR; @@ -225,7 +225,7 @@ res_init(ResourceData *pResData, if( indexLength>URES_INDEX_16BIT_TOP && indexes[URES_INDEX_16BIT_TOP]>indexes[URES_INDEX_KEYS_TOP] ) { - pResData->p16BitUnits=(const uint16_t *)(pResData->pRoot+indexes[URES_INDEX_KEYS_TOP]); + pResData->p16BitUnits = reinterpret_cast<const uint16_t*>(pResData->pRoot + indexes[URES_INDEX_KEYS_TOP]); } } @@ -361,14 +361,14 @@ UBool isNoInheritanceMarker(const ResourceData *pResData, Resource res) { } else if (res == offset) { const int32_t *p32=pResData->pRoot+res; int32_t length=*p32; - const char16_t *p=(const char16_t *)p32; + const char16_t* p = reinterpret_cast<const char16_t*>(p32); return length == 3 && p[2] == 0x2205 && p[3] == 0x2205 && p[4] == 0x2205; } else if (RES_GET_TYPE(res) == URES_STRING_V2) { const char16_t *p; - if((int32_t)offset<pResData->poolStringIndexLimit) { - p=(const char16_t *)pResData->poolBundleStrings+offset; + if (static_cast<int32_t>(offset) < pResData->poolStringIndexLimit) { + p = reinterpret_cast<const char16_t*>(pResData->poolBundleStrings) + offset; } else { - p=(const char16_t *)pResData->p16BitUnits+(offset-pResData->poolStringIndexLimit); + p = reinterpret_cast<const char16_t*>(pResData->p16BitUnits) + (offset - pResData->poolStringIndexLimit); } int32_t first=*p; if (first == 0x2205) { // implicit length @@ -580,7 +580,7 @@ ResourceArray ResourceDataValue::getArray(UErrorCode &errorCode) const { switch(RES_GET_TYPE(res)) { case URES_ARRAY: if (offset!=0) { // empty if offset==0 - items32 = (const Resource *)getData().pRoot+offset; + items32 = reinterpret_cast<const Resource*>(getData().pRoot) + offset; length = *items32++; } break; @@ -608,9 +608,9 @@ ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const { switch(RES_GET_TYPE(res)) { case URES_TABLE: if (offset != 0) { // empty if offset==0 - keys16 = (const uint16_t *)(getData().pRoot+offset); + keys16 = reinterpret_cast<const uint16_t*>(getData().pRoot + offset); length = *keys16++; - items32 = (const Resource *)(keys16+length+(~length&1)); + items32 = reinterpret_cast<const Resource*>(keys16 + length + (~length & 1)); } break; case URES_TABLE16: @@ -622,7 +622,7 @@ ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const { if (offset != 0) { // empty if offset==0 keys32 = getData().pRoot+offset; length = *keys32++; - items32 = (const Resource *)keys32 + length; + items32 = reinterpret_cast<const Resource*>(keys32) + length; } break; default: @@ -1019,9 +1019,9 @@ typedef struct Row { static int32_t U_CALLCONV ures_compareRows(const void *context, const void *left, const void *right) { - const char *keyChars=(const char *)context; - return (int32_t)uprv_strcmp(keyChars+((const Row *)left)->keyIndex, - keyChars+((const Row *)right)->keyIndex); + const char* keyChars = static_cast<const char*>(context); + return static_cast<int32_t>(uprv_strcmp(keyChars + static_cast<const Row*>(left)->keyIndex, + keyChars + static_cast<const Row*>(right)->keyIndex)); } typedef struct TempTable { @@ -1040,13 +1040,10 @@ enum { /* The table item key string is not locally available. */ static const char *const gUnknownKey=""; -/* resource table key for collation binaries: "%%CollationBin" */ -static const char16_t gCollationBinKey[]={ - 0x25, 0x25, - 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x69, 0x6e, - 0 -}; +#if !UCONFIG_NO_COLLATION +// resource table key for collation binaries +static const char16_t gCollationBinKey[]=u"%%CollationBin"; +#endif /* * swap one resource item @@ -1074,17 +1071,17 @@ ures_swapResource(const UDataSwapper *ds, } /* all other types use an offset to point to their data */ - offset=(int32_t)RES_GET_OFFSET(res); + offset = static_cast<int32_t>(RES_GET_OFFSET(res)); if(offset==0) { /* special offset indicating an empty item */ return; } - if(pTempTable->resFlags[offset>>5]&((uint32_t)1<<(offset&0x1f))) { + if (pTempTable->resFlags[offset >> 5] & (static_cast<uint32_t>(1) << (offset & 0x1f))) { /* we already swapped this resource item */ return; } else { /* mark it as swapped now */ - pTempTable->resFlags[offset>>5]|=((uint32_t)1<<(offset&0x1f)); + pTempTable->resFlags[offset >> 5] |= static_cast<uint32_t>(1) << (offset & 0x1f); } p=inBundle+offset; @@ -1095,14 +1092,14 @@ ures_swapResource(const UDataSwapper *ds, /* physically same value layout as string, fall through */ U_FALLTHROUGH; case URES_STRING: - count=udata_readInt32(ds, (int32_t)*p); + count = udata_readInt32(ds, static_cast<int32_t>(*p)); /* swap length */ ds->swapArray32(ds, p, 4, q, pErrorCode); /* swap each char16_t (the terminating NUL would not change) */ ds->swapArray16(ds, p+1, 2*count, q+1, pErrorCode); break; case URES_BINARY: - count=udata_readInt32(ds, (int32_t)*p); + count = udata_readInt32(ds, static_cast<int32_t>(*p)); /* swap length */ ds->swapArray32(ds, p, 4, q, pErrorCode); /* no need to swap or copy bytes - ures_swap() copied them all */ @@ -1135,8 +1132,8 @@ ures_swapResource(const UDataSwapper *ds, if(RES_GET_TYPE(res)==URES_TABLE) { /* get table item count */ - pKey16=(const uint16_t *)p; - qKey16=(uint16_t *)q; + pKey16 = reinterpret_cast<const uint16_t*>(p); + qKey16 = reinterpret_cast<uint16_t*>(q); count=ds->readUInt16(*pKey16); pKey32=qKey32=nullptr; @@ -1147,8 +1144,8 @@ ures_swapResource(const UDataSwapper *ds, offset+=((1+count)+1)/2; } else { /* get table item count */ - pKey32=(const int32_t *)p; - qKey32=(int32_t *)q; + pKey32 = reinterpret_cast<const int32_t*>(p); + qKey32 = reinterpret_cast<int32_t*>(q); count=udata_readInt32(ds, *pKey32); pKey16=qKey16=nullptr; @@ -1172,12 +1169,12 @@ ures_swapResource(const UDataSwapper *ds, if(pKey16!=nullptr) { int32_t keyOffset=ds->readUInt16(pKey16[i]); if(keyOffset<pTempTable->localKeyLimit) { - itemKey=(const char *)outBundle+keyOffset; + itemKey = reinterpret_cast<const char*>(outBundle) + keyOffset; } } else { int32_t keyOffset=udata_readInt32(ds, pKey32[i]); if(keyOffset>=0) { - itemKey=(const char *)outBundle+keyOffset; + itemKey = reinterpret_cast<const char*>(outBundle) + keyOffset; } } item=ds->readUInt32(p[i]); @@ -1243,7 +1240,7 @@ ures_swapResource(const UDataSwapper *ds, if(pKey16!=qKey16) { rKey16=qKey16; } else { - rKey16=(uint16_t *)pTempTable->resort; + rKey16 = reinterpret_cast<uint16_t*>(pTempTable->resort); } for(i=0; i<count; ++i) { oldIndex=pTempTable->rows[i].sortIndex; @@ -1277,7 +1274,7 @@ ures_swapResource(const UDataSwapper *ds, if(p!=q) { r=q; } else { - r=(Resource *)pTempTable->resort; + r = reinterpret_cast<Resource*>(pTempTable->resort); } for(i=0; i<count; ++i) { oldIndex=pTempTable->rows[i].sortIndex; @@ -1294,7 +1291,7 @@ ures_swapResource(const UDataSwapper *ds, Resource item; int32_t i; - count=udata_readInt32(ds, (int32_t)*p); + count = udata_readInt32(ds, static_cast<int32_t>(*p)); /* swap length */ ds->swapArray32(ds, p++, 4, q++, pErrorCode); @@ -1314,7 +1311,7 @@ ures_swapResource(const UDataSwapper *ds, } break; case URES_INT_VECTOR: - count=udata_readInt32(ds, (int32_t)*p); + count = udata_readInt32(ds, static_cast<int32_t>(*p)); /* swap length and each integer */ ds->swapArray32(ds, p, 4*(1+count), q, pErrorCode); break; @@ -1457,6 +1454,9 @@ ures_swap(const UDataSwapper *ds, outBundle+keysBottom, pErrorCode); if(U_FAILURE(*pErrorCode)) { udata_printError(ds, "ures_swap().udata_swapInvStringBlock(keys[%d]) failed\n", 4*(keysTop-keysBottom)); + if(tempTable.resFlags!=stackResFlags) { + uprv_free(tempTable.resFlags); + } return 0; } @@ -1465,6 +1465,9 @@ ures_swap(const UDataSwapper *ds, ds->swapArray16(ds, inBundle+keysTop, (resBottom-keysTop)*4, outBundle+keysTop, pErrorCode); if(U_FAILURE(*pErrorCode)) { udata_printError(ds, "ures_swap().swapArray16(16-bit units[%d]) failed\n", 2*(resBottom-keysTop)); + if(tempTable.resFlags!=stackResFlags) { + uprv_free(tempTable.resFlags); + } return 0; } } diff --git a/thirdparty/icu4c/common/uscript.cpp b/thirdparty/icu4c/common/uscript.cpp index 2e9012a982..c48a28fd14 100644 --- a/thirdparty/icu4c/common/uscript.cpp +++ b/thirdparty/icu4c/common/uscript.cpp @@ -74,7 +74,7 @@ getCodesFromLocale(const char *locale, } // Explicit script code. if (!script.isEmpty()) { - UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script.data()); + UScriptCode scriptCode = static_cast<UScriptCode>(u_getPropertyValueEnum(UCHAR_SCRIPT, script.data())); if(scriptCode != USCRIPT_INVALID_CODE) { if(scriptCode == USCRIPT_SIMPLIFIED_HAN || scriptCode == USCRIPT_TRADITIONAL_HAN) { scriptCode = USCRIPT_HAN; diff --git a/thirdparty/icu4c/common/uscript_props.cpp b/thirdparty/icu4c/common/uscript_props.cpp index b26164408a..8d36bd3393 100644 --- a/thirdparty/icu4c/common/uscript_props.cpp +++ b/thirdparty/icu4c/common/uscript_props.cpp @@ -244,6 +244,14 @@ const int32_t SCRIPT_PROPS[] = { 0x10582 | EXCLUSION | CASED, // Vith 0x11F1B | EXCLUSION | LB_LETTERS, // Kawi 0x1E4E6 | EXCLUSION, // Nagm + 0, + 0x10D5D | EXCLUSION | RTL | CASED, // Gara + 0x1611C | EXCLUSION, // Gukh + 0x16D45 | EXCLUSION, // Krai + 0x1E5D0 | EXCLUSION, // Onao + 0x11BC4 | EXCLUSION, // Sunu + 0x105C2 | EXCLUSION, // Todr + 0x11392 | EXCLUSION, // Tutg // End copy-paste from parsescriptmetadata.py }; diff --git a/thirdparty/icu4c/common/uset.cpp b/thirdparty/icu4c/common/uset.cpp index b2d0b91d4b..29b8655ac9 100644 --- a/thirdparty/icu4c/common/uset.cpp +++ b/thirdparty/icu4c/common/uset.cpp @@ -21,6 +21,7 @@ */ #include "unicode/utypes.h" +#include "unicode/char16ptr.h" #include "unicode/uobject.h" #include "unicode/uset.h" #include "unicode/uniset.h" @@ -307,11 +308,31 @@ uset_getRangeCount(const USet *set) { } U_CAPI int32_t U_EXPORT2 +uset_getStringCount(const USet *uset) { + const UnicodeSet &set = *(const UnicodeSet *)uset; + return USetAccess::getStringCount(set); +} + +U_CAPI int32_t U_EXPORT2 uset_getItemCount(const USet* uset) { const UnicodeSet& set = *(const UnicodeSet*)uset; return set.getRangeCount() + USetAccess::getStringCount(set); } +U_CAPI const UChar* U_EXPORT2 +uset_getString(const USet *uset, int32_t index, int32_t *pLength) { + if (pLength == nullptr) { return nullptr; } + const UnicodeSet &set = *(const UnicodeSet *)uset; + int32_t count = USetAccess::getStringCount(set); + if (index < 0 || count <= index) { + *pLength = 0; + return nullptr; + } + const UnicodeString *s = USetAccess::getString(set, index); + *pLength = s->length(); + return toUCharPtr(s->getBuffer()); +} + U_CAPI int32_t U_EXPORT2 uset_getItem(const USet* uset, int32_t itemIndex, UChar32* start, UChar32* end, @@ -475,7 +496,7 @@ uset_serializedContains(const USerializedSet* set, UChar32 c) { } else { hi += 1; } - return (UBool)(hi&1); + return hi&1; } else { /* find c in the supplementary part */ uint16_t high=(uint16_t)(c>>16), low=(uint16_t)c; @@ -500,7 +521,7 @@ uset_serializedContains(const USerializedSet* set, UChar32 c) { hi += 2; } /* count pairs of 16-bit units even per BMP and check if the number of pairs is odd */ - return (UBool)(((hi+(base<<1))&2)!=0); + return ((hi+(base<<1))&2)!=0; } } diff --git a/thirdparty/icu4c/common/usetiter.cpp b/thirdparty/icu4c/common/usetiter.cpp index d24a15ab2d..a79d1a26f1 100644 --- a/thirdparty/icu4c/common/usetiter.cpp +++ b/thirdparty/icu4c/common/usetiter.cpp @@ -60,8 +60,8 @@ UBool UnicodeSetIterator::next() { } if (nextString >= stringCount) return false; - codepoint = (UChar32)IS_STRING; // signal that value is actually a string - string = (const UnicodeString*) set->strings->elementAt(nextString++); + codepoint = static_cast<UChar32>(IS_STRING); // signal that value is actually a string + string = static_cast<const UnicodeString*>(set->strings_->elementAt(nextString++)); return true; } @@ -93,8 +93,8 @@ UBool UnicodeSetIterator::nextRange() { } if (nextString >= stringCount) return false; - codepoint = (UChar32)IS_STRING; // signal that value is actually a string - string = (const UnicodeString*) set->strings->elementAt(nextString++); + codepoint = static_cast<UChar32>(IS_STRING); // signal that value is actually a string + string = static_cast<const UnicodeString*>(set->strings_->elementAt(nextString++)); return true; } @@ -135,12 +135,12 @@ void UnicodeSetIterator::loadRange(int32_t iRange) { const UnicodeString& UnicodeSetIterator::getString() { - if (string==nullptr && codepoint!=(UChar32)IS_STRING) { + if (string == nullptr && codepoint != static_cast<UChar32>(IS_STRING)) { if (cpString == nullptr) { cpString = new UnicodeString(); } if (cpString != nullptr) { - cpString->setTo((UChar32)codepoint); + cpString->setTo(codepoint); } string = cpString; } diff --git a/thirdparty/icu4c/common/ushape.cpp b/thirdparty/icu4c/common/ushape.cpp index d0ac95e0b2..00125635cb 100644 --- a/thirdparty/icu4c/common/ushape.cpp +++ b/thirdparty/icu4c/common/ushape.cpp @@ -360,8 +360,8 @@ _shapeToArabicDigitsWithContext(char16_t *s, int32_t length, lastStrongWasAL=true; break; case U_EUROPEAN_NUMBER: /* EN */ - if(lastStrongWasAL && (uint32_t)(c-0x30)<10) { - s[i]=(char16_t)(digitBase+c); /* digitBase+(c-0x30) - digitBase was modified above */ + if (lastStrongWasAL && static_cast<uint32_t>(c - 0x30) < 10) { + s[i] = static_cast<char16_t>(digitBase + c); /* digitBase+(c-0x30) - digitBase was modified above */ } break; default : @@ -380,8 +380,8 @@ _shapeToArabicDigitsWithContext(char16_t *s, int32_t length, lastStrongWasAL=true; break; case U_EUROPEAN_NUMBER: /* EN */ - if(lastStrongWasAL && (uint32_t)(c-0x30)<10) { - s[i]=(char16_t)(digitBase+c); /* digitBase+(c-0x30) - digitBase was modified above */ + if (lastStrongWasAL && static_cast<uint32_t>(c - 0x30) < 10) { + s[i] = static_cast<char16_t>(digitBase + c); /* digitBase+(c-0x30) - digitBase was modified above */ } break; default : @@ -483,7 +483,7 @@ countSpaces(char16_t *dest, int32_t size, uint32_t /*options*/, int32_t *spacesC */ static inline int32_t isTashkeelChar(char16_t ch) { - return (int32_t)( ch>=0x064B && ch<= 0x0652 ); + return static_cast<int32_t>(ch >= 0x064B && ch <= 0x0652); } /* @@ -492,7 +492,7 @@ isTashkeelChar(char16_t ch) { */ static inline int32_t isTashkeelCharFE(char16_t ch) { - return (int32_t)( ch>=0xFE70 && ch<= 0xFE7F ); + return static_cast<int32_t>(ch >= 0xFE70 && ch <= 0xFE7F); } /* @@ -501,7 +501,7 @@ isTashkeelCharFE(char16_t ch) { */ static inline int32_t isAlefChar(char16_t ch) { - return (int32_t)( (ch==0x0622)||(ch==0x0623)||(ch==0x0625)||(ch==0x0627) ); + return static_cast<int32_t>(ch == 0x0622 || ch == 0x0623 || ch == 0x0625 || ch == 0x0627); } /* @@ -510,7 +510,7 @@ isAlefChar(char16_t ch) { */ static inline int32_t isLamAlefChar(char16_t ch) { - return (int32_t)((ch>=0xFEF5)&&(ch<=0xFEFC) ); + return static_cast<int32_t>(ch >= 0xFEF5 && ch <= 0xFEFC); } /*BIDI @@ -564,7 +564,7 @@ isSeenFamilyChar(char16_t ch){ */ static inline int32_t isAlefMaksouraChar(char16_t ch) { - return (int32_t)( (ch == 0xFEEF) || ( ch == 0xFEF0) || (ch == 0x0649)); + return static_cast<int32_t>(ch == 0xFEEF || ch == 0xFEF0 || ch == 0x0649); } /* @@ -747,7 +747,7 @@ handleGeneratedSpaces(char16_t *dest, int32_t sourceLength, } } - tempbuffer = (char16_t *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR); + tempbuffer = static_cast<char16_t*>(uprv_malloc((sourceLength + 1) * U_SIZEOF_UCHAR)); /* Test for nullptr */ if(tempbuffer == nullptr) { *pErrorCode = U_MEMORY_ALLOCATION_ERROR; @@ -905,7 +905,7 @@ expandCompositCharAtBegin(char16_t *dest, int32_t sourceLength, int32_t destSize int32_t countl = 0; char16_t *tempbuffer=nullptr; - tempbuffer = (char16_t *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR); + tempbuffer = static_cast<char16_t*>(uprv_malloc((sourceLength + 1) * U_SIZEOF_UCHAR)); /* Test for nullptr */ if(tempbuffer == nullptr) { @@ -967,7 +967,7 @@ expandCompositCharAtEnd(char16_t *dest, int32_t sourceLength, int32_t destSize,U int32_t inpsize = sourceLength; char16_t *tempbuffer=nullptr; - tempbuffer = (char16_t *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR); + tempbuffer = static_cast<char16_t*>(uprv_malloc((sourceLength + 1) * U_SIZEOF_UCHAR)); /* Test for nullptr */ if(tempbuffer == nullptr) { @@ -1154,7 +1154,7 @@ expandCompositChar(char16_t *dest, int32_t sourceLength, if (shapingMode == 1){ if ( (options&U_SHAPE_LAMALEF_MASK) == U_SHAPE_LAMALEF_RESIZE){ destSize = calculateSize(dest,sourceLength,destSize,options); - tempbuffer = (char16_t *)uprv_malloc((destSize+1)*U_SIZEOF_UCHAR); + tempbuffer = static_cast<char16_t*>(uprv_malloc((destSize + 1) * U_SIZEOF_UCHAR)); /* Test for nullptr */ if(tempbuffer == nullptr) { @@ -1326,9 +1326,9 @@ shapeUnicode(char16_t *dest, int32_t sourceLength, dest[i] = 0xFE70 + IrrelevantPos[(dest[i] - 0x064B)] + static_cast<char16_t>(Shape); } }else if ((currLink & APRESENT) > 0) { - dest[i] = (char16_t)(0xFB50 + (currLink >> 8) + Shape); + dest[i] = static_cast<char16_t>(0xFB50 + (currLink >> 8) + Shape); }else if ((currLink >> 8) > 0 && (currLink & IRRELEVANT) == 0) { - dest[i] = (char16_t)(0xFE70 + (currLink >> 8) + Shape); + dest[i] = static_cast<char16_t>(0xFE70 + (currLink >> 8) + Shape); } } } @@ -1709,13 +1709,13 @@ u_shapeArabic(const char16_t *source, int32_t sourceLength, case U_SHAPE_DIGITS_ALEN2AN_INIT_LR: _shapeToArabicDigitsWithContext(dest, destLength, digitBase, - (UBool)((options&U_SHAPE_TEXT_DIRECTION_MASK)==U_SHAPE_TEXT_DIRECTION_LOGICAL), + (options & U_SHAPE_TEXT_DIRECTION_MASK) == U_SHAPE_TEXT_DIRECTION_LOGICAL, false); break; case U_SHAPE_DIGITS_ALEN2AN_INIT_AL: _shapeToArabicDigitsWithContext(dest, destLength, digitBase, - (UBool)((options&U_SHAPE_TEXT_DIRECTION_MASK)==U_SHAPE_TEXT_DIRECTION_LOGICAL), + (options & U_SHAPE_TEXT_DIRECTION_MASK) == U_SHAPE_TEXT_DIRECTION_LOGICAL, true); break; default: diff --git a/thirdparty/icu4c/common/usprep.cpp b/thirdparty/icu4c/common/usprep.cpp index 22ab0c24eb..477b8f2309 100644 --- a/thirdparty/icu4c/common/usprep.cpp +++ b/thirdparty/icu4c/common/usprep.cpp @@ -126,8 +126,7 @@ compareEntries(const UHashTok p1, const UHashTok p2) { name2.pointer = b2->name; path1.pointer = b1->path; path2.pointer = b2->path; - return ((UBool)(uhash_compareChars(name1, name2) & - uhash_compareChars(path1, path2))); + return uhash_compareChars(name1, name2) & uhash_compareChars(path1, path2); } static void @@ -246,8 +245,8 @@ loadData(UStringPrepProfile* profile, return false; } - p=(const int32_t *)udata_getMemory(dataMemory); - pb=(const uint8_t *)(p+_SPREP_INDEX_TOP); + p = static_cast<const int32_t*>(udata_getMemory(dataMemory)); + pb = reinterpret_cast<const uint8_t*>(p + _SPREP_INDEX_TOP); utrie_unserialize(&_sprepTrie, pb, p[_SPREP_INDEX_TRIE_SIZE], errorCode); _sprepTrie.getFoldingOffset=getSPrepFoldingOffset; @@ -265,11 +264,11 @@ loadData(UStringPrepProfile* profile, uprv_memcpy(&profile->indexes, p, sizeof(profile->indexes)); uprv_memcpy(&profile->sprepTrie, &_sprepTrie, sizeof(UTrie)); } else { - p=(const int32_t *)udata_getMemory(profile->sprepData); + p = static_cast<const int32_t*>(udata_getMemory(profile->sprepData)); } umtx_unlock(&usprepMutex); /* initialize some variables */ - profile->mappingData=(uint16_t *)((uint8_t *)(p+_SPREP_INDEX_TOP)+profile->indexes[_SPREP_INDEX_TRIE_SIZE]); + profile->mappingData = reinterpret_cast<const uint16_t*>(reinterpret_cast<const uint8_t*>(p + _SPREP_INDEX_TOP) + profile->indexes[_SPREP_INDEX_TRIE_SIZE]); u_getUnicodeVersion(normUnicodeVersion); normUniVer = (normUnicodeVersion[0] << 24) + (normUnicodeVersion[1] << 16) + @@ -320,12 +319,12 @@ usprep_getProfile(const char* path, * we use the passed in pointers for fetching the data from the * hash table which is safe */ - stackKey.name = (char*) name; - stackKey.path = (char*) path; + stackKey.name = const_cast<char*>(name); + stackKey.path = const_cast<char*>(path); /* fetch the data from the cache */ umtx_lock(&usprepMutex); - profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); + profile = static_cast<UStringPrepProfile*>(uhash_get(SHARED_DATA_HASHTABLE, &stackKey)); if(profile != nullptr) { profile->refCount++; } @@ -345,8 +344,8 @@ usprep_getProfile(const char* path, } /* get the options */ - newProfile->doNFKC = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0); - newProfile->checkBiDi = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_CHECK_BIDI_ON) > 0); + newProfile->doNFKC = static_cast<UBool>((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0); + newProfile->checkBiDi = static_cast<UBool>((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_CHECK_BIDI_ON) > 0); LocalMemory<UStringPrepKey> key; LocalMemory<char> keyName; @@ -363,7 +362,7 @@ usprep_getProfile(const char* path, umtx_lock(&usprepMutex); // If another thread already inserted the same key/value, refcount and cleanup our thread data - profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); + profile = static_cast<UStringPrepProfile*>(uhash_get(SHARED_DATA_HASHTABLE, &stackKey)); if(profile != nullptr) { profile->refCount++; usprep_unload(newProfile.getAlias()); @@ -477,7 +476,7 @@ getValues(uint16_t trieWord, int16_t& value, UBool& isIndex){ isIndex =false; value = 0; }else if(trieWord >= _SPREP_TYPE_THRESHOLD){ - type = (UStringPrepType) (trieWord - _SPREP_TYPE_THRESHOLD); + type = static_cast<UStringPrepType>(trieWord - _SPREP_TYPE_THRESHOLD); isIndex =false; value = 0; }else{ @@ -489,7 +488,7 @@ getValues(uint16_t trieWord, int16_t& value, UBool& isIndex){ value = trieWord >> 2; //mask off the lower 2 bits and shift }else{ isIndex = false; - value = (int16_t)trieWord; + value = static_cast<int16_t>(trieWord); value = (value >> 2); } @@ -514,7 +513,7 @@ usprep_map( const UStringPrepProfile* profile, uint16_t result; int32_t destIndex=0; int32_t srcIndex; - UBool allowUnassigned = (UBool) ((options & USPREP_ALLOW_UNASSIGNED)>0); + UBool allowUnassigned = static_cast<UBool>((options & USPREP_ALLOW_UNASSIGNED) > 0); UStringPrepType type; int16_t value; UBool isIndex; @@ -581,7 +580,7 @@ usprep_map( const UStringPrepProfile* profile, //copy the code point into destination if(ch <= 0xFFFF){ if(destIndex < destCapacity ){ - dest[destIndex] = (char16_t)ch; + dest[destIndex] = static_cast<char16_t>(ch); } destIndex++; }else{ diff --git a/thirdparty/icu4c/common/ustr_titlecase_brkiter.cpp b/thirdparty/icu4c/common/ustr_titlecase_brkiter.cpp index 82beaca65b..e96af0df87 100644 --- a/thirdparty/icu4c/common/ustr_titlecase_brkiter.cpp +++ b/thirdparty/icu4c/common/ustr_titlecase_brkiter.cpp @@ -93,7 +93,7 @@ void WholeStringBreakIterator::setText(UText *text, UErrorCode &errorCode) { if (U_SUCCESS(errorCode)) { int64_t length64 = utext_nativeLength(text); if (length64 <= INT32_MAX) { - length = (int32_t)length64; + length = static_cast<int32_t>(length64); } else { errorCode = U_INDEX_OUTOFBOUNDS_ERROR; } diff --git a/thirdparty/icu4c/common/ustr_wcs.cpp b/thirdparty/icu4c/common/ustr_wcs.cpp index efbbbc2f18..8ce0855226 100644 --- a/thirdparty/icu4c/common/ustr_wcs.cpp +++ b/thirdparty/icu4c/common/ustr_wcs.cpp @@ -57,7 +57,7 @@ u_growAnyBufferFromStatic(void *context, } *pBuffer=newBuffer; - return (UBool)(newBuffer!=nullptr); + return newBuffer!=nullptr; } /* helper function */ diff --git a/thirdparty/icu4c/common/ustrcase.cpp b/thirdparty/icu4c/common/ustrcase.cpp index 4c726d47db..58b5c5ef62 100644 --- a/thirdparty/icu4c/common/ustrcase.cpp +++ b/thirdparty/icu4c/common/ustrcase.cpp @@ -77,7 +77,7 @@ appendResult(char16_t *dest, int32_t destIndex, int32_t destCapacity, } c=~result; if(destIndex<destCapacity && c<=0xffff) { // BMP slightly-fastpath - dest[destIndex++]=(char16_t)c; + dest[destIndex++] = static_cast<char16_t>(c); return destIndex; } length=cpLength; @@ -86,7 +86,7 @@ appendResult(char16_t *dest, int32_t destIndex, int32_t destCapacity, c=U_SENTINEL; length=result; } else if(destIndex<destCapacity && result<=0xffff) { // BMP slightly-fastpath - dest[destIndex++]=(char16_t)result; + dest[destIndex++] = static_cast<char16_t>(result); if(edits!=nullptr) { edits->addReplace(cpLength, 1); } @@ -171,7 +171,7 @@ appendUnchanged(char16_t *dest, int32_t destIndex, int32_t destCapacity, UChar32 U_CALLCONV utf16_caseContextIterator(void *context, int8_t dir) { - UCaseContext *csc=(UCaseContext *)context; + UCaseContext* csc = static_cast<UCaseContext*>(context); UChar32 c; if(dir<0) { @@ -272,7 +272,7 @@ int32_t toLower(int32_t caseLocale, uint32_t options, } else { c = lead; } - const char16_t *s; + const char16_t *s = nullptr; if (caseLocale >= 0) { csc->cpStart = cpStart; csc->cpLimit = srcIndex; @@ -369,7 +369,7 @@ int32_t toUpper(int32_t caseLocale, uint32_t options, c = lead; } csc->cpLimit = srcIndex; - const char16_t *s; + const char16_t *s = nullptr; c = ucase_toFullUpper(c, utf16_caseContextIterator, csc, &s, caseLocale); if (c >= 0) { destIndex = appendUnchanged(dest, destIndex, destCapacity, @@ -579,8 +579,8 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it } if (c == u'I' || c == u'Í') { - titleLimit = maybeTitleDutchIJ(src, c, titleStart + 1, index, - dest, destIndex, destCapacity, options, + titleLimit = maybeTitleDutchIJ(src, c, titleStart + 1, index, + dest, destIndex, destCapacity, options, edits); } } @@ -1216,7 +1216,7 @@ int32_t toUpper(uint32_t options, } if (change) { - destIndex=appendUChar(dest, destIndex, destCapacity, (char16_t)upper); + destIndex = appendUChar(dest, destIndex, destCapacity, static_cast<char16_t>(upper)); if (destIndex >= 0 && (data & HAS_EITHER_DIALYTIKA) != 0) { destIndex=appendUChar(dest, destIndex, destCapacity, 0x308); // restore or add a dialytika } @@ -1698,7 +1698,7 @@ static int32_t _cmpFold( */ if( level1==0 && - (length=ucase_toFullFolding((UChar32)cp1, &p, options))>=0 + (length = ucase_toFullFolding(cp1, &p, options)) >= 0 ) { /* cp1 case-folds to the code point "length" or to p[length] */ if(U_IS_SURROGATE(c1)) { @@ -1744,7 +1744,7 @@ static int32_t _cmpFold( } if( level2==0 && - (length=ucase_toFullFolding((UChar32)cp2, &p, options))>=0 + (length = ucase_toFullFolding(cp2, &p, options)) >= 0 ) { /* cp2 case-folds to the code point "length" or to p[length] */ if(U_IS_SURROGATE(c2)) { diff --git a/thirdparty/icu4c/common/ustrenum.cpp b/thirdparty/icu4c/common/ustrenum.cpp index f4fc5906ed..c42014d617 100644 --- a/thirdparty/icu4c/common/ustrenum.cpp +++ b/thirdparty/icu4c/common/ustrenum.cpp @@ -89,7 +89,7 @@ StringEnumeration::ensureCharsCapacity(int32_t capacity, UErrorCode &status) { if(chars!=charsBuffer) { uprv_free(chars); } - chars=(char *)uprv_malloc(capacity); + chars = static_cast<char*>(uprv_malloc(capacity)); if(chars==nullptr) { chars=charsBuffer; charsCapacity=sizeof(charsBuffer); @@ -104,7 +104,7 @@ UnicodeString * StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) { if(U_SUCCESS(status) && s!=nullptr) { if(length<0) { - length=(int32_t)uprv_strlen(s); + length = static_cast<int32_t>(uprv_strlen(s)); } char16_t *buffer=unistr.getBuffer(length+1); @@ -307,7 +307,7 @@ ucharstrenum_unext(UEnumeration* en, } const char16_t* result = ((const char16_t**)e->uenum.context)[e->index++]; if (resultLength) { - *resultLength = (int32_t)u_strlen(result); + *resultLength = u_strlen(result); } return result; } diff --git a/thirdparty/icu4c/common/ustring.cpp b/thirdparty/icu4c/common/ustring.cpp index 4f7443cc88..8375121e2f 100644 --- a/thirdparty/icu4c/common/ustring.cpp +++ b/thirdparty/icu4c/common/ustring.cpp @@ -1356,7 +1356,7 @@ _charPtr_charAt(int32_t offset, void *context) { char16_t c16; /* It would be more efficient to access the invariant tables * directly but there is no API for that. */ - u_charsToUChars(((char*) context) + offset, &c16, 1); + u_charsToUChars(static_cast<char*>(context) + offset, &c16, 1); return c16; } @@ -1394,7 +1394,7 @@ u_unescape(const char *src, char16_t *dest, int32_t destCapacity) { i += (int32_t)(src - segment); } ++src; /* advance past '\\' */ - c32 = (UChar32)u_unescapeAt(_charPtr_charAt, &lenParsed, (int32_t)uprv_strlen(src), (void*)src); + c32 = u_unescapeAt(_charPtr_charAt, &lenParsed, (int32_t)uprv_strlen(src), const_cast<char*>(src)); if (lenParsed == 0) { goto err; } diff --git a/thirdparty/icu4c/common/ustrtrns.cpp b/thirdparty/icu4c/common/ustrtrns.cpp index 244c111fc4..d16eabe99f 100644 --- a/thirdparty/icu4c/common/ustrtrns.cpp +++ b/thirdparty/icu4c/common/ustrtrns.cpp @@ -771,19 +771,19 @@ static inline uint8_t * _appendUTF8(uint8_t *pDest, UChar32 c) { /* it is 0<=c<=0x10ffff and not a surrogate if called by a validating function */ if((c)<=0x7f) { - *pDest++=(uint8_t)c; + *pDest++ = static_cast<uint8_t>(c); } else if(c<=0x7ff) { - *pDest++=(uint8_t)((c>>6)|0xc0); - *pDest++=(uint8_t)((c&0x3f)|0x80); + *pDest++ = static_cast<uint8_t>((c >> 6) | 0xc0); + *pDest++ = static_cast<uint8_t>((c & 0x3f) | 0x80); } else if(c<=0xffff) { - *pDest++=(uint8_t)((c>>12)|0xe0); - *pDest++=(uint8_t)(((c>>6)&0x3f)|0x80); - *pDest++=(uint8_t)(((c)&0x3f)|0x80); + *pDest++ = static_cast<uint8_t>((c >> 12) | 0xe0); + *pDest++ = static_cast<uint8_t>(((c >> 6) & 0x3f) | 0x80); + *pDest++ = static_cast<uint8_t>(((c) & 0x3f) | 0x80); } else /* if((uint32_t)(c)<=0x10ffff) */ { - *pDest++=(uint8_t)(((c)>>18)|0xf0); - *pDest++=(uint8_t)((((c)>>12)&0x3f)|0x80); - *pDest++=(uint8_t)((((c)>>6)&0x3f)|0x80); - *pDest++=(uint8_t)(((c)&0x3f)|0x80); + *pDest++ = static_cast<uint8_t>(((c) >> 18) | 0xf0); + *pDest++ = static_cast<uint8_t>((((c) >> 12) & 0x3f) | 0x80); + *pDest++ = static_cast<uint8_t>((((c) >> 6) & 0x3f) | 0x80); + *pDest++ = static_cast<uint8_t>(((c) & 0x3f) | 0x80); } return pDest; } diff --git a/thirdparty/icu4c/common/utext.cpp b/thirdparty/icu4c/common/utext.cpp index eb0a6984bd..0a4248c4e4 100644 --- a/thirdparty/icu4c/common/utext.cpp +++ b/thirdparty/icu4c/common/utext.cpp @@ -738,7 +738,7 @@ pinIndex(int64_t &index, int64_t limit) { } else if (index > limit) { index = limit; } - return (int32_t)index; + return static_cast<int32_t>(index); } @@ -1937,7 +1937,7 @@ repTextReplace(UText *ut, } // Do the actual replace operation using methods of the Replaceable class - UnicodeString replStr((UBool)(length<0), src, length); // read-only alias + UnicodeString replStr(length < 0, src, length); // read-only alias rep->handleReplaceBetween(start32, limit32, replStr); int32_t newLength = rep->length(); int32_t lengthDelta = newLength - oldLength; diff --git a/thirdparty/icu4c/common/util.cpp b/thirdparty/icu4c/common/util.cpp index f6a13aa445..d80ccb50ed 100644 --- a/thirdparty/icu4c/common/util.cpp +++ b/thirdparty/icu4c/common/util.cpp @@ -37,12 +37,12 @@ UnicodeString& ICU_Utility::appendNumber(UnicodeString& result, int32_t n, int32_t radix, int32_t minDigits) { if (radix < 2 || radix > 36) { // Bogus radix - return result.append((char16_t)63/*?*/); + return result.append(static_cast<char16_t>(63)/*?*/); } // Handle negatives if (n < 0) { n = -n; - result.append((char16_t)45/*-*/); + result.append(static_cast<char16_t>(45)/*-*/); } // First determine the number of digits int32_t nn = n; @@ -150,7 +150,7 @@ int32_t ICU_Utility::skipWhitespace(const UnicodeString& str, int32_t& pos, UBool advance) { int32_t p = pos; const char16_t* s = str.getBuffer(); - p = (int32_t)(PatternProps::skipWhiteSpace(s + p, str.length() - p) - s); + p = static_cast<int32_t>(PatternProps::skipWhiteSpace(s + p, str.length() - p) - s); if (advance) { pos = p; } @@ -361,7 +361,7 @@ void ICU_Utility::appendToRule(UnicodeString& rule, rule.append(BACKSLASH).append(APOSTROPHE); } } - if (c != (UChar32)-1) { + if (c != static_cast<UChar32>(-1)) { /* Since spaces are ignored during parsing, they are * emitted only for readability. We emit one here * only if there isn't already one at the end of the diff --git a/thirdparty/icu4c/common/util_props.cpp b/thirdparty/icu4c/common/util_props.cpp index 366a555eee..b1862c24e6 100644 --- a/thirdparty/icu4c/common/util_props.cpp +++ b/thirdparty/icu4c/common/util_props.cpp @@ -120,7 +120,7 @@ int32_t ICU_Utility::parsePattern(const UnicodeString& rule, int32_t pos, int32_ if (pos >= limit) { return -1; } - c = (char16_t) u_tolower(rule.charAt(pos++)); + c = static_cast<char16_t>(u_tolower(rule.charAt(pos++))); if (c != cpat) { return -1; } diff --git a/thirdparty/icu4c/common/utrace.cpp b/thirdparty/icu4c/common/utrace.cpp index 1f536d5643..875bef31a2 100644 --- a/thirdparty/icu4c/common/utrace.cpp +++ b/thirdparty/icu4c/common/utrace.cpp @@ -138,7 +138,7 @@ static void outputHexBytes(int64_t val, int32_t charsToOutput, static void outputPtrBytes(void *val, char *outBuf, int32_t *outIx, int32_t capacity) { uint32_t i; int32_t incVal = 1; /* +1 for big endian, -1 for little endian */ - char *p = (char *)&val; /* point to current byte to output in the ptr val */ + char* p = reinterpret_cast<char*>(&val); /* point to current byte to output in the ptr val */ #if !U_IS_BIG_ENDIAN /* Little Endian. Move p to most significant end of the value */ @@ -233,7 +233,7 @@ utrace_vformat(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, case 'S': /* char16_t * string, with length, len==-1 for NUL terminated. */ ptrArg = va_arg(args, char *); /* Ptr */ - intArg =(int32_t)va_arg(args, int32_t); /* Length */ + intArg = va_arg(args, int32_t); /* Length */ outputUString((const char16_t *)ptrArg, intArg, outBuf, &outIx, capacity, indent); break; @@ -298,7 +298,7 @@ utrace_vformat(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, i32Ptr = (int32_t *)i8Ptr; i64Ptr = (int64_t *)i8Ptr; ptrPtr = (void **)i8Ptr; - vectorLen =(int32_t)va_arg(args, int32_t); + vectorLen = va_arg(args, int32_t); if (ptrPtr == nullptr) { outputString("*NULL* ", outBuf, &outIx, capacity, indent); } else { diff --git a/thirdparty/icu4c/common/utrie.cpp b/thirdparty/icu4c/common/utrie.cpp index 83be0e3407..6a2cf1a9d9 100644 --- a/thirdparty/icu4c/common/utrie.cpp +++ b/thirdparty/icu4c/common/utrie.cpp @@ -40,7 +40,7 @@ equal_uint32(const uint32_t *s, const uint32_t *t, int32_t length) { ++t; --length; } - return (UBool)(length==0); + return length == 0; } /* Building a trie ----------------------------------------------------------*/ @@ -68,7 +68,7 @@ utrie_open(UNewTrie *fillIn, } } uprv_memset(trie, 0, sizeof(UNewTrie)); - trie->isAllocated= (UBool)(fillIn==nullptr); + trie->isAllocated = fillIn == nullptr; if(aliasData!=nullptr) { trie->data=aliasData; @@ -250,7 +250,7 @@ utrie_get32(UNewTrie *trie, UChar32 c, UBool *pInBlockZero) { block=trie->index[c>>UTRIE_SHIFT]; if(pInBlockZero!=nullptr) { - *pInBlockZero= (UBool)(block==0); + *pInBlockZero = block == 0; } return trie->data[ABS(block)+(c&UTRIE_MASK)]; @@ -730,7 +730,7 @@ defaultGetFoldedValue(UNewTrie *trie, UChar32 start, int32_t offset) { if(inBlockZero) { start+=UTRIE_DATA_BLOCK_LENGTH; } else if(value!=initialValue) { - return (uint32_t)offset; + return static_cast<uint32_t>(offset); } else { ++start; } @@ -884,7 +884,7 @@ utrie_unserialize(UTrie *trie, const void *data, int32_t length, UErrorCode *pEr *pErrorCode=U_INVALID_FORMAT_ERROR; return -1; } - trie->isLatin1Linear= (UBool)((options&UTRIE_OPTIONS_LATIN1_IS_LINEAR)!=0); + trie->isLatin1Linear = (options & UTRIE_OPTIONS_LATIN1_IS_LINEAR) != 0; /* get the length values */ trie->indexLength=header->indexLength; diff --git a/thirdparty/icu4c/common/utrie2.cpp b/thirdparty/icu4c/common/utrie2.cpp index 2c3488a4cd..35be698fbb 100644 --- a/thirdparty/icu4c/common/utrie2.cpp +++ b/thirdparty/icu4c/common/utrie2.cpp @@ -389,7 +389,7 @@ utrie2_close(UTrie2 *trie) { U_CAPI UBool U_EXPORT2 utrie2_isFrozen(const UTrie2 *trie) { - return (UBool)(trie->newTrie==nullptr); + return trie->newTrie==nullptr; } U_CAPI int32_t U_EXPORT2 @@ -552,7 +552,7 @@ enumEitherTrie(const UTrie2 *trie, } for(; i2<i2Limit; ++i2) { if(idx!=nullptr) { - block=(int32_t)idx[i2Block+i2]<<UTRIE2_INDEX_SHIFT; + block = static_cast<int32_t>(idx[i2Block + i2]) << UTRIE2_INDEX_SHIFT; } else { block=trie->newTrie->index2[i2Block+i2]; } diff --git a/thirdparty/icu4c/common/utrie2_builder.cpp b/thirdparty/icu4c/common/utrie2_builder.cpp index 02a62e3fd4..4bd49c7adf 100644 --- a/thirdparty/icu4c/common/utrie2_builder.cpp +++ b/thirdparty/icu4c/common/utrie2_builder.cpp @@ -249,12 +249,12 @@ static UNewTrie2 * cloneBuilder(const UNewTrie2 *other) { UNewTrie2 *trie; - trie=(UNewTrie2 *)uprv_malloc(sizeof(UNewTrie2)); + trie = static_cast<UNewTrie2*>(uprv_malloc(sizeof(UNewTrie2))); if(trie==nullptr) { return nullptr; } - trie->data=(uint32_t *)uprv_malloc(other->dataCapacity*4); + trie->data = static_cast<uint32_t*>(uprv_malloc(other->dataCapacity * 4)); if(trie->data==nullptr) { uprv_free(trie); return nullptr; @@ -506,7 +506,7 @@ isInNullBlock(UNewTrie2 *trie, UChar32 c, UBool forLSCP) { ((c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK); } block=trie->index2[i2]; - return (UBool)(block==trie->dataNullOffset); + return block == trie->dataNullOffset; } static int32_t @@ -577,7 +577,7 @@ allocDataBlock(UNewTrie2 *trie, int32_t copyBlock) { */ return -1; } - data=(uint32_t *)uprv_malloc(capacity*4); + data = static_cast<uint32_t*>(uprv_malloc(capacity * 4)); if(data==nullptr) { return -1; } @@ -603,7 +603,7 @@ releaseDataBlock(UNewTrie2 *trie, int32_t block) { static inline UBool isWritableBlock(UNewTrie2 *trie, int32_t block) { - return (UBool)(block!=trie->dataNullOffset && 1==trie->map[block>>UTRIE2_SHIFT_2]); + return block != trie->dataNullOffset && 1 == trie->map[block >> UTRIE2_SHIFT_2]; } static inline void @@ -891,7 +891,7 @@ equal_int32(const int32_t *s, const int32_t *t, int32_t length) { ++t; --length; } - return (UBool)(length==0); + return length == 0; } static inline UBool @@ -901,7 +901,7 @@ equal_uint32(const uint32_t *s, const uint32_t *t, int32_t length) { ++t; --length; } - return (UBool)(length==0); + return length == 0; } static int32_t @@ -1211,7 +1211,7 @@ compactIndex2(UNewTrie2 *trie) { */ while((newStart&((UTRIE2_DATA_GRANULARITY-1)|1))!=0) { /* Arbitrary value: 0x3fffc not possible for real data. */ - trie->index2[newStart++]=(int32_t)0xffff<<UTRIE2_INDEX_SHIFT; + trie->index2[newStart++] = static_cast<int32_t>(0xffff) << UTRIE2_INDEX_SHIFT; } #ifdef UTRIE2_DEBUG diff --git a/thirdparty/icu4c/common/utrie_swap.cpp b/thirdparty/icu4c/common/utrie_swap.cpp index 83d183699d..bb060203fd 100644 --- a/thirdparty/icu4c/common/utrie_swap.cpp +++ b/thirdparty/icu4c/common/utrie_swap.cpp @@ -64,7 +64,7 @@ utrie_swap(const UDataSwapper *ds, return 0; } - dataIs32=(UBool)((trie.options&UTRIE_OPTIONS_DATA_IS_32_BIT)!=0); + dataIs32 = (trie.options & UTRIE_OPTIONS_DATA_IS_32_BIT) != 0; size=sizeof(UTrieHeader)+trie.indexLength*2+trie.dataLength*(dataIs32?4:2); if(length>=0) { @@ -305,7 +305,7 @@ getVersion(const void *data, int32_t length, UBool anyEndianOk) { if(length<16 || data==nullptr || (U_POINTER_MASK_LSB(data, 3)!=0)) { return 0; } - signature=*(const uint32_t *)data; + signature = *static_cast<const uint32_t*>(data); if(signature==UCPTRIE_SIG) { return 3; } diff --git a/thirdparty/icu4c/common/uts46.cpp b/thirdparty/icu4c/common/uts46.cpp index f0e1372422..018c0e19b7 100644 --- a/thirdparty/icu4c/common/uts46.cpp +++ b/thirdparty/icu4c/common/uts46.cpp @@ -451,10 +451,10 @@ UTS46::processUTF8(StringPiece src, return; } char c=srcArray[i]; - if((int8_t)c<0) { // (uint8_t)c>0x7f + if (static_cast<int8_t>(c) < 0) { // (uint8_t)c>0x7f break; } - int cData=asciiData[(int)c]; // Cast: gcc warns about indexing with a char. + int cData = asciiData[static_cast<int>(c)]; // Cast: gcc warns about indexing with a char. if(cData>0) { destArray[i]=c+0x20; // Lowercase an uppercase ASCII letter. } else if(cData<0 && disallowNonLDHDot) { @@ -756,7 +756,12 @@ UTS46::processLabel(UnicodeString &dest, if(U_FAILURE(errorCode)) { return labelLength; } - if(!isValid) { + // Unicode 15.1 UTS #46: + // Added an additional condition in 4.1 Validity Criteria to + // disallow labels such as xn--xn---epa., which do not round-trip. + // --> Validity Criteria new criterion 4: + // If not CheckHyphens, the label must not begin with “xn--”. + if(!isValid || fromPunycode.startsWith(UnicodeString::readOnlyAlias(u"xn--"))) { info.labelErrors|=UIDNA_ERROR_INVALID_ACE_LABEL; return markBadACELabel(dest, labelStart, labelLength, toASCII, info, errorCode); } @@ -796,7 +801,7 @@ UTS46::processLabel(UnicodeString &dest, // in a non-Punycode label or U+FFFD itself in a Punycode label. // We also check for dots which can come from the input to a single-label function. // Ok to cast away const because we own the UnicodeString. - char16_t *s=(char16_t *)label; + char16_t* s = const_cast<char16_t*>(label); const char16_t *limit=label+labelLength; char16_t oredChars=0; // If we enforce STD3 rules, then ASCII characters other than LDH and dot are disallowed. @@ -827,7 +832,7 @@ UTS46::processLabel(UnicodeString &dest, U16_NEXT_UNSAFE(label, cpLength, c); if((U_GET_GC_MASK(c)&U_GC_M_MASK)!=0) { info.labelErrors|=UIDNA_ERROR_LEADING_COMBINING_MARK; - labelString->replace(labelStart, cpLength, (char16_t)0xfffd); + labelString->replace(labelStart, cpLength, static_cast<char16_t>(0xfffd)); label=labelString->getBuffer()+labelStart; labelLength+=1-cpLength; if(labelString==&dest) { @@ -947,7 +952,7 @@ UTS46::markBadACELabel(UnicodeString &dest, } } if(onlyLDH) { - dest.insert(labelStart+labelLength, (char16_t)0xfffd); + dest.insert(labelStart + labelLength, static_cast<char16_t>(0xfffd)); if(dest.isBogus()) { errorCode=U_MEMORY_ALLOCATION_ERROR; return 0; @@ -1361,7 +1366,7 @@ uidna_labelToASCII(const UIDNA *idna, if(!checkArgs(label, length, dest, capacity, pInfo, pErrorCode)) { return 0; } - UnicodeString src((UBool)(length<0), label, length); + UnicodeString src(length < 0, label, length); UnicodeString destString(dest, 0, capacity); IDNAInfo info; reinterpret_cast<const IDNA *>(idna)->labelToASCII(src, destString, info, *pErrorCode); @@ -1377,7 +1382,7 @@ uidna_labelToUnicode(const UIDNA *idna, if(!checkArgs(label, length, dest, capacity, pInfo, pErrorCode)) { return 0; } - UnicodeString src((UBool)(length<0), label, length); + UnicodeString src(length < 0, label, length); UnicodeString destString(dest, 0, capacity); IDNAInfo info; reinterpret_cast<const IDNA *>(idna)->labelToUnicode(src, destString, info, *pErrorCode); @@ -1393,7 +1398,7 @@ uidna_nameToASCII(const UIDNA *idna, if(!checkArgs(name, length, dest, capacity, pInfo, pErrorCode)) { return 0; } - UnicodeString src((UBool)(length<0), name, length); + UnicodeString src(length < 0, name, length); UnicodeString destString(dest, 0, capacity); IDNAInfo info; reinterpret_cast<const IDNA *>(idna)->nameToASCII(src, destString, info, *pErrorCode); @@ -1409,7 +1414,7 @@ uidna_nameToUnicode(const UIDNA *idna, if(!checkArgs(name, length, dest, capacity, pInfo, pErrorCode)) { return 0; } - UnicodeString src((UBool)(length<0), name, length); + UnicodeString src(length < 0, name, length); UnicodeString destString(dest, 0, capacity); IDNAInfo info; reinterpret_cast<const IDNA *>(idna)->nameToUnicode(src, destString, info, *pErrorCode); diff --git a/thirdparty/icu4c/common/utypes.cpp b/thirdparty/icu4c/common/utypes.cpp index 715994d67f..4602314147 100644 --- a/thirdparty/icu4c/common/utypes.cpp +++ b/thirdparty/icu4c/common/utypes.cpp @@ -140,8 +140,7 @@ _uFmtErrorName[U_FMT_PARSE_ERROR_LIMIT - U_FMT_PARSE_ERROR_START] = { "U_MF_MISSING_SELECTOR_ANNOTATION_ERROR", "U_MF_DUPLICATE_DECLARATION_ERROR", "U_MF_OPERAND_MISMATCH_ERROR", - "U_MF_UNSUPPORTED_STATEMENT_ERROR", - "U_MF_UNSUPPORTED_EXPRESSION_ERROR" + "U_MF_DUPLICATE_VARIANT_ERROR" }; static const char * const diff --git a/thirdparty/icu4c/common/uvector.cpp b/thirdparty/icu4c/common/uvector.cpp index 85c322cea7..5eb89c9a56 100644 --- a/thirdparty/icu4c/common/uvector.cpp +++ b/thirdparty/icu4c/common/uvector.cpp @@ -49,10 +49,10 @@ UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacit return; } // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow - if ((initialCapacity < 1) || (initialCapacity > (int32_t)(INT32_MAX / sizeof(UElement)))) { + if ((initialCapacity < 1) || (initialCapacity > static_cast<int32_t>(INT32_MAX / sizeof(UElement)))) { initialCapacity = DEFAULT_CAPACITY; } - elements = (UElement *)uprv_malloc(sizeof(UElement)*initialCapacity); + elements = static_cast<UElement*>(uprv_malloc(sizeof(UElement) * initialCapacity)); if (elements == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; } else { @@ -340,12 +340,12 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { if (newCap < minimumCapacity) { newCap = minimumCapacity; } - if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check + if (newCap > static_cast<int32_t>(INT32_MAX / sizeof(UElement))) { // integer overflow check // We keep the original memory contents on bad minimumCapacity. status = U_ILLEGAL_ARGUMENT_ERROR; return false; } - UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap); + UElement* newElems = static_cast<UElement*>(uprv_realloc(elements, sizeof(UElement) * newCap)); if (newElems == nullptr) { // We keep the original contents on the memory failure on realloc or bad minimumCapacity. status = U_MEMORY_ALLOCATION_ERROR; diff --git a/thirdparty/icu4c/common/uvectr32.cpp b/thirdparty/icu4c/common/uvectr32.cpp index a2dc1bdbc9..7389b3f06d 100644 --- a/thirdparty/icu4c/common/uvectr32.cpp +++ b/thirdparty/icu4c/common/uvectr32.cpp @@ -54,10 +54,10 @@ void UVector32::_init(int32_t initialCapacity, UErrorCode &status) { if (maxCapacity>0 && maxCapacity<initialCapacity) { initialCapacity = maxCapacity; } - if (initialCapacity > (int32_t)(INT32_MAX / sizeof(int32_t))) { + if (initialCapacity > static_cast<int32_t>(INT32_MAX / sizeof(int32_t))) { initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity); } - elements = (int32_t *)uprv_malloc(sizeof(int32_t)*initialCapacity); + elements = static_cast<int32_t*>(uprv_malloc(sizeof(int32_t) * initialCapacity)); if (elements == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; } else { @@ -223,12 +223,12 @@ UBool UVector32::expandCapacity(int32_t minimumCapacity, UErrorCode &status) { if (maxCapacity > 0 && newCap > maxCapacity) { newCap = maxCapacity; } - if (newCap > (int32_t)(INT32_MAX / sizeof(int32_t))) { // integer overflow check + if (newCap > static_cast<int32_t>(INT32_MAX / sizeof(int32_t))) { // integer overflow check // We keep the original memory contents on bad minimumCapacity/maxCapacity. status = U_ILLEGAL_ARGUMENT_ERROR; return false; } - int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*newCap); + int32_t* newElems = static_cast<int32_t*>(uprv_realloc(elements, sizeof(int32_t) * newCap)); if (newElems == nullptr) { // We keep the original contents on the memory failure on realloc. status = U_MEMORY_ALLOCATION_ERROR; @@ -244,7 +244,7 @@ void UVector32::setMaxCapacity(int32_t limit) { if (limit < 0) { limit = 0; } - if (limit > (int32_t)(INT32_MAX / sizeof(int32_t))) { // integer overflow check for realloc + if (limit > static_cast<int32_t>(INT32_MAX / sizeof(int32_t))) { // integer overflow check for realloc // Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged return; } @@ -256,7 +256,7 @@ void UVector32::setMaxCapacity(int32_t limit) { // New maximum capacity is smaller than the current size. // Realloc the storage to the new, smaller size. - int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*maxCapacity); + int32_t* newElems = static_cast<int32_t*>(uprv_realloc(elements, sizeof(int32_t) * maxCapacity)); if (newElems == nullptr) { // Realloc to smaller failed. // Just keep what we had. No need to call it a failure. diff --git a/thirdparty/icu4c/common/uvectr64.cpp b/thirdparty/icu4c/common/uvectr64.cpp index 58b0b1f8b8..81c923f4f8 100644 --- a/thirdparty/icu4c/common/uvectr64.cpp +++ b/thirdparty/icu4c/common/uvectr64.cpp @@ -51,10 +51,10 @@ void UVector64::_init(int32_t initialCapacity, UErrorCode &status) { if (maxCapacity>0 && maxCapacity<initialCapacity) { initialCapacity = maxCapacity; } - if (initialCapacity > (int32_t)(INT32_MAX / sizeof(int64_t))) { + if (initialCapacity > static_cast<int32_t>(INT32_MAX / sizeof(int64_t))) { initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity); } - elements = (int64_t *)uprv_malloc(sizeof(int64_t)*initialCapacity); + elements = static_cast<int64_t*>(uprv_malloc(sizeof(int64_t) * initialCapacity)); if (elements == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; } else { @@ -141,12 +141,12 @@ UBool UVector64::expandCapacity(int32_t minimumCapacity, UErrorCode &status) { if (maxCapacity > 0 && newCap > maxCapacity) { newCap = maxCapacity; } - if (newCap > (int32_t)(INT32_MAX / sizeof(int64_t))) { // integer overflow check + if (newCap > static_cast<int32_t>(INT32_MAX / sizeof(int64_t))) { // integer overflow check // We keep the original memory contents on bad minimumCapacity/maxCapacity. status = U_ILLEGAL_ARGUMENT_ERROR; return false; } - int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*newCap); + int64_t* newElems = static_cast<int64_t*>(uprv_realloc(elements, sizeof(int64_t) * newCap)); if (newElems == nullptr) { // We keep the original contents on the memory failure on realloc. status = U_MEMORY_ALLOCATION_ERROR; @@ -162,7 +162,7 @@ void UVector64::setMaxCapacity(int32_t limit) { if (limit < 0) { limit = 0; } - if (limit > (int32_t)(INT32_MAX / sizeof(int64_t))) { // integer overflow check for realloc + if (limit > static_cast<int32_t>(INT32_MAX / sizeof(int64_t))) { // integer overflow check for realloc // Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged return; } @@ -174,7 +174,7 @@ void UVector64::setMaxCapacity(int32_t limit) { // New maximum capacity is smaller than the current size. // Realloc the storage to the new, smaller size. - int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*maxCapacity); + int64_t* newElems = static_cast<int64_t*>(uprv_realloc(elements, sizeof(int64_t) * maxCapacity)); if (newElems == nullptr) { // Realloc to smaller failed. // Just keep what we had. No need to call it a failure. diff --git a/thirdparty/icu4c/i18n/scriptset.cpp b/thirdparty/icu4c/i18n/scriptset.cpp index 736a85cf8c..eec1eeb37d 100644 --- a/thirdparty/icu4c/i18n/scriptset.cpp +++ b/thirdparty/icu4c/i18n/scriptset.cpp @@ -57,7 +57,7 @@ UBool ScriptSet::test(UScriptCode script, UErrorCode &status) const { if (U_FAILURE(status)) { return false; } - if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { + if (script < 0 || static_cast<int32_t>(script) >= SCRIPT_LIMIT) { status = U_ILLEGAL_ARGUMENT_ERROR; return false; } @@ -71,7 +71,7 @@ ScriptSet &ScriptSet::set(UScriptCode script, UErrorCode &status) { if (U_FAILURE(status)) { return *this; } - if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { + if (script < 0 || static_cast<int32_t>(script) >= SCRIPT_LIMIT) { status = U_ILLEGAL_ARGUMENT_ERROR; return *this; } @@ -85,7 +85,7 @@ ScriptSet &ScriptSet::reset(UScriptCode script, UErrorCode &status) { if (U_FAILURE(status)) { return *this; } - if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { + if (script < 0 || static_cast<int32_t>(script) >= SCRIPT_LIMIT) { status = U_ILLEGAL_ARGUMENT_ERROR; return *this; } @@ -178,7 +178,7 @@ int32_t ScriptSet::nextSetBit(int32_t fromIndex) const { } UErrorCode status = U_ZERO_ERROR; for (int32_t scriptIndex = fromIndex; scriptIndex < SCRIPT_LIMIT; scriptIndex++) { - if (test((UScriptCode)scriptIndex, status)) { + if (test(static_cast<UScriptCode>(scriptIndex), status)) { return scriptIndex; } } @@ -198,10 +198,10 @@ UnicodeString &ScriptSet::displayScripts(UnicodeString &dest) const { UBool firstTime = true; for (int32_t i = nextSetBit(0); i >= 0; i = nextSetBit(i + 1)) { if (!firstTime) { - dest.append((char16_t)0x20); + dest.append(static_cast<char16_t>(0x20)); } firstTime = false; - const char *scriptName = uscript_getShortName((UScriptCode(i))); + const char* scriptName = uscript_getShortName(static_cast<UScriptCode>(i)); dest.append(UnicodeString(scriptName, -1, US_INV)); } return dest; @@ -230,7 +230,7 @@ ScriptSet &ScriptSet::parseScripts(const UnicodeString &scriptString, UErrorCode if (sc == UCHAR_INVALID_CODE) { status = U_ILLEGAL_ARGUMENT_ERROR; } else { - this->set((UScriptCode)sc, status); + this->set(static_cast<UScriptCode>(sc), status); } if (U_FAILURE(status)) { return *this; diff --git a/thirdparty/icu4c/i18n/unicode/uspoof.h b/thirdparty/icu4c/i18n/unicode/uspoof.h index 20d29d62b2..4e029fe951 100644 --- a/thirdparty/icu4c/i18n/unicode/uspoof.h +++ b/thirdparty/icu4c/i18n/unicode/uspoof.h @@ -1224,7 +1224,6 @@ uspoof_areConfusable(const USpoofChecker *sc, const UChar *id2, int32_t length2, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * Check whether two specified strings are visually confusable when * displayed in a context with the given paragraph direction. @@ -1269,13 +1268,12 @@ uspoof_areConfusable(const USpoofChecker *sc, * enum USpoofChecks. Zero is returned if the identifiers * are not confusable. * - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusable(const USpoofChecker *sc, UBiDiDirection direction, const UChar *id1, int32_t length1, const UChar *id2, int32_t length2, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ /** * A version of {@link uspoof_areConfusable} accepting strings in UTF-8 format. @@ -1308,7 +1306,6 @@ uspoof_areConfusableUTF8(const USpoofChecker *sc, const char *id2, int32_t length2, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * A version of {@link uspoof_areBidiConfusable} accepting strings in UTF-8 format. * @@ -1332,7 +1329,7 @@ uspoof_areConfusableUTF8(const USpoofChecker *sc, * enum USpoofChecks. Zero is returned if the strings * are not confusable. * - * @draft ICU 74 + * @stable ICU 74 * * @see uspoof_areBidiConfusable */ @@ -1340,7 +1337,6 @@ U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusableUTF8(const USpoofChecker *sc, const char *id1, int32_t length1, const char *id2, int32_t length2, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ /** * Get the "skeleton" for an identifier. @@ -1380,7 +1376,6 @@ uspoof_getSkeleton(const USpoofChecker *sc, UChar *dest, int32_t destCapacity, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * Get the "bidiSkeleton" for an identifier and a direction. * Skeletons are a transformation of the input identifier; @@ -1410,14 +1405,13 @@ uspoof_getSkeleton(const USpoofChecker *sc, * is always that of the complete skeleton, even when the * supplied buffer is too small (or of zero length) * - * @draft ICU 74 + * @stable ICU 74 * @see uspoof_areBidiConfusable */ U_CAPI int32_t U_EXPORT2 uspoof_getBidiSkeleton(const USpoofChecker *sc, UBiDiDirection direction, const UChar *id, int32_t length, UChar *dest, int32_t destCapacity, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ /** * Get the "skeleton" for an identifier. @@ -1459,7 +1453,6 @@ uspoof_getSkeletonUTF8(const USpoofChecker *sc, char *dest, int32_t destCapacity, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * Get the "bidiSkeleton" for an identifier and a direction. * Skeletons are a transformation of the input identifier; @@ -1492,12 +1485,11 @@ uspoof_getSkeletonUTF8(const USpoofChecker *sc, * is always that of the complete skeleton, even when the * supplied buffer is too small (or of zero length) * - * @draft ICU 74 + * @stable ICU 74 */ U_CAPI int32_t U_EXPORT2 uspoof_getBidiSkeletonUTF8(const USpoofChecker *sc, UBiDiDirection direction, const char *id, int32_t length, char *dest, int32_t destCapacity, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ /** * Get the set of Candidate Characters for Inclusion in Identifiers, as defined @@ -1736,7 +1728,6 @@ uspoof_areConfusableUnicodeString(const USpoofChecker *sc, const icu::UnicodeString &s2, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * A version of {@link uspoof_areBidiConfusable} accepting UnicodeStrings. * @@ -1756,7 +1747,7 @@ uspoof_areConfusableUnicodeString(const USpoofChecker *sc, * enum USpoofChecks. Zero is returned if the identifiers * are not confusable. * - * @draft ICU 74 + * @stable ICU 74 * * @see uspoof_areBidiConfusable */ @@ -1765,7 +1756,6 @@ U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusableUnicodeString(const USpoofChec const icu::UnicodeString &s1, const icu::UnicodeString &s2, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ /** * Get the "skeleton" for an identifier. @@ -1797,7 +1787,6 @@ uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, icu::UnicodeString &dest, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * Get the "bidiSkeleton" for an identifier and a direction. * Skeletons are a transformation of the input identifier; @@ -1820,12 +1809,11 @@ uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, * perform the check. * @return A reference to the destination (skeleton) string. * - * @draft ICU 74 + * @stable ICU 74 */ U_I18N_API icu::UnicodeString &U_EXPORT2 uspoof_getBidiSkeletonUnicodeString( const USpoofChecker *sc, UBiDiDirection direction, const icu::UnicodeString &id, icu::UnicodeString &dest, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ /** * Get the set of Candidate Characters for Inclusion in Identifiers, as defined diff --git a/thirdparty/icu4c/i18n/uspoof_impl.cpp b/thirdparty/icu4c/i18n/uspoof_impl.cpp index 93402e670b..c727fafb37 100644 --- a/thirdparty/icu4c/i18n/uspoof_impl.cpp +++ b/thirdparty/icu4c/i18n/uspoof_impl.cpp @@ -148,7 +148,7 @@ void SpoofImpl::setAllowedLocales(const char *localesList, UErrorCode &status) { if (trimmedEnd <= locStart) { break; } - const char *locale = uprv_strndup(locStart, (int32_t)(trimmedEnd + 1 - locStart)); + const char* locale = uprv_strndup(locStart, static_cast<int32_t>(trimmedEnd + 1 - locStart)); localeListCount++; // We have one locale from the locales list. @@ -305,7 +305,7 @@ void SpoofImpl::getNumerics(const UnicodeString& input, UnicodeSet& result, UErr if (u_charType(codePoint) == U_DECIMAL_DIGIT_NUMBER) { // Store the zero character as a representative for comparison. // Unicode guarantees it is codePoint - value - result.add(codePoint - (UChar32)u_getNumericValue(codePoint)); + result.add(codePoint - static_cast<UChar32>(u_getNumericValue(codePoint))); } } } @@ -432,7 +432,7 @@ UChar32 SpoofImpl::ScanHex(const char16_t *s, int32_t start, int32_t limit, UErr status = U_PARSE_ERROR; val = 0; } - return (UChar32)val; + return static_cast<UChar32>(val); } @@ -601,7 +601,7 @@ SpoofData::SpoofData(const void *data, int32_t length, UErrorCode &status) if (U_FAILURE(status)) { return; } - if ((size_t)length < sizeof(SpoofDataHeader)) { + if (static_cast<size_t>(length) < sizeof(SpoofDataHeader)) { status = U_INVALID_FORMAT_ERROR; return; } @@ -688,13 +688,13 @@ void SpoofData::initPtrs(UErrorCode &status) { return; } if (fRawData->fCFUKeys != 0) { - fCFUKeys = (int32_t *)((char *)fRawData + fRawData->fCFUKeys); + fCFUKeys = reinterpret_cast<int32_t*>(reinterpret_cast<char*>(fRawData) + fRawData->fCFUKeys); } if (fRawData->fCFUStringIndex != 0) { - fCFUValues = (uint16_t *)((char *)fRawData + fRawData->fCFUStringIndex); + fCFUValues = reinterpret_cast<uint16_t*>(reinterpret_cast<char*>(fRawData) + fRawData->fCFUStringIndex); } if (fRawData->fCFUStringTable != 0) { - fCFUStrings = (char16_t *)((char *)fRawData + fRawData->fCFUStringTable); + fCFUStrings = reinterpret_cast<char16_t*>(reinterpret_cast<char*>(fRawData) + fRawData->fCFUStringTable); } } @@ -739,7 +739,7 @@ void *SpoofData::reserveSpace(int32_t numBytes, UErrorCode &status) { fRawData->fLength = fMemLimit; uprv_memset((char *)fRawData + returnOffset, 0, numBytes); initPtrs(status); - return (char *)fRawData + returnOffset; + return reinterpret_cast<char*>(fRawData) + returnOffset; } int32_t SpoofData::serialize(void *buf, int32_t capacity, UErrorCode &status) const { @@ -806,7 +806,7 @@ int32_t SpoofData::appendValueTo(int32_t index, UnicodeString& dest) const { // an index into the string table (for longer strings) uint16_t value = fCFUValues[index]; if (stringLength == 1) { - dest.append((char16_t)value); + dest.append(static_cast<char16_t>(value)); } else { dest.append(fCFUStrings + value, stringLength); } diff --git a/thirdparty/icu4c/icudt75l.dat b/thirdparty/icu4c/icudt76l.dat Binary files differindex 76728ca6d6..58bead426f 100644 --- a/thirdparty/icu4c/icudt75l.dat +++ b/thirdparty/icu4c/icudt76l.dat diff --git a/thirdparty/mbedtls/library/bignum_mod.c b/thirdparty/mbedtls/library/bignum_mod.c deleted file mode 100644 index dfd332a703..0000000000 --- a/thirdparty/mbedtls/library/bignum_mod.c +++ /dev/null @@ -1,394 +0,0 @@ -/** - * Modular bignum functions - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#include "common.h" - -#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT) - -#include <string.h> - -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" -#include "mbedtls/bignum.h" - -#include "mbedtls/platform.h" - -#include "bignum_core.h" -#include "bignum_mod.h" -#include "bignum_mod_raw.h" -#include "constant_time_internal.h" - -int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, - const mbedtls_mpi_mod_modulus *N, - mbedtls_mpi_uint *p, - size_t p_limbs) -{ - if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - r->limbs = N->limbs; - r->p = p; - - return 0; -} - -void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r) -{ - if (r == NULL) { - return; - } - - r->limbs = 0; - r->p = NULL; -} - -void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N) -{ - if (N == NULL) { - return; - } - - N->p = NULL; - N->limbs = 0; - N->bits = 0; - N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; -} - -void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N) -{ - if (N == NULL) { - return; - } - - switch (N->int_rep) { - case MBEDTLS_MPI_MOD_REP_MONTGOMERY: - if (N->rep.mont.rr != NULL) { - mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr, - N->limbs * sizeof(mbedtls_mpi_uint)); - N->rep.mont.rr = NULL; - } - N->rep.mont.mm = 0; - break; - case MBEDTLS_MPI_MOD_REP_OPT_RED: - N->rep.ored.modp = NULL; - break; - case MBEDTLS_MPI_MOD_REP_INVALID: - break; - } - - N->p = NULL; - N->limbs = 0; - N->bits = 0; - N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; -} - -static int set_mont_const_square(const mbedtls_mpi_uint **X, - const mbedtls_mpi_uint *A, - size_t limbs) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi N; - mbedtls_mpi RR; - *X = NULL; - - mbedtls_mpi_init(&N); - mbedtls_mpi_init(&RR); - - if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) { - goto cleanup; - } - - if (mbedtls_mpi_grow(&N, limbs)) { - goto cleanup; - } - - memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs); - - ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N); - - if (ret == 0) { - *X = RR.p; - RR.p = NULL; - } - -cleanup: - mbedtls_mpi_free(&N); - mbedtls_mpi_free(&RR); - ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0; - return ret; -} - -static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N, - const mbedtls_mpi_uint *p, - size_t p_limbs, - mbedtls_mpi_mod_rep_selector int_rep) -{ - N->p = p; - N->limbs = p_limbs; - N->bits = mbedtls_mpi_core_bitlen(p, p_limbs); - N->int_rep = int_rep; -} - -int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, - const mbedtls_mpi_uint *p, - size_t p_limbs) -{ - int ret = 0; - standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY); - N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p); - ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs); - - if (ret != 0) { - mbedtls_mpi_mod_modulus_free(N); - } - - return ret; -} - -int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N, - const mbedtls_mpi_uint *p, - size_t p_limbs, - mbedtls_mpi_modp_fn modp) -{ - standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED); - N->rep.ored.modp = modp; - return 0; -} - -int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, - const mbedtls_mpi_mod_residue *A, - const mbedtls_mpi_mod_residue *B, - const mbedtls_mpi_mod_modulus *N) -{ - if (N->limbs == 0) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL); - if (T == NULL) { - return MBEDTLS_ERR_MPI_ALLOC_FAILED; - } - - mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T); - - mbedtls_free(T); - - return 0; -} - -int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, - const mbedtls_mpi_mod_residue *A, - const mbedtls_mpi_mod_residue *B, - const mbedtls_mpi_mod_modulus *N) -{ - if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N); - - return 0; -} - -static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X, - const mbedtls_mpi_mod_residue *A, - const mbedtls_mpi_mod_modulus *N, - mbedtls_mpi_uint *working_memory) -{ - /* Input already in Montgomery form, so there's little to do */ - mbedtls_mpi_mod_raw_inv_prime(X->p, A->p, - N->p, N->limbs, - N->rep.mont.rr, - working_memory); - return 0; -} - -static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X, - const mbedtls_mpi_mod_residue *A, - const mbedtls_mpi_mod_modulus *N, - mbedtls_mpi_uint *working_memory) -{ - /* Need to convert input into Montgomery form */ - - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - mbedtls_mpi_mod_modulus Nmont; - mbedtls_mpi_mod_modulus_init(&Nmont); - - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs)); - - /* We'll use X->p to hold the Montgomery form of the input A->p */ - mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs, - Nmont.rep.mont.mm, Nmont.rep.mont.rr, - working_memory); - - mbedtls_mpi_mod_raw_inv_prime(X->p, X->p, - Nmont.p, Nmont.limbs, - Nmont.rep.mont.rr, - working_memory); - - /* And convert back from Montgomery form */ - - mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs, - Nmont.rep.mont.mm, working_memory); - -cleanup: - mbedtls_mpi_mod_modulus_free(&Nmont); - return ret; -} - -int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, - const mbedtls_mpi_mod_residue *A, - const mbedtls_mpi_mod_modulus *N) -{ - if (X->limbs != N->limbs || A->limbs != N->limbs) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - /* Zero has the same value regardless of Montgomery form or not */ - if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - size_t working_limbs = - mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs); - - mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs, - sizeof(mbedtls_mpi_uint)); - if (working_memory == NULL) { - return MBEDTLS_ERR_MPI_ALLOC_FAILED; - } - - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - switch (N->int_rep) { - case MBEDTLS_MPI_MOD_REP_MONTGOMERY: - ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory); - break; - case MBEDTLS_MPI_MOD_REP_OPT_RED: - ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory); - break; - default: - ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - break; - } - - mbedtls_zeroize_and_free(working_memory, - working_limbs * sizeof(mbedtls_mpi_uint)); - - return ret; -} - -int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, - const mbedtls_mpi_mod_residue *A, - const mbedtls_mpi_mod_residue *B, - const mbedtls_mpi_mod_modulus *N) -{ - if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N); - - return 0; -} - -int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, - mbedtls_mpi_uint min, - const mbedtls_mpi_mod_modulus *N, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - if (X->limbs != N->limbs) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng); -} - -int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, - const mbedtls_mpi_mod_modulus *N, - const unsigned char *buf, - size_t buflen, - mbedtls_mpi_mod_ext_rep ext_rep) -{ - int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - - /* Do our best to check if r and m have been set up */ - if (r->limbs == 0 || N->limbs == 0) { - goto cleanup; - } - if (r->limbs != N->limbs) { - goto cleanup; - } - - ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep); - if (ret != 0) { - goto cleanup; - } - - r->limbs = N->limbs; - - ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N); - -cleanup: - return ret; -} - -int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, - const mbedtls_mpi_mod_modulus *N, - unsigned char *buf, - size_t buflen, - mbedtls_mpi_mod_ext_rep ext_rep) -{ - /* Do our best to check if r and m have been set up */ - if (r->limbs == 0 || N->limbs == 0) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - if (r->limbs != N->limbs) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi_uint *working_memory = r->p; - size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs; - - if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) { - - working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint)); - - if (working_memory == NULL) { - ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; - goto cleanup; - } - - memcpy(working_memory, r->p, working_memory_len); - - ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N); - if (ret != 0) { - goto cleanup; - } - } - - ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep); - -cleanup: - - if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY && - working_memory != NULL) { - - mbedtls_zeroize_and_free(working_memory, working_memory_len); - } - - return ret; -} - -#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */ diff --git a/thirdparty/mbedtls/library/block_cipher.c b/thirdparty/mbedtls/library/block_cipher.c deleted file mode 100644 index 51cdcdf46b..0000000000 --- a/thirdparty/mbedtls/library/block_cipher.c +++ /dev/null @@ -1,207 +0,0 @@ -/** - * \file block_cipher.c - * - * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, - * for use by the GCM and CCM modules. - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#include "common.h" - -#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) -#include "psa/crypto.h" -#include "psa_crypto_core.h" -#include "psa_util_internal.h" -#endif - -#include "block_cipher_internal.h" - -#if defined(MBEDTLS_BLOCK_CIPHER_C) - -#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) -static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id) -{ - switch (cipher_id) { -#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) - case MBEDTLS_BLOCK_CIPHER_ID_AES: - return PSA_KEY_TYPE_AES; -#endif -#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) - case MBEDTLS_BLOCK_CIPHER_ID_ARIA: - return PSA_KEY_TYPE_ARIA; -#endif -#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) - case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: - return PSA_KEY_TYPE_CAMELLIA; -#endif - default: - return PSA_KEY_TYPE_NONE; - } -} - -static int mbedtls_cipher_error_from_psa(psa_status_t status) -{ - return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors, - psa_generic_status_to_mbedtls); -} -#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ - -void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx) -{ - if (ctx == NULL) { - return; - } - -#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) - if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { - psa_destroy_key(ctx->psa_key_id); - return; - } -#endif - switch (ctx->id) { -#if defined(MBEDTLS_AES_C) - case MBEDTLS_BLOCK_CIPHER_ID_AES: - mbedtls_aes_free(&ctx->ctx.aes); - break; -#endif -#if defined(MBEDTLS_ARIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_ARIA: - mbedtls_aria_free(&ctx->ctx.aria); - break; -#endif -#if defined(MBEDTLS_CAMELLIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: - mbedtls_camellia_free(&ctx->ctx.camellia); - break; -#endif - default: - break; - } - ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; -} - -int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, - mbedtls_cipher_id_t cipher_id) -{ - ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES : - (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA : - (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA : - MBEDTLS_BLOCK_CIPHER_ID_NONE; - -#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) - psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id); - if (psa_key_type != PSA_KEY_TYPE_NONE && - psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) { - ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA; - return 0; - } - ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY; -#endif - - switch (ctx->id) { -#if defined(MBEDTLS_AES_C) - case MBEDTLS_BLOCK_CIPHER_ID_AES: - mbedtls_aes_init(&ctx->ctx.aes); - return 0; -#endif -#if defined(MBEDTLS_ARIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_ARIA: - mbedtls_aria_init(&ctx->ctx.aria); - return 0; -#endif -#if defined(MBEDTLS_CAMELLIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: - mbedtls_camellia_init(&ctx->ctx.camellia); - return 0; -#endif - default: - ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; - return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; - } -} - -int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, - const unsigned char *key, - unsigned key_bitlen) -{ -#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) - if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { - psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - psa_status_t status; - - psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id)); - psa_set_key_bits(&key_attr, key_bitlen); - psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); - psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); - - status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id); - if (status != PSA_SUCCESS) { - return mbedtls_cipher_error_from_psa(status); - } - psa_reset_key_attributes(&key_attr); - - return 0; - } -#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ - - switch (ctx->id) { -#if defined(MBEDTLS_AES_C) - case MBEDTLS_BLOCK_CIPHER_ID_AES: - return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen); -#endif -#if defined(MBEDTLS_ARIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_ARIA: - return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen); -#endif -#if defined(MBEDTLS_CAMELLIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: - return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen); -#endif - default: - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; - } -} - -int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, - const unsigned char input[16], - unsigned char output[16]) -{ -#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) - if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { - psa_status_t status; - size_t olen; - - status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING, - input, 16, output, 16, &olen); - if (status != PSA_SUCCESS) { - return mbedtls_cipher_error_from_psa(status); - } - return 0; - } -#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ - - switch (ctx->id) { -#if defined(MBEDTLS_AES_C) - case MBEDTLS_BLOCK_CIPHER_ID_AES: - return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT, - input, output); -#endif -#if defined(MBEDTLS_ARIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_ARIA: - return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output); -#endif -#if defined(MBEDTLS_CAMELLIA_C) - case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: - return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia, - MBEDTLS_CAMELLIA_ENCRYPT, - input, output); -#endif - default: - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; - } -} - -#endif /* MBEDTLS_BLOCK_CIPHER_C */ diff --git a/thirdparty/mbedtls/library/ecp_curves_new.c b/thirdparty/mbedtls/library/ecp_curves_new.c deleted file mode 100644 index 035b23a1b4..0000000000 --- a/thirdparty/mbedtls/library/ecp_curves_new.c +++ /dev/null @@ -1,6036 +0,0 @@ -/* - * Elliptic curves over GF(p): curve-specific data and functions - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#include "common.h" - -#if defined(MBEDTLS_ECP_WITH_MPI_UINT) - -#if defined(MBEDTLS_ECP_LIGHT) - -#include "mbedtls/ecp.h" -#include "mbedtls/platform.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" - -#include "mbedtls/platform.h" - -#include "constant_time_internal.h" - -#include "bn_mul.h" -#include "bignum_core.h" -#include "ecp_invasive.h" - -#include <string.h> - -#if !defined(MBEDTLS_ECP_ALT) - -#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } - -#define ECP_MPI_INIT_ARRAY(x) \ - ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) - -#define ECP_POINT_INIT_XY_Z0(x, y) { \ - ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) } -#define ECP_POINT_INIT_XY_Z1(x, y) { \ - ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) } - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -/* For these curves, we build the group parameters dynamically. */ -#define ECP_LOAD_GROUP -static mbedtls_mpi_uint mpi_one[] = { 1 }; -#endif - -/* - * Note: the constants are in little-endian order - * to be directly usable in MPIs - */ - -/* - * Domain parameters for secp192r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -static const mbedtls_mpi_uint secp192r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; -static const mbedtls_mpi_uint secp192r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64), -}; -static const mbedtls_mpi_uint secp192r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), -}; -static const mbedtls_mpi_uint secp192r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), -}; -static const mbedtls_mpi_uint secp192r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp192r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), -}; -static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), -}; -static const mbedtls_mpi_uint secp192r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), -}; -static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), -}; -static const mbedtls_mpi_uint secp192r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), -}; -static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), -}; -static const mbedtls_mpi_uint secp192r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), -}; -static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), -}; -static const mbedtls_mpi_uint secp192r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), -}; -static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), -}; -static const mbedtls_mpi_uint secp192r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), -}; -static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), -}; -static const mbedtls_mpi_uint secp192r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), -}; -static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), -}; -static const mbedtls_mpi_uint secp192r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), -}; -static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), -}; -static const mbedtls_mpi_uint secp192r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), -}; -static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), -}; -static const mbedtls_mpi_uint secp192r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), -}; -static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), -}; -static const mbedtls_mpi_uint secp192r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), -}; -static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), -}; -static const mbedtls_mpi_uint secp192r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), -}; -static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), -}; -static const mbedtls_mpi_uint secp192r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), -}; -static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), -}; -static const mbedtls_mpi_uint secp192r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), -}; -static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), -}; -static const mbedtls_mpi_uint secp192r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), -}; -static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), -}; -static const mbedtls_mpi_uint secp192r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), - MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), -}; -static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), -}; -static const mbedtls_ecp_point secp192r1_T[16] = { - ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), -}; -#else -#define secp192r1_T NULL -#endif -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -/* - * Domain parameters for secp224r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -static const mbedtls_mpi_uint secp224r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C), - MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4), -}; -static const mbedtls_mpi_uint secp224r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7), -}; -static const mbedtls_mpi_uint secp224r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD), -}; -static const mbedtls_mpi_uint secp224r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), -}; -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp224r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_ecp_point secp224r1_T[16] = { - ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), -}; -#else -#define secp224r1_T NULL -#endif -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -/* - * Domain parameters for secp256r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -static const mbedtls_mpi_uint secp256r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), -}; -static const mbedtls_mpi_uint secp256r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A), -}; -static const mbedtls_mpi_uint secp256r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), -}; -static const mbedtls_mpi_uint secp256r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), -}; -static const mbedtls_mpi_uint secp256r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), -}; -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp256r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), -}; -static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), -}; -static const mbedtls_mpi_uint secp256r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), -}; -static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), -}; -static const mbedtls_mpi_uint secp256r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), -}; -static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), -}; -static const mbedtls_mpi_uint secp256r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), -}; -static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), -}; -static const mbedtls_mpi_uint secp256r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), -}; -static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), -}; -static const mbedtls_mpi_uint secp256r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), -}; -static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), -}; -static const mbedtls_mpi_uint secp256r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), -}; -static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), -}; -static const mbedtls_mpi_uint secp256r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), -}; -static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), -}; -static const mbedtls_mpi_uint secp256r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), -}; -static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), -}; -static const mbedtls_mpi_uint secp256r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), -}; -static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), -}; -static const mbedtls_mpi_uint secp256r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), -}; -static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), -}; -static const mbedtls_mpi_uint secp256r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), -}; -static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), -}; -static const mbedtls_mpi_uint secp256r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), -}; -static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), -}; -static const mbedtls_mpi_uint secp256r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), -}; -static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), -}; -static const mbedtls_mpi_uint secp256r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), -}; -static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), -}; -static const mbedtls_mpi_uint secp256r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), -}; -static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), -}; -static const mbedtls_ecp_point secp256r1_T[16] = { - ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), -}; -#else -#define secp256r1_T NULL -#endif - -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -/* - * Domain parameters for secp384r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -static const mbedtls_mpi_uint secp384r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; -static const mbedtls_mpi_uint secp384r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3), -}; -static const mbedtls_mpi_uint secp384r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), -}; -static const mbedtls_mpi_uint secp384r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), -}; -static const mbedtls_mpi_uint secp384r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp384r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), -}; -static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), -}; -static const mbedtls_mpi_uint secp384r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), -}; -static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), -}; -static const mbedtls_mpi_uint secp384r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), -}; -static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), -}; -static const mbedtls_mpi_uint secp384r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), -}; -static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), -}; -static const mbedtls_mpi_uint secp384r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), -}; -static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), - MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), -}; -static const mbedtls_mpi_uint secp384r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), -}; -static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), -}; -static const mbedtls_mpi_uint secp384r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), -}; -static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), -}; -static const mbedtls_mpi_uint secp384r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), -}; -static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), -}; -static const mbedtls_mpi_uint secp384r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), -}; -static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), -}; -static const mbedtls_mpi_uint secp384r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), -}; -static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), -}; -static const mbedtls_mpi_uint secp384r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), -}; -static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), -}; -static const mbedtls_mpi_uint secp384r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), -}; -static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), -}; -static const mbedtls_mpi_uint secp384r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), -}; -static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), -}; -static const mbedtls_mpi_uint secp384r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), -}; -static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), -}; -static const mbedtls_mpi_uint secp384r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), -}; -static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), -}; -static const mbedtls_mpi_uint secp384r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), -}; -static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), -}; -static const mbedtls_mpi_uint secp384r1_T_16_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), -}; -static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), -}; -static const mbedtls_mpi_uint secp384r1_T_17_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), -}; -static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), -}; -static const mbedtls_mpi_uint secp384r1_T_18_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), -}; -static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), -}; -static const mbedtls_mpi_uint secp384r1_T_19_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), -}; -static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), -}; -static const mbedtls_mpi_uint secp384r1_T_20_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), -}; -static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), -}; -static const mbedtls_mpi_uint secp384r1_T_21_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), -}; -static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), -}; -static const mbedtls_mpi_uint secp384r1_T_22_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), -}; -static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), -}; -static const mbedtls_mpi_uint secp384r1_T_23_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), -}; -static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), -}; -static const mbedtls_mpi_uint secp384r1_T_24_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), -}; -static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), -}; -static const mbedtls_mpi_uint secp384r1_T_25_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), -}; -static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), -}; -static const mbedtls_mpi_uint secp384r1_T_26_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), -}; -static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), -}; -static const mbedtls_mpi_uint secp384r1_T_27_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), -}; -static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), -}; -static const mbedtls_mpi_uint secp384r1_T_28_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), -}; -static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), - MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), - MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), -}; -static const mbedtls_mpi_uint secp384r1_T_29_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), -}; -static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), -}; -static const mbedtls_mpi_uint secp384r1_T_30_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), -}; -static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), -}; -static const mbedtls_mpi_uint secp384r1_T_31_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), -}; -static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), -}; -static const mbedtls_ecp_point secp384r1_T[32] = { - ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), - ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), -}; -#else -#define secp384r1_T NULL -#endif - -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -/* - * Domain parameters for secp521r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -static const mbedtls_mpi_uint secp521r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), -}; -static const mbedtls_mpi_uint secp521r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95), - MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), - MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), - MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01), -}; -static const mbedtls_mpi_uint secp521r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), -}; -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp521r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), - MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_16_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_17_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_18_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), - MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_19_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_20_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), - MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_21_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_22_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_23_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_24_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_25_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_26_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_27_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_28_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_29_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_30_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_31_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_ecp_point secp521r1_T[32] = { - ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), - ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), -}; -#else -#define secp521r1_T NULL -#endif -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -static const mbedtls_mpi_uint secp192k1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; -static const mbedtls_mpi_uint secp192k1_a[] = { - MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), -}; -static const mbedtls_mpi_uint secp192k1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00), -}; -static const mbedtls_mpi_uint secp192k1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), -}; -static const mbedtls_mpi_uint secp192k1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), -}; -static const mbedtls_mpi_uint secp192k1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; - -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp192k1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), -}; -static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), -}; -static const mbedtls_mpi_uint secp192k1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), -}; -static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), -}; -static const mbedtls_mpi_uint secp192k1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), -}; -static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), -}; -static const mbedtls_mpi_uint secp192k1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), -}; -static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), -}; -static const mbedtls_mpi_uint secp192k1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), -}; -static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), -}; -static const mbedtls_mpi_uint secp192k1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), -}; -static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), -}; -static const mbedtls_mpi_uint secp192k1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), -}; -static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), -}; -static const mbedtls_mpi_uint secp192k1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), -}; -static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), -}; -static const mbedtls_mpi_uint secp192k1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), -}; -static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), -}; -static const mbedtls_mpi_uint secp192k1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), -}; -static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), -}; -static const mbedtls_mpi_uint secp192k1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), -}; -static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), -}; -static const mbedtls_mpi_uint secp192k1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), -}; -static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), -}; -static const mbedtls_mpi_uint secp192k1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), -}; -static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), -}; -static const mbedtls_mpi_uint secp192k1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), -}; -static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), -}; -static const mbedtls_mpi_uint secp192k1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), -}; -static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), -}; -static const mbedtls_mpi_uint secp192k1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), -}; -static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), -}; -static const mbedtls_ecp_point secp192k1_T[16] = { - ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), -}; -#else -#define secp192k1_T NULL -#endif - -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -static const mbedtls_mpi_uint secp224k1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), -}; -static const mbedtls_mpi_uint secp224k1_a[] = { - MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1), -}; -static const mbedtls_mpi_uint secp224k1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E), -}; -static const mbedtls_mpi_uint secp224k1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), -}; - -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp224k1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), - MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), -}; -static const mbedtls_ecp_point secp224k1_T[16] = { - ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), -}; -#else -#define secp224k1_T NULL -#endif -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -static const mbedtls_mpi_uint secp256k1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; -static const mbedtls_mpi_uint secp256k1_a[] = { - MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), -}; -static const mbedtls_mpi_uint secp256k1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00), -}; -static const mbedtls_mpi_uint secp256k1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), -}; -static const mbedtls_mpi_uint secp256k1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), -}; -static const mbedtls_mpi_uint secp256k1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), -}; - -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint secp256k1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), -}; -static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), -}; -static const mbedtls_mpi_uint secp256k1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), -}; -static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), -}; -static const mbedtls_mpi_uint secp256k1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), -}; -static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), -}; -static const mbedtls_mpi_uint secp256k1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), -}; -static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), -}; -static const mbedtls_mpi_uint secp256k1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), -}; -static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), -}; -static const mbedtls_mpi_uint secp256k1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), -}; -static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), -}; -static const mbedtls_mpi_uint secp256k1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), -}; -static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), -}; -static const mbedtls_mpi_uint secp256k1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), -}; -static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), -}; -static const mbedtls_mpi_uint secp256k1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), -}; -static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), -}; -static const mbedtls_mpi_uint secp256k1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), -}; -static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), -}; -static const mbedtls_mpi_uint secp256k1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), -}; -static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), -}; -static const mbedtls_mpi_uint secp256k1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), -}; -static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), -}; -static const mbedtls_mpi_uint secp256k1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), -}; -static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), -}; -static const mbedtls_mpi_uint secp256k1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), -}; -static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), -}; -static const mbedtls_mpi_uint secp256k1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), -}; -static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), -}; -static const mbedtls_mpi_uint secp256k1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), -}; -static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), -}; -static const mbedtls_ecp_point secp256k1_T[16] = { - ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), - ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), -}; -#else -#define secp256k1_T NULL -#endif -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -/* - * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) - */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP256r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), -}; -static const mbedtls_mpi_uint brainpoolP256r1_a[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D), -}; -static const mbedtls_mpi_uint brainpoolP256r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26), -}; -static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), -}; -static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), -}; -static const mbedtls_mpi_uint brainpoolP256r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), -}; - -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), - MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), -}; -static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), -}; -static const mbedtls_ecp_point brainpoolP256r1_T[16] = { - ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), -}; -#else -#define brainpoolP256r1_T NULL -#endif - -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ - -/* - * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) - */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP384r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), -}; -static const mbedtls_mpi_uint brainpoolP384r1_a[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B), -}; -static const mbedtls_mpi_uint brainpoolP384r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), -}; -static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), -}; -static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), -}; -static const mbedtls_mpi_uint brainpoolP384r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), -}; - -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), - MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), - MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), - MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), - MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), - MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), - MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), - MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), - MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), - MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), -}; -static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), -}; -static const mbedtls_ecp_point brainpoolP384r1_T[32] = { - ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), -}; -#else -#define brainpoolP384r1_T NULL -#endif - -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ - -/* - * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) - */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP512r1_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), -}; -static const mbedtls_mpi_uint brainpoolP512r1_a[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78), -}; -static const mbedtls_mpi_uint brainpoolP512r1_b[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77), - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), -}; -static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), -}; - -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 -static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), - MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), - MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), - MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), - MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), - MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), - MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), - MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), - MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), - MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), - MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), - MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), - MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), - MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), - MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), - MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), - MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), - MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), - MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), - MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), - MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), - MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), - MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), - MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), - MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), - MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), - MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), - MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), - MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), - MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), - MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), - MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), - MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), - MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), - MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), - MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), - MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), - MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), - MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), - MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), - MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), - MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), - MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), - MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), - MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), - MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), - MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), - MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), - MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), - MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), - MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), - MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), - MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), - MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), - MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), - MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), - MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), - MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), - MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), - MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), - MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), - MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), - MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), - MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), - MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), - MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), - MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), - MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), - MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), - MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), - MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), - MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), - MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), - MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), - MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), - MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), - MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), - MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), - MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), - MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), - MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), - MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), - MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), - MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), - MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), - MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), - MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), - MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), - MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), - MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), - MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), - MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), - MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), - MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), - MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), - MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), - MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), - MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), - MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), - MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), - MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), - MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), - MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), - MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), - MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), - MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), - MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), - MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), - MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), - MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), - MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), - MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), - MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), - MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), - MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), - MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), - MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), - MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), - MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), - MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), - MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), - MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), - MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), - MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), - MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), - MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), -}; -static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), - MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), - MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), - MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), - MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), - MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), - MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), -}; -static const mbedtls_ecp_point brainpoolP512r1_T[32] = { - ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), - ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), -}; -#else -#define brainpoolP512r1_T NULL -#endif -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - - -#if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ - defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) -/* - * Create an MPI from embedded constants - * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint) and - * len < 1048576) - */ -static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) -{ - X->s = 1; - X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint)); - X->p = (mbedtls_mpi_uint *) p; -} -#endif - -#if defined(ECP_LOAD_GROUP) -/* - * Set an MPI to static value 1 - */ -static inline void ecp_mpi_set1(mbedtls_mpi *X) -{ - X->s = 1; - X->n = 1; - X->p = mpi_one; -} - -/* - * Make group available from embedded constants - */ -static int ecp_group_load(mbedtls_ecp_group *grp, - const mbedtls_mpi_uint *p, size_t plen, - const mbedtls_mpi_uint *a, size_t alen, - const mbedtls_mpi_uint *b, size_t blen, - const mbedtls_mpi_uint *gx, size_t gxlen, - const mbedtls_mpi_uint *gy, size_t gylen, - const mbedtls_mpi_uint *n, size_t nlen, - const mbedtls_ecp_point *T) -{ - ecp_mpi_load(&grp->P, p, plen); - if (a != NULL) { - ecp_mpi_load(&grp->A, a, alen); - } - ecp_mpi_load(&grp->B, b, blen); - ecp_mpi_load(&grp->N, n, nlen); - - ecp_mpi_load(&grp->G.X, gx, gxlen); - ecp_mpi_load(&grp->G.Y, gy, gylen); - ecp_mpi_set1(&grp->G.Z); - - grp->pbits = mbedtls_mpi_bitlen(&grp->P); - grp->nbits = mbedtls_mpi_bitlen(&grp->N); - - grp->h = 1; - - grp->T = (mbedtls_ecp_point *) T; - /* - * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. - */ - grp->T_size = 0; - - return 0; -} -#endif /* ECP_LOAD_GROUP */ - -#if defined(MBEDTLS_ECP_NIST_OPTIM) -/* Forward declarations */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -static int ecp_mod_p192(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); -#endif -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -static int ecp_mod_p224(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); -#endif -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -static int ecp_mod_p256(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); -#endif -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -static int ecp_mod_p384(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs); -#endif -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -static int ecp_mod_p521(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n); -#endif - -#define NIST_MODP(P) grp->modp = ecp_mod_ ## P; -#else -#define NIST_MODP(P) -#endif /* MBEDTLS_ECP_NIST_OPTIM */ - -/* Additional forward declarations */ -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -static int ecp_mod_p255(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs); -#endif -#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) -static int ecp_mod_p448(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *, size_t); -#endif -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -static int ecp_mod_p192k1(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); -#endif -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -static int ecp_mod_p224k1(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); -#endif -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -static int ecp_mod_p256k1(mbedtls_mpi *); -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); -#endif - -#if defined(ECP_LOAD_GROUP) -#define LOAD_GROUP_A(G) ecp_group_load(grp, \ - G ## _p, sizeof(G ## _p), \ - G ## _a, sizeof(G ## _a), \ - G ## _b, sizeof(G ## _b), \ - G ## _gx, sizeof(G ## _gx), \ - G ## _gy, sizeof(G ## _gy), \ - G ## _n, sizeof(G ## _n), \ - G ## _T \ - ) - -#define LOAD_GROUP(G) ecp_group_load(grp, \ - G ## _p, sizeof(G ## _p), \ - NULL, 0, \ - G ## _b, sizeof(G ## _b), \ - G ## _gx, sizeof(G ## _gx), \ - G ## _gy, sizeof(G ## _gy), \ - G ## _n, sizeof(G ## _n), \ - G ## _T \ - ) -#endif /* ECP_LOAD_GROUP */ - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -/* Constants used by ecp_use_curve25519() */ -static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; - -/* P = 2^255 - 19 */ -static const mbedtls_mpi_uint curve25519_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F) -}; - -/* N = 2^252 + 27742317777372353535851937790883648493 */ -static const mbedtls_mpi_uint curve25519_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58), - MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14), - MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00), - MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10) -}; - -/* - * Specialized function for creating the Curve25519 group - */ -static int ecp_use_curve25519(mbedtls_ecp_group *grp) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* Actually ( A + 2 ) / 4 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24)); - - ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p)); - - grp->pbits = mbedtls_mpi_bitlen(&grp->P); - - ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n)); - - /* Y intentionally not set, since we use x/z coordinates. - * This is used as a marker to identify Montgomery curves! */ - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); - mbedtls_mpi_free(&grp->G.Y); - - /* Actually, the required msb for private keys */ - grp->nbits = 254; - -cleanup: - if (ret != 0) { - mbedtls_ecp_group_free(grp); - } - - return ret; -} -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) -/* Constants used by ecp_use_curve448() */ -static const mbedtls_mpi_sint curve448_a24 = 0x98AA; - -/* P = 2^448 - 2^224 - 1 */ -static const mbedtls_mpi_uint curve448_p[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) -}; - -/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ -static const mbedtls_mpi_uint curve448_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23), - MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21), - MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4), - MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), - MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F), - MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) -}; - -/* - * Specialized function for creating the Curve448 group - */ -static int ecp_use_curve448(mbedtls_ecp_group *grp) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* Actually ( A + 2 ) / 4 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24)); - - ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p)); - grp->pbits = mbedtls_mpi_bitlen(&grp->P); - - /* Y intentionally not set, since we use x/z coordinates. - * This is used as a marker to identify Montgomery curves! */ - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); - mbedtls_mpi_free(&grp->G.Y); - - ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n)); - - /* Actually, the required msb for private keys */ - grp->nbits = 447; - -cleanup: - if (ret != 0) { - mbedtls_ecp_group_free(grp); - } - - return ret; -} -#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ - -/* - * Set a group using well-known domain parameters - */ -int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) -{ - mbedtls_ecp_group_free(grp); - - mbedtls_ecp_group_init(grp); - - grp->id = id; - - switch (id) { -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - case MBEDTLS_ECP_DP_SECP192R1: - NIST_MODP(p192); - return LOAD_GROUP(secp192r1); -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - case MBEDTLS_ECP_DP_SECP224R1: - NIST_MODP(p224); - return LOAD_GROUP(secp224r1); -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - case MBEDTLS_ECP_DP_SECP256R1: - NIST_MODP(p256); - return LOAD_GROUP(secp256r1); -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - case MBEDTLS_ECP_DP_SECP384R1: - NIST_MODP(p384); - return LOAD_GROUP(secp384r1); -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - case MBEDTLS_ECP_DP_SECP521R1: - NIST_MODP(p521); - return LOAD_GROUP(secp521r1); -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - case MBEDTLS_ECP_DP_SECP192K1: - grp->modp = ecp_mod_p192k1; - return LOAD_GROUP_A(secp192k1); -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - case MBEDTLS_ECP_DP_SECP224K1: - grp->modp = ecp_mod_p224k1; - return LOAD_GROUP_A(secp224k1); -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - case MBEDTLS_ECP_DP_SECP256K1: - grp->modp = ecp_mod_p256k1; - return LOAD_GROUP_A(secp256k1); -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - case MBEDTLS_ECP_DP_BP256R1: - return LOAD_GROUP_A(brainpoolP256r1); -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - case MBEDTLS_ECP_DP_BP384R1: - return LOAD_GROUP_A(brainpoolP384r1); -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - case MBEDTLS_ECP_DP_BP512R1: - return LOAD_GROUP_A(brainpoolP512r1); -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - case MBEDTLS_ECP_DP_CURVE25519: - grp->modp = ecp_mod_p255; - return ecp_use_curve25519(grp); -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) - case MBEDTLS_ECP_DP_CURVE448: - grp->modp = ecp_mod_p448; - return ecp_use_curve448(grp); -#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ - - default: - grp->id = MBEDTLS_ECP_DP_NONE; - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } -} - -#if defined(MBEDTLS_ECP_NIST_OPTIM) -/* - * Fast reduction modulo the primes used by the NIST curves. - * - * These functions are critical for speed, but not needed for correct - * operations. So, we make the choice to heavily rely on the internals of our - * bignum library, which creates a tight coupling between these functions and - * our MPI implementation. However, the coupling between the ECP module and - * MPI remains loose, since these functions can be deactivated at will. - */ - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -/* - * Compared to the way things are presented in FIPS 186-3 D.2, - * we proceed in columns, from right (least significant chunk) to left, - * adding chunks to N in place, and keeping a carry for the next chunk. - * This avoids moving things around in memory, and uselessly adding zeros, - * compared to the more straightforward, line-oriented approach. - * - * For this prime we need to handle data in chunks of 64 bits. - * Since this is always a multiple of our basic mbedtls_mpi_uint, we can - * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. - */ - -/* Add 64-bit chunks (dst += src) and update carry */ -static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry) -{ - unsigned char i; - mbedtls_mpi_uint c = 0; - for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) { - *dst += c; c = (*dst < c); - *dst += *src; c += (*dst < *src); - } - *carry += c; -} - -/* Add carry to a 64-bit chunk and update carry */ -static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) -{ - unsigned char i; - for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) { - *dst += *carry; - *carry = (*dst < *carry); - } -} - -#define WIDTH 8 / sizeof(mbedtls_mpi_uint) -#define A(i) Np + (i) * WIDTH -#define ADD(i) add64(p, A(i), &c) -#define NEXT p += WIDTH; carry64(p, &c) -#define LAST p += WIDTH; do *p = 0; while (++p < end) -#define RESET last_carry[0] = c; c = 0; p = Np -#define ADD_LAST add64(p, last_carry, &c) - -/* - * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) - */ -static int ecp_mod_p192(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(192) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width); - -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) -{ - mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; - mbedtls_mpi_uint *p, *end; - - if (Nn != BITS_TO_LIMBS(192) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - p = Np; - end = p + Nn; - - ADD(3); ADD(5); NEXT; // A0 += A3 + A5 - ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 - ADD(4); ADD(5); // A2 += A4 + A5 - - RESET; - - /* Use the reduction for the carry as well: - * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 - * It can generate a carry. */ - ADD_LAST; NEXT; // A0 += last_carry - ADD_LAST; NEXT; // A1 += last_carry - // A2 += carry - - RESET; - - /* Use the reduction for the carry as well: - * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 - */ - ADD_LAST; NEXT; // A0 += last_carry - ADD_LAST; NEXT; // A1 += last_carry - // A2 += carry - - LAST; - - return 0; -} - -#undef WIDTH -#undef A -#undef ADD -#undef NEXT -#undef LAST -#undef RESET -#undef ADD_LAST -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - -/* - * The reader is advised to first understand ecp_mod_p192() since the same - * general structure is used here, but with additional complications: - * (1) chunks of 32 bits, and (2) subtractions. - */ - -/* - * For these primes, we need to handle data in chunks of 32 bits. - * This makes it more complicated if we use 64 bits limbs in MPI, - * which prevents us from using a uniform access method as for p192. - * - * So, we define a mini abstraction layer to access 32 bit chunks, - * load them in 'cur' for work, and store them back from 'cur' when done. - * - * While at it, also define the size of N in terms of 32-bit chunks. - */ -#define LOAD32 cur = A(i); - -#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ - -#define MAX32 X_limbs -#define A(j) X[j] -#define STORE32 X[i] = (mbedtls_mpi_uint) cur; -#define STORE0 X[i] = 0; - -#else /* 64 bit */ - -#define MAX32 X_limbs * 2 -#define A(j) \ - (j) % 2 ? \ - (uint32_t) (X[(j) / 2] >> 32) : \ - (uint32_t) (X[(j) / 2]) -#define STORE32 \ - if (i % 2) { \ - X[i/2] &= 0x00000000FFFFFFFF; \ - X[i/2] |= (uint64_t) (cur) << 32; \ - } else { \ - X[i/2] &= 0xFFFFFFFF00000000; \ - X[i/2] |= (uint32_t) cur; \ - } - -#define STORE0 \ - if (i % 2) { \ - X[i/2] &= 0x00000000FFFFFFFF; \ - } else { \ - X[i/2] &= 0xFFFFFFFF00000000; \ - } - -#endif - -static inline int8_t extract_carry(int64_t cur) -{ - return (int8_t) (cur >> 32); -} - -#define ADD(j) cur += A(j) -#define SUB(j) cur -= A(j) - -#define ADD_CARRY(cc) cur += (cc) -#define SUB_CARRY(cc) cur -= (cc) - -#define ADD_LAST ADD_CARRY(last_c) -#define SUB_LAST SUB_CARRY(last_c) - -/* - * Helpers for the main 'loop' - */ -#define INIT(b) \ - int8_t c = 0, last_c; \ - int64_t cur; \ - size_t i = 0; \ - LOAD32; - -#define NEXT \ - c = extract_carry(cur); \ - STORE32; i++; LOAD32; \ - ADD_CARRY(c); - -#define RESET \ - c = extract_carry(cur); \ - last_c = c; \ - STORE32; i = 0; LOAD32; \ - c = 0; \ - -#define LAST \ - c = extract_carry(cur); \ - STORE32; i++; \ - if (c != 0) \ - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; \ - while (i < MAX32) { STORE0; i++; } - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - -/* - * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) - */ -static int ecp_mod_p224(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(224) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width); -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - if (X_limbs != BITS_TO_LIMBS(224) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - INIT(224); - - SUB(7); SUB(11); NEXT; // A0 += -A7 - A11 - SUB(8); SUB(12); NEXT; // A1 += -A8 - A12 - SUB(9); SUB(13); NEXT; // A2 += -A9 - A13 - SUB(10); ADD(7); ADD(11); NEXT; // A3 += -A10 + A7 + A11 - SUB(11); ADD(8); ADD(12); NEXT; // A4 += -A11 + A8 + A12 - SUB(12); ADD(9); ADD(13); NEXT; // A5 += -A12 + A9 + A13 - SUB(13); ADD(10); // A6 += -A13 + A10 - - RESET; - - /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */ - SUB_LAST; NEXT; // A0 -= last_c - ; NEXT; // A1 - ; NEXT; // A2 - ADD_LAST; NEXT; // A3 += last_c - ; NEXT; // A4 - ; NEXT; // A5 - // A6 - - /* The carry reduction cannot generate a carry - * (see commit 73e8553 for details)*/ - - LAST; - - return 0; -} - -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - -/* - * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) - */ -static int ecp_mod_p256(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(256) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width); -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - if (X_limbs != BITS_TO_LIMBS(256) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - INIT(256); - - ADD(8); ADD(9); - SUB(11); SUB(12); SUB(13); SUB(14); NEXT; // A0 - - ADD(9); ADD(10); - SUB(12); SUB(13); SUB(14); SUB(15); NEXT; // A1 - - ADD(10); ADD(11); - SUB(13); SUB(14); SUB(15); NEXT; // A2 - - ADD(11); ADD(11); ADD(12); ADD(12); ADD(13); - SUB(15); SUB(8); SUB(9); NEXT; // A3 - - ADD(12); ADD(12); ADD(13); ADD(13); ADD(14); - SUB(9); SUB(10); NEXT; // A4 - - ADD(13); ADD(13); ADD(14); ADD(14); ADD(15); - SUB(10); SUB(11); NEXT; // A5 - - ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13); - SUB(8); SUB(9); NEXT; // A6 - - ADD(15); ADD(15); ADD(15); ADD(8); - SUB(10); SUB(11); SUB(12); SUB(13); // A7 - - RESET; - - /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 - * to modulo reduce the final carry. */ - ADD_LAST; NEXT; // A0 - ; NEXT; // A1 - ; NEXT; // A2 - SUB_LAST; NEXT; // A3 - ; NEXT; // A4 - ; NEXT; // A5 - SUB_LAST; NEXT; // A6 - ADD_LAST; // A7 - - RESET; - - /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 - * to modulo reduce the carry generated by the previous reduction. */ - ADD_LAST; NEXT; // A0 - ; NEXT; // A1 - ; NEXT; // A2 - SUB_LAST; NEXT; // A3 - ; NEXT; // A4 - ; NEXT; // A5 - SUB_LAST; NEXT; // A6 - ADD_LAST; // A7 - - LAST; - - return 0; -} - -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -/* - * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) - */ -static int ecp_mod_p384(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(384) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p384_raw(N->p, expected_width); -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - if (X_limbs != BITS_TO_LIMBS(384) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - INIT(384); - - ADD(12); ADD(21); ADD(20); - SUB(23); NEXT; // A0 - - ADD(13); ADD(22); ADD(23); - SUB(12); SUB(20); NEXT; // A1 - - ADD(14); ADD(23); - SUB(13); SUB(21); NEXT; // A2 - - ADD(15); ADD(12); ADD(20); ADD(21); - SUB(14); SUB(22); SUB(23); NEXT; // A3 - - ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22); - SUB(15); SUB(23); SUB(23); NEXT; // A4 - - ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23); - SUB(16); NEXT; // A5 - - ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22); - SUB(17); NEXT; // A6 - - ADD(19); ADD(16); ADD(15); ADD(23); - SUB(18); NEXT; // A7 - - ADD(20); ADD(17); ADD(16); - SUB(19); NEXT; // A8 - - ADD(21); ADD(18); ADD(17); - SUB(20); NEXT; // A9 - - ADD(22); ADD(19); ADD(18); - SUB(21); NEXT; // A10 - - ADD(23); ADD(20); ADD(19); - SUB(22); // A11 - - RESET; - - /* Use 2^384 = P + 2^128 + 2^96 - 2^32 + 1 to modulo reduce the final carry */ - ADD_LAST; NEXT; // A0 - SUB_LAST; NEXT; // A1 - ; NEXT; // A2 - ADD_LAST; NEXT; // A3 - ADD_LAST; NEXT; // A4 - ; NEXT; // A5 - ; NEXT; // A6 - ; NEXT; // A7 - ; NEXT; // A8 - ; NEXT; // A9 - ; NEXT; // A10 - // A11 - - RESET; - - ADD_LAST; NEXT; // A0 - SUB_LAST; NEXT; // A1 - ; NEXT; // A2 - ADD_LAST; NEXT; // A3 - ADD_LAST; NEXT; // A4 - ; NEXT; // A5 - ; NEXT; // A6 - ; NEXT; // A7 - ; NEXT; // A8 - ; NEXT; // A9 - ; NEXT; // A10 - // A11 - - LAST; - - return 0; -} -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#undef LOAD32 -#undef MAX32 -#undef A -#undef STORE32 -#undef STORE0 -#undef ADD -#undef SUB -#undef ADD_CARRY -#undef SUB_CARRY -#undef ADD_LAST -#undef SUB_LAST -#undef INIT -#undef NEXT -#undef RESET -#undef LAST - -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || - MBEDTLS_ECP_DP_SECP256R1_ENABLED || - MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -/* Size of p521 in terms of mbedtls_mpi_uint */ -#define P521_WIDTH (521 / 8 / sizeof(mbedtls_mpi_uint) + 1) - -/* Bits to keep in the most significant mbedtls_mpi_uint */ -#define P521_MASK 0x01FF - -/* - * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) - */ -static int ecp_mod_p521(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(521) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width); -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - mbedtls_mpi_uint carry = 0; - - if (X_limbs != BITS_TO_LIMBS(521) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - /* Step 1: Reduction to P521_WIDTH limbs */ - /* Helper references for bottom part of X */ - mbedtls_mpi_uint *X0 = X; - size_t X0_limbs = P521_WIDTH; - /* Helper references for top part of X */ - mbedtls_mpi_uint *X1 = X + X0_limbs; - size_t X1_limbs = X_limbs - X0_limbs; - /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1. - * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that - * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.) - * The high order limb of the result will be held in carry and the rest - * in X0 (that is the result will be represented as - * 2^P521_WIDTH carry + X0). - * - * Also, note that the resulting carry is either 0 or 1: - * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512 - * therefore - * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9) - * which in turn is less than 2 * 2^(512 + biL). - */ - mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9); - carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift); - /* Set X to X0 (by clearing the top part). */ - memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint)); - - /* Step 2: Reduction modulo P521 - * - * At this point X is reduced to P521_WIDTH limbs. What remains is to add - * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */ - - /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521. - * Also, recall that carry is either 0 or 1. */ - mbedtls_mpi_uint addend = carry << (biL - 9); - /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */ - addend += (X[P521_WIDTH - 1] >> 9); - X[P521_WIDTH - 1] &= P521_MASK; - - /* Reuse the top part of X (already zeroed) as a helper array for - * carrying out the addition. */ - mbedtls_mpi_uint *addend_arr = X + P521_WIDTH; - addend_arr[0] = addend; - (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH); - /* Both addends were less than P521 therefore X < 2 * P521. (This also means - * that the result fit in P521_WIDTH limbs and there won't be any carry.) */ - - /* Clear the reused part of X. */ - addend_arr[0] = 0; - - return 0; -} - -#undef P521_WIDTH -#undef P521_MASK - -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#endif /* MBEDTLS_ECP_NIST_OPTIM */ - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - -/* Size of p255 in terms of mbedtls_mpi_uint */ -#define P255_WIDTH (255 / 8 / sizeof(mbedtls_mpi_uint) + 1) - -/* - * Fast quasi-reduction modulo p255 = 2^255 - 19 - * Write N as A0 + 2^256 A1, return A0 + 38 * A1 - */ -static int ecp_mod_p255(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(255) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p255_raw(N->p, expected_width); -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_Limbs) -{ - - if (X_Limbs != BITS_TO_LIMBS(255) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - mbedtls_mpi_uint *carry = mbedtls_calloc(P255_WIDTH, ciL); - if (carry == NULL) { - return MBEDTLS_ERR_ECP_ALLOC_FAILED; - } - - /* Step 1: Reduction to P255_WIDTH limbs */ - if (X_Limbs > P255_WIDTH) { - /* Helper references for top part of X */ - mbedtls_mpi_uint * const A1 = X + P255_WIDTH; - const size_t A1_limbs = X_Limbs - P255_WIDTH; - - /* X = A0 + 38 * A1, capture carry out */ - *carry = mbedtls_mpi_core_mla(X, P255_WIDTH, A1, A1_limbs, 38); - /* Clear top part */ - memset(A1, 0, sizeof(mbedtls_mpi_uint) * A1_limbs); - } - - /* Step 2: Reduce to <2p - * Split as A0 + 2^255*c, with c a scalar, and compute A0 + 19*c */ - *carry <<= 1; - *carry += (X[P255_WIDTH - 1] >> (biL - 1)); - *carry *= 19; - - /* Clear top bit */ - X[P255_WIDTH - 1] <<= 1; X[P255_WIDTH - 1] >>= 1; - /* Since the top bit for X has been cleared 0 + 0 + Carry - * will not overflow. - * - * Furthermore for 2p = 2^256-38. When a carry propagation on the highest - * limb occurs, X > 2^255 and all the remaining bits on the limb are zero. - * - If X < 2^255 ==> X < 2p - * - If X > 2^255 ==> X < 2^256 - 2^255 < 2p */ - (void) mbedtls_mpi_core_add(X, X, carry, P255_WIDTH); - - mbedtls_free(carry); - return 0; -} -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) - -/* Size of p448 in terms of mbedtls_mpi_uint */ -#define P448_WIDTH (448 / 8 / sizeof(mbedtls_mpi_uint)) - -/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ -#define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y)) -#define P224_SIZE (224 / 8) -#define P224_WIDTH_MIN (P224_SIZE / sizeof(mbedtls_mpi_uint)) -#define P224_WIDTH_MAX DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint)) -#define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224) - -static int ecp_mod_p448(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(448) * 2; - - /* This is required as some tests and use cases do not pass in a Bignum of - * the correct size, and expect the growth to be done automatically, which - * will no longer happen. */ - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - - ret = mbedtls_ecp_mod_p448_raw(N->p, N->n); - -cleanup: - return ret; -} - -/* - * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 - * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 + - * (B0 + B1) * 2^224. This is different to the reference implementation of - * Curve448, which uses its own special 56-bit limbs rather than a generic - * bignum library. We could squeeze some extra speed out on 32-bit machines by - * splitting N up into 32-bit limbs and doing the arithmetic using the limbs - * directly as we do for the NIST primes above, but for 64-bit targets it should - * use half the number of operations if we do the reduction with 224-bit limbs, - * since mpi_core_add will then use 64-bit adds. - */ -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - size_t round; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (X_limbs != BITS_TO_LIMBS(448) * 2) { - return 0; - } - - size_t M_limbs = X_limbs - (P448_WIDTH); - - if (M_limbs > P448_WIDTH) { - /* Shouldn't be called with X larger than 2^896! */ - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - /* Both M and Q require an extra limb to catch carries. */ - M_limbs++; - - const size_t Q_limbs = M_limbs; - mbedtls_mpi_uint *M = NULL; - mbedtls_mpi_uint *Q = NULL; - - M = mbedtls_calloc(M_limbs, ciL); - - if (M == NULL) { - return MBEDTLS_ERR_ECP_ALLOC_FAILED; - } - - Q = mbedtls_calloc(Q_limbs, ciL); - - if (Q == NULL) { - ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; - goto cleanup; - } - - /* M = A1 */ - memset(M, 0, (M_limbs * ciL)); - /* Do not copy into the overflow limb, as this would read past the end of - * X. */ - memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); - - /* X = A0 */ - memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); - - /* X = X + M = A0 + A1 */ - /* Carry here fits in oversize X. Oversize M means it will get - * added in, not returned as carry. */ - (void) mbedtls_mpi_core_add(X, X, M, M_limbs); - - /* Q = B1 = M >> 224 */ - memcpy(Q, (char *) M + P224_SIZE, P224_SIZE); - memset((char *) Q + P224_SIZE, 0, P224_SIZE); - - /* X = X + Q = (A0 + A1) + B1 - * Oversize Q catches potential carry here when X is already max 448 bits. - */ - (void) mbedtls_mpi_core_add(X, X, Q, Q_limbs); - - /* M = B0 */ -#ifdef MBEDTLS_HAVE_INT64 - M[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS); - #endif - memset(M + P224_WIDTH_MAX, 0, ((M_limbs - P224_WIDTH_MAX) * ciL)); - - /* M = M + Q = B0 + B1 */ - (void) mbedtls_mpi_core_add(M, M, Q, Q_limbs); - - /* M = (B0 + B1) * 2^224 */ - /* Shifted carry bit from the addition fits in oversize M. */ - memmove((char *) M + P224_SIZE, M, P224_SIZE + ciL); - memset(M, 0, P224_SIZE); - - /* X = X + M = (A0 + A1 + B1) + (B0 + B1) * 2^224 */ - (void) mbedtls_mpi_core_add(X, X, M, M_limbs); - - /* In the second and third rounds A1 and B0 have at most 1 non-zero limb and - * B1=0. - * Using this we need to calculate: - * A0 + A1 + B1 + (B0 + B1) * 2^224 = A0 + A1 + B0 * 2^224. */ - for (round = 0; round < 2; ++round) { - - /* M = A1 */ - memset(M, 0, (M_limbs * ciL)); - memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); - - /* X = A0 */ - memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); - - /* M = A1 + B0 * 2^224 - * We know that only one limb of A1 will be non-zero and that it will be - * limb 0. We also know that B0 is the bottom 224 bits of A1 (which is - * then shifted up 224 bits), so, given M is currently A1 this turns - * into: - * M = M + (M << 224) - * As the single non-zero limb in B0 will be A1 limb 0 shifted up by 224 - * bits, we can just move that into the right place, shifted up - * accordingly.*/ - M[P224_WIDTH_MIN] = M[0] << (224 & (biL - 1)); - - /* X = A0 + (A1 + B0 * 2^224) */ - (void) mbedtls_mpi_core_add(X, X, M, M_limbs); - } - - ret = 0; - -cleanup: - mbedtls_free(M); - mbedtls_free(Q); - - return ret; -} -#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - -/* - * Fast quasi-reduction modulo P = 2^s - R, - * with R about 33 bits, used by the Koblitz curves. - * - * Write X as A0 + 2^224 A1, return A0 + R * A1. - */ -#define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R - -static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, - size_t X_limbs, - mbedtls_mpi_uint *R, - size_t bits) -{ - int ret = 0; - - /* Determine if A1 is aligned to limb bitsize. If not then the used limbs - * of P, A0 and A1 must be set accordingly and there is a middle limb - * which is shared by A0 and A1 and need to handle accordingly. - */ - size_t shift = bits % biL; - size_t adjust = (shift + biL - 1) / biL; - size_t P_limbs = bits / biL + adjust; - - mbedtls_mpi_uint *A1 = mbedtls_calloc(P_limbs, ciL); - if (A1 == NULL) { - return MBEDTLS_ERR_ECP_ALLOC_FAILED; - } - - /* Create a buffer to store the value of `R * A1` */ - size_t R_limbs = P_KOBLITZ_R; - size_t M_limbs = P_limbs + R_limbs; - mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); - if (M == NULL) { - ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; - goto cleanup; - } - - mbedtls_mpi_uint mask = 0; - if (adjust != 0) { - mask = ((mbedtls_mpi_uint) 1 << shift) - 1; - } - - /* Two passes are needed to reduce the value of `A0 + R * A1` and then - * we need an additional one to reduce the possible overflow during - * the addition. - */ - for (size_t pass = 0; pass < 3; pass++) { - /* Copy A1 */ - memcpy(A1, X + P_limbs - adjust, P_limbs * ciL); - - /* Shift A1 to be aligned */ - if (shift != 0) { - mbedtls_mpi_core_shift_r(A1, P_limbs, shift); - } - - /* Zeroize the A1 part of the shared limb */ - if (mask != 0) { - X[P_limbs - 1] &= mask; - } - - /* X = A0 - * Zeroize the A1 part of X to keep only the A0 part. - */ - for (size_t i = P_limbs; i < X_limbs; i++) { - X[i] = 0; - } - - /* X = A0 + R * A1 */ - mbedtls_mpi_core_mul(M, A1, P_limbs, R, R_limbs); - (void) mbedtls_mpi_core_add(X, X, M, P_limbs + R_limbs); - - /* Carry can not be generated since R is a 33-bit value and stored in - * 64 bits. The result value of the multiplication is at most - * P length + 33 bits in length and the result value of the addition - * is at most P length + 34 bits in length. So the result of the - * addition always fits in P length + 64 bits. - */ - } - -cleanup: - mbedtls_free(M); - mbedtls_free(A1); - - return ret; -} - -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || - MBEDTLS_ECP_DP_SECP224K1_ENABLED) || - MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - -/* - * Fast quasi-reduction modulo p192k1 = 2^192 - R, - * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 - */ -static int ecp_mod_p192k1(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(192) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p192k1_raw(N->p, expected_width); - -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - static mbedtls_mpi_uint Rp[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00) - }; - - if (X_limbs != BITS_TO_LIMBS(192) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - return ecp_mod_koblitz(X, X_limbs, Rp, 192); -} - -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - -/* - * Fast quasi-reduction modulo p224k1 = 2^224 - R, - * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 - */ -static int ecp_mod_p224k1(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(224) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p224k1_raw(N->p, expected_width); - -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - static mbedtls_mpi_uint Rp[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00) - }; - - if (X_limbs != BITS_TO_LIMBS(224) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - return ecp_mod_koblitz(X, X_limbs, Rp, 224); -} - -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - -/* - * Fast quasi-reduction modulo p256k1 = 2^256 - R, - * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 - */ -static int ecp_mod_p256k1(mbedtls_mpi *N) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_width = BITS_TO_LIMBS(256) * 2; - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = mbedtls_ecp_mod_p256k1_raw(N->p, expected_width); - -cleanup: - return ret; -} - -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) -{ - static mbedtls_mpi_uint Rp[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00) - }; - - if (X_limbs != BITS_TO_LIMBS(256) * 2) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - return ecp_mod_koblitz(X, X_limbs, Rp, 256); -} - -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -#if defined(MBEDTLS_TEST_HOOKS) -MBEDTLS_STATIC_TESTABLE -int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, - const mbedtls_ecp_group_id id, - const mbedtls_ecp_modulus_type ctype) -{ - mbedtls_mpi_modp_fn modp = NULL; - mbedtls_mpi_uint *p = NULL; - size_t p_limbs; - - if (!(ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE || \ - ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_SCALAR)) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - switch (id) { -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - case MBEDTLS_ECP_DP_SECP192R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { -#if defined(MBEDTLS_ECP_NIST_OPTIM) - modp = &mbedtls_ecp_mod_p192_raw; -#endif - p = (mbedtls_mpi_uint *) secp192r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p)); - } else { - p = (mbedtls_mpi_uint *) secp192r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - case MBEDTLS_ECP_DP_SECP224R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { -#if defined(MBEDTLS_ECP_NIST_OPTIM) - modp = &mbedtls_ecp_mod_p224_raw; -#endif - p = (mbedtls_mpi_uint *) secp224r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p)); - } else { - p = (mbedtls_mpi_uint *) secp224r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - case MBEDTLS_ECP_DP_SECP256R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { -#if defined(MBEDTLS_ECP_NIST_OPTIM) - modp = &mbedtls_ecp_mod_p256_raw; -#endif - p = (mbedtls_mpi_uint *) secp256r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p)); - } else { - p = (mbedtls_mpi_uint *) secp256r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - case MBEDTLS_ECP_DP_SECP384R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { -#if defined(MBEDTLS_ECP_NIST_OPTIM) - modp = &mbedtls_ecp_mod_p384_raw; -#endif - p = (mbedtls_mpi_uint *) secp384r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p)); - } else { - p = (mbedtls_mpi_uint *) secp384r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - case MBEDTLS_ECP_DP_SECP521R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { -#if defined(MBEDTLS_ECP_NIST_OPTIM) - modp = &mbedtls_ecp_mod_p521_raw; -#endif - p = (mbedtls_mpi_uint *) secp521r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p)); - } else { - p = (mbedtls_mpi_uint *) secp521r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - case MBEDTLS_ECP_DP_BP256R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - p = (mbedtls_mpi_uint *) brainpoolP256r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p)); - } else { - p = (mbedtls_mpi_uint *) brainpoolP256r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - case MBEDTLS_ECP_DP_BP384R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - p = (mbedtls_mpi_uint *) brainpoolP384r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p)); - } else { - p = (mbedtls_mpi_uint *) brainpoolP384r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - case MBEDTLS_ECP_DP_BP512R1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - p = (mbedtls_mpi_uint *) brainpoolP512r1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p)); - } else { - p = (mbedtls_mpi_uint *) brainpoolP512r1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - case MBEDTLS_ECP_DP_CURVE25519: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - modp = &mbedtls_ecp_mod_p255_raw; - p = (mbedtls_mpi_uint *) curve25519_p; - p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p)); - } else { - p = (mbedtls_mpi_uint *) curve25519_n; - p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - case MBEDTLS_ECP_DP_SECP192K1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - modp = &mbedtls_ecp_mod_p192k1_raw; - p = (mbedtls_mpi_uint *) secp192k1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p)); - } else { - p = (mbedtls_mpi_uint *) secp192k1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - case MBEDTLS_ECP_DP_SECP224K1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - modp = &mbedtls_ecp_mod_p224k1_raw; - p = (mbedtls_mpi_uint *) secp224k1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p)); - } else { - p = (mbedtls_mpi_uint *) secp224k1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - case MBEDTLS_ECP_DP_SECP256K1: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - modp = &mbedtls_ecp_mod_p256k1_raw; - p = (mbedtls_mpi_uint *) secp256k1_p; - p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p)); - } else { - p = (mbedtls_mpi_uint *) secp256k1_n; - p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n)); - } - break; -#endif - -#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) - case MBEDTLS_ECP_DP_CURVE448: - if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { - modp = &mbedtls_ecp_mod_p448_raw; - p = (mbedtls_mpi_uint *) curve448_p; - p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p)); - } else { - p = (mbedtls_mpi_uint *) curve448_n; - p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n)); - } - break; -#endif - - default: - case MBEDTLS_ECP_DP_NONE: - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if (modp != NULL) { - if (mbedtls_mpi_mod_optred_modulus_setup(N, p, p_limbs, modp)) { - return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - } - } else { - if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs)) { - return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - } - } - return 0; -} -#endif /* MBEDTLS_TEST_HOOKS */ - -#if defined(MBEDTLS_TEST_HOOKS) - -MBEDTLS_STATIC_TESTABLE -mbedtls_ecp_variant mbedtls_ecp_get_variant(void) -{ - return MBEDTLS_ECP_VARIANT_WITH_MPI_UINT; -} - -#endif /* MBEDTLS_TEST_HOOKS */ - -#endif /* !MBEDTLS_ECP_ALT */ -#endif /* MBEDTLS_ECP_LIGHT */ -#endif /* MBEDTLS_ECP_WITH_MPI_UINT */ diff --git a/thirdparty/mbedtls/library/lmots.c b/thirdparty/mbedtls/library/lmots.c deleted file mode 100644 index c51cb41ece..0000000000 --- a/thirdparty/mbedtls/library/lmots.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * The LM-OTS one-time public-key signature scheme - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -/* - * The following sources were referenced in the design of this implementation - * of the LM-OTS algorithm: - * - * [1] IETF RFC8554 - * D. McGrew, M. Curcio, S.Fluhrer - * https://datatracker.ietf.org/doc/html/rfc8554 - * - * [2] NIST Special Publication 800-208 - * David A. Cooper et. al. - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf - */ - -#include "common.h" - -#if defined(MBEDTLS_LMS_C) - -#include <string.h> - -#include "lmots.h" - -#include "mbedtls/lms.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" -#include "psa_util_internal.h" - -#include "psa/crypto.h" - -/* Define a local translating function to save code size by not using too many - * arguments in each translating place. */ -static int local_err_translation(psa_status_t status) -{ - return psa_status_to_mbedtls(status, psa_to_lms_errors, - ARRAY_LENGTH(psa_to_lms_errors), - psa_generic_status_to_mbedtls); -} -#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) - -#define PUBLIC_KEY_TYPE_OFFSET (0) -#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ - MBEDTLS_LMOTS_TYPE_LEN) -#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ - MBEDTLS_LMOTS_I_KEY_ID_LEN) -#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ - MBEDTLS_LMOTS_Q_LEAF_ID_LEN) - -/* We only support parameter sets that use 8-bit digits, as it does not require - * translation logic between digits and bytes */ -#define W_WINTERNITZ_PARAMETER (8u) -#define CHECKSUM_LEN (2) -#define I_DIGIT_IDX_LEN (2) -#define J_HASH_IDX_LEN (1) -#define D_CONST_LEN (2) - -#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) - -#define D_CONST_LEN (2) -static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 }; -static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 }; - -#if defined(MBEDTLS_TEST_HOOKS) -int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL; -#endif /* defined(MBEDTLS_TEST_HOOKS) */ - -/* Calculate the checksum digits that are appended to the end of the LMOTS digit - * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of - * the checksum algorithm. - * - * params The LMOTS parameter set, I and q values which - * describe the key being used. - * - * digest The digit string to create the digest from. As - * this does not contain a checksum, it is the same - * size as a hash output. - */ -static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params, - const unsigned char *digest) -{ - size_t idx; - unsigned sum = 0; - - for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) { - sum += DIGIT_MAX_VALUE - digest[idx]; - } - - return sum; -} - -/* Create the string of digest digits (in the base determined by the Winternitz - * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST - * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm - * 4b step 3) for details. - * - * params The LMOTS parameter set, I and q values which - * describe the key being used. - * - * msg The message that will be hashed to create the - * digest. - * - * msg_size The size of the message. - * - * C_random_value The random value that will be combined with the - * message digest. This is always the same size as a - * hash output for whichever hash algorithm is - * determined by the parameter set. - * - * output An output containing the digit string (+ - * checksum) of length P digits (in the case of - * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of - * size P bytes). - */ -static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params, - const unsigned char *msg, - size_t msg_len, - const unsigned char *C_random_value, - unsigned char *out) -{ - psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t output_hash_len; - unsigned short checksum; - - status = psa_hash_setup(&op, PSA_ALG_SHA_256); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, params->I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, params->q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, C_random_value, - MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, msg, msg_len); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_finish(&op, out, - MBEDTLS_LMOTS_N_HASH_LEN(params->type), - &output_hash_len); - if (status != PSA_SUCCESS) { - goto exit; - } - - checksum = lmots_checksum_calculate(params, out); - MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); - -exit: - psa_hash_abort(&op); - - return PSA_TO_MBEDTLS_ERR(status); -} - -/* Hash each element of the string of digits (+ checksum), producing a hash - * output for each element. This is used in several places (by varying the - * hash_idx_min/max_values) in order to calculate a public key from a private - * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554 - * Algorithm 3 step 5), and to calculate a public key candidate from a - * signature and message (RFC8554 Algorithm 4b step 3). - * - * params The LMOTS parameter set, I and q values which - * describe the key being used. - * - * x_digit_array The array of digits (of size P, 34 in the case of - * MBEDTLS_LMOTS_SHA256_N32_W8). - * - * hash_idx_min_values An array of the starting values of the j iterator - * for each of the members of the digit array. If - * this value in NULL, then all iterators will start - * at 0. - * - * hash_idx_max_values An array of the upper bound values of the j - * iterator for each of the members of the digit - * array. If this value in NULL, then iterator is - * bounded to be less than 2^w - 1 (255 in the case - * of MBEDTLS_LMOTS_SHA256_N32_W8) - * - * output An array containing a hash output for each member - * of the digit string P. In the case of - * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * - * 34. - */ -static int hash_digit_array(const mbedtls_lmots_parameters_t *params, - const unsigned char *x_digit_array, - const unsigned char *hash_idx_min_values, - const unsigned char *hash_idx_max_values, - unsigned char *output) -{ - unsigned int i_digit_idx; - unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; - unsigned int j_hash_idx; - unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; - unsigned int j_hash_idx_min; - unsigned int j_hash_idx_max; - psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t output_hash_len; - unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - - for (i_digit_idx = 0; - i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); - i_digit_idx++) { - - memcpy(tmp_hash, - &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], - MBEDTLS_LMOTS_N_HASH_LEN(params->type)); - - j_hash_idx_min = hash_idx_min_values != NULL ? - hash_idx_min_values[i_digit_idx] : 0; - j_hash_idx_max = hash_idx_max_values != NULL ? - hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; - - for (j_hash_idx = j_hash_idx_min; - j_hash_idx < j_hash_idx_max; - j_hash_idx++) { - status = psa_hash_setup(&op, PSA_ALG_SHA_256); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, - params->I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, - params->q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); - status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - j_hash_idx_bytes[0] = (uint8_t) j_hash_idx; - status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, tmp_hash, - MBEDTLS_LMOTS_N_HASH_LEN(params->type)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash), - &output_hash_len); - if (status != PSA_SUCCESS) { - goto exit; - } - - psa_hash_abort(&op); - } - - memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], - tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); - } - -exit: - psa_hash_abort(&op); - mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash)); - - return PSA_TO_MBEDTLS_ERR(status); -} - -/* Combine the hashes of the digit array into a public key. This is used in - * in order to calculate a public key from a private key (RFC8554 Algorithm 1 - * step 4), and to calculate a public key candidate from a signature and message - * (RFC8554 Algorithm 4b step 3). - * - * params The LMOTS parameter set, I and q values which describe - * the key being used. - * y_hashed_digits The array of hashes, one hash for each digit of the - * symbol array (which is of size P, 34 in the case of - * MBEDTLS_LMOTS_SHA256_N32_W8) - * - * pub_key The output public key (or candidate public key in - * case this is being run as part of signature - * verification), in the form of a hash output. - */ -static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params, - const unsigned char *y_hashed_digits, - unsigned char *pub_key) -{ - psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t output_hash_len; - - status = psa_hash_setup(&op, PSA_ALG_SHA_256); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, - params->I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, params->q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, y_hashed_digits, - MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * - MBEDTLS_LMOTS_N_HASH_LEN(params->type)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_finish(&op, pub_key, - MBEDTLS_LMOTS_N_HASH_LEN(params->type), - &output_hash_len); - if (status != PSA_SUCCESS) { - -exit: - psa_hash_abort(&op); - } - - return PSA_TO_MBEDTLS_ERR(status); -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -int mbedtls_lms_error_from_psa(psa_status_t status) -{ - switch (status) { - case PSA_SUCCESS: - return 0; - case PSA_ERROR_HARDWARE_FAILURE: - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - case PSA_ERROR_NOT_SUPPORTED: - return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; - case PSA_ERROR_BUFFER_TOO_SMALL: - return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; - case PSA_ERROR_INVALID_ARGUMENT: - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - default: - return MBEDTLS_ERR_ERROR_GENERIC_ERROR; - } -} -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); -} - -void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, sizeof(*ctx)); -} - -int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, - const unsigned char *key, size_t key_len) -{ - if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - ctx->params.type = (mbedtls_lmots_algorithm_type_t) - MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); - - if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - memcpy(ctx->params.I_key_identifier, - key + PUBLIC_KEY_I_KEY_ID_OFFSET, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - - memcpy(ctx->params.q_leaf_identifier, - key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN); - - memcpy(ctx->public_key, - key + PUBLIC_KEY_KEY_HASH_OFFSET, - MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); - - ctx->have_public_key = 1; - - return 0; -} - -int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, - unsigned char *key, size_t key_size, - size_t *key_len) -{ - if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { - return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; - } - - if (!ctx->have_public_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); - - memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - - memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, - ctx->params.q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN); - - memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, - MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); - - if (key_len != NULL) { - *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); - } - - return 0; -} - -int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, - const unsigned char *msg, - size_t msg_size, - const unsigned char *sig, - size_t sig_size, - unsigned char *out, - size_t out_size, - size_t *out_len) -{ - unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; - unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (msg == NULL && msg_size != 0) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || - out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - ret = create_digit_array_with_checksum(params, msg, msg_size, - sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, - tmp_digit_array); - if (ret) { - return ret; - } - - ret = hash_digit_array(params, - sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), - tmp_digit_array, NULL, (unsigned char *) y_hashed_digits); - if (ret) { - return ret; - } - - ret = public_key_from_hashed_digit_array(params, - (unsigned char *) y_hashed_digits, - out); - if (ret) { - return ret; - } - - if (out_len != NULL) { - *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); - } - - return 0; -} - -int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, - const unsigned char *msg, size_t msg_size, - const unsigned char *sig, size_t sig_size) -{ - unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (msg == NULL && msg_size != 0) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (!ctx->have_public_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params, - msg, msg_size, sig, sig_size, - Kc_public_key_candidate, - MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), - NULL); - if (ret) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - if (memcmp(&Kc_public_key_candidate, ctx->public_key, - sizeof(ctx->public_key))) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - return 0; -} - -#if defined(MBEDTLS_LMS_PRIVATE) - -void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); -} - -void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, - sizeof(*ctx)); -} - -int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, - mbedtls_lmots_algorithm_type_t type, - const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], - uint32_t q_leaf_identifier, - const unsigned char *seed, - size_t seed_size) -{ - psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t output_hash_len; - unsigned int i_digit_idx; - unsigned char i_digit_idx_bytes[2]; - unsigned char const_bytes[1] = { 0xFF }; - - if (ctx->have_private_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (type != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - ctx->params.type = type; - - memcpy(ctx->params.I_key_identifier, - I_key_identifier, - sizeof(ctx->params.I_key_identifier)); - - MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0); - - for (i_digit_idx = 0; - i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); - i_digit_idx++) { - status = psa_hash_setup(&op, PSA_ALG_SHA_256); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, - ctx->params.I_key_identifier, - sizeof(ctx->params.I_key_identifier)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, - ctx->params.q_leaf_identifier, - MBEDTLS_LMOTS_Q_LEAF_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); - status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, const_bytes, sizeof(const_bytes)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, seed, seed_size); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_finish(&op, - ctx->private_key[i_digit_idx], - MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), - &output_hash_len); - if (status != PSA_SUCCESS) { - goto exit; - } - - psa_hash_abort(&op); - } - - ctx->have_private_key = 1; - -exit: - psa_hash_abort(&op); - - return PSA_TO_MBEDTLS_ERR(status); -} - -int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, - const mbedtls_lmots_private_t *priv_ctx) -{ - unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* Check that a private key is loaded */ - if (!priv_ctx->have_private_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - ret = hash_digit_array(&priv_ctx->params, - (unsigned char *) priv_ctx->private_key, NULL, - NULL, (unsigned char *) y_hashed_digits); - if (ret) { - goto exit; - } - - ret = public_key_from_hashed_digit_array(&priv_ctx->params, - (unsigned char *) y_hashed_digits, - ctx->public_key); - if (ret) { - goto exit; - } - - memcpy(&ctx->params, &priv_ctx->params, - sizeof(ctx->params)); - - ctx->have_public_key = 1; - -exit: - mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits)); - - return ret; -} - -int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, const unsigned char *msg, size_t msg_size, - unsigned char *sig, size_t sig_size, size_t *sig_len) -{ - unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; - /* Create a temporary buffer to prepare the signature in. This allows us to - * finish creating a signature (ensuring the process doesn't fail), and then - * erase the private key **before** writing any data into the sig parameter - * buffer. If data were directly written into the sig buffer, it might leak - * a partial signature on failure, which effectively compromises the private - * key. - */ - unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (msg == NULL && msg_size != 0) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) { - return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; - } - - /* Check that a private key is loaded */ - if (!ctx->have_private_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - ret = f_rng(p_rng, tmp_c_random, - MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); - if (ret) { - return ret; - } - - ret = create_digit_array_with_checksum(&ctx->params, - msg, msg_size, - tmp_c_random, - tmp_digit_array); - if (ret) { - goto exit; - } - - ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key, - NULL, tmp_digit_array, (unsigned char *) tmp_sig); - if (ret) { - goto exit; - } - - MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); - - /* Test hook to check if sig is being written to before we invalidate the - * private key. - */ -#if defined(MBEDTLS_TEST_HOOKS) - if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) { - ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig); - if (ret != 0) { - return ret; - } - } -#endif /* defined(MBEDTLS_TEST_HOOKS) */ - - /* We've got a valid signature now, so it's time to make sure the private - * key can't be reused. - */ - ctx->have_private_key = 0; - mbedtls_platform_zeroize(ctx->private_key, - sizeof(ctx->private_key)); - - memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, - MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type)); - - memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig, - MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type) - * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); - - if (sig_len != NULL) { - *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); - } - - ret = 0; - -exit: - mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array)); - mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig)); - - return ret; -} - -#endif /* defined(MBEDTLS_LMS_PRIVATE) */ -#endif /* defined(MBEDTLS_LMS_C) */ diff --git a/thirdparty/mbedtls/library/lms.c b/thirdparty/mbedtls/library/lms.c deleted file mode 100644 index 7f7bec068b..0000000000 --- a/thirdparty/mbedtls/library/lms.c +++ /dev/null @@ -1,769 +0,0 @@ -/* - * The LMS stateful-hash public-key signature scheme - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -/* - * The following sources were referenced in the design of this implementation - * of the LMS algorithm: - * - * [1] IETF RFC8554 - * D. McGrew, M. Curcio, S.Fluhrer - * https://datatracker.ietf.org/doc/html/rfc8554 - * - * [2] NIST Special Publication 800-208 - * David A. Cooper et. al. - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf - */ - -#include "common.h" - -#if defined(MBEDTLS_LMS_C) - -#include <string.h> - -#include "lmots.h" - -#include "psa/crypto.h" -#include "psa_util_internal.h" -#include "mbedtls/lms.h" -#include "mbedtls/error.h" -#include "mbedtls/platform_util.h" - -#include "mbedtls/platform.h" - -/* Define a local translating function to save code size by not using too many - * arguments in each translating place. */ -static int local_err_translation(psa_status_t status) -{ - return psa_status_to_mbedtls(status, psa_to_lms_errors, - ARRAY_LENGTH(psa_to_lms_errors), - psa_generic_status_to_mbedtls); -} -#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) - -#define SIG_Q_LEAF_ID_OFFSET (0) -#define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \ - MBEDTLS_LMOTS_Q_LEAF_ID_LEN) -#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \ - MBEDTLS_LMOTS_SIG_LEN(otstype)) -#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \ - MBEDTLS_LMS_TYPE_LEN) - -#define PUBLIC_KEY_TYPE_OFFSET (0) -#define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ - MBEDTLS_LMS_TYPE_LEN) -#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \ - MBEDTLS_LMOTS_TYPE_LEN) -#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ - MBEDTLS_LMOTS_I_KEY_ID_LEN) - - -/* Currently only support H=10 */ -#define H_TREE_HEIGHT_MAX 10 -#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u)) -#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type)) -#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \ - (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))) - -#define D_CONST_LEN (2) -static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 }; -static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 }; - - -/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a - * public key and some other parameters like the leaf index). This function - * implements RFC8554 section 5.3, in the case where r >= 2^h. - * - * params The LMS parameter set, the underlying LMOTS - * parameter set, and I value which describe the key - * being used. - * - * pub_key The public key of the private whose index - * corresponds to the index of this leaf node. This - * is a hash output. - * - * r_node_idx The index of this node in the Merkle tree. Note - * that the root node of the Merkle tree is - * 1-indexed. - * - * out The output node value, which is a hash output. - */ -static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params, - unsigned char *pub_key, - unsigned int r_node_idx, - unsigned char *out) -{ - psa_hash_operation_t op; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t output_hash_len; - unsigned char r_node_idx_bytes[4]; - - op = psa_hash_operation_init(); - status = psa_hash_setup(&op, PSA_ALG_SHA_256); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, params->I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); - status = psa_hash_update(&op, r_node_idx_bytes, 4); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, pub_key, - MBEDTLS_LMOTS_N_HASH_LEN(params->otstype)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), - &output_hash_len); - if (status != PSA_SUCCESS) { - goto exit; - } - -exit: - psa_hash_abort(&op); - - return PSA_TO_MBEDTLS_ERR(status); -} - -/* Calculate the value of an internal node of the Merkle tree (which is a hash - * of a public key and some other parameters like the node index). This function - * implements RFC8554 section 5.3, in the case where r < 2^h. - * - * params The LMS parameter set, the underlying LMOTS - * parameter set, and I value which describe the key - * being used. - * - * left_node The value of the child of this node which is on - * the left-hand side. As with all nodes on the - * Merkle tree, this is a hash output. - * - * right_node The value of the child of this node which is on - * the right-hand side. As with all nodes on the - * Merkle tree, this is a hash output. - * - * r_node_idx The index of this node in the Merkle tree. Note - * that the root node of the Merkle tree is - * 1-indexed. - * - * out The output node value, which is a hash output. - */ -static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params, - const unsigned char *left_node, - const unsigned char *right_node, - unsigned int r_node_idx, - unsigned char *out) -{ - psa_hash_operation_t op; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t output_hash_len; - unsigned char r_node_idx_bytes[4]; - - op = psa_hash_operation_init(); - status = psa_hash_setup(&op, PSA_ALG_SHA_256); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, params->I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); - status = psa_hash_update(&op, r_node_idx_bytes, 4); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, left_node, - MBEDTLS_LMS_M_NODE_BYTES(params->type)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_update(&op, right_node, - MBEDTLS_LMS_M_NODE_BYTES(params->type)); - if (status != PSA_SUCCESS) { - goto exit; - } - - status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), - &output_hash_len); - if (status != PSA_SUCCESS) { - goto exit; - } - -exit: - psa_hash_abort(&op); - - return PSA_TO_MBEDTLS_ERR(status); -} - -void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); -} - -void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, sizeof(*ctx)); -} - -int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, - const unsigned char *key, size_t key_size) -{ - mbedtls_lms_algorithm_type_t type; - mbedtls_lmots_algorithm_type_t otstype; - - type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET); - if (type != MBEDTLS_LMS_SHA256_M32_H10) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - ctx->params.type = type; - - if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - otstype = (mbedtls_lmots_algorithm_type_t) - MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET); - if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - ctx->params.otstype = otstype; - - memcpy(ctx->params.I_key_identifier, - key + PUBLIC_KEY_I_KEY_ID_OFFSET, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET, - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); - - ctx->have_public_key = 1; - - return 0; -} - -int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, - unsigned char *key, - size_t key_size, size_t *key_len) -{ - if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { - return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; - } - - if (!ctx->have_public_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET); - MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET); - memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET, - ctx->T_1_pub_key, - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); - - if (key_len != NULL) { - *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); - } - - return 0; -} - -int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, - const unsigned char *msg, size_t msg_size, - const unsigned char *sig, size_t sig_size) -{ - unsigned int q_leaf_identifier; - unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; - unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX]; - unsigned int height; - unsigned int curr_node_id; - unsigned int parent_node_id; - const unsigned char *left_node; - const unsigned char *right_node; - mbedtls_lmots_parameters_t ots_params; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (!ctx->have_public_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (ctx->params.type - != MBEDTLS_LMS_SHA256_M32_H10) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (ctx->params.otstype - != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) - != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype)) - != MBEDTLS_LMS_SHA256_M32_H10) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - - q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET); - - if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - memcpy(ots_params.I_key_identifier, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0); - ots_params.type = ctx->params.otstype; - - ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params, - msg, - msg_size, - sig + SIG_OTS_SIG_OFFSET, - MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), - Kc_candidate_ots_pub_key, - sizeof(Kc_candidate_ots_pub_key), - NULL); - if (ret != 0) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - create_merkle_leaf_value( - &ctx->params, - Kc_candidate_ots_pub_key, - MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, - Tc_candidate_root_node); - - curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + - q_leaf_identifier; - - for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); - height++) { - parent_node_id = curr_node_id / 2; - - /* Left/right node ordering matters for the hash */ - if (curr_node_id & 1) { - left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + - height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); - right_node = Tc_candidate_root_node; - } else { - left_node = Tc_candidate_root_node; - right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + - height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); - } - - create_merkle_internal_value(&ctx->params, left_node, right_node, - parent_node_id, Tc_candidate_root_node); - - curr_node_id /= 2; - } - - if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key, - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) { - return MBEDTLS_ERR_LMS_VERIFY_FAILED; - } - - return 0; -} - -#if defined(MBEDTLS_LMS_PRIVATE) - -/* Calculate a full Merkle tree based on a private key. This function - * implements RFC8554 section 5.3, and is used to generate a public key (as the - * public key is the root node of the Merkle tree). - * - * ctx The LMS private context, containing a parameter - * set and private key material consisting of both - * public and private OTS. - * - * tree The output tree, which is 2^(H + 1) hash outputs. - * In the case of H=10 we have 2048 tree nodes (of - * which 1024 of them are leaf nodes). Note that - * because the Merkle tree root is 1-indexed, the 0 - * index tree node is never used. - */ -static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx, - unsigned char *tree) -{ - unsigned int priv_key_idx; - unsigned int r_node_idx; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* First create the leaf nodes, in ascending order */ - for (priv_key_idx = 0; - priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type); - priv_key_idx++) { - r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx; - - ret = create_merkle_leaf_value(&ctx->params, - ctx->ots_public_keys[priv_key_idx].public_key, - r_node_idx, - &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES( - ctx->params.type)]); - if (ret != 0) { - return ret; - } - } - - /* Then the internal nodes, in reverse order so that we can guarantee the - * parent has been created */ - for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1; - r_node_idx > 0; - r_node_idx--) { - ret = create_merkle_internal_value(&ctx->params, - &tree[(r_node_idx * 2) * - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], - &tree[(r_node_idx * 2 + 1) * - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], - r_node_idx, - &tree[r_node_idx * - MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]); - if (ret != 0) { - return ret; - } - } - - return 0; -} - -/* Calculate a path from a leaf node of the Merkle tree to the root of the tree, - * and return the full path. This function implements RFC8554 section 5.4.1, as - * the Merkle path is the main component of an LMS signature. - * - * ctx The LMS private context, containing a parameter - * set and private key material consisting of both - * public and private OTS. - * - * leaf_node_id Which leaf node to calculate the path from. - * - * path The output path, which is H hash outputs. - */ -static int get_merkle_path(mbedtls_lms_private_t *ctx, - unsigned int leaf_node_id, - unsigned char *path) -{ - const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); - unsigned int curr_node_id = leaf_node_id; - unsigned int adjacent_node_id; - unsigned char *tree = NULL; - unsigned int height; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type), - node_bytes); - if (tree == NULL) { - return MBEDTLS_ERR_LMS_ALLOC_FAILED; - } - - ret = calculate_merkle_tree(ctx, tree); - if (ret != 0) { - goto exit; - } - - for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); - height++) { - adjacent_node_id = curr_node_id ^ 1; - - memcpy(&path[height * node_bytes], - &tree[adjacent_node_id * node_bytes], node_bytes); - - curr_node_id >>= 1; - } - - ret = 0; - -exit: - mbedtls_zeroize_and_free(tree, node_bytes * - (size_t) MERKLE_TREE_NODE_AM(ctx->params.type)); - - return ret; -} - -void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); -} - -void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx) -{ - if (ctx == NULL) { - return; - } - - unsigned int idx; - - if (ctx->have_private_key) { - if (ctx->ots_private_keys != NULL) { - for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { - mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]); - } - } - - if (ctx->ots_public_keys != NULL) { - for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { - mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]); - } - } - - mbedtls_free(ctx->ots_private_keys); - mbedtls_free(ctx->ots_public_keys); - } - - mbedtls_platform_zeroize(ctx, sizeof(*ctx)); -} - - -int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, - mbedtls_lms_algorithm_type_t type, - mbedtls_lmots_algorithm_type_t otstype, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, const unsigned char *seed, - size_t seed_size) -{ - unsigned int idx = 0; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (type != MBEDTLS_LMS_SHA256_M32_H10) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (ctx->have_private_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - ctx->params.type = type; - ctx->params.otstype = otstype; - ctx->have_private_key = 1; - - ret = f_rng(p_rng, - ctx->params.I_key_identifier, - MBEDTLS_LMOTS_I_KEY_ID_LEN); - if (ret != 0) { - goto exit; - } - - /* Requires a cast to size_t to avoid an implicit cast warning on certain - * platforms (particularly Windows) */ - ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), - sizeof(*ctx->ots_private_keys)); - if (ctx->ots_private_keys == NULL) { - ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; - goto exit; - } - - /* Requires a cast to size_t to avoid an implicit cast warning on certain - * platforms (particularly Windows) */ - ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), - sizeof(*ctx->ots_public_keys)); - if (ctx->ots_public_keys == NULL) { - ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; - goto exit; - } - - for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { - mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]); - mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]); - } - - - for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { - ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx], - otstype, - ctx->params.I_key_identifier, - idx, seed, seed_size); - if (ret != 0) { - goto exit; - } - - ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx], - &ctx->ots_private_keys[idx]); - if (ret != 0) { - goto exit; - } - } - - ctx->q_next_usable_key = 0; - -exit: - if (ret != 0) { - mbedtls_lms_private_free(ctx); - } - - return ret; -} - -int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, - const mbedtls_lms_private_t *priv_ctx) -{ - const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type); - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *tree = NULL; - - if (!priv_ctx->have_private_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (priv_ctx->params.type - != MBEDTLS_LMS_SHA256_M32_H10) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (priv_ctx->params.otstype - != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type), - node_bytes); - if (tree == NULL) { - return MBEDTLS_ERR_LMS_ALLOC_FAILED; - } - - memcpy(&ctx->params, &priv_ctx->params, - sizeof(mbedtls_lmots_parameters_t)); - - ret = calculate_merkle_tree(priv_ctx, tree); - if (ret != 0) { - goto exit; - } - - /* Root node is always at position 1, due to 1-based indexing */ - memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes); - - ctx->have_public_key = 1; - - ret = 0; - -exit: - mbedtls_zeroize_and_free(tree, node_bytes * - (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type)); - - return ret; -} - - -int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, const unsigned char *msg, - unsigned int msg_size, unsigned char *sig, size_t sig_size, - size_t *sig_len) -{ - uint32_t q_leaf_identifier; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (!ctx->have_private_key) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { - return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; - } - - if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (ctx->params.otstype - != MBEDTLS_LMOTS_SHA256_N32_W8) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { - return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS; - } - - - q_leaf_identifier = ctx->q_next_usable_key; - /* This new value must _always_ be written back to the disk before the - * signature is returned. - */ - ctx->q_next_usable_key += 1; - - if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) - < SIG_OTS_SIG_OFFSET) { - return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; - } - - ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier], - f_rng, - p_rng, - msg, - msg_size, - sig + SIG_OTS_SIG_OFFSET, - MBEDTLS_LMS_SIG_LEN(ctx->params.type, - ctx->params.otstype) - SIG_OTS_SIG_OFFSET, - NULL); - if (ret != 0) { - return ret; - } - - MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype)); - MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET); - - ret = get_merkle_path(ctx, - MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, - sig + SIG_PATH_OFFSET(ctx->params.otstype)); - if (ret != 0) { - return ret; - } - - if (sig_len != NULL) { - *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype); - } - - - return 0; -} - -#endif /* defined(MBEDTLS_LMS_PRIVATE) */ -#endif /* defined(MBEDTLS_LMS_C) */ diff --git a/thirdparty/meshoptimizer/LICENSE.md b/thirdparty/meshoptimizer/LICENSE.md index 962ed41ffb..ef9f5919f2 100644 --- a/thirdparty/meshoptimizer/LICENSE.md +++ b/thirdparty/meshoptimizer/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016-2023 Arseny Kapoulkine +Copyright (c) 2016-2024 Arseny Kapoulkine Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/meshoptimizer/allocator.cpp b/thirdparty/meshoptimizer/allocator.cpp index 072e8e51ac..b8cb33c280 100644 --- a/thirdparty/meshoptimizer/allocator.cpp +++ b/thirdparty/meshoptimizer/allocator.cpp @@ -1,7 +1,7 @@ // This file is part of meshoptimizer library; see meshoptimizer.h for version/license details #include "meshoptimizer.h" -void meshopt_setAllocator(void* (MESHOPTIMIZER_ALLOC_CALLCONV *allocate)(size_t), void (MESHOPTIMIZER_ALLOC_CALLCONV *deallocate)(void*)) +void meshopt_setAllocator(void* (MESHOPTIMIZER_ALLOC_CALLCONV* allocate)(size_t), void (MESHOPTIMIZER_ALLOC_CALLCONV* deallocate)(void*)) { meshopt_Allocator::Storage::allocate = allocate; meshopt_Allocator::Storage::deallocate = deallocate; diff --git a/thirdparty/meshoptimizer/clusterizer.cpp b/thirdparty/meshoptimizer/clusterizer.cpp index c4672ad606..738add5f2f 100644 --- a/thirdparty/meshoptimizer/clusterizer.cpp +++ b/thirdparty/meshoptimizer/clusterizer.cpp @@ -238,7 +238,7 @@ static bool appendMeshlet(meshopt_Meshlet& meshlet, unsigned int a, unsigned int bool result = false; - unsigned int used_extra = (av == 0xff) + (bv == 0xff) + (cv == 0xff); + int used_extra = (av == 0xff) + (bv == 0xff) + (cv == 0xff); if (meshlet.vertex_count + used_extra > max_vertices || meshlet.triangle_count >= max_triangles) { @@ -283,10 +283,10 @@ static bool appendMeshlet(meshopt_Meshlet& meshlet, unsigned int a, unsigned int return result; } -static unsigned int getNeighborTriangle(const meshopt_Meshlet& meshlet, const Cone* meshlet_cone, unsigned int* meshlet_vertices, const unsigned int* indices, const TriangleAdjacency2& adjacency, const Cone* triangles, const unsigned int* live_triangles, const unsigned char* used, float meshlet_expected_radius, float cone_weight, unsigned int* out_extra) +static unsigned int getNeighborTriangle(const meshopt_Meshlet& meshlet, const Cone* meshlet_cone, unsigned int* meshlet_vertices, const unsigned int* indices, const TriangleAdjacency2& adjacency, const Cone* triangles, const unsigned int* live_triangles, const unsigned char* used, float meshlet_expected_radius, float cone_weight) { unsigned int best_triangle = ~0u; - unsigned int best_extra = 5; + int best_priority = 5; float best_score = FLT_MAX; for (size_t i = 0; i < meshlet.vertex_count; ++i) @@ -301,20 +301,26 @@ static unsigned int getNeighborTriangle(const meshopt_Meshlet& meshlet, const Co unsigned int triangle = neighbors[j]; unsigned int a = indices[triangle * 3 + 0], b = indices[triangle * 3 + 1], c = indices[triangle * 3 + 2]; - unsigned int extra = (used[a] == 0xff) + (used[b] == 0xff) + (used[c] == 0xff); + int extra = (used[a] == 0xff) + (used[b] == 0xff) + (used[c] == 0xff); + assert(extra <= 2); - // triangles that don't add new vertices to meshlets are max. priority - if (extra != 0) - { - // artificially increase the priority of dangling triangles as they're expensive to add to new meshlets - if (live_triangles[a] == 1 || live_triangles[b] == 1 || live_triangles[c] == 1) - extra = 0; + int priority = -1; - extra++; - } + // triangles that don't add new vertices to meshlets are max. priority + if (extra == 0) + priority = 0; + // artificially increase the priority of dangling triangles as they're expensive to add to new meshlets + else if (live_triangles[a] == 1 || live_triangles[b] == 1 || live_triangles[c] == 1) + priority = 1; + // if two vertices have live count of 2, removing this triangle will make another triangle dangling which is good for overall flow + else if ((live_triangles[a] == 2) + (live_triangles[b] == 2) + (live_triangles[c] == 2) >= 2) + priority = 1 + extra; + // otherwise adjust priority to be after the above cases, 3 or 4 based on used[] count + else + priority = 2 + extra; // since topology-based priority is always more important than the score, we can skip scoring in some cases - if (extra > best_extra) + if (priority > best_priority) continue; float score = 0; @@ -341,18 +347,15 @@ static unsigned int getNeighborTriangle(const meshopt_Meshlet& meshlet, const Co // note that topology-based priority is always more important than the score // this helps maintain reasonable effectiveness of meshlet data and reduces scoring cost - if (extra < best_extra || score < best_score) + if (priority < best_priority || score < best_score) { best_triangle = triangle; - best_extra = extra; + best_priority = priority; best_score = score; } } } - if (out_extra) - *out_extra = best_extra; - return best_triangle; } @@ -441,7 +444,7 @@ static size_t kdtreeBuild(size_t offset, KDNode* nodes, size_t node_count, const } // split axis is one where the variance is largest - unsigned int axis = vars[0] >= vars[1] && vars[0] >= vars[2] ? 0 : vars[1] >= vars[2] ? 1 : 2; + unsigned int axis = (vars[0] >= vars[1] && vars[0] >= vars[2]) ? 0 : (vars[1] >= vars[2] ? 1 : 2); float split = mean[axis]; size_t middle = kdtreePartition(indices, count, points, stride, axis, split); @@ -588,13 +591,13 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve { Cone meshlet_cone = getMeshletCone(meshlet_cone_acc, meshlet.triangle_count); - unsigned int best_extra = 0; - unsigned int best_triangle = getNeighborTriangle(meshlet, &meshlet_cone, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, cone_weight, &best_extra); + unsigned int best_triangle = getNeighborTriangle(meshlet, &meshlet_cone, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, cone_weight); + int best_extra = best_triangle == ~0u ? -1 : (used[indices[best_triangle * 3 + 0]] == 0xff) + (used[indices[best_triangle * 3 + 1]] == 0xff) + (used[indices[best_triangle * 3 + 2]] == 0xff); // if the best triangle doesn't fit into current meshlet, the spatial scoring we've used is not very meaningful, so we re-select using topological scoring if (best_triangle != ~0u && (meshlet.vertex_count + best_extra > max_vertices || meshlet.triangle_count >= max_triangles)) { - best_triangle = getNeighborTriangle(meshlet, NULL, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, 0.f, NULL); + best_triangle = getNeighborTriangle(meshlet, NULL, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, 0.f); } // when we run out of neighboring triangles we need to switch to spatial search; we currently just pick the closest triangle irrespective of connectivity @@ -882,3 +885,93 @@ meshopt_Bounds meshopt_computeMeshletBounds(const unsigned int* meshlet_vertices return meshopt_computeClusterBounds(indices, triangle_count * 3, vertex_positions, vertex_count, vertex_positions_stride); } + +void meshopt_optimizeMeshlet(unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, size_t triangle_count, size_t vertex_count) +{ + using namespace meshopt; + + assert(triangle_count <= kMeshletMaxTriangles); + assert(vertex_count <= kMeshletMaxVertices); + + unsigned char* indices = meshlet_triangles; + unsigned int* vertices = meshlet_vertices; + + // cache tracks vertex timestamps (corresponding to triangle index! all 3 vertices are added at the same time and never removed) + unsigned char cache[kMeshletMaxVertices]; + memset(cache, 0, vertex_count); + + // note that we start from a value that means all vertices aren't in cache + unsigned char cache_last = 128; + const unsigned char cache_cutoff = 3; // 3 triangles = ~5..9 vertices depending on reuse + + for (size_t i = 0; i < triangle_count; ++i) + { + int next = -1; + int next_match = -1; + + for (size_t j = i; j < triangle_count; ++j) + { + unsigned char a = indices[j * 3 + 0], b = indices[j * 3 + 1], c = indices[j * 3 + 2]; + assert(a < vertex_count && b < vertex_count && c < vertex_count); + + // score each triangle by how many vertices are in cache + // note: the distance is computed using unsigned 8-bit values, so cache timestamp overflow is handled gracefully + int aok = (unsigned char)(cache_last - cache[a]) < cache_cutoff; + int bok = (unsigned char)(cache_last - cache[b]) < cache_cutoff; + int cok = (unsigned char)(cache_last - cache[c]) < cache_cutoff; + + if (aok + bok + cok > next_match) + { + next = (int)j; + next_match = aok + bok + cok; + + // note that we could end up with all 3 vertices in the cache, but 2 is enough for ~strip traversal + if (next_match >= 2) + break; + } + } + + assert(next >= 0); + + unsigned char a = indices[next * 3 + 0], b = indices[next * 3 + 1], c = indices[next * 3 + 2]; + + // shift triangles before the next one forward so that we always keep an ordered partition + // note: this could have swapped triangles [i] and [next] but that distorts the order and may skew the output sequence + memmove(indices + (i + 1) * 3, indices + i * 3, (next - i) * 3 * sizeof(unsigned char)); + + indices[i * 3 + 0] = a; + indices[i * 3 + 1] = b; + indices[i * 3 + 2] = c; + + // cache timestamp is the same between all vertices of each triangle to reduce overflow + cache_last++; + cache[a] = cache_last; + cache[b] = cache_last; + cache[c] = cache_last; + } + + // reorder meshlet vertices for access locality assuming index buffer is scanned sequentially + unsigned int order[kMeshletMaxVertices]; + + unsigned char remap[kMeshletMaxVertices]; + memset(remap, -1, vertex_count); + + size_t vertex_offset = 0; + + for (size_t i = 0; i < triangle_count * 3; ++i) + { + unsigned char& r = remap[indices[i]]; + + if (r == 0xff) + { + r = (unsigned char)(vertex_offset); + order[vertex_offset] = vertices[indices[i]]; + vertex_offset++; + } + + indices[i] = r; + } + + assert(vertex_offset <= vertex_count); + memcpy(vertices, order, vertex_offset * sizeof(unsigned int)); +} diff --git a/thirdparty/meshoptimizer/indexcodec.cpp b/thirdparty/meshoptimizer/indexcodec.cpp index 4cc2fea63a..b300460052 100644 --- a/thirdparty/meshoptimizer/indexcodec.cpp +++ b/thirdparty/meshoptimizer/indexcodec.cpp @@ -33,7 +33,7 @@ static int rotateTriangle(unsigned int a, unsigned int b, unsigned int c, unsign { (void)a; - return (b == next) ? 1 : (c == next) ? 2 : 0; + return (b == next) ? 1 : (c == next ? 2 : 0); } static int getEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, unsigned int c, size_t offset) @@ -217,7 +217,7 @@ size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, cons int fe = fer >> 2; int fc = getVertexFifo(vertexfifo, c, vertexfifooffset); - int fec = (fc >= 1 && fc < fecmax) ? fc : (c == next) ? (next++, 0) : 15; + int fec = (fc >= 1 && fc < fecmax) ? fc : (c == next ? (next++, 0) : 15); if (fec == 15 && version >= 1) { @@ -267,8 +267,8 @@ size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, cons // after rotation, a is almost always equal to next, so we don't waste bits on FIFO encoding for a int fea = (a == next) ? (next++, 0) : 15; - int feb = (fb >= 0 && fb < 14) ? (fb + 1) : (b == next) ? (next++, 0) : 15; - int fec = (fc >= 0 && fc < 14) ? (fc + 1) : (c == next) ? (next++, 0) : 15; + int feb = (fb >= 0 && fb < 14) ? fb + 1 : (b == next ? (next++, 0) : 15); + int fec = (fc >= 0 && fc < 14) ? fc + 1 : (c == next ? (next++, 0) : 15); // we encode feb & fec in 4 bits using a table if possible, and as a full byte otherwise unsigned char codeaux = (unsigned char)((feb << 4) | fec); diff --git a/thirdparty/meshoptimizer/indexgenerator.cpp b/thirdparty/meshoptimizer/indexgenerator.cpp index f6728345a9..0d53020e32 100644 --- a/thirdparty/meshoptimizer/indexgenerator.cpp +++ b/thirdparty/meshoptimizer/indexgenerator.cpp @@ -6,6 +6,7 @@ // This work is based on: // John McDonald, Mark Kilgard. Crack-Free Point-Normal Triangles using Adjacent Edge Normals. 2010 +// John Hable. Variable Rate Shading with Visibility Buffer Rendering. 2024 namespace meshopt { @@ -576,3 +577,99 @@ void meshopt_generateTessellationIndexBuffer(unsigned int* destination, const un memcpy(destination + i * 4, patch, sizeof(patch)); } } + +size_t meshopt_generateProvokingIndexBuffer(unsigned int* destination, unsigned int* reorder, const unsigned int* indices, size_t index_count, size_t vertex_count) +{ + assert(index_count % 3 == 0); + + meshopt_Allocator allocator; + + unsigned int* remap = allocator.allocate<unsigned int>(vertex_count); + memset(remap, -1, vertex_count * sizeof(unsigned int)); + + // compute vertex valence; this is used to prioritize least used corner + // note: we use 8-bit counters for performance; for outlier vertices the valence is incorrect but that just affects the heuristic + unsigned char* valence = allocator.allocate<unsigned char>(vertex_count); + memset(valence, 0, vertex_count); + + for (size_t i = 0; i < index_count; ++i) + { + unsigned int index = indices[i]; + assert(index < vertex_count); + + valence[index]++; + } + + unsigned int reorder_offset = 0; + + // assign provoking vertices; leave the rest for the next pass + for (size_t i = 0; i < index_count; i += 3) + { + unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2]; + assert(a < vertex_count && b < vertex_count && c < vertex_count); + + // try to rotate triangle such that provoking vertex hasn't been seen before + // if multiple vertices are new, prioritize the one with least valence + // this reduces the risk that a future triangle will have all three vertices seen + unsigned int va = remap[a] == ~0u ? valence[a] : ~0u; + unsigned int vb = remap[b] == ~0u ? valence[b] : ~0u; + unsigned int vc = remap[c] == ~0u ? valence[c] : ~0u; + + if (vb != ~0u && vb <= va && vb <= vc) + { + // abc -> bca + unsigned int t = a; + a = b, b = c, c = t; + } + else if (vc != ~0u && vc <= va && vc <= vb) + { + // abc -> cab + unsigned int t = c; + c = b, b = a, a = t; + } + + unsigned int newidx = reorder_offset; + + // now remap[a] = ~0u or all three vertices are old + // recording remap[a] makes it possible to remap future references to the same index, conserving space + if (remap[a] == ~0u) + remap[a] = newidx; + + // we need to clone the provoking vertex to get a unique index + // if all three are used the choice is arbitrary since no future triangle will be able to reuse any of these + reorder[reorder_offset++] = a; + + // note: first vertex is final, the other two will be fixed up in next pass + destination[i + 0] = newidx; + destination[i + 1] = b; + destination[i + 2] = c; + + // update vertex valences for corner heuristic + valence[a]--; + valence[b]--; + valence[c]--; + } + + // remap or clone non-provoking vertices (iterating to skip provoking vertices) + int step = 1; + + for (size_t i = 1; i < index_count; i += step, step ^= 3) + { + unsigned int index = destination[i]; + + if (remap[index] == ~0u) + { + // we haven't seen the vertex before as a provoking vertex + // to maintain the reference to the original vertex we need to clone it + unsigned int newidx = reorder_offset; + + remap[index] = newidx; + reorder[reorder_offset++] = index; + } + + destination[i] = remap[index]; + } + + assert(reorder_offset <= vertex_count + index_count / 3); + return reorder_offset; +} diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h index dbafd4e6e4..77be5371fc 100644 --- a/thirdparty/meshoptimizer/meshoptimizer.h +++ b/thirdparty/meshoptimizer/meshoptimizer.h @@ -1,7 +1,7 @@ /** - * meshoptimizer - version 0.20 + * meshoptimizer - version 0.22 * - * Copyright (C) 2016-2023, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2016-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://github.com/zeux/meshoptimizer * * This library is distributed under the MIT License. See notice at the end of this file. @@ -12,7 +12,7 @@ #include <stddef.h> /* Version macro; major * 1000 + minor * 10 + patch */ -#define MESHOPTIMIZER_VERSION 200 /* 0.20 */ +#define MESHOPTIMIZER_VERSION 220 /* 0.22 */ /* If no API is defined, assume default */ #ifndef MESHOPTIMIZER_API @@ -29,11 +29,14 @@ #endif /* Experimental APIs have unstable interface and might have implementation that's not fully tested or optimized */ +#ifndef MESHOPTIMIZER_EXPERIMENTAL #define MESHOPTIMIZER_EXPERIMENTAL MESHOPTIMIZER_API +#endif /* C interface */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /** @@ -138,6 +141,19 @@ MESHOPTIMIZER_API void meshopt_generateAdjacencyIndexBuffer(unsigned int* destin MESHOPTIMIZER_API void meshopt_generateTessellationIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); /** + * Experimental: Generate index buffer that can be used for visibility buffer rendering and returns the size of the reorder table + * Each triangle's provoking vertex index is equal to primitive id; this allows passing it to the fragment shader using nointerpolate attribute. + * This is important for performance on hardware where primitive id can't be accessed efficiently in fragment shader. + * The reorder table stores the original vertex id for each vertex in the new index buffer, and should be used in the vertex shader to load vertex data. + * The provoking vertex is assumed to be the first vertex in the triangle; if this is not the case (OpenGL), rotate each triangle (abc -> bca) before rendering. + * For maximum efficiency the input index buffer should be optimized for vertex cache first. + * + * destination must contain enough space for the resulting index buffer (index_count elements) + * reorder must contain enough space for the worst case reorder table (vertex_count + index_count/3 elements) + */ +MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_generateProvokingIndexBuffer(unsigned int* destination, unsigned int* reorder, const unsigned int* indices, size_t index_count, size_t vertex_count); + +/** * Vertex transform cache optimizer * Reorders indices to reduce the number of GPU vertex shader invocations * If index buffer contains multiple ranges for multiple draw calls, this functions needs to be called on each range individually. @@ -254,6 +270,7 @@ MESHOPTIMIZER_API int meshopt_decodeIndexSequence(void* destination, size_t inde * Returns encoded data size on success, 0 on error; the only error condition is if buffer doesn't have enough space * This function works for a single vertex stream; for multiple vertex streams, call meshopt_encodeVertexBuffer for each stream. * Note that all vertex_size bytes of each vertex are encoded verbatim, including padding which should be zero-initialized. + * For maximum efficiency the vertex buffer being encoded has to be quantized and optimized for locality of reference (cache/fetch) first. * * buffer must contain enough space for the encoded vertex buffer (use meshopt_encodeVertexBufferBound to compute worst case size) */ @@ -289,9 +306,9 @@ MESHOPTIMIZER_API int meshopt_decodeVertexBuffer(void* destination, size_t verte * meshopt_decodeFilterExp decodes exponential encoding of floating-point data with 8-bit exponent and 24-bit integer mantissa as 2^E*M. * Each 32-bit component is decoded in isolation; stride must be divisible by 4. */ -MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterOct(void* buffer, size_t count, size_t stride); -MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterQuat(void* buffer, size_t count, size_t stride); -MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t count, size_t stride); +MESHOPTIMIZER_API void meshopt_decodeFilterOct(void* buffer, size_t count, size_t stride); +MESHOPTIMIZER_API void meshopt_decodeFilterQuat(void* buffer, size_t count, size_t stride); +MESHOPTIMIZER_API void meshopt_decodeFilterExp(void* buffer, size_t count, size_t stride); /** * Vertex buffer filter encoders @@ -311,32 +328,40 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t cou */ enum meshopt_EncodeExpMode { - /* When encoding exponents, use separate values for each component (maximum quality) */ - meshopt_EncodeExpSeparate, - /* When encoding exponents, use shared value for all components of each vector (better compression) */ - meshopt_EncodeExpSharedVector, - /* When encoding exponents, use shared value for each component of all vectors (best compression) */ - meshopt_EncodeExpSharedComponent, + /* When encoding exponents, use separate values for each component (maximum quality) */ + meshopt_EncodeExpSeparate, + /* When encoding exponents, use shared value for all components of each vector (better compression) */ + meshopt_EncodeExpSharedVector, + /* When encoding exponents, use shared value for each component of all vectors (best compression) */ + meshopt_EncodeExpSharedComponent, + /* Experimental: When encoding exponents, use separate values for each component, but clamp to 0 (good quality if very small values are not important) */ + meshopt_EncodeExpClamped, }; -MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterOct(void* destination, size_t count, size_t stride, int bits, const float* data); -MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterQuat(void* destination, size_t count, size_t stride, int bits, const float* data); -MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterExp(void* destination, size_t count, size_t stride, int bits, const float* data, enum meshopt_EncodeExpMode mode); +MESHOPTIMIZER_API void meshopt_encodeFilterOct(void* destination, size_t count, size_t stride, int bits, const float* data); +MESHOPTIMIZER_API void meshopt_encodeFilterQuat(void* destination, size_t count, size_t stride, int bits, const float* data); +MESHOPTIMIZER_API void meshopt_encodeFilterExp(void* destination, size_t count, size_t stride, int bits, const float* data, enum meshopt_EncodeExpMode mode); /** * Simplification options */ enum { - /* Do not move vertices that are located on the topological border (vertices on triangle edges that don't have a paired triangle). Useful for simplifying portions of the larger mesh. */ - meshopt_SimplifyLockBorder = 1 << 0, + /* Do not move vertices that are located on the topological border (vertices on triangle edges that don't have a paired triangle). Useful for simplifying portions of the larger mesh. */ + meshopt_SimplifyLockBorder = 1 << 0, + /* Improve simplification performance assuming input indices are a sparse subset of the mesh. Note that error becomes relative to subset extents. */ + meshopt_SimplifySparse = 1 << 1, + /* Treat error limit and resulting error as absolute instead of relative to mesh extents. */ + meshopt_SimplifyErrorAbsolute = 1 << 2, + /* Experimental: remove disconnected parts of the mesh during simplification incrementally, regardless of the topological restrictions inside components. */ + meshopt_SimplifyPrune = 1 << 3, }; /** * Mesh simplifier * Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible * The algorithm tries to preserve mesh topology and can stop short of the target goal based on topology constraints or target error. - * If not all attributes from the input mesh are required, it's recommended to reindex the mesh using meshopt_generateShadowIndexBuffer prior to simplification. + * If not all attributes from the input mesh are required, it's recommended to reindex the mesh without them prior to simplification. * Returns the number of indices after simplification, with destination containing new index data * The resulting index buffer references vertices from the original vertex buffer. * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended. @@ -351,15 +376,15 @@ MESHOPTIMIZER_API size_t meshopt_simplify(unsigned int* destination, const unsig /** * Experimental: Mesh simplifier with attribute metric - * The algorithm ehnahces meshopt_simplify by incorporating attribute values into the error metric used to prioritize simplification order; see meshopt_simplify documentation for details. + * The algorithm enhances meshopt_simplify by incorporating attribute values into the error metric used to prioritize simplification order; see meshopt_simplify documentation for details. * Note that the number of attributes affects memory requirements and running time; this algorithm requires ~1.5x more memory and time compared to meshopt_simplify when using 4 scalar attributes. * * vertex_attributes should have attribute_count floats for each vertex - * attribute_weights should have attribute_count floats in total; the weights determine relative priority of attributes between each other and wrt position. The recommended weight range is [1e-3..1e-1], assuming attribute data is in [0..1] range. - * attribute_count must be <= 16 - * TODO target_error/result_error currently use combined distance+attribute error; this may change in the future + * attribute_weights should have attribute_count floats in total; the weights determine relative priority of attributes between each other and wrt position + * attribute_count must be <= 32 + * vertex_lock can be NULL; when it's not NULL, it should have a value for each vertex; 1 denotes vertices that can't be moved */ -MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float* result_error); +MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned char* vertex_lock, size_t target_index_count, float target_error, unsigned int options, float* result_error); /** * Experimental: Mesh simplifier (sloppy) @@ -386,6 +411,7 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destinati * destination must contain enough space for the target index buffer (target_vertex_count elements) * vertex_positions should have float3 position in the first 12 bytes of each vertex * vertex_colors should can be NULL; when it's not NULL, it should have float3 color in the first 12 bytes of each vertex + * color_weight determines relative priority of color wrt position; 1.0 is a safe default */ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_colors, size_t vertex_colors_stride, float color_weight, size_t target_vertex_count); @@ -464,6 +490,13 @@ struct meshopt_VertexFetchStatistics */ MESHOPTIMIZER_API struct meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const unsigned int* indices, size_t index_count, size_t vertex_count, size_t vertex_size); +/** + * Meshlet is a small mesh cluster (subset) that consists of: + * - triangles, an 8-bit micro triangle (index) buffer, that for each triangle specifies three local vertices to use; + * - vertices, a 32-bit vertex indirection buffer, that for each local vertex specifies which mesh vertex to fetch vertex attributes from. + * + * For efficiency, meshlet triangles and vertices are packed into two large arrays; this structure contains offsets and counts to access the data. + */ struct meshopt_Meshlet { /* offsets within meshlet_vertices and meshlet_triangles arrays with meshlet data */ @@ -479,6 +512,7 @@ struct meshopt_Meshlet * Meshlet builder * Splits the mesh into a set of meshlets where each meshlet has a micro index buffer indexing into meshlet vertices that refer to the original vertex buffer * The resulting data can be used to render meshes using NVidia programmable mesh shading pipeline, or in other cluster-based renderers. + * When targeting mesh shading hardware, for maximum efficiency meshlets should be further optimized using meshopt_optimizeMeshlet. * When using buildMeshlets, vertex positions need to be provided to minimize the size of the resulting clusters. * When using buildMeshletsScan, for maximum efficiency the index buffer being converted has to be optimized for vertex cache first. * @@ -486,13 +520,23 @@ struct meshopt_Meshlet * meshlet_vertices must contain enough space for all meshlets, worst case size is equal to max_meshlets * max_vertices * meshlet_triangles must contain enough space for all meshlets, worst case size is equal to max_meshlets * max_triangles * 3 * vertex_positions should have float3 position in the first 12 bytes of each vertex - * max_vertices and max_triangles must not exceed implementation limits (max_vertices <= 255 - not 256!, max_triangles <= 512) + * max_vertices and max_triangles must not exceed implementation limits (max_vertices <= 255 - not 256!, max_triangles <= 512; max_triangles must be divisible by 4) * cone_weight should be set to 0 when cone culling is not used, and a value between 0 and 1 otherwise to balance between cluster size and cone culling efficiency */ MESHOPTIMIZER_API size_t meshopt_buildMeshlets(struct meshopt_Meshlet* meshlets, unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t max_vertices, size_t max_triangles, float cone_weight); MESHOPTIMIZER_API size_t meshopt_buildMeshletsScan(struct meshopt_Meshlet* meshlets, unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, const unsigned int* indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles); MESHOPTIMIZER_API size_t meshopt_buildMeshletsBound(size_t index_count, size_t max_vertices, size_t max_triangles); +/** + * Experimental: Meshlet optimizer + * Reorders meshlet vertices and triangles to maximize locality to improve rasterizer throughput + * + * meshlet_triangles and meshlet_vertices must refer to meshlet triangle and vertex index data; when buildMeshlets* is used, these + * need to be computed from meshlet's vertex_offset and triangle_offset + * triangle_count and vertex_count must not exceed implementation limits (vertex_count <= 255 - not 256!, triangle_count <= 512) + */ +MESHOPTIMIZER_EXPERIMENTAL void meshopt_optimizeMeshlet(unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, size_t triangle_count, size_t vertex_count); + struct meshopt_Bounds { /* bounding sphere, useful for frustum and occlusion culling */ @@ -529,7 +573,8 @@ struct meshopt_Bounds * Real-Time Rendering 4th Edition, section 19.3). * * vertex_positions should have float3 position in the first 12 bytes of each vertex - * index_count/3 should be less than or equal to 512 (the function assumes clusters of limited size) + * vertex_count should specify the number of vertices in the entire mesh, not cluster or meshlet + * index_count/3 and triangle_count must not exceed implementation limits (<= 512) */ MESHOPTIMIZER_API struct meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); MESHOPTIMIZER_API struct meshopt_Bounds meshopt_computeMeshletBounds(const unsigned int* meshlet_vertices, const unsigned char* meshlet_triangles, size_t triangle_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); @@ -559,7 +604,7 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_spatialSortTriangles(unsigned int* desti * Note that all algorithms only allocate memory for temporary use. * allocate/deallocate are always called in a stack-like order - last pointer to be allocated is deallocated first. */ -MESHOPTIMIZER_API void meshopt_setAllocator(void* (MESHOPTIMIZER_ALLOC_CALLCONV *allocate)(size_t), void (MESHOPTIMIZER_ALLOC_CALLCONV *deallocate)(void*)); +MESHOPTIMIZER_API void meshopt_setAllocator(void* (MESHOPTIMIZER_ALLOC_CALLCONV* allocate)(size_t), void (MESHOPTIMIZER_ALLOC_CALLCONV* deallocate)(void*)); #ifdef __cplusplus } /* extern "C" */ @@ -627,6 +672,8 @@ inline void meshopt_generateAdjacencyIndexBuffer(T* destination, const T* indice template <typename T> inline void meshopt_generateTessellationIndexBuffer(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); template <typename T> +inline size_t meshopt_generateProvokingIndexBuffer(T* destination, unsigned int* reorder, const T* indices, size_t index_count, size_t vertex_count); +template <typename T> inline void meshopt_optimizeVertexCache(T* destination, const T* indices, size_t index_count, size_t vertex_count); template <typename T> inline void meshopt_optimizeVertexCacheStrip(T* destination, const T* indices, size_t index_count, size_t vertex_count); @@ -649,7 +696,7 @@ inline int meshopt_decodeIndexSequence(T* destination, size_t index_count, const template <typename T> inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options = 0, float* result_error = NULL); template <typename T> -inline size_t meshopt_simplifyWithAttributes(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options = 0, float* result_error = NULL); +inline size_t meshopt_simplifyWithAttributes(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned char* vertex_lock, size_t target_index_count, float target_error, unsigned int options = 0, float* result_error = NULL); template <typename T> inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error = NULL); template <typename T> @@ -705,15 +752,15 @@ public: template <typename T> struct StorageT { - static void* (MESHOPTIMIZER_ALLOC_CALLCONV *allocate)(size_t); - static void (MESHOPTIMIZER_ALLOC_CALLCONV *deallocate)(void*); + static void* (MESHOPTIMIZER_ALLOC_CALLCONV* allocate)(size_t); + static void (MESHOPTIMIZER_ALLOC_CALLCONV* deallocate)(void*); }; typedef StorageT<void> Storage; meshopt_Allocator() - : blocks() - , count(0) + : blocks() + , count(0) { } @@ -723,7 +770,8 @@ public: Storage::deallocate(blocks[i - 1]); } - template <typename T> T* allocate(size_t size) + template <typename T> + T* allocate(size_t size) { assert(count < sizeof(blocks) / sizeof(blocks[0])); T* result = static_cast<T*>(Storage::allocate(size > size_t(-1) / sizeof(T) ? size_t(-1) : size * sizeof(T))); @@ -744,8 +792,10 @@ private: }; // This makes sure that allocate/deallocate are lazily generated in translation units that need them and are deduplicated by the linker -template <typename T> void* (MESHOPTIMIZER_ALLOC_CALLCONV *meshopt_Allocator::StorageT<T>::allocate)(size_t) = operator new; -template <typename T> void (MESHOPTIMIZER_ALLOC_CALLCONV *meshopt_Allocator::StorageT<T>::deallocate)(void*) = operator delete; +template <typename T> +void* (MESHOPTIMIZER_ALLOC_CALLCONV* meshopt_Allocator::StorageT<T>::allocate)(size_t) = operator new; +template <typename T> +void (MESHOPTIMIZER_ALLOC_CALLCONV* meshopt_Allocator::StorageT<T>::deallocate)(void*) = operator delete; #endif /* Inline implementation for C++ templated wrappers */ @@ -861,6 +911,19 @@ inline void meshopt_generateTessellationIndexBuffer(T* destination, const T* ind } template <typename T> +inline size_t meshopt_generateProvokingIndexBuffer(T* destination, unsigned int* reorder, const T* indices, size_t index_count, size_t vertex_count) +{ + meshopt_IndexAdapter<T> in(NULL, indices, index_count); + meshopt_IndexAdapter<T> out(destination, NULL, index_count); + + size_t bound = vertex_count + (index_count / 3); + assert(size_t(T(bound - 1)) == bound - 1); // bound - 1 must fit in T + (void)bound; + + return meshopt_generateProvokingIndexBuffer(out.data, reorder, in.data, index_count, vertex_count); +} + +template <typename T> inline void meshopt_optimizeVertexCache(T* destination, const T* indices, size_t index_count, size_t vertex_count) { meshopt_IndexAdapter<T> in(NULL, indices, index_count); @@ -956,12 +1019,12 @@ inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_co } template <typename T> -inline size_t meshopt_simplifyWithAttributes(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float* result_error) +inline size_t meshopt_simplifyWithAttributes(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned char* vertex_lock, size_t target_index_count, float target_error, unsigned int options, float* result_error) { - meshopt_IndexAdapter<T> in(NULL, indices, index_count); - meshopt_IndexAdapter<T> out(destination, NULL, index_count); + meshopt_IndexAdapter<T> in(NULL, indices, index_count); + meshopt_IndexAdapter<T> out(destination, NULL, index_count); - return meshopt_simplifyWithAttributes(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, vertex_attributes, vertex_attributes_stride, attribute_weights, attribute_count, target_index_count, target_error, options, result_error); + return meshopt_simplifyWithAttributes(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, vertex_attributes, vertex_attributes_stride, attribute_weights, attribute_count, vertex_lock, target_index_count, target_error, options, result_error); } template <typename T> @@ -1050,7 +1113,7 @@ inline void meshopt_spatialSortTriangles(T* destination, const T* indices, size_ #endif /** - * Copyright (c) 2016-2023 Arseny Kapoulkine + * Copyright (c) 2016-2024 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/thirdparty/meshoptimizer/overdrawanalyzer.cpp b/thirdparty/meshoptimizer/overdrawanalyzer.cpp index 8b6f254134..31cf6f146a 100644 --- a/thirdparty/meshoptimizer/overdrawanalyzer.cpp +++ b/thirdparty/meshoptimizer/overdrawanalyzer.cpp @@ -53,11 +53,10 @@ static void rasterize(OverdrawBuffer* buffer, float v1x, float v1y, float v1z, f // flip backfacing triangles to simplify rasterization logic if (sign) { - // flipping v2 & v3 preserves depth gradients since they're based on v1 + // flipping v2 & v3 preserves depth gradients since they're based on v1; only v1z is used below float t; t = v2x, v2x = v3x, v3x = t; t = v2y, v2y = v3y, v3y = t; - t = v2z, v2z = v3z, v3z = t; // flip depth since we rasterize backfacing triangles to second buffer with reverse Z; only v1z is used below v1z = kViewport - v1z; diff --git a/thirdparty/meshoptimizer/patches/distance-only-metric.patch b/thirdparty/meshoptimizer/patches/distance-only-metric.patch index 651bdba5ef..ce16f4ab9c 100644 --- a/thirdparty/meshoptimizer/patches/distance-only-metric.patch +++ b/thirdparty/meshoptimizer/patches/distance-only-metric.patch @@ -1,39 +1,13 @@ diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp -index 5ba8570076..6f8b0e520e 100644 +index af64cbda49..8a7072fe4e 100644 --- a/thirdparty/meshoptimizer/simplifier.cpp +++ b/thirdparty/meshoptimizer/simplifier.cpp -@@ -476,6 +476,8 @@ struct Collapse - float error; - unsigned int errorui; - }; -+ -+ float distance_error; - }; +@@ -2048,7 +2048,7 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic - static float normalize(Vector3& v) -@@ -941,6 +943,8 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const - float ei = quadricError(vertex_quadrics[remap[i0]], vertex_positions[i1]); - float ej = quadricError(vertex_quadrics[remap[j0]], vertex_positions[j1]); + // result_error is quadratic; we need to remap it back to linear + if (out_result_error) +- *out_result_error = sqrtf(result_error) * error_scale; ++ *out_result_error = sqrtf(vertex_error) * error_scale; -+ float dei = ei, dej = ej; -+ - if (attribute_count) - { - ei += quadricError(attribute_quadrics[remap[i0]], &attribute_gradients[remap[i0] * attribute_count], attribute_count, vertex_positions[i1], &vertex_attributes[i1 * attribute_count]); -@@ -951,6 +955,7 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const - c.v0 = ei <= ej ? i0 : j0; - c.v1 = ei <= ej ? i1 : j1; - c.error = ei <= ej ? ei : ej; -+ c.distance_error = ei <= ej ? dei : dej; - } + return result_count; } - -@@ -1097,7 +1102,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* - triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2; - edge_collapses++; - -- result_error = result_error < c.error ? c.error : result_error; -+ result_error = result_error < c.distance_error ? c.distance_error : result_error; - } - - #if TRACE diff --git a/thirdparty/meshoptimizer/quantization.cpp b/thirdparty/meshoptimizer/quantization.cpp index 09a314d602..149835f501 100644 --- a/thirdparty/meshoptimizer/quantization.cpp +++ b/thirdparty/meshoptimizer/quantization.cpp @@ -3,9 +3,15 @@ #include <assert.h> +union FloatBits +{ + float f; + unsigned int ui; +}; + unsigned short meshopt_quantizeHalf(float v) { - union { float f; unsigned int ui; } u = {v}; + FloatBits u = {v}; unsigned int ui = u.ui; int s = (ui >> 16) & 0x8000; @@ -30,7 +36,7 @@ float meshopt_quantizeFloat(float v, int N) { assert(N >= 0 && N <= 23); - union { float f; unsigned int ui; } u = {v}; + FloatBits u = {v}; unsigned int ui = u.ui; const int mask = (1 << (23 - N)) - 1; @@ -64,7 +70,7 @@ float meshopt_dequantizeHalf(unsigned short h) // 112 is an exponent bias fixup; since we already applied it once, applying it twice converts 31 to 255 r += (em >= (31 << 10)) ? (112 << 23) : 0; - union { float f; unsigned int ui; } u; + FloatBits u; u.ui = s | r; return u.f; } diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp index 6f8b0e520e..8a7072fe4e 100644 --- a/thirdparty/meshoptimizer/simplifier.cpp +++ b/thirdparty/meshoptimizer/simplifier.cpp @@ -111,10 +111,12 @@ struct PositionHasher { const float* vertex_positions; size_t vertex_stride_float; + const unsigned int* sparse_remap; size_t hash(unsigned int index) const { - const unsigned int* key = reinterpret_cast<const unsigned int*>(vertex_positions + index * vertex_stride_float); + unsigned int ri = sparse_remap ? sparse_remap[index] : index; + const unsigned int* key = reinterpret_cast<const unsigned int*>(vertex_positions + ri * vertex_stride_float); // scramble bits to make sure that integer coordinates have entropy in lower bits unsigned int x = key[0] ^ (key[0] >> 17); @@ -127,7 +129,25 @@ struct PositionHasher bool equal(unsigned int lhs, unsigned int rhs) const { - return memcmp(vertex_positions + lhs * vertex_stride_float, vertex_positions + rhs * vertex_stride_float, sizeof(float) * 3) == 0; + unsigned int li = sparse_remap ? sparse_remap[lhs] : lhs; + unsigned int ri = sparse_remap ? sparse_remap[rhs] : rhs; + + return memcmp(vertex_positions + li * vertex_stride_float, vertex_positions + ri * vertex_stride_float, sizeof(float) * 3) == 0; + } +}; + +struct RemapHasher +{ + unsigned int* remap; + + size_t hash(unsigned int id) const + { + return id * 0x5bd1e995; + } + + bool equal(unsigned int lhs, unsigned int rhs) const + { + return remap[lhs] == rhs; } }; @@ -167,9 +187,9 @@ static T* hashLookup2(T* table, size_t buckets, const Hash& hash, const T& key, return NULL; } -static void buildPositionRemap(unsigned int* remap, unsigned int* wedge, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, meshopt_Allocator& allocator) +static void buildPositionRemap(unsigned int* remap, unsigned int* wedge, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const unsigned int* sparse_remap, meshopt_Allocator& allocator) { - PositionHasher hasher = {vertex_positions_data, vertex_positions_stride / sizeof(float)}; + PositionHasher hasher = {vertex_positions_data, vertex_positions_stride / sizeof(float), sparse_remap}; size_t table_size = hashBuckets2(vertex_count); unsigned int* table = allocator.allocate<unsigned int>(table_size); @@ -205,6 +225,57 @@ static void buildPositionRemap(unsigned int* remap, unsigned int* wedge, const f allocator.deallocate(table); } +static unsigned int* buildSparseRemap(unsigned int* indices, size_t index_count, size_t vertex_count, size_t* out_vertex_count, meshopt_Allocator& allocator) +{ + // use a bit set to compute the precise number of unique vertices + unsigned char* filter = allocator.allocate<unsigned char>((vertex_count + 7) / 8); + memset(filter, 0, (vertex_count + 7) / 8); + + size_t unique = 0; + for (size_t i = 0; i < index_count; ++i) + { + unsigned int index = indices[i]; + assert(index < vertex_count); + + unique += (filter[index / 8] & (1 << (index % 8))) == 0; + filter[index / 8] |= 1 << (index % 8); + } + + unsigned int* remap = allocator.allocate<unsigned int>(unique); + size_t offset = 0; + + // temporary map dense => sparse; we allocate it last so that we can deallocate it + size_t revremap_size = hashBuckets2(unique); + unsigned int* revremap = allocator.allocate<unsigned int>(revremap_size); + memset(revremap, -1, revremap_size * sizeof(unsigned int)); + + // fill remap, using revremap as a helper, and rewrite indices in the same pass + RemapHasher hasher = {remap}; + + for (size_t i = 0; i < index_count; ++i) + { + unsigned int index = indices[i]; + + unsigned int* entry = hashLookup2(revremap, revremap_size, hasher, index, ~0u); + + if (*entry == ~0u) + { + remap[offset] = index; + *entry = unsigned(offset); + offset++; + } + + indices[i] = *entry; + } + + allocator.deallocate(revremap); + + assert(offset == unique); + *out_vertex_count = unique; + + return remap; +} + enum VertexKind { Kind_Manifold, // not on an attribute seam, not on any boundary @@ -217,14 +288,14 @@ enum VertexKind }; // manifold vertices can collapse onto anything -// border/seam vertices can only be collapsed onto border/seam respectively +// border/seam vertices can collapse onto border/seam respectively, or locked // complex vertices can collapse onto complex/locked // a rule of thumb is that collapsing kind A into kind B preserves the kind B in the target vertex // for example, while we could collapse Complex into Manifold, this would mean the target vertex isn't Manifold anymore const unsigned char kCanCollapse[Kind_Count][Kind_Count] = { {1, 1, 1, 1, 1}, - {0, 1, 0, 0, 0}, - {0, 0, 1, 0, 0}, + {0, 1, 0, 0, 1}, + {0, 0, 1, 0, 1}, {0, 0, 0, 1, 1}, {0, 0, 0, 0, 0}, }; @@ -252,7 +323,7 @@ static bool hasEdge(const EdgeAdjacency& adjacency, unsigned int a, unsigned int return false; } -static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge, unsigned int options) +static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_lock, const unsigned int* sparse_remap, unsigned int options) { memset(loop, -1, vertex_count * sizeof(unsigned int)); memset(loopback, -1, vertex_count * sizeof(unsigned int)); @@ -331,7 +402,7 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned if (openiv != ~0u && openiv != i && openov != ~0u && openov != i && openiw != ~0u && openiw != w && openow != ~0u && openow != w) { - if (remap[openiv] == remap[openow] && remap[openov] == remap[openiw]) + if (remap[openiv] == remap[openow] && remap[openov] == remap[openiw] && remap[openiv] != remap[openov]) { result[i] = Kind_Seam; } @@ -362,6 +433,18 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned } } + if (vertex_lock) + { + // vertex_lock may lock any wedge, not just the primary vertex, so we need to lock the primary vertex and relock any wedges + for (size_t i = 0; i < vertex_count; ++i) + if (vertex_lock[sparse_remap ? sparse_remap[i] : i]) + result[remap[i]] = Kind_Locked; + + for (size_t i = 0; i < vertex_count; ++i) + if (result[remap[i]] == Kind_Locked) + result[i] = Kind_Locked; + } + if (options & meshopt_SimplifyLockBorder) for (size_t i = 0; i < vertex_count; ++i) if (result[i] == Kind_Border) @@ -378,7 +461,7 @@ struct Vector3 float x, y, z; }; -static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride) +static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const unsigned int* sparse_remap = NULL) { size_t vertex_stride_float = vertex_positions_stride / sizeof(float); @@ -387,7 +470,8 @@ static float rescalePositions(Vector3* result, const float* vertex_positions_dat for (size_t i = 0; i < vertex_count; ++i) { - const float* v = vertex_positions_data + i * vertex_stride_float; + unsigned int ri = sparse_remap ? sparse_remap[i] : unsigned(i); + const float* v = vertex_positions_data + ri * vertex_stride_float; if (result) { @@ -426,22 +510,25 @@ static float rescalePositions(Vector3* result, const float* vertex_positions_dat return extent; } -static void rescaleAttributes(float* result, const float* vertex_attributes_data, size_t vertex_count, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count) +static void rescaleAttributes(float* result, const float* vertex_attributes_data, size_t vertex_count, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned int* attribute_remap, const unsigned int* sparse_remap) { size_t vertex_attributes_stride_float = vertex_attributes_stride / sizeof(float); for (size_t i = 0; i < vertex_count; ++i) { + unsigned int ri = sparse_remap ? sparse_remap[i] : unsigned(i); + for (size_t k = 0; k < attribute_count; ++k) { - float a = vertex_attributes_data[i * vertex_attributes_stride_float + k]; + unsigned int rk = attribute_remap[k]; + float a = vertex_attributes_data[ri * vertex_attributes_stride_float + rk]; - result[i * attribute_count + k] = a * attribute_weights[k]; + result[i * attribute_count + k] = a * attribute_weights[rk]; } } } -static const size_t kMaxAttributes = 16; +static const size_t kMaxAttributes = 32; struct Quadric { @@ -476,8 +563,6 @@ struct Collapse float error; unsigned int errorui; }; - - float distance_error; }; static float normalize(Vector3& v) @@ -520,7 +605,7 @@ static void quadricAdd(QuadricGrad* G, const QuadricGrad* R, size_t attribute_co } } -static float quadricError(const Quadric& Q, const Vector3& v) +static float quadricEval(const Quadric& Q, const Vector3& v) { float rx = Q.b0; float ry = Q.b1; @@ -543,6 +628,12 @@ static float quadricError(const Quadric& Q, const Vector3& v) r += ry * v.y; r += rz * v.z; + return r; +} + +static float quadricError(const Quadric& Q, const Vector3& v) +{ + float r = quadricEval(Q, v); float s = Q.w == 0.f ? 0.f : 1.f / Q.w; return fabsf(r) * s; @@ -550,26 +641,7 @@ static float quadricError(const Quadric& Q, const Vector3& v) static float quadricError(const Quadric& Q, const QuadricGrad* G, size_t attribute_count, const Vector3& v, const float* va) { - float rx = Q.b0; - float ry = Q.b1; - float rz = Q.b2; - - rx += Q.a10 * v.y; - ry += Q.a21 * v.z; - rz += Q.a20 * v.x; - - rx *= 2; - ry *= 2; - rz *= 2; - - rx += Q.a00 * v.x; - ry += Q.a11 * v.y; - rz += Q.a22 * v.z; - - float r = Q.c; - r += rx * v.x; - r += ry * v.y; - r += rz * v.z; + float r = quadricEval(Q, v); // see quadricFromAttributes for general derivation; here we need to add the parts of (eval(pos) - attr)^2 that depend on attr for (size_t k = 0; k < attribute_count; ++k) @@ -577,14 +649,11 @@ static float quadricError(const Quadric& Q, const QuadricGrad* G, size_t attribu float a = va[k]; float g = v.x * G[k].gx + v.y * G[k].gy + v.z * G[k].gz + G[k].gw; - r += a * a * Q.w; - r -= 2 * a * g; + r += a * (a * Q.w - 2 * g); } - // TODO: weight normalization is breaking attribute error somehow - float s = 1;// Q.w == 0.f ? 0.f : 1.f / Q.w; - - return fabsf(r) * s; + // note: unlike position error, we do not normalize by Q.w to retain edge scaling as described in quadricFromAttributes + return fabsf(r); } static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, float w) @@ -625,20 +694,24 @@ static void quadricFromTriangle(Quadric& Q, const Vector3& p0, const Vector3& p1 static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float weight) { Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z}; - float length = normalize(p10); - // p20p = length of projection of p2-p0 onto normalize(p1 - p0) + // edge length; keep squared length around for projection correction + float lengthsq = p10.x * p10.x + p10.y * p10.y + p10.z * p10.z; + float length = sqrtf(lengthsq); + + // p20p = length of projection of p2-p0 onto p1-p0; note that p10 is unnormalized so we need to correct it later Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z}; float p20p = p20.x * p10.x + p20.y * p10.y + p20.z * p10.z; - // normal = altitude of triangle from point p2 onto edge p1-p0 - Vector3 normal = {p20.x - p10.x * p20p, p20.y - p10.y * p20p, p20.z - p10.z * p20p}; - normalize(normal); + // perp = perpendicular vector from p2 to line segment p1-p0 + // note: since p10 is unnormalized we need to correct the projection; we scale p20 instead to take advantage of normalize below + Vector3 perp = {p20.x * lengthsq - p10.x * p20p, p20.y * lengthsq - p10.y * p20p, p20.z * lengthsq - p10.z * p20p}; + normalize(perp); - float distance = normal.x * p0.x + normal.y * p0.y + normal.z * p0.z; + float distance = perp.x * p0.x + perp.y * p0.y + perp.z * p0.z; // note: the weight is scaled linearly with edge length; this has to match the triangle weight - quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight); + quadricFromPlane(Q, perp.x, perp.y, perp.z, -distance, length * weight); } static void quadricFromAttributes(Quadric& Q, QuadricGrad* G, const Vector3& p0, const Vector3& p1, const Vector3& p2, const float* va0, const float* va1, const float* va2, size_t attribute_count) @@ -651,16 +724,21 @@ static void quadricFromAttributes(Quadric& Q, QuadricGrad* G, const Vector3& p0, Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z}; Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z}; - // weight is scaled linearly with edge length + // normal = cross(p1 - p0, p2 - p0) Vector3 normal = {p10.y * p20.z - p10.z * p20.y, p10.z * p20.x - p10.x * p20.z, p10.x * p20.y - p10.y * p20.x}; - float area = sqrtf(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z); - float w = sqrtf(area); // TODO this needs more experimentation + float area = sqrtf(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z) * 0.5f; + + // quadric is weighted with the square of edge length (= area) + // this equalizes the units with the positional error (which, after normalization, is a square of distance) + // as a result, a change in weighted attribute of 1 along distance d is approximately equivalent to a change in position of d + float w = area; // we compute gradients using barycentric coordinates; barycentric coordinates can be computed as follows: // v = (d11 * d20 - d01 * d21) / denom // w = (d00 * d21 - d01 * d20) / denom // u = 1 - v - w // here v0, v1 are triangle edge vectors, v2 is a vector from point to triangle corner, and dij = dot(vi, vj) + // note: v2 and d20/d21 can not be evaluated here as v2 is effectively an unknown variable; we need these only as variables for derivation of gradients const Vector3& v0 = p10; const Vector3& v1 = p20; float d00 = v0.x * v0.x + v0.y * v0.y + v0.z * v0.z; @@ -670,7 +748,7 @@ static void quadricFromAttributes(Quadric& Q, QuadricGrad* G, const Vector3& p0, float denomr = denom == 0 ? 0.f : 1.f / denom; // precompute gradient factors - // these are derived by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w and factoring out common factors that are shared between attributes + // these are derived by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w and factoring out expressions that are shared between attributes float gx1 = (d11 * v0.x - d01 * v1.x) * denomr; float gx2 = (d00 * v1.x - d01 * v0.x) * denomr; float gy1 = (d11 * v0.y - d01 * v1.y) * denomr; @@ -695,6 +773,7 @@ static void quadricFromAttributes(Quadric& Q, QuadricGrad* G, const Vector3& p0, // quadric encodes (eval(pos)-attr)^2; this means that the resulting expansion needs to compute, for example, pos.x * pos.y * K // since quadrics already encode factors for pos.x * pos.y, we can accumulate almost everything in basic quadric fields + // note: for simplicity we scale all factors by weight here instead of outside the loop Q.a00 += w * (gx * gx); Q.a11 += w * (gy * gy); Q.a22 += w * (gz * gz); @@ -782,7 +861,7 @@ static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indic } } -static void fillAttributeQuadrics(Quadric* attribute_quadrics, QuadricGrad* attribute_gradients, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const float* vertex_attributes, size_t attribute_count, const unsigned int* remap) +static void fillAttributeQuadrics(Quadric* attribute_quadrics, QuadricGrad* attribute_gradients, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const float* vertex_attributes, size_t attribute_count) { for (size_t i = 0; i < index_count; i += 3) { @@ -794,14 +873,13 @@ static void fillAttributeQuadrics(Quadric* attribute_quadrics, QuadricGrad* attr QuadricGrad G[kMaxAttributes]; quadricFromAttributes(QA, G, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], &vertex_attributes[i0 * attribute_count], &vertex_attributes[i1 * attribute_count], &vertex_attributes[i2 * attribute_count], attribute_count); - // TODO: This blends together attribute weights across attribute discontinuities, which is probably not a great idea - quadricAdd(attribute_quadrics[remap[i0]], QA); - quadricAdd(attribute_quadrics[remap[i1]], QA); - quadricAdd(attribute_quadrics[remap[i2]], QA); + quadricAdd(attribute_quadrics[i0], QA); + quadricAdd(attribute_quadrics[i1], QA); + quadricAdd(attribute_quadrics[i2], QA); - quadricAdd(&attribute_gradients[remap[i0] * attribute_count], G, attribute_count); - quadricAdd(&attribute_gradients[remap[i1] * attribute_count], G, attribute_count); - quadricAdd(&attribute_gradients[remap[i2] * attribute_count], G, attribute_count); + quadricAdd(&attribute_gradients[i0 * attribute_count], G, attribute_count); + quadricAdd(&attribute_gradients[i1 * attribute_count], G, attribute_count); + quadricAdd(&attribute_gradients[i2 * attribute_count], G, attribute_count); } } @@ -815,7 +893,13 @@ static bool hasTriangleFlip(const Vector3& a, const Vector3& b, const Vector3& c Vector3 nbc = {eb.y * ec.z - eb.z * ec.y, eb.z * ec.x - eb.x * ec.z, eb.x * ec.y - eb.y * ec.x}; Vector3 nbd = {eb.y * ed.z - eb.z * ed.y, eb.z * ed.x - eb.x * ed.z, eb.x * ed.y - eb.y * ed.x}; - return nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z <= 0; + float ndp = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; + float abc = nbc.x * nbc.x + nbc.y * nbc.y + nbc.z * nbc.z; + float abd = nbd.x * nbd.x + nbd.y * nbd.y + nbd.z * nbd.z; + + // scale is cos(angle); somewhat arbitrarily set to ~75 degrees + // note that the "pure" check is ndp <= 0 (90 degree cutoff) but that allows flipping through a series of close-to-90 collapses + return ndp <= 0.25f * sqrtf(abc * abd); } static bool hasTriangleFlips(const EdgeAdjacency& adjacency, const Vector3* vertex_positions, const unsigned int* collapse_remap, unsigned int i0, unsigned int i1) @@ -840,7 +924,13 @@ static bool hasTriangleFlips(const EdgeAdjacency& adjacency, const Vector3* vert // early-out when at least one triangle flips due to a collapse if (hasTriangleFlip(vertex_positions[a], vertex_positions[b], v0, v1)) + { +#if TRACE >= 2 + printf("edge block %d -> %d: flip welded %d %d %d\n", i0, i1, a, i0, b); +#endif + return true; + } } return false; @@ -864,7 +954,7 @@ static size_t boundEdgeCollapses(const EdgeAdjacency& adjacency, size_t vertex_c return (index_count - dual_count / 2) + 3; } -static size_t pickEdgeCollapses(Collapse* collapses, size_t collapse_capacity, const unsigned int* indices, size_t index_count, const unsigned int* remap, const unsigned char* vertex_kind, const unsigned int* loop) +static size_t pickEdgeCollapses(Collapse* collapses, size_t collapse_capacity, const unsigned int* indices, size_t index_count, const unsigned int* remap, const unsigned char* vertex_kind, const unsigned int* loop, const unsigned int* loopback) { size_t collapse_count = 0; @@ -904,6 +994,16 @@ static size_t pickEdgeCollapses(Collapse* collapses, size_t collapse_capacity, c if (k0 == k1 && (k0 == Kind_Border || k0 == Kind_Seam) && loop[i0] != i1) continue; + if (k0 == Kind_Locked || k1 == Kind_Locked) + { + // the same check as above, but for border/seam -> locked collapses + // loop[] and loopback[] track half edges so we only need to check one of them + if ((k0 == Kind_Border || k0 == Kind_Seam) && loop[i0] != i1) + continue; + if ((k1 == Kind_Border || k1 == Kind_Seam) && loopback[i1] != i0) + continue; + } + // edge can be collapsed in either direction - we will pick the one with minimum error // note: we evaluate error later during collapse ranking, here we just tag the edge as bidirectional if (kCanCollapse[k0][k1] & kCanCollapse[k1][k0]) @@ -943,34 +1043,52 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const float ei = quadricError(vertex_quadrics[remap[i0]], vertex_positions[i1]); float ej = quadricError(vertex_quadrics[remap[j0]], vertex_positions[j1]); - float dei = ei, dej = ej; +#if TRACE >= 3 + float di = ei, dj = ej; +#endif if (attribute_count) { - ei += quadricError(attribute_quadrics[remap[i0]], &attribute_gradients[remap[i0] * attribute_count], attribute_count, vertex_positions[i1], &vertex_attributes[i1 * attribute_count]); - ej += quadricError(attribute_quadrics[remap[j0]], &attribute_gradients[remap[j0] * attribute_count], attribute_count, vertex_positions[j1], &vertex_attributes[j1 * attribute_count]); + // note: ideally we would evaluate max/avg of attribute errors for seam edges, but it's not clear if it's worth the extra cost + ei += quadricError(attribute_quadrics[i0], &attribute_gradients[i0 * attribute_count], attribute_count, vertex_positions[i1], &vertex_attributes[i1 * attribute_count]); + ej += quadricError(attribute_quadrics[j0], &attribute_gradients[j0 * attribute_count], attribute_count, vertex_positions[j1], &vertex_attributes[j1 * attribute_count]); } // pick edge direction with minimal error c.v0 = ei <= ej ? i0 : j0; c.v1 = ei <= ej ? i1 : j1; c.error = ei <= ej ? ei : ej; - c.distance_error = ei <= ej ? dei : dej; + +#if TRACE >= 3 + if (i0 == j0) // c.bidi has been overwritten + printf("edge eval %d -> %d: error %f (pos %f, attr %f)\n", c.v0, c.v1, + sqrtf(c.error), sqrtf(ei <= ej ? di : dj), sqrtf(ei <= ej ? ei - di : ej - dj)); + else + printf("edge eval %d -> %d: error %f (pos %f, attr %f); reverse %f (pos %f, attr %f)\n", c.v0, c.v1, + sqrtf(ei <= ej ? ei : ej), sqrtf(ei <= ej ? di : dj), sqrtf(ei <= ej ? ei - di : ej - dj), + sqrtf(ei <= ej ? ej : ei), sqrtf(ei <= ej ? dj : di), sqrtf(ei <= ej ? ej - dj : ei - di)); +#endif } } static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapses, size_t collapse_count) { - const int sort_bits = 11; + // we use counting sort to order collapses by error; since the exact sort order is not as critical, + // only top 12 bits of exponent+mantissa (8 bits of exponent and 4 bits of mantissa) are used. + // to avoid excessive stack usage, we clamp the exponent range as collapses with errors much higher than 1 are not useful. + const unsigned int sort_bits = 12; + const unsigned int sort_bins = 2048 + 512; // exponent range [-127, 32) // fill histogram for counting sort - unsigned int histogram[1 << sort_bits]; + unsigned int histogram[sort_bins]; memset(histogram, 0, sizeof(histogram)); for (size_t i = 0; i < collapse_count; ++i) { // skip sign bit since error is non-negative - unsigned int key = (collapses[i].errorui << 1) >> (32 - sort_bits); + unsigned int error = collapses[i].errorui; + unsigned int key = (error << 1) >> (32 - sort_bits); + key = key < sort_bins ? key : sort_bins - 1; histogram[key]++; } @@ -978,7 +1096,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse // compute offsets based on histogram data size_t histogram_sum = 0; - for (size_t i = 0; i < 1 << sort_bits; ++i) + for (size_t i = 0; i < sort_bins; ++i) { size_t count = histogram[i]; histogram[i] = unsigned(histogram_sum); @@ -991,13 +1109,15 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse for (size_t i = 0; i < collapse_count; ++i) { // skip sign bit since error is non-negative - unsigned int key = (collapses[i].errorui << 1) >> (32 - sort_bits); + unsigned int error = collapses[i].errorui; + unsigned int key = (error << 1) >> (32 - sort_bits); + key = key < sort_bins ? key : sort_bins - 1; sort_order[histogram[key]++] = unsigned(i); } } -static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_locked, Quadric* vertex_quadrics, Quadric* attribute_quadrics, QuadricGrad* attribute_gradients, size_t attribute_count, const Collapse* collapses, size_t collapse_count, const unsigned int* collapse_order, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_kind, const Vector3* vertex_positions, const EdgeAdjacency& adjacency, size_t triangle_collapse_goal, float error_limit, float& result_error) +static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_locked, const Collapse* collapses, size_t collapse_count, const unsigned int* collapse_order, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_kind, const unsigned int* loop, const unsigned int* loopback, const Vector3* vertex_positions, const EdgeAdjacency& adjacency, size_t triangle_collapse_goal, float error_limit, float& result_error) { size_t edge_collapses = 0; size_t triangle_collapses = 0; @@ -1007,7 +1127,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* size_t edge_collapse_goal = triangle_collapse_goal / 2; #if TRACE - size_t stats[4] = {}; + size_t stats[7] = {}; #endif for (size_t i = 0; i < collapse_count; ++i) @@ -1017,10 +1137,16 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* TRACESTATS(0); if (c.error > error_limit) + { + TRACESTATS(4); break; + } if (triangle_collapses >= triangle_collapse_goal) + { + TRACESTATS(5); break; + } // we limit the error in each pass based on the error of optimal last collapse; since many collapses will be locked // as they will share vertices with other successfull collapses, we need to increase the acceptable error by some factor @@ -1028,8 +1154,11 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* // on average, each collapse is expected to lock 6 other collapses; to avoid degenerate passes on meshes with odd // topology, we only abort if we got over 1/6 collapses accordingly. - if (c.error > error_goal && triangle_collapses > triangle_collapse_goal / 6) + if (c.error > error_goal && c.error > result_error && triangle_collapses > triangle_collapse_goal / 6) + { + TRACESTATS(6); break; + } unsigned int i0 = c.v0; unsigned int i1 = c.v1; @@ -1037,6 +1166,8 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* unsigned int r0 = remap[i0]; unsigned int r1 = remap[i1]; + unsigned char kind = vertex_kind[i0]; + // we don't collapse vertices that had source or target vertex involved in a collapse // it's important to not move the vertices twice since it complicates the tracking/remapping logic // it's important to not move other vertices towards a moved vertex to preserve error since we don't re-rank collapses mid-pass @@ -1055,35 +1186,39 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* continue; } +#if TRACE >= 2 + printf("edge commit %d -> %d: kind %d->%d, error %f\n", i0, i1, vertex_kind[i0], vertex_kind[i1], sqrtf(c.error)); +#endif + assert(collapse_remap[r0] == r0); assert(collapse_remap[r1] == r1); - quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]); - - if (attribute_count) - { - quadricAdd(attribute_quadrics[r1], attribute_quadrics[r0]); - quadricAdd(&attribute_gradients[r1 * attribute_count], &attribute_gradients[r0 * attribute_count], attribute_count); - } - - if (vertex_kind[i0] == Kind_Complex) + if (kind == Kind_Complex) { + // remap all vertices in the complex to the target vertex unsigned int v = i0; do { - collapse_remap[v] = r1; + collapse_remap[v] = i1; v = wedge[v]; } while (v != i0); } - else if (vertex_kind[i0] == Kind_Seam) + else if (kind == Kind_Seam) { - // remap v0 to v1 and seam pair of v0 to seam pair of v1 + // for seam collapses we need to move the seam pair together; this is a bit tricky to compute since we need to rely on edge loops as target vertex may be locked (and thus have more than two wedges) unsigned int s0 = wedge[i0]; - unsigned int s1 = wedge[i1]; + unsigned int s1 = loop[i0] == i1 ? loopback[s0] : loop[s0]; + assert(s0 != i0 && wedge[s0] == i0); + assert(s1 != ~0u && remap[s1] == r1); + + // additional asserts to verify that the seam pair is consistent + assert(kind != vertex_kind[i1] || s1 == wedge[i1]); + assert(loop[i0] == i1 || loopback[i0] == i1); + assert(loop[s0] == s1 || loopback[s0] == s1); - assert(s0 != i0 && s1 != i1); - assert(wedge[s0] == i0 && wedge[s1] == i1); + // note: this should never happen due to the assertion above, but when disabled if we ever hit this case we'll get a memory safety issue; for now play it safe + s1 = (s1 != ~0u) ? s1 : wedge[i1]; collapse_remap[i0] = i1; collapse_remap[s0] = s1; @@ -1095,27 +1230,63 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_remap[i0] = i1; } + // note: we technically don't need to lock r1 if it's a locked vertex, as it can't move and its quadric won't be used + // however, this results in slightly worse error on some meshes because the locked collapses get an unfair advantage wrt scheduling collapse_locked[r0] = 1; collapse_locked[r1] = 1; // border edges collapse 1 triangle, other edges collapse 2 or more - triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2; + triangle_collapses += (kind == Kind_Border) ? 1 : 2; edge_collapses++; - result_error = result_error < c.distance_error ? c.distance_error : result_error; + result_error = result_error < c.error ? c.error : result_error; } #if TRACE - float error_goal_perfect = edge_collapse_goal < collapse_count ? collapses[collapse_order[edge_collapse_goal]].error : 0.f; + float error_goal_last = edge_collapse_goal < collapse_count ? 1.5f * collapses[collapse_order[edge_collapse_goal]].error : FLT_MAX; + float error_goal_limit = error_goal_last < error_limit ? error_goal_last : error_limit; - printf("removed %d triangles, error %e (goal %e); evaluated %d/%d collapses (done %d, skipped %d, invalid %d)\n", - int(triangle_collapses), sqrtf(result_error), sqrtf(error_goal_perfect), - int(stats[0]), int(collapse_count), int(edge_collapses), int(stats[1]), int(stats[2])); + printf("removed %d triangles, error %e (goal %e); evaluated %d/%d collapses (done %d, skipped %d, invalid %d); %s\n", + int(triangle_collapses), sqrtf(result_error), sqrtf(error_goal_limit), + int(stats[0]), int(collapse_count), int(edge_collapses), int(stats[1]), int(stats[2]), + stats[4] ? "error limit" : (stats[5] ? "count limit" : (stats[6] ? "error goal" : "out of collapses"))); #endif return edge_collapses; } +static void updateQuadrics(const unsigned int* collapse_remap, size_t vertex_count, Quadric* vertex_quadrics, Quadric* attribute_quadrics, QuadricGrad* attribute_gradients, size_t attribute_count, const Vector3* vertex_positions, const unsigned int* remap, float& vertex_error) +{ + for (size_t i = 0; i < vertex_count; ++i) + { + if (collapse_remap[i] == i) + continue; + + unsigned int i0 = unsigned(i); + unsigned int i1 = collapse_remap[i]; + + unsigned int r0 = remap[i0]; + unsigned int r1 = remap[i1]; + + // ensure we only update vertex_quadrics once: primary vertex must be moved if any wedge is moved + if (i0 == r0) + quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]); + + if (attribute_count) + { + quadricAdd(attribute_quadrics[i1], attribute_quadrics[i0]); + quadricAdd(&attribute_gradients[i1 * attribute_count], &attribute_gradients[i0 * attribute_count], attribute_count); + + if (i0 == r0) + { + // when attributes are used, distance error needs to be recomputed as collapses don't track it; it is safe to do this after the quadric adjustment + float derr = quadricError(vertex_quadrics[r0], vertex_positions[r1]); + vertex_error = vertex_error < derr ? derr : vertex_error; + } + } + } +} + static size_t remapIndexBuffer(unsigned int* indices, size_t index_count, const unsigned int* collapse_remap) { size_t write = 0; @@ -1147,15 +1318,179 @@ static void remapEdgeLoops(unsigned int* loop, size_t vertex_count, const unsign { for (size_t i = 0; i < vertex_count; ++i) { + // note: this is a no-op for vertices that were remapped + // ideally we would clear the loop entries for those for consistency, even though they aren't going to be used + // however, the remapping process needs loop information for remapped vertices, so this would require a separate pass if (loop[i] != ~0u) { unsigned int l = loop[i]; unsigned int r = collapse_remap[l]; // i == r is a special case when the seam edge is collapsed in a direction opposite to where loop goes - loop[i] = (i == r) ? loop[l] : r; + if (i == r) + loop[i] = (loop[l] != ~0u) ? collapse_remap[loop[l]] : ~0u; + else + loop[i] = r; + } + } +} + +static unsigned int follow(unsigned int* parents, unsigned int index) +{ + while (index != parents[index]) + { + unsigned int parent = parents[index]; + parents[index] = parents[parent]; + index = parent; + } + + return index; +} + +static size_t buildComponents(unsigned int* components, size_t vertex_count, const unsigned int* indices, size_t index_count, const unsigned int* remap) +{ + for (size_t i = 0; i < vertex_count; ++i) + components[i] = unsigned(i); + + // compute a unique (but not sequential!) index for each component via union-find + for (size_t i = 0; i < index_count; i += 3) + { + static const int next[4] = {1, 2, 0, 1}; + + for (int e = 0; e < 3; ++e) + { + unsigned int i0 = indices[i + e]; + unsigned int i1 = indices[i + next[e]]; + + unsigned int r0 = remap[i0]; + unsigned int r1 = remap[i1]; + + r0 = follow(components, r0); + r1 = follow(components, r1); + + // merge components with larger indices into components with smaller indices + // this guarantees that the root of the component is always the one with the smallest index + if (r0 != r1) + components[r0 < r1 ? r1 : r0] = r0 < r1 ? r0 : r1; } } + + // make sure each element points to the component root *before* we renumber the components + for (size_t i = 0; i < vertex_count; ++i) + if (remap[i] == i) + components[i] = follow(components, unsigned(i)); + + unsigned int next_component = 0; + + // renumber components using sequential indices + // a sequential pass is sufficient because component root always has the smallest index + // note: it is unsafe to use follow() in this pass because we're replacing component links with sequential indices inplace + for (size_t i = 0; i < vertex_count; ++i) + { + if (remap[i] == i) + { + unsigned int root = components[i]; + assert(root <= i); // make sure we already computed the component for non-roots + components[i] = (root == i) ? next_component++ : components[root]; + } + else + { + assert(remap[i] < i); // make sure we already computed the component + components[i] = components[remap[i]]; + } + } + + return next_component; +} + +static void measureComponents(float* component_errors, size_t component_count, const unsigned int* components, const Vector3* vertex_positions, size_t vertex_count) +{ + memset(component_errors, 0, component_count * 4 * sizeof(float)); + + // compute approximate sphere center for each component as an average + for (size_t i = 0; i < vertex_count; ++i) + { + unsigned int c = components[i]; + assert(components[i] < component_count); + + Vector3 v = vertex_positions[i]; // copy avoids aliasing issues + + component_errors[c * 4 + 0] += v.x; + component_errors[c * 4 + 1] += v.y; + component_errors[c * 4 + 2] += v.z; + component_errors[c * 4 + 3] += 1; // weight + } + + // complete the center computation, and reinitialize [3] as a radius + for (size_t i = 0; i < component_count; ++i) + { + float w = component_errors[i * 4 + 3]; + float iw = w == 0.f ? 0.f : 1.f / w; + + component_errors[i * 4 + 0] *= iw; + component_errors[i * 4 + 1] *= iw; + component_errors[i * 4 + 2] *= iw; + component_errors[i * 4 + 3] = 0; // radius + } + + // compute squared radius for each component + for (size_t i = 0; i < vertex_count; ++i) + { + unsigned int c = components[i]; + + float dx = vertex_positions[i].x - component_errors[c * 4 + 0]; + float dy = vertex_positions[i].y - component_errors[c * 4 + 1]; + float dz = vertex_positions[i].z - component_errors[c * 4 + 2]; + float r = dx * dx + dy * dy + dz * dz; + + component_errors[c * 4 + 3] = component_errors[c * 4 + 3] < r ? r : component_errors[c * 4 + 3]; + } + + // we've used the output buffer as scratch space, so we need to move the results to proper indices + for (size_t i = 0; i < component_count; ++i) + { +#if TRACE >= 2 + printf("component %d: center %f %f %f, error %e\n", int(i), + component_errors[i * 4 + 0], component_errors[i * 4 + 1], component_errors[i * 4 + 2], sqrtf(component_errors[i * 4 + 3])); +#endif + // note: we keep the squared error to make it match quadric error metric + component_errors[i] = component_errors[i * 4 + 3]; + } +} + +static size_t pruneComponents(unsigned int* indices, size_t index_count, const unsigned int* components, const float* component_errors, size_t component_count, float error_cutoff, float& nexterror) +{ + size_t write = 0; + + for (size_t i = 0; i < index_count; i += 3) + { + unsigned int c = components[indices[i]]; + assert(c == components[indices[i + 1]] && c == components[indices[i + 2]]); + + if (component_errors[c] > error_cutoff) + { + indices[write + 0] = indices[i + 0]; + indices[write + 1] = indices[i + 1]; + indices[write + 2] = indices[i + 2]; + write += 3; + } + } + +#if TRACE + size_t pruned_components = 0; + for (size_t i = 0; i < component_count; ++i) + pruned_components += (component_errors[i] >= nexterror && component_errors[i] <= error_cutoff); + + printf("pruned %d triangles in %d components (goal %e)\n", int((index_count - write) / 3), int(pruned_components), sqrtf(error_cutoff)); +#endif + + // update next error with the smallest error of the remaining components for future pruning + nexterror = FLT_MAX; + for (size_t i = 0; i < component_count; ++i) + if (component_errors[i] > error_cutoff) + nexterror = nexterror > component_errors[i] ? component_errors[i] : nexterror; + + return write; } struct CellHasher @@ -1310,7 +1645,7 @@ static void fillCellQuadrics(Quadric* cell_quadrics, const unsigned int* indices unsigned int c1 = vertex_cells[i1]; unsigned int c2 = vertex_cells[i2]; - bool single_cell = (c0 == c1) & (c0 == c2); + int single_cell = (c0 == c1) & (c0 == c2); Quadric Q; quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], single_cell ? 3.f : 1.f); @@ -1330,7 +1665,7 @@ static void fillCellQuadrics(Quadric* cell_quadrics, const unsigned int* indices static void fillCellReservoirs(Reservoir* cell_reservoirs, size_t cell_count, const Vector3* vertex_positions, const float* vertex_colors, size_t vertex_colors_stride, size_t vertex_count, const unsigned int* vertex_cells) { - static const float dummy_color[] = { 0.f, 0.f, 0.f }; + static const float dummy_color[] = {0.f, 0.f, 0.f}; size_t vertex_colors_stride_float = vertex_colors_stride / sizeof(float); @@ -1385,7 +1720,7 @@ static void fillCellRemap(unsigned int* cell_remap, float* cell_errors, size_t c static void fillCellRemap(unsigned int* cell_remap, float* cell_errors, size_t cell_count, const unsigned int* vertex_cells, const Reservoir* cell_reservoirs, const Vector3* vertex_positions, const float* vertex_colors, size_t vertex_colors_stride, float color_weight, size_t vertex_count) { - static const float dummy_color[] = { 0.f, 0.f, 0.f }; + static const float dummy_color[] = {0.f, 0.f, 0.f}; size_t vertex_colors_stride_float = vertex_colors_stride / sizeof(float); @@ -1466,14 +1801,13 @@ static float interpolate(float y, float x0, float y0, float x1, float y1, float } // namespace meshopt -#ifndef NDEBUG -// Note: this is only exposed for debug visualization purposes; do *not* use these in debug builds -MESHOPTIMIZER_API unsigned char* meshopt_simplifyDebugKind = NULL; -MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoop = NULL; -MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = NULL; -#endif +// Note: this is only exposed for debug visualization purposes; do *not* use +enum +{ + meshopt_SimplifyInternalDebug = 1 << 30 +}; -size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) +size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned char* vertex_lock, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) { using namespace meshopt; @@ -1481,30 +1815,41 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); assert(target_index_count <= index_count); - assert((options & ~(meshopt_SimplifyLockBorder)) == 0); + assert(target_error >= 0); + assert((options & ~(meshopt_SimplifyLockBorder | meshopt_SimplifySparse | meshopt_SimplifyErrorAbsolute | meshopt_SimplifyPrune | meshopt_SimplifyInternalDebug)) == 0); assert(vertex_attributes_stride >= attribute_count * sizeof(float) && vertex_attributes_stride <= 256); assert(vertex_attributes_stride % sizeof(float) == 0); assert(attribute_count <= kMaxAttributes); + for (size_t i = 0; i < attribute_count; ++i) + assert(attribute_weights[i] >= 0); meshopt_Allocator allocator; unsigned int* result = destination; + if (result != indices) + memcpy(result, indices, index_count * sizeof(unsigned int)); + + // build an index remap and update indices/vertex_count to minimize the subsequent work + // note: as a consequence, errors will be computed relative to the subset extent + unsigned int* sparse_remap = NULL; + if (options & meshopt_SimplifySparse) + sparse_remap = buildSparseRemap(result, index_count, vertex_count, &vertex_count, allocator); // build adjacency information EdgeAdjacency adjacency = {}; prepareEdgeAdjacency(adjacency, index_count, vertex_count, allocator); - updateEdgeAdjacency(adjacency, indices, index_count, vertex_count, NULL); + updateEdgeAdjacency(adjacency, result, index_count, vertex_count, NULL); // build position remap that maps each vertex to the one with identical position unsigned int* remap = allocator.allocate<unsigned int>(vertex_count); unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count); - buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, allocator); + buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, sparse_remap, allocator); // classify vertices; vertex kind determines collapse rules, see kCanCollapse unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count); unsigned int* loop = allocator.allocate<unsigned int>(vertex_count); unsigned int* loopback = allocator.allocate<unsigned int>(vertex_count); - classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge, options); + classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge, vertex_lock, sparse_remap, options); #if TRACE size_t unique_positions = 0; @@ -1522,14 +1867,23 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic #endif Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count); - rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride); + float vertex_scale = rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride, sparse_remap); float* vertex_attributes = NULL; if (attribute_count) { + unsigned int attribute_remap[kMaxAttributes]; + + // remap attributes to only include ones with weight > 0 to minimize memory/compute overhead for quadrics + size_t attributes_used = 0; + for (size_t i = 0; i < attribute_count; ++i) + if (attribute_weights[i] > 0) + attribute_remap[attributes_used++] = unsigned(i); + + attribute_count = attributes_used; vertex_attributes = allocator.allocate<float>(vertex_count * attribute_count); - rescaleAttributes(vertex_attributes, vertex_attributes_data, vertex_count, vertex_attributes_stride, attribute_weights, attribute_count); + rescaleAttributes(vertex_attributes, vertex_attributes_data, vertex_count, vertex_attributes_stride, attribute_weights, attribute_count, attribute_remap, sparse_remap); } Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count); @@ -1547,14 +1901,33 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic memset(attribute_gradients, 0, vertex_count * attribute_count * sizeof(QuadricGrad)); } - fillFaceQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap); - fillEdgeQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap, vertex_kind, loop, loopback); + fillFaceQuadrics(vertex_quadrics, result, index_count, vertex_positions, remap); + fillEdgeQuadrics(vertex_quadrics, result, index_count, vertex_positions, remap, vertex_kind, loop, loopback); if (attribute_count) - fillAttributeQuadrics(attribute_quadrics, attribute_gradients, indices, index_count, vertex_positions, vertex_attributes, attribute_count, remap); + fillAttributeQuadrics(attribute_quadrics, attribute_gradients, result, index_count, vertex_positions, vertex_attributes, attribute_count); - if (result != indices) - memcpy(result, indices, index_count * sizeof(unsigned int)); + unsigned int* components = NULL; + float* component_errors = NULL; + size_t component_count = 0; + float component_nexterror = 0; + + if (options & meshopt_SimplifyPrune) + { + components = allocator.allocate<unsigned int>(vertex_count); + component_count = buildComponents(components, vertex_count, result, index_count, remap); + + component_errors = allocator.allocate<float>(component_count * 4); // overallocate for temporary use inside measureComponents + measureComponents(component_errors, component_count, components, vertex_positions, vertex_count); + + component_nexterror = FLT_MAX; + for (size_t i = 0; i < component_count; ++i) + component_nexterror = component_nexterror > component_errors[i] ? component_errors[i] : component_nexterror; + +#if TRACE + printf("components: %d (min error %e)\n", int(component_count), sqrtf(component_nexterror)); +#endif + } #if TRACE size_t pass_count = 0; @@ -1569,22 +1942,28 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic size_t result_count = index_count; float result_error = 0; + float vertex_error = 0; // target_error input is linear; we need to adjust it to match quadricError units - float error_limit = target_error * target_error; + float error_scale = (options & meshopt_SimplifyErrorAbsolute) ? vertex_scale : 1.f; + float error_limit = (target_error * target_error) / (error_scale * error_scale); while (result_count > target_index_count) { // note: throughout the simplification process adjacency structure reflects welded topology for result-in-progress updateEdgeAdjacency(adjacency, result, result_count, vertex_count, remap); - size_t edge_collapse_count = pickEdgeCollapses(edge_collapses, collapse_capacity, result, result_count, remap, vertex_kind, loop); + size_t edge_collapse_count = pickEdgeCollapses(edge_collapses, collapse_capacity, result, result_count, remap, vertex_kind, loop, loopback); assert(edge_collapse_count <= collapse_capacity); // no edges can be collapsed any more due to topology restrictions if (edge_collapse_count == 0) break; +#if TRACE + printf("pass %d:%c", int(pass_count++), TRACE >= 2 ? '\n' : ' '); +#endif + rankEdgeCollapses(edge_collapses, edge_collapse_count, vertex_positions, vertex_attributes, vertex_quadrics, attribute_quadrics, attribute_gradients, attribute_count, remap); sortEdgeCollapses(collapse_order, edge_collapses, edge_collapse_count); @@ -1596,16 +1975,17 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic memset(collapse_locked, 0, vertex_count); -#if TRACE - printf("pass %d: ", int(pass_count++)); -#endif - - size_t collapses = performEdgeCollapses(collapse_remap, collapse_locked, vertex_quadrics, attribute_quadrics, attribute_gradients, attribute_count, edge_collapses, edge_collapse_count, collapse_order, remap, wedge, vertex_kind, vertex_positions, adjacency, triangle_collapse_goal, error_limit, result_error); + size_t collapses = performEdgeCollapses(collapse_remap, collapse_locked, edge_collapses, edge_collapse_count, collapse_order, remap, wedge, vertex_kind, loop, loopback, vertex_positions, adjacency, triangle_collapse_goal, error_limit, result_error); // no edges can be collapsed any more due to hitting the error limit or triangle collapse limit if (collapses == 0) break; + updateQuadrics(collapse_remap, vertex_count, vertex_quadrics, attribute_quadrics, attribute_gradients, attribute_count, vertex_positions, remap, vertex_error); + + // updateQuadrics will update vertex error if we use attributes, but if we don't then result_error and vertex_error are equivalent + vertex_error = attribute_count == 0 ? result_error : vertex_error; + remapEdgeLoops(loop, vertex_count, collapse_remap); remapEdgeLoops(loopback, vertex_count, collapse_remap); @@ -1613,38 +1993,74 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic assert(new_count < result_count); result_count = new_count; + + if ((options & meshopt_SimplifyPrune) && result_count > target_index_count && component_nexterror <= vertex_error) + result_count = pruneComponents(result, result_count, components, component_errors, component_count, vertex_error, component_nexterror); } + // we're done with the regular simplification but we're still short of the target; try pruning more aggressively towards error_limit + while ((options & meshopt_SimplifyPrune) && result_count > target_index_count && component_nexterror <= error_limit) + { #if TRACE - printf("result: %d triangles, error: %e; total %d passes\n", int(result_count), sqrtf(result_error), int(pass_count)); + printf("pass %d: cleanup; ", int(pass_count++)); #endif -#ifndef NDEBUG - if (meshopt_simplifyDebugKind) - memcpy(meshopt_simplifyDebugKind, vertex_kind, vertex_count); + float component_cutoff = component_nexterror * 1.5f < error_limit ? component_nexterror * 1.5f : error_limit; - if (meshopt_simplifyDebugLoop) - memcpy(meshopt_simplifyDebugLoop, loop, vertex_count * sizeof(unsigned int)); + // track maximum error in eligible components as we are increasing resulting error + float component_maxerror = 0; + for (size_t i = 0; i < component_count; ++i) + if (component_errors[i] > component_maxerror && component_errors[i] <= component_cutoff) + component_maxerror = component_errors[i]; - if (meshopt_simplifyDebugLoopBack) - memcpy(meshopt_simplifyDebugLoopBack, loopback, vertex_count * sizeof(unsigned int)); + size_t new_count = pruneComponents(result, result_count, components, component_errors, component_count, component_cutoff, component_nexterror); + if (new_count == result_count) + break; + + result_count = new_count; + result_error = result_error < component_maxerror ? component_maxerror : result_error; + vertex_error = vertex_error < component_maxerror ? component_maxerror : vertex_error; + } + +#if TRACE + printf("result: %d triangles, error: %e; total %d passes\n", int(result_count / 3), sqrtf(result_error), int(pass_count)); #endif + // if debug visualization data is requested, fill it instead of index data; for simplicity, this doesn't work with sparsity + if ((options & meshopt_SimplifyInternalDebug) && !sparse_remap) + { + assert(Kind_Count <= 8 && vertex_count < (1 << 28)); // 3 bit kind, 1 bit loop + + for (size_t i = 0; i < result_count; i += 3) + { + unsigned int a = result[i + 0], b = result[i + 1], c = result[i + 2]; + + result[i + 0] |= (vertex_kind[a] << 28) | (unsigned(loop[a] == b || loopback[b] == a) << 31); + result[i + 1] |= (vertex_kind[b] << 28) | (unsigned(loop[b] == c || loopback[c] == b) << 31); + result[i + 2] |= (vertex_kind[c] << 28) | (unsigned(loop[c] == a || loopback[a] == c) << 31); + } + } + + // convert resulting indices back into the dense space of the larger mesh + if (sparse_remap) + for (size_t i = 0; i < result_count; ++i) + result[i] = sparse_remap[result[i]]; + // result_error is quadratic; we need to remap it back to linear if (out_result_error) - *out_result_error = sqrtf(result_error); + *out_result_error = sqrtf(vertex_error) * error_scale; return result_count; } size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) { - return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, NULL, 0, NULL, 0, target_index_count, target_error, options, out_result_error); + return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, NULL, 0, NULL, 0, NULL, target_index_count, target_error, options, out_result_error); } -size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) +size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned char* vertex_lock, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) { - return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, vertex_attributes_data, vertex_attributes_stride, attribute_weights, attribute_count, target_index_count, target_error, options, out_result_error); + return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, vertex_attributes_data, vertex_attributes_stride, attribute_weights, attribute_count, vertex_lock, target_index_count, target_error, options, out_result_error); } size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error) @@ -1697,19 +2113,19 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind // we clamp the prediction of the grid size to make sure that the search converges int grid_size = next_grid_size; - grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1 : grid_size; + grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid ? max_grid - 1 : grid_size); computeVertexIds(vertex_ids, vertex_positions, vertex_count, grid_size); size_t triangles = countTriangles(vertex_ids, indices, index_count); #if TRACE printf("pass %d (%s): grid size %d, triangles %d, %s\n", - pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses) ? "lerp" : "binary", + pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses ? "lerp" : "binary"), grid_size, int(triangles), (triangles <= target_index_count / 3) ? "under" : "over"); #endif - float tip = interpolate(float(target_index_count / 3), float(min_grid), float(min_triangles), float(grid_size), float(triangles), float(max_grid), float(max_triangles)); + float tip = interpolate(float(size_t(target_index_count / 3)), float(min_grid), float(min_triangles), float(grid_size), float(triangles), float(max_grid), float(max_triangles)); if (triangles <= target_index_count / 3) { @@ -1829,14 +2245,14 @@ size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_pos // we clamp the prediction of the grid size to make sure that the search converges int grid_size = next_grid_size; - grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1 : grid_size; + grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid ? max_grid - 1 : grid_size); computeVertexIds(vertex_ids, vertex_positions, vertex_count, grid_size); size_t vertices = countVertexCells(table, table_size, vertex_ids, vertex_count); #if TRACE printf("pass %d (%s): grid size %d, vertices %d, %s\n", - pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses) ? "lerp" : "binary", + pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses ? "lerp" : "binary"), grid_size, int(vertices), (vertices <= target_vertex_count) ? "under" : "over"); #endif @@ -1881,7 +2297,10 @@ size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_pos unsigned int* cell_remap = allocator.allocate<unsigned int>(cell_count); float* cell_errors = allocator.allocate<float>(cell_count); - fillCellRemap(cell_remap, cell_errors, cell_count, vertex_cells, cell_reservoirs, vertex_positions, vertex_colors, vertex_colors_stride, color_weight * color_weight, vertex_count); + // we scale the color weight to bring it to the same scale as position so that error addition makes sense + float color_weight_scaled = color_weight * (min_grid == 1 ? 1.f : 1.f / (min_grid - 1)); + + fillCellRemap(cell_remap, cell_errors, cell_count, vertex_cells, cell_reservoirs, vertex_positions, vertex_colors, vertex_colors_stride, color_weight_scaled * color_weight_scaled, vertex_count); // copy results to the output assert(cell_count <= target_vertex_count); diff --git a/thirdparty/meshoptimizer/stripifier.cpp b/thirdparty/meshoptimizer/stripifier.cpp index 8ce17ef3dc..4043195aeb 100644 --- a/thirdparty/meshoptimizer/stripifier.cpp +++ b/thirdparty/meshoptimizer/stripifier.cpp @@ -10,15 +10,15 @@ namespace meshopt { -static unsigned int findStripFirst(const unsigned int buffer[][3], unsigned int buffer_size, const unsigned int* valence) +static unsigned int findStripFirst(const unsigned int buffer[][3], unsigned int buffer_size, const unsigned char* valence) { unsigned int index = 0; unsigned int iv = ~0u; for (size_t i = 0; i < buffer_size; ++i) { - unsigned int va = valence[buffer[i][0]], vb = valence[buffer[i][1]], vc = valence[buffer[i][2]]; - unsigned int v = (va < vb && va < vc) ? va : (vb < vc) ? vb : vc; + unsigned char va = valence[buffer[i][0]], vb = valence[buffer[i][1]], vc = valence[buffer[i][2]]; + unsigned int v = (va < vb && va < vc) ? va : (vb < vc ? vb : vc); if (v < iv) { @@ -71,8 +71,9 @@ size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices, size_t strip_size = 0; // compute vertex valence; this is used to prioritize starting triangle for strips - unsigned int* valence = allocator.allocate<unsigned int>(vertex_count); - memset(valence, 0, vertex_count * sizeof(unsigned int)); + // note: we use 8-bit counters for performance; for outlier vertices the valence is incorrect but that just affects the heuristic + unsigned char* valence = allocator.allocate<unsigned char>(vertex_count); + memset(valence, 0, vertex_count); for (size_t i = 0; i < index_count; ++i) { @@ -151,7 +152,7 @@ size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices, { // if we didn't find anything, we need to find the next new triangle // we use a heuristic to maximize the strip length - unsigned int i = findStripFirst(buffer, buffer_size, &valence[0]); + unsigned int i = findStripFirst(buffer, buffer_size, valence); unsigned int a = buffer[i][0], b = buffer[i][1], c = buffer[i][2]; // ordered removal from the buffer diff --git a/thirdparty/meshoptimizer/vcacheoptimizer.cpp b/thirdparty/meshoptimizer/vcacheoptimizer.cpp index d4b08ba340..e4ecc71d36 100644 --- a/thirdparty/meshoptimizer/vcacheoptimizer.cpp +++ b/thirdparty/meshoptimizer/vcacheoptimizer.cpp @@ -195,9 +195,8 @@ void meshopt_optimizeVertexCacheTable(unsigned int* destination, const unsigned TriangleAdjacency adjacency = {}; buildTriangleAdjacency(adjacency, indices, index_count, vertex_count, allocator); - // live triangle counts - unsigned int* live_triangles = allocator.allocate<unsigned int>(vertex_count); - memcpy(live_triangles, adjacency.counts, vertex_count * sizeof(unsigned int)); + // live triangle counts; note, we alias adjacency.counts as we remove triangles after emitting them so the counts always match + unsigned int* live_triangles = adjacency.counts; // emitted flags unsigned char* emitted_flags = allocator.allocate<unsigned char>(face_count); @@ -261,20 +260,16 @@ void meshopt_optimizeVertexCacheTable(unsigned int* destination, const unsigned unsigned int index = cache[i]; cache_new[cache_write] = index; - cache_write += (index != a && index != b && index != c); + cache_write += (index != a) & (index != b) & (index != c); } unsigned int* cache_temp = cache; cache = cache_new, cache_new = cache_temp; cache_count = cache_write > cache_size ? cache_size : cache_write; - // update live triangle counts - live_triangles[a]--; - live_triangles[b]--; - live_triangles[c]--; - // remove emitted triangle from adjacency data // this makes sure that we spend less time traversing these lists on subsequent iterations + // live triangle counts are updated as a byproduct of these adjustments for (size_t k = 0; k < 3; ++k) { unsigned int index = indices[current_triangle * 3 + k]; diff --git a/thirdparty/meshoptimizer/vertexcodec.cpp b/thirdparty/meshoptimizer/vertexcodec.cpp index 8ab0662d88..1dbd2e35f8 100644 --- a/thirdparty/meshoptimizer/vertexcodec.cpp +++ b/thirdparty/meshoptimizer/vertexcodec.cpp @@ -90,6 +90,14 @@ #include <wasm_simd128.h> #endif +#ifndef TRACE +#define TRACE 0 +#endif + +#if TRACE +#include <stdio.h> +#endif + #ifdef SIMD_WASM #define wasmx_splat_v32x4(v, i) wasm_i32x4_shuffle(v, v, i, i, i, i) #define wasmx_unpacklo_v8x16(a, b) wasm_i8x16_shuffle(a, b, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23) @@ -135,6 +143,19 @@ inline unsigned char unzigzag8(unsigned char v) return -(v & 1) ^ (v >> 1); } +#if TRACE +struct Stats +{ + size_t size; + size_t header; // bytes for header + size_t bitg[4]; // bytes for bit groups + size_t bitc[8]; // bit consistency: how many bits are shared between all bytes in a group +}; + +static Stats* bytestats = NULL; +static Stats vertexstats[256]; +#endif + static bool encodeBytesGroupZero(const unsigned char* buffer) { for (size_t i = 0; i < kByteGroupSize; ++i) @@ -245,7 +266,7 @@ static unsigned char* encodeBytes(unsigned char* data, unsigned char* data_end, } } - int bitslog2 = (best_bits == 1) ? 0 : (best_bits == 2) ? 1 : (best_bits == 4) ? 2 : 3; + int bitslog2 = (best_bits == 1) ? 0 : (best_bits == 2 ? 1 : (best_bits == 4 ? 2 : 3)); assert((1 << bitslog2) == best_bits); size_t header_offset = i / kByteGroupSize; @@ -256,8 +277,16 @@ static unsigned char* encodeBytes(unsigned char* data, unsigned char* data_end, assert(data + best_size == next); data = next; + +#if TRACE + bytestats->bitg[bitslog2] += best_size; +#endif } +#if TRACE + bytestats->header += header_size; +#endif + return data; } @@ -286,9 +315,31 @@ static unsigned char* encodeVertexBlock(unsigned char* data, unsigned char* data vertex_offset += vertex_size; } +#if TRACE + const unsigned char* olddata = data; + bytestats = &vertexstats[k]; + + for (size_t ig = 0; ig < vertex_count; ig += kByteGroupSize) + { + unsigned char last = (ig == 0) ? last_vertex[k] : vertex_data[vertex_size * (ig - 1) + k]; + unsigned char delta = 0xff; + + for (size_t i = ig; i < ig + kByteGroupSize && i < vertex_count; ++i) + delta &= ~(vertex_data[vertex_size * i + k] ^ last); + + for (int j = 0; j < 8; ++j) + bytestats->bitc[j] += (vertex_count - ig < kByteGroupSize ? vertex_count - ig : kByteGroupSize) * ((delta >> j) & 1); + } +#endif + data = encodeBytes(data, data_end, buffer, (vertex_count + kByteGroupSize - 1) & ~(kByteGroupSize - 1)); if (!data) return NULL; + +#if TRACE + bytestats = NULL; + vertexstats[k].size += data - olddata; +#endif } memcpy(last_vertex, &vertex_data[vertex_size * (vertex_count - 1)], vertex_size); @@ -383,6 +434,7 @@ static const unsigned char* decodeVertexBlock(const unsigned char* data, const u unsigned char transposed[kVertexBlockSizeBytes]; size_t vertex_count_aligned = (vertex_count + kByteGroupSize - 1) & ~(kByteGroupSize - 1); + assert(vertex_count <= vertex_count_aligned); for (size_t k = 0; k < vertex_size; ++k) { @@ -1095,6 +1147,10 @@ size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, con assert(vertex_size > 0 && vertex_size <= 256); assert(vertex_size % 4 == 0); +#if TRACE + memset(vertexstats, 0, sizeof(vertexstats)); +#endif + const unsigned char* vertex_data = static_cast<const unsigned char*>(vertices); unsigned char* data = buffer; @@ -1147,6 +1203,30 @@ size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, con assert(data >= buffer + tail_size); assert(data <= buffer + buffer_size); +#if TRACE + size_t total_size = data - buffer; + + for (size_t k = 0; k < vertex_size; ++k) + { + const Stats& vsk = vertexstats[k]; + + printf("%2d: %7d bytes [%4.1f%%] %.1f bpv", int(k), int(vsk.size), double(vsk.size) / double(total_size) * 100, double(vsk.size) / double(vertex_count) * 8); + + size_t total_k = vsk.header + vsk.bitg[0] + vsk.bitg[1] + vsk.bitg[2] + vsk.bitg[3]; + + printf(" |\thdr [%5.1f%%] bitg 1-3 [%4.1f%% %4.1f%% %4.1f%%]", + double(vsk.header) / double(total_k) * 100, double(vsk.bitg[1]) / double(total_k) * 100, + double(vsk.bitg[2]) / double(total_k) * 100, double(vsk.bitg[3]) / double(total_k) * 100); + + printf(" |\tbitc [%3.0f%% %3.0f%% %3.0f%% %3.0f%% %3.0f%% %3.0f%% %3.0f%% %3.0f%%]", + double(vsk.bitc[0]) / double(vertex_count) * 100, double(vsk.bitc[1]) / double(vertex_count) * 100, + double(vsk.bitc[2]) / double(vertex_count) * 100, double(vsk.bitc[3]) / double(vertex_count) * 100, + double(vsk.bitc[4]) / double(vertex_count) * 100, double(vsk.bitc[5]) / double(vertex_count) * 100, + double(vsk.bitc[6]) / double(vertex_count) * 100, double(vsk.bitc[7]) / double(vertex_count) * 100); + printf("\n"); + } +#endif + return data - buffer; } @@ -1246,3 +1326,4 @@ int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t ve #undef SIMD_WASM #undef SIMD_FALLBACK #undef SIMD_TARGET +#undef SIMD_LATENCYOPT diff --git a/thirdparty/meshoptimizer/vertexfilter.cpp b/thirdparty/meshoptimizer/vertexfilter.cpp index 4b5f444f04..1f456bb9de 100644 --- a/thirdparty/meshoptimizer/vertexfilter.cpp +++ b/thirdparty/meshoptimizer/vertexfilter.cpp @@ -807,7 +807,7 @@ inline int optlog2(float v) u.f = v; // +1 accounts for implicit 1. in mantissa; denormalized numbers will end up clamped to min_exp by calling code - return u.ui == 0 ? 0 : int((u.ui >> 23) & 0xff) - 127 + 1; + return v == 0 ? 0 : int((u.ui >> 23) & 0xff) - 127 + 1; } // optimized variant of ldexp @@ -1010,6 +1010,20 @@ void meshopt_encodeFilterExp(void* destination_, size_t count, size_t stride, in component_exp[j] = (min_exp < e) ? e : min_exp; } } + else if (mode == meshopt_EncodeExpClamped) + { + for (size_t j = 0; j < stride_float; ++j) + { + int e = optlog2(v[j]); + + component_exp[j] = (0 < e) ? e : 0; + } + } + else + { + // the code below assumes component_exp is initialized outside of the loop + assert(mode == meshopt_EncodeExpSharedComponent); + } for (size_t j = 0; j < stride_float; ++j) { @@ -1020,7 +1034,6 @@ void meshopt_encodeFilterExp(void* destination_, size_t count, size_t stride, in // compute renormalized rounded mantissa for each component int mmask = (1 << 24) - 1; - int m = int(v[j] * optexp2(-exp) + (v[j] >= 0 ? 0.5f : -0.5f)); d[j] = (m & mmask) | (unsigned(exp) << 24); diff --git a/thirdparty/misc/smolv.cpp b/thirdparty/misc/smolv.cpp index 26ed7294f9..67b914606c 100644 --- a/thirdparty/misc/smolv.cpp +++ b/thirdparty/misc/smolv.cpp @@ -1,5 +1,5 @@ // smol-v - public domain - https://github.com/aras-p/smol-v -// authored 2016-2020 by Aras Pranckevicius +// authored 2016-2024 by Aras Pranckevicius // no warranty implied; use at your own risk // See end of file for license information. @@ -1197,8 +1197,8 @@ static bool smolv_CheckGenericHeader(const uint32_t* words, size_t wordCount, ui if (headerMagic != expectedMagic) return false; uint32_t headerVersion = words[1] & versionMask; - if (headerVersion < 0x00010000 || headerVersion > 0x00010500) - return false; // only support 1.0 through 1.5 + if (headerVersion < 0x00010000 || headerVersion > 0x00010600) + return false; // only support 1.0 through 1.6 return true; } @@ -2071,7 +2071,7 @@ void smolv::StatsPrint(const Stats* stats) // This software is available under 2 licenses -- choose whichever you prefer. // ------------------------------------------------------------------------------ // ALTERNATIVE A - MIT License -// Copyright (c) 2016-2020 Aras Pranckevicius +// Copyright (c) 2016-2024 Aras Pranckevicius // 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 diff --git a/thirdparty/misc/smolv.h b/thirdparty/misc/smolv.h index 798ee4126f..231dfc6f30 100644 --- a/thirdparty/misc/smolv.h +++ b/thirdparty/misc/smolv.h @@ -1,5 +1,5 @@ // smol-v - public domain - https://github.com/aras-p/smol-v -// authored 2016-2020 by Aras Pranckevicius +// authored 2016-2024 by Aras Pranckevicius // no warranty implied; use at your own risk // See end of file for license information. // @@ -132,7 +132,7 @@ namespace smolv // This software is available under 2 licenses -- choose whichever you prefer. // ------------------------------------------------------------------------------ // ALTERNATIVE A - MIT License -// Copyright (c) 2016-2020 Aras Pranckevicius +// Copyright (c) 2016-2024 Aras Pranckevicius // 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 diff --git a/thirdparty/openxr/patches/use-egl-from-glad.diff b/thirdparty/openxr/patches/use-egl-from-glad.diff new file mode 100644 index 0000000000..29c746d5c7 --- /dev/null +++ b/thirdparty/openxr/patches/use-egl-from-glad.diff @@ -0,0 +1,27 @@ +diff -Nur openxr-orig/src/common/xr_dependencies.h openxr/src/common/xr_dependencies.h +--- openxr-orig/src/common/xr_dependencies.h 2024-11-04 10:38:11.940682727 -0600 ++++ openxr/src/common/xr_dependencies.h 2024-11-04 10:38:46.351415476 -0600 +@@ -65,7 +65,11 @@ + #endif // XR_USE_GRAPHICS_API_OPENGL + + #ifdef XR_USE_GRAPHICS_API_OPENGL_ES ++#ifdef GLAD_ENABLED ++#include "thirdparty/glad/glad/egl.h" ++#else + #include <EGL/egl.h> ++#endif + #endif // XR_USE_GRAPHICS_API_OPENGL_ES + + #ifdef XR_USE_GRAPHICS_API_VULKAN +@@ -77,7 +81,11 @@ + #endif // XR_USE_PLATFORM_WAYLAND + + #ifdef XR_USE_PLATFORM_EGL ++#ifdef GLAD_ENABLED ++#include "thirdparty/glad/glad/egl.h" ++#else + #include <EGL/egl.h> ++#endif + #endif // XR_USE_PLATFORM_EGL + + #if defined(XR_USE_PLATFORM_XLIB) || defined(XR_USE_PLATFORM_XCB) diff --git a/thirdparty/openxr/src/common/xr_dependencies.h b/thirdparty/openxr/src/common/xr_dependencies.h index 55d93bfbac..a192a2ec6d 100644 --- a/thirdparty/openxr/src/common/xr_dependencies.h +++ b/thirdparty/openxr/src/common/xr_dependencies.h @@ -65,7 +65,11 @@ #endif // XR_USE_GRAPHICS_API_OPENGL #ifdef XR_USE_GRAPHICS_API_OPENGL_ES +#ifdef GLAD_ENABLED +#include "thirdparty/glad/glad/egl.h" +#else #include <EGL/egl.h> +#endif #endif // XR_USE_GRAPHICS_API_OPENGL_ES #ifdef XR_USE_GRAPHICS_API_VULKAN @@ -77,7 +81,11 @@ #endif // XR_USE_PLATFORM_WAYLAND #ifdef XR_USE_PLATFORM_EGL +#ifdef GLAD_ENABLED +#include "thirdparty/glad/glad/egl.h" +#else #include <EGL/egl.h> +#endif #endif // XR_USE_PLATFORM_EGL #if defined(XR_USE_PLATFORM_XLIB) || defined(XR_USE_PLATFORM_XCB) diff --git a/thirdparty/swappy-frame-pacing/common/gamesdk_common.h b/thirdparty/swappy-frame-pacing/common/gamesdk_common.h new file mode 100644 index 0000000000..d29ac01af3 --- /dev/null +++ b/thirdparty/swappy-frame-pacing/common/gamesdk_common.h @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This is the main interface to the Android Performance Tuner library, also + * known as Tuning Fork. + * + * It is part of the Android Games SDK and produces best results when integrated + * with the Swappy Frame Pacing Library. + * + * See the documentation at + * https://developer.android.com/games/sdk/performance-tuner/custom-engine for + * more information on using this library in a native Android game. + * + */ + +#pragma once + +// There are separate versions for each GameSDK component that use this format: +#define ANDROID_GAMESDK_PACKED_VERSION(MAJOR, MINOR, BUGFIX) \ + ((MAJOR << 16) | (MINOR << 8) | (BUGFIX)) +// Accessors +#define ANDROID_GAMESDK_MAJOR_VERSION(PACKED) ((PACKED) >> 16) +#define ANDROID_GAMESDK_MINOR_VERSION(PACKED) (((PACKED) >> 8) & 0xff) +#define ANDROID_GAMESDK_BUGFIX_VERSION(PACKED) ((PACKED) & 0xff) + +#define AGDK_STRING_VERSION(MAJOR, MINOR, BUGFIX, GIT) \ +#MAJOR "." #MINOR "." #BUGFIX "." #GIT diff --git a/thirdparty/swappy-frame-pacing/swappyVk.h b/thirdparty/swappy-frame-pacing/swappyVk.h new file mode 100644 index 0000000000..020683cbc4 --- /dev/null +++ b/thirdparty/swappy-frame-pacing/swappyVk.h @@ -0,0 +1,420 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @defgroup swappyVk Swappy for Vulkan + * Vulkan part of Swappy. + * @{ + */ + +#pragma once + +#include "jni.h" +#include "swappy_common.h" + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES 1 +#endif +#include <vulkan/vulkan.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Determine any Vulkan device extensions that must be enabled for a new + * VkDevice. + * + * Swappy-for-Vulkan (SwappyVk) benefits from certain Vulkan device extensions + * (e.g. VK_GOOGLE_display_timing). Before the application calls + * vkCreateDevice, SwappyVk needs to look at the list of available extensions + * (returned by vkEnumerateDeviceExtensionProperties) and potentially identify + * one or more extensions that the application must add to: + * + * - VkDeviceCreateInfo::enabledExtensionCount + * - VkDeviceCreateInfo::ppEnabledExtensionNames + * + * before the application calls vkCreateDevice. For each VkPhysicalDevice that + * the application will call vkCreateDevice for, the application must call this + * function, and then must add the identified extension(s) to the list that are + * enabled for the VkDevice. Similar to many Vulkan functions, this function + * can be called twice, once to identify the number of required extensions, and + * again with application-allocated memory that the function can write into. + * + * @param[in] physicalDevice - The VkPhysicalDevice associated with + * the available extensions. + * @param[in] availableExtensionCount - This is the returned value of + * pPropertyCount from vkEnumerateDeviceExtensionProperties. + * @param[in] pAvailableExtensions - This is the returned value of + * pProperties from vkEnumerateDeviceExtensionProperties. + * @param[inout] pRequiredExtensionCount - If pRequiredExtensions is nullptr, + * the function sets this to the number of extensions that are required. If + * pRequiredExtensions is non-nullptr, this is the number of required extensions + * that the function should write into pRequiredExtensions. + * @param[inout] pRequiredExtensions - If non-nullptr, this is + * application-allocated memory into which the function will write the names of + * required extensions. It is a pointer to an array of + * char* strings (i.e. the same as + * VkDeviceCreateInfo::ppEnabledExtensionNames). + */ +void SwappyVk_determineDeviceExtensions( + VkPhysicalDevice physicalDevice, uint32_t availableExtensionCount, + VkExtensionProperties* pAvailableExtensions, + uint32_t* pRequiredExtensionCount, char** pRequiredExtensions); + +/** + * @brief Tell Swappy the queueFamilyIndex used to create a specific VkQueue + * + * Swappy needs to know the queueFamilyIndex used for creating a specific + * VkQueue so it can use it when presenting. + * + * @param[in] device - The VkDevice associated with the queue + * @param[in] queue - A device queue. + * @param[in] queueFamilyIndex - The queue family index used to create the + * VkQueue. + * + */ +void SwappyVk_setQueueFamilyIndex(VkDevice device, VkQueue queue, + uint32_t queueFamilyIndex); + +// TBD: For now, SwappyVk assumes only one VkSwapchainKHR per VkDevice, and that +// applications don't re-create swapchains. Is this long-term sufficient? + +/** + * Internal init function. Do not call directly. + * See SwappyVk_initAndGetRefreshCycleDuration instead. + * @private + */ +bool SwappyVk_initAndGetRefreshCycleDuration_internal( + JNIEnv* env, jobject jactivity, VkPhysicalDevice physicalDevice, + VkDevice device, VkSwapchainKHR swapchain, uint64_t* pRefreshDuration); + +/** + * @brief Initialize SwappyVk for a given device and swapchain, and obtain the + * approximate time duration between vertical-blanking periods. + * + * Uses JNI to query AppVsyncOffset and PresentationDeadline. + * + * If your application presents to more than one swapchain at a time, you must + * call this for each swapchain before calling swappyVkSetSwapInterval() for it. + * + * The duration between vertical-blanking periods (an interval) is expressed as + * the approximate number of nanoseconds between vertical-blanking periods of + * the swapchain’s physical display. + * + * If the application converts this number to a fraction (e.g. 16,666,666 nsec + * to 0.016666666) and divides one by that fraction, it will be the approximate + * refresh rate of the display (e.g. 16,666,666 nanoseconds corresponds to a + * 60Hz display, 11,111,111 nsec corresponds to a 90Hz display). + * + * @param[in] env - JNIEnv that is assumed to be from AttachCurrentThread + * function + * @param[in] jactivity - NativeActivity object handle, used for JNI + * @param[in] physicalDevice - The VkPhysicalDevice associated with the + * swapchain + * @param[in] device - The VkDevice associated with the swapchain + * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to + * swap + * @param[out] pRefreshDuration - The returned refresh cycle duration + * + * @return bool - true if the value returned by pRefreshDuration is + * valid, otherwise false if an error. + */ +bool SwappyVk_initAndGetRefreshCycleDuration(JNIEnv* env, jobject jactivity, + VkPhysicalDevice physicalDevice, + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t* pRefreshDuration); + +/** + * @brief Tell Swappy which ANativeWindow to use when calling to ANativeWindow_* + * API. + * @param[in] device - The VkDevice associated with the swapchain + * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to + * swap + * @param[in] window - The ANativeWindow that was used to create the + * VkSwapchainKHR + */ +void SwappyVk_setWindow(VkDevice device, VkSwapchainKHR swapchain, + ANativeWindow* window); + +/** + * @brief Tell Swappy the duration of that each presented image should be + * visible. + * + * If your application presents to more than one swapchain at a time, you must + * call this for each swapchain before presenting to it. + * + * @param[in] device - The VkDevice associated with the swapchain + * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to + * swap + * @param[in] swap_ns - The duration of that each presented image should be + * visible in nanoseconds + */ +void SwappyVk_setSwapIntervalNS(VkDevice device, VkSwapchainKHR swapchain, + uint64_t swap_ns); + +/** + * @brief Tell Swappy to present one or more images to corresponding swapchains. + * + * Swappy will call vkQueuePresentKHR for your application. Swappy may insert a + * struct to the pNext-chain of VkPresentInfoKHR, or it may insert other Vulkan + * commands in order to attempt to honor the desired swap interval. + * + * @note If your application presents to more than one swapchain at a time, and + * if you use a different swap interval for each swapchain, Swappy will attempt + * to honor the swap interval for each swapchain (being more successful on + * devices that support an underlying presentation-timing extension, such as + * VK_GOOGLE_display_timing). + * + * @param[in] queue - The VkQueue associated with the device and swapchain + * @param[in] pPresentInfo - A pointer to the VkPresentInfoKHR containing the + * information about what image(s) to present on which + * swapchain(s). + */ +VkResult SwappyVk_queuePresent(VkQueue queue, + const VkPresentInfoKHR* pPresentInfo); + +/** + * @brief Destroy the SwappyVk instance associated with a swapchain. + * + * This API is expected to be called before calling vkDestroySwapchainKHR() + * so Swappy can cleanup its internal state. + * + * @param[in] device - The VkDevice associated with SwappyVk + * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to + * destroy + */ +void SwappyVk_destroySwapchain(VkDevice device, VkSwapchainKHR swapchain); + +/** + * @brief Destroy any swapchains associated with the device and clean up the + * device's resources + * + * This function should be called after SwappyVk_destroySwapchain if you no + * longer need the device. + * + * @param[in] device - The VkDevice associated with SwappyVk + */ +void SwappyVk_destroyDevice(VkDevice device); + +/** + * @brief Enables Auto-Swap-Interval feature for all instances. + * + * By default this feature is enabled. Changing it is completely + * optional for fine-tuning swappy behaviour. + * + * @param[in] enabled - True means enable, false means disable + */ +void SwappyVk_setAutoSwapInterval(bool enabled); + +/** + * @brief Enables Auto-Pipeline-Mode feature for all instances. + * + * By default this feature is enabled. Changing it is completely + * optional for fine-tuning swappy behaviour. + * + * @param[in] enabled - True means enable, false means disable + */ +void SwappyVk_setAutoPipelineMode(bool enabled); + +/** + * @brief Sets the maximal swap duration for all instances. + * + * Sets the maximal duration for Auto-Swap-Interval in milliseconds. + * If SwappyVk is operating in Auto-Swap-Interval and the frame duration is + * longer than the provided duration, SwappyVk will not do any pacing and just + * submit the frame as soon as possible. + * + * @param[in] max_swap_ns - maximal swap duration in milliseconds. + */ +void SwappyVk_setMaxAutoSwapIntervalNS(uint64_t max_swap_ns); + +/** + * @brief The fence timeout parameter can be set for devices with faulty + * drivers. Its default value is 50,000,000. + */ +void SwappyVk_setFenceTimeoutNS(uint64_t fence_timeout_ns); + +/** + * @brief Get the fence timeout parameter, for devices with faulty + * drivers. Its default value is 50,000,000. + */ +uint64_t SwappyVk_getFenceTimeoutNS(); + +/** + * @brief Inject callback functions to be called each frame. + * + * @param[in] tracer - Collection of callback functions + */ +void SwappyVk_injectTracer(const SwappyTracer* tracer); + +/** + * @brief Remove callbacks that were previously added using + * SwappyVk_injectTracer. + * + * Only removes callbacks that were previously added using + * SwappyVK_injectTracer. If SwappyVK_injectTracker was not called with the + * tracer, then there is no effect. + * + * @param[in] tracer - Collection of callback functions + */ +void SwappyVk_uninjectTracer(const SwappyTracer* tracer); + +/** + * @brief A structure enabling you to provide your own Vulkan function wrappers + * by calling ::SwappyVk_setFunctionProvider. + * + * Usage of this functionality is optional. + */ +typedef struct SwappyVkFunctionProvider { + /** + * @brief Callback to initialize the function provider. + * + * This function is called by Swappy before any functions are requested. + * E.g. so you can call dlopen on the Vulkan library. + */ + bool (*init)(); + + /** + * @brief Callback to get the address of a function. + * + * This function is called by Swappy to get the address of a Vulkan + * function. + * @param name The null-terminated name of the function. + */ + void* (*getProcAddr)(const char* name); + + /** + * @brief Callback to close any resources owned by the function provider. + * + * This function is called by Swappy when no more functions will be + * requested, e.g. so you can call dlclose on the Vulkan library. + */ + void (*close)(); +} SwappyVkFunctionProvider; + +/** + * @brief Set the Vulkan function provider. + * + * This enables you to provide an object that will be used to look up Vulkan + * functions, e.g. to hook usage of these functions. + * + * To use this functionality, you *must* call this function before any others. + * + * Usage of this function is entirely optional. If you do not use it, the Vulkan + * functions required by Swappy will be dynamically loaded from libvulkan.so. + * + * @param[in] provider - provider object + */ +void SwappyVk_setFunctionProvider( + const SwappyVkFunctionProvider* pSwappyVkFunctionProvider); + +/** + * @brief Get the swap interval value, in nanoseconds, for a given swapchain. + * + * @param[in] swapchain - the swapchain to query + */ +uint64_t SwappyVk_getSwapIntervalNS(VkSwapchainKHR swapchain); + +/** + * @brief Get the supported refresh periods of this device. Call once with + * out_refreshrates set to nullptr to get the number of supported refresh + * periods, then call again passing that number as allocated_entries and + * an array of size equal to allocated_entries that will be filled with the + * refresh periods. + */ +int SwappyVk_getSupportedRefreshPeriodsNS(uint64_t* out_refreshrates, + int allocated_entries, + VkSwapchainKHR swapchain); +/** + * @brief Check if Swappy is enabled for the specified swapchain. + * + * @return false if SwappyVk_initAndGetRefreshCycleDuration was not + * called for the specified swapchain, true otherwise. + */ +bool SwappyVk_isEnabled(VkSwapchainKHR swapchain, bool* isEnabled); + +/** + * @brief Toggle statistics collection on/off + * + * By default, stats collection is off and there is no overhead related to + * stats. An app can turn on stats collection by calling + * `SwappyVk_enableStats(swapchain, true)`. Then, the app is expected to call + * ::SwappyVk_recordFrameStart for each frame before starting to do any CPU + * related work. Stats will be logged to logcat with a 'FrameStatistics' tag. An + * app can get the stats by calling ::SwappyVk_getStats. + * + * SwappyVk_initAndGetRefreshCycleDuration must have been called successfully + * before for this swapchain, otherwise there is no effect in this call. Frame + * stats are only available if the platform supports VK_GOOGLE_display_timing + * extension. + * + * @param[in] swapchain - The swapchain for which frame stat collection is + * configured. + * @param enabled - Whether to enable/disable frame stat collection. + */ +void SwappyVk_enableStats(VkSwapchainKHR swapchain, bool enabled); + +/** + * @brief Should be called if stats have been enabled with SwappyVk_enableStats. + * + * When stats collection is enabled with SwappyVk_enableStats, the app is + * expected to call this function for each frame before starting to do any CPU + * related work. It is assumed that this function will be called after a + * successful call to vkAcquireNextImageKHR. See ::SwappyVk_enableStats for more + * conditions. + * + * @param[in] queue - The VkQueue associated with the device and swapchain + * @param[in] swapchain - The swapchain where the frame is presented to. + * @param[in] image - The image in swapchain that corresponds to the frame. + + * @see SwappyVk_enableStats. + */ +void SwappyVk_recordFrameStart(VkQueue queue, VkSwapchainKHR swapchain, uint32_t image); + +/** + * @brief Returns the stats collected, if statistics collection was toggled on. + * + * Given that this API uses VkSwapchainKHR and the potential for this call to be + * done on different threads, all calls to ::SwappyVk_getStats + * must be externally synchronized with other SwappyVk calls. Unsynchronized + * calls may lead to undefined behavior. See ::SwappyVk_enableStats for more + * conditions. + * + * @param[in] swapchain - The swapchain for which stats are being queried. + * @param swappyStats - Pointer to a SwappyStats that will be populated with + * the collected stats. Cannot be NULL. + * @see SwappyStats + */ +void SwappyVk_getStats(VkSwapchainKHR swapchain, SwappyStats *swappyStats); + +/** + * @brief Clears the frame statistics collected so far. + * + * All the frame statistics collected are reset to 0, frame statistics are + * collected normally after this call. See ::SwappyVk_enableStats for more + * conditions. + * + * @param[in] swapchain - The swapchain for which stats are being cleared. + */ +void SwappyVk_clearStats(VkSwapchainKHR swapchain); + +#ifdef __cplusplus +} // extern "C" +#endif + +/** @} */ diff --git a/thirdparty/swappy-frame-pacing/swappy_common.h b/thirdparty/swappy-frame-pacing/swappy_common.h new file mode 100644 index 0000000000..b711ca910f --- /dev/null +++ b/thirdparty/swappy-frame-pacing/swappy_common.h @@ -0,0 +1,278 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @defgroup swappy_common Swappy common tools + * Tools to be used with Swappy for OpenGL or Swappy for Vulkan. + * @{ + */ + +#pragma once + +#include <android/native_window.h> +#include <stdint.h> + +#include "common/gamesdk_common.h" + +/** @brief Swap interval for 60fps, in nanoseconds. */ +#define SWAPPY_SWAP_60FPS (16666667L) + +/** @brief Swap interval for 30fps, in nanoseconds. */ +#define SWAPPY_SWAP_30FPS (33333333L) + +/** @brief Swap interval for 20fps, in nanoseconds. */ +#define SWAPPY_SWAP_20FPS (50000000L) + +/** + * The longest duration, in refresh periods, represented by the statistics. + * @see SwappyStats + */ +#define MAX_FRAME_BUCKETS 6 + +/** @cond INTERNAL */ + +#define SWAPPY_SYSTEM_PROP_KEY_DISABLE "swappy.disable" + +// Internal macros to track Swappy version, do not use directly. +#define SWAPPY_MAJOR_VERSION 2 +#define SWAPPY_MINOR_VERSION 0 +#define SWAPPY_BUGFIX_VERSION 0 +#define SWAPPY_PACKED_VERSION \ + ANDROID_GAMESDK_PACKED_VERSION(SWAPPY_MAJOR_VERSION, SWAPPY_MINOR_VERSION, \ + SWAPPY_BUGFIX_VERSION) + +// Internal macros to generate a symbol to track Swappy version, do not use +// directly. +#define SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) \ + PREFIX##_##MAJOR##_##MINOR##_##BUGFIX##_##GITCOMMIT +#define SWAPPY_VERSION_CONCAT(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) \ + SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) +#define SWAPPY_VERSION_SYMBOL \ + SWAPPY_VERSION_CONCAT(Swappy_version, SWAPPY_MAJOR_VERSION, \ + SWAPPY_MINOR_VERSION, SWAPPY_BUGFIX_VERSION, \ + AGDK_GIT_COMMIT) + +// Define this to 1 to enable all logging from Swappy, by default it is +// disabled in a release build and enabled in a debug build. +#ifndef ENABLE_SWAPPY_LOGGING +#define ENABLE_SWAPPY_LOGGING 0 +#endif +/** @endcond */ + +/** @brief Id of a thread returned by an external thread manager. */ +typedef uint64_t SwappyThreadId; + +/** + * @brief A structure enabling you to set how Swappy starts and joins threads by + * calling + * ::Swappy_setThreadFunctions. + * + * Usage of this functionality is optional. + */ +typedef struct SwappyThreadFunctions { + /** @brief Thread start callback. + * + * This function is called by Swappy to start thread_func on a new thread. + * @param user_data A value to be passed the thread function. + * If the thread was started, this function should set the thread_id and + * return 0. If the thread was not started, this function should return a + * non-zero value. + */ + int (*start)(SwappyThreadId* thread_id, void* (*thread_func)(void*), + void* user_data); + + /** @brief Thread join callback. + * + * This function is called by Swappy to join the thread with given id. + */ + void (*join)(SwappyThreadId thread_id); + + /** @brief Thread joinable callback. + * + * This function is called by Swappy to discover whether the thread with the + * given id is joinable. + */ + bool (*joinable)(SwappyThreadId thread_id); +} SwappyThreadFunctions; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Return the version of the Swappy library at runtime. + */ +uint32_t Swappy_version(); + +/** + * @brief Call this before any other functions in order to use a custom thread + * manager. + * + * Usage of this function is entirely optional. Swappy uses std::thread by + * default. + * + */ +void Swappy_setThreadFunctions(const SwappyThreadFunctions* thread_functions); + +/** + * @brief Return the full version of the Swappy library at runtime, e.g. + * "1.9.0_8a85ab7c46" + */ +const char* Swappy_versionString(); + +/** + * @brief Swappy frame statistics, collected if toggled on with + * ::SwappyGL_enableStats or ::SwappyVk_enableStats. + */ +typedef struct SwappyStats { + /** @brief Total frames swapped by swappy */ + uint64_t totalFrames; + + /** @brief Histogram of the number of screen refreshes a frame waited in the + * compositor queue after rendering was completed. + * + * For example: + * if a frame waited 2 refresh periods in the compositor queue after + * rendering was done, the frame will be counted in idleFrames[2] + */ + uint64_t idleFrames[MAX_FRAME_BUCKETS]; + + /** @brief Histogram of the number of screen refreshes passed between the + * requested presentation time and the actual present time. + * + * For example: + * if a frame was presented 2 refresh periods after the requested + * timestamp swappy set, the frame will be counted in lateFrames[2] + */ + uint64_t lateFrames[MAX_FRAME_BUCKETS]; + + /** @brief Histogram of the number of screen refreshes passed between two + * consecutive frames + * + * For example: + * if frame N was presented 2 refresh periods after frame N-1 + * frame N will be counted in offsetFromPreviousFrame[2] + */ + uint64_t offsetFromPreviousFrame[MAX_FRAME_BUCKETS]; + + /** @brief Histogram of the number of screen refreshes passed between the + * call to Swappy_recordFrameStart and the actual present time. + * + * For example: + * if a frame was presented 2 refresh periods after the call to + * `Swappy_recordFrameStart` the frame will be counted in latencyFrames[2] + */ + uint64_t latencyFrames[MAX_FRAME_BUCKETS]; +} SwappyStats; + + +#ifdef __cplusplus +} // extern "C" +#endif + +/** + * Pointer to a function that can be attached to SwappyTracer::preWait + * @param userData Pointer to arbitrary data, see SwappyTracer::userData. + */ +typedef void (*SwappyPreWaitCallback)(void*); + +/** + * Pointer to a function that can be attached to SwappyTracer::postWait. + * @param userData Pointer to arbitrary data, see SwappyTracer::userData. + * @param cpu_time_ns Time for CPU processing of this frame in nanoseconds. + * @param gpu_time_ns Time for GPU processing of previous frame in nanoseconds. + */ +typedef void (*SwappyPostWaitCallback)(void*, int64_t cpu_time_ns, + int64_t gpu_time_ns); + +/** + * Pointer to a function that can be attached to SwappyTracer::preSwapBuffers. + * @param userData Pointer to arbitrary data, see SwappyTracer::userData. + */ +typedef void (*SwappyPreSwapBuffersCallback)(void*); + +/** + * Pointer to a function that can be attached to SwappyTracer::postSwapBuffers. + * @param userData Pointer to arbitrary data, see SwappyTracer::userData. + * @param desiredPresentationTimeMillis The target time, in milliseconds, at + * which the frame would be presented on screen. + */ +typedef void (*SwappyPostSwapBuffersCallback)( + void*, int64_t desiredPresentationTimeMillis); + +/** + * Pointer to a function that can be attached to SwappyTracer::startFrame. + * @param userData Pointer to arbitrary data, see SwappyTracer::userData. + * @param desiredPresentationTimeMillis The time, in milliseconds, at which the + * frame is scheduled to be presented. + */ +typedef void (*SwappyStartFrameCallback)(void*, int currentFrame, + int64_t desiredPresentationTimeMillis); + +/** + * Pointer to a function that can be attached to + * SwappyTracer::swapIntervalChanged. Call ::SwappyGL_getSwapIntervalNS or + * ::SwappyVk_getSwapIntervalNS to get the latest swapInterval. + * @param userData Pointer to arbitrary data, see SwappyTracer::userData. + */ +typedef void (*SwappySwapIntervalChangedCallback)(void*); + +/** + * @brief Collection of callbacks to be called each frame to trace execution. + * + * Injection of these is optional. + */ +typedef struct SwappyTracer { + /** + * Callback called before waiting to queue the frame to the composer. + */ + SwappyPreWaitCallback preWait; + + /** + * Callback called after wait to queue the frame to the composer is done. + */ + SwappyPostWaitCallback postWait; + + /** + * Callback called before calling the function to queue the frame to the + * composer. + */ + SwappyPreSwapBuffersCallback preSwapBuffers; + + /** + * Callback called after calling the function to queue the frame to the + * composer. + */ + SwappyPostSwapBuffersCallback postSwapBuffers; + + /** + * Callback called at the start of a frame. + */ + SwappyStartFrameCallback startFrame; + + /** + * Pointer to some arbitrary data that will be passed as the first argument + * of callbacks. + */ + void* userData; + + /** + * Callback called when the swap interval was changed. + */ + SwappySwapIntervalChangedCallback swapIntervalChanged; +} SwappyTracer; + +/** @} */ diff --git a/thirdparty/zlib/gzclose.c b/thirdparty/zlib/gzclose.c deleted file mode 100644 index 48d6a86f04..0000000000 --- a/thirdparty/zlib/gzclose.c +++ /dev/null @@ -1,23 +0,0 @@ -/* gzclose.c -- zlib gzclose() function - * Copyright (C) 2004, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* gzclose() is in a separate file so that it is linked in only if it is used. - That way the other gzclose functions can be used instead to avoid linking in - unneeded compression or decompression routines. */ -int ZEXPORT gzclose(gzFile file) { -#ifndef NO_GZCOMPRESS - gz_statep state; - - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); -#else - return gzclose_r(file); -#endif -} diff --git a/thirdparty/zlib/gzlib.c b/thirdparty/zlib/gzlib.c deleted file mode 100644 index 983153cc8e..0000000000 --- a/thirdparty/zlib/gzlib.c +++ /dev/null @@ -1,582 +0,0 @@ -/* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004-2024 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -#if defined(_WIN32) && !defined(__BORLANDC__) -# define LSEEK _lseeki64 -#else -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define LSEEK lseek64 -#else -# define LSEEK lseek -#endif -#endif - -#if defined UNDER_CE - -/* Map the Windows error number in ERROR to a locale-dependent error message - string and return a pointer to it. Typically, the values for ERROR come - from GetLastError. - - The string pointed to shall not be modified by the application, but may be - overwritten by a subsequent call to gz_strwinerror - - The gz_strwinerror function does not change the current setting of - GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { - static char buf[1024]; - - wchar_t *msgbuf; - DWORD lasterr = GetLastError(); - DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - error, - 0, /* Default language */ - (LPVOID)&msgbuf, - 0, - NULL); - if (chars != 0) { - /* If there is an \r\n appended, zap it. */ - if (chars >= 2 - && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { - chars -= 2; - msgbuf[chars] = 0; - } - - if (chars > sizeof (buf) - 1) { - chars = sizeof (buf) - 1; - msgbuf[chars] = 0; - } - - wcstombs(buf, msgbuf, chars + 1); - LocalFree(msgbuf); - } - else { - sprintf(buf, "unknown win32 error (%ld)", error); - } - - SetLastError(lasterr); - return buf; -} - -#endif /* UNDER_CE */ - -/* Reset gzip file state */ -local void gz_reset(gz_statep state) { - state->x.have = 0; /* no output data available */ - if (state->mode == GZ_READ) { /* for reading ... */ - state->eof = 0; /* not at end of file */ - state->past = 0; /* have not read past end yet */ - state->how = LOOK; /* look for gzip header */ - } - else /* for writing ... */ - state->reset = 0; /* no deflateReset pending */ - state->seek = 0; /* no seek request pending */ - gz_error(state, Z_OK, NULL); /* clear error */ - state->x.pos = 0; /* no uncompressed data yet */ - state->strm.avail_in = 0; /* no input data yet */ -} - -/* Open a gzip file either by name or file descriptor. */ -local gzFile gz_open(const void *path, int fd, const char *mode) { - gz_statep state; - z_size_t len; - int oflag; -#ifdef O_CLOEXEC - int cloexec = 0; -#endif -#ifdef O_EXCL - int exclusive = 0; -#endif - - /* check input */ - if (path == NULL) - return NULL; - - /* allocate gzFile structure to return */ - state = (gz_statep)malloc(sizeof(gz_state)); - if (state == NULL) - return NULL; - state->size = 0; /* no buffers allocated yet */ - state->want = GZBUFSIZE; /* requested buffer size */ - state->msg = NULL; /* no error message yet */ - - /* interpret mode */ - state->mode = GZ_NONE; - state->level = Z_DEFAULT_COMPRESSION; - state->strategy = Z_DEFAULT_STRATEGY; - state->direct = 0; - while (*mode) { - if (*mode >= '0' && *mode <= '9') - state->level = *mode - '0'; - else - switch (*mode) { - case 'r': - state->mode = GZ_READ; - break; -#ifndef NO_GZCOMPRESS - case 'w': - state->mode = GZ_WRITE; - break; - case 'a': - state->mode = GZ_APPEND; - break; -#endif - case '+': /* can't read and write at the same time */ - free(state); - return NULL; - case 'b': /* ignore -- will request binary anyway */ - break; -#ifdef O_CLOEXEC - case 'e': - cloexec = 1; - break; -#endif -#ifdef O_EXCL - case 'x': - exclusive = 1; - break; -#endif - case 'f': - state->strategy = Z_FILTERED; - break; - case 'h': - state->strategy = Z_HUFFMAN_ONLY; - break; - case 'R': - state->strategy = Z_RLE; - break; - case 'F': - state->strategy = Z_FIXED; - break; - case 'T': - state->direct = 1; - break; - default: /* could consider as an error, but just ignore */ - ; - } - mode++; - } - - /* must provide an "r", "w", or "a" */ - if (state->mode == GZ_NONE) { - free(state); - return NULL; - } - - /* can't force transparent read */ - if (state->mode == GZ_READ) { - if (state->direct) { - free(state); - return NULL; - } - state->direct = 1; /* for empty file */ - } - - /* save the path name for error messages */ -#ifdef WIDECHAR - if (fd == -2) { - len = wcstombs(NULL, path, 0); - if (len == (z_size_t)-1) - len = 0; - } - else -#endif - len = strlen((const char *)path); - state->path = (char *)malloc(len + 1); - if (state->path == NULL) { - free(state); - return NULL; - } -#ifdef WIDECHAR - if (fd == -2) - if (len) - wcstombs(state->path, path, len + 1); - else - *(state->path) = 0; - else -#endif -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - (void)snprintf(state->path, len + 1, "%s", (const char *)path); -#else - strcpy(state->path, path); -#endif - - /* compute the flags for open() */ - oflag = -#ifdef O_LARGEFILE - O_LARGEFILE | -#endif -#ifdef O_BINARY - O_BINARY | -#endif -#ifdef O_CLOEXEC - (cloexec ? O_CLOEXEC : 0) | -#endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | -#ifdef O_EXCL - (exclusive ? O_EXCL : 0) | -#endif - (state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))); - - /* open the file with the appropriate flags (or just use fd) */ - state->fd = fd > -1 ? fd : ( -#ifdef WIDECHAR - fd == -2 ? _wopen(path, oflag, 0666) : -#endif - open((const char *)path, oflag, 0666)); - if (state->fd == -1) { - free(state->path); - free(state); - return NULL; - } - if (state->mode == GZ_APPEND) { - LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ - state->mode = GZ_WRITE; /* simplify later checks */ - } - - /* save the current position for rewinding (only if reading) */ - if (state->mode == GZ_READ) { - state->start = LSEEK(state->fd, 0, SEEK_CUR); - if (state->start == -1) state->start = 0; - } - - /* initialize stream */ - gz_reset(state); - - /* return stream */ - return (gzFile)state; -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen(const char *path, const char *mode) { - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen64(const char *path, const char *mode) { - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzdopen(int fd, const char *mode) { - char *path; /* identifier for error messages */ - gzFile gz; - - if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) - return NULL; -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); -#else - sprintf(path, "<fd:%d>", fd); /* for debugging */ -#endif - gz = gz_open(path, fd, mode); - free(path); - return gz; -} - -/* -- see zlib.h -- */ -#ifdef WIDECHAR -gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) { - return gz_open(path, -2, mode); -} -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzbuffer(gzFile file, unsigned size) { - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* make sure we haven't already allocated memory */ - if (state->size != 0) - return -1; - - /* check and set requested size */ - if ((size << 1) < size) - return -1; /* need to be able to double it */ - if (size < 8) - size = 8; /* needed to behave well with flushing */ - state->want = size; - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzrewind(gzFile file) { - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* back up and start over */ - if (LSEEK(state->fd, state->start, SEEK_SET) == -1) - return -1; - gz_reset(state); - return 0; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { - unsigned n; - z_off64_t ret; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* check that there's no error */ - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* can only seek from start or relative to current position */ - if (whence != SEEK_SET && whence != SEEK_CUR) - return -1; - - /* normalize offset to a SEEK_CUR specification */ - if (whence == SEEK_SET) - offset -= state->x.pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; - - /* if within raw area while reading, just go there */ - if (state->mode == GZ_READ && state->how == COPY && - state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); - if (ret == -1) - return -1; - state->x.have = 0; - state->eof = 0; - state->past = 0; - state->seek = 0; - gz_error(state, Z_OK, NULL); - state->strm.avail_in = 0; - state->x.pos += offset; - return state->x.pos; - } - - /* calculate skip amount, rewinding if needed for back seek when reading */ - if (offset < 0) { - if (state->mode != GZ_READ) /* writing -- can't go backwards */ - return -1; - offset += state->x.pos; - if (offset < 0) /* before start of file! */ - return -1; - if (gzrewind(file) == -1) /* rewind, then skip to offset */ - return -1; - } - - /* if reading, skip what's in output buffer (one less gzgetc() check) */ - if (state->mode == GZ_READ) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? - (unsigned)offset : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - offset -= n; - } - - /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } - return state->x.pos + offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) { - z_off64_t ret; - - ret = gzseek64(file, (z_off64_t)offset, whence); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gztell64(gzFile file) { - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* return position */ - return state->x.pos + (state->seek ? state->skip : 0); -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gztell(gzFile file) { - z_off64_t ret; - - ret = gztell64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzoffset64(gzFile file) { - z_off64_t offset; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* compute and return effective offset in file */ - offset = LSEEK(state->fd, 0, SEEK_CUR); - if (offset == -1) - return -1; - if (state->mode == GZ_READ) /* reading */ - offset -= state->strm.avail_in; /* don't count buffered input */ - return offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset(gzFile file) { - z_off64_t ret; - - ret = gzoffset64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzeof(gzFile file) { - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return 0; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return 0; - - /* return end-of-file state */ - return state->mode == GZ_READ ? state->past : 0; -} - -/* -- see zlib.h -- */ -const char * ZEXPORT gzerror(gzFile file, int *errnum) { - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return NULL; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return NULL; - - /* return error information */ - if (errnum != NULL) - *errnum = state->err; - return state->err == Z_MEM_ERROR ? "out of memory" : - (state->msg == NULL ? "" : state->msg); -} - -/* -- see zlib.h -- */ -void ZEXPORT gzclearerr(gzFile file) { - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return; - - /* clear error and end-of-file */ - if (state->mode == GZ_READ) { - state->eof = 0; - state->past = 0; - } - gz_error(state, Z_OK, NULL); -} - -/* Create an error message in allocated memory and set state->err and - state->msg accordingly. Free any previous error message already there. Do - not try to free or allocate space if the error is Z_MEM_ERROR (out of - memory). Simply save the error message as a static string. If there is an - allocation failure constructing the error message, then convert the error to - out of memory. */ -void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { - /* free previously allocated message and clear */ - if (state->msg != NULL) { - if (state->err != Z_MEM_ERROR) - free(state->msg); - state->msg = NULL; - } - - /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ - if (err != Z_OK && err != Z_BUF_ERROR) - state->x.have = 0; - - /* set error code, and if no message, then done */ - state->err = err; - if (msg == NULL) - return; - - /* for an out of memory error, return literal string when requested */ - if (err == Z_MEM_ERROR) - return; - - /* construct error message with path */ - if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == - NULL) { - state->err = Z_MEM_ERROR; - return; - } -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, - "%s%s%s", state->path, ": ", msg); -#else - strcpy(state->msg, state->path); - strcat(state->msg, ": "); - strcat(state->msg, msg); -#endif -} - -/* portably return maximum value for an int (when limits.h presumed not - available) -- we need to do this to cover cases where 2's complement not - used, since C standard permits 1's complement and sign-bit representations, - otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax(void) { -#ifdef INT_MAX - return INT_MAX; -#else - unsigned p = 1, q; - do { - q = p; - p <<= 1; - p++; - } while (p > q); - return q >> 1; -#endif -} diff --git a/thirdparty/zlib/gzread.c b/thirdparty/zlib/gzread.c deleted file mode 100644 index 4168cbc887..0000000000 --- a/thirdparty/zlib/gzread.c +++ /dev/null @@ -1,602 +0,0 @@ -/* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from - state->fd, and update state->eof, state->err, and state->msg as appropriate. - This function needs to loop on read(), since read() is not guaranteed to - read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load(gz_statep state, unsigned char *buf, unsigned len, - unsigned *have) { - int ret; - unsigned get, max = ((unsigned)-1 >> 2) + 1; - - *have = 0; - do { - get = len - *have; - if (get > max) - get = max; - ret = read(state->fd, buf + *have, get); - if (ret <= 0) - break; - *have += (unsigned)ret; - } while (*have < len); - if (ret < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (ret == 0) - state->eof = 1; - return 0; -} - -/* Load up input buffer and set eof flag if last data loaded -- return -1 on - error, 0 otherwise. Note that the eof flag is set when the end of the input - file is reached, even though there may be unused data in the buffer. Once - that data has been used, no more attempts will be made to read the file. - If strm->avail_in != 0, then the current data is moved to the beginning of - the input buffer, and then the remainder of the buffer is loaded with the - available data from the input file. */ -local int gz_avail(gz_statep state) { - unsigned got; - z_streamp strm = &(state->strm); - - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - if (state->eof == 0) { - if (strm->avail_in) { /* copy what's there to the start */ - unsigned char *p = state->in; - unsigned const char *q = strm->next_in; - unsigned n = strm->avail_in; - do { - *p++ = *q++; - } while (--n); - } - if (gz_load(state, state->in + strm->avail_in, - state->size - strm->avail_in, &got) == -1) - return -1; - strm->avail_in += got; - strm->next_in = state->in; - } - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. - If this is the first time in, allocate required memory. state->how will be - left unchanged if there is no more input data available, will be set to COPY - if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression. If direct copying, then leftover input - data from the input buffer will be copied to the output buffer. In that - case, all further file reads will be directly to either the output buffer or - a user buffer. If decompressing, the inflate state will be initialized. - gz_look() will return 0 on success or -1 on failure. */ -local int gz_look(gz_statep state) { - z_streamp strm = &(state->strm); - - /* allocate read buffers and inflate memory */ - if (state->size == 0) { - /* allocate buffers */ - state->in = (unsigned char *)malloc(state->want); - state->out = (unsigned char *)malloc(state->want << 1); - if (state->in == NULL || state->out == NULL) { - free(state->out); - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - state->size = state->want; - - /* allocate inflate memory */ - state->strm.zalloc = Z_NULL; - state->strm.zfree = Z_NULL; - state->strm.opaque = Z_NULL; - state->strm.avail_in = 0; - state->strm.next_in = Z_NULL; - if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ - free(state->out); - free(state->in); - state->size = 0; - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - } - - /* get at least the magic bytes in the input buffer */ - if (strm->avail_in < 2) { - if (gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) - return 0; - } - - /* look for gzip magic bytes -- if there, do gzip decoding (note: there is - a logical dilemma here when considering the case of a partially written - gzip file, to wit, if a single 31 byte is written, then we cannot tell - whether this is a single-byte file, or just a partially written gzip - file -- for here we assume that if a gzip file is being written, then - the header will be written in a single operation, so that reading a - single byte is sufficient indication that it is not a gzip file) */ - if (strm->avail_in > 1 && - strm->next_in[0] == 31 && strm->next_in[1] == 139) { - inflateReset(strm); - state->how = GZIP; - state->direct = 0; - return 0; - } - - /* no gzip header -- if we were decoding gzip before, then this is trailing - garbage. Ignore the trailing garbage and finish. */ - if (state->direct == 0) { - strm->avail_in = 0; - state->eof = 1; - state->x.have = 0; - return 0; - } - - /* doing raw i/o, copy any leftover input to output -- this assumes that - the output buffer is larger than the input buffer, which also assures - space for gzungetc() */ - state->x.next = state->out; - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - state->how = COPY; - state->direct = 1; - return 0; -} - -/* Decompress from input to the provided next_out and avail_out in the state. - On return, state->x.have and state->x.next point to the just decompressed - data. If the gzip stream completes, state->how is reset to LOOK to look for - the next gzip stream or raw data, once state->x.have is depleted. Returns 0 - on success, -1 on failure. */ -local int gz_decomp(gz_statep state) { - int ret = Z_OK; - unsigned had; - z_streamp strm = &(state->strm); - - /* fill output buffer up to end of deflate stream */ - had = strm->avail_out; - do { - /* get more input for inflate() */ - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) { - gz_error(state, Z_BUF_ERROR, "unexpected end of file"); - break; - } - - /* decompress and handle errors */ - ret = inflate(strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { - gz_error(state, Z_STREAM_ERROR, - "internal error: inflate stream corrupt"); - return -1; - } - if (ret == Z_MEM_ERROR) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ - gz_error(state, Z_DATA_ERROR, - strm->msg == NULL ? "compressed data error" : strm->msg); - return -1; - } - } while (strm->avail_out && ret != Z_STREAM_END); - - /* update available output */ - state->x.have = had - strm->avail_out; - state->x.next = strm->next_out - state->x.have; - - /* if the gzip stream completed successfully, look for another */ - if (ret == Z_STREAM_END) - state->how = LOOK; - - /* good decompression */ - return 0; -} - -/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. - Data is either copied from the input file or decompressed from the input - file depending on state->how. If state->how is LOOK, then a gzip header is - looked for to determine whether to copy or decompress. Returns -1 on error, - otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the - end of the input file has been reached and all data has been processed. */ -local int gz_fetch(gz_statep state) { - z_streamp strm = &(state->strm); - - do { - switch(state->how) { - case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ - if (gz_look(state) == -1) - return -1; - if (state->how == LOOK) - return 0; - break; - case COPY: /* -> COPY */ - if (gz_load(state, state->out, state->size << 1, &(state->x.have)) - == -1) - return -1; - state->x.next = state->out; - return 0; - case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) - return -1; - } - } while (state->x.have == 0 && (!state->eof || strm->avail_in)); - return 0; -} - -/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip(gz_statep state, z_off64_t len) { - unsigned n; - - /* skip over len bytes or reach end-of-file, whichever comes first */ - while (len) - /* skip over whatever is in output buffer */ - if (state->x.have) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? - (unsigned)len : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - len -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && state->strm.avail_in == 0) - break; - - /* need more data to skip -- load up output buffer */ - else { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return -1; - } - return 0; -} - -/* Read len bytes into buf from file, or less than len up to the end of the - input. Return the number of bytes read. If zero is returned, either the - end of file was reached, or there was an error. state->err must be - consulted in that case to determine which. */ -local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { - z_size_t got; - unsigned n; - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return 0; - } - - /* get len bytes to buf, or less than len if at the end */ - got = 0; - do { - /* set n to the maximum amount of len that fits in an unsigned int */ - n = (unsigned)-1; - if (n > len) - n = (unsigned)len; - - /* first just try copying data from the output buffer */ - if (state->x.have) { - if (state->x.have < n) - n = state->x.have; - memcpy(buf, state->x.next, n); - state->x.next += n; - state->x.have -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && state->strm.avail_in == 0) { - state->past = 1; /* tried to read past end */ - break; - } - - /* need output data -- for small len or new stream load up our output - buffer */ - else if (state->how == LOOK || n < (state->size << 1)) { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return 0; - continue; /* no progress yet -- go back to copy above */ - /* the copy above assures that we will leave with space in the - output buffer, allowing at least one gzungetc() to succeed */ - } - - /* large len -- read directly into user buffer */ - else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, n, &n) == -1) - return 0; - } - - /* large len -- decompress directly into user buffer */ - else { /* state->how == GZIP */ - state->strm.avail_out = n; - state->strm.next_out = (unsigned char *)buf; - if (gz_decomp(state) == -1) - return 0; - n = state->x.have; - state->x.have = 0; - } - - /* update progress */ - len -= n; - buf = (char *)buf + n; - got += n; - state->x.pos += n; - } while (len); - - /* return number of bytes read into user buffer */ - return got; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids a flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); - return -1; - } - - /* read len or fewer bytes to buf */ - len = (unsigned)gz_read(state, buf, len); - - /* check for an error */ - if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* return the number of bytes read (this is assured to fit in an int) */ - return (int)len; -} - -/* -- see zlib.h -- */ -z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) { - z_size_t len; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return 0; - - /* compute bytes to read -- error on overflow */ - len = nitems * size; - if (size && len / size != nitems) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); - return 0; - } - - /* read len or fewer bytes to buf, return the number of full items read */ - return len ? gz_read(state, buf, len) / size : 0; -} - -/* -- see zlib.h -- */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -#else -# undef gzgetc -#endif -int ZEXPORT gzgetc(gzFile file) { - unsigned char buf[1]; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* try output buffer (no need to check for skip request) */ - if (state->x.have) { - state->x.have--; - state->x.pos++; - return *(state->x.next)++; - } - - /* nothing there -- try gz_read() */ - return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; -} - -int ZEXPORT gzgetc_(gzFile file) { - return gzgetc(file); -} - -/* -- see zlib.h -- */ -int ZEXPORT gzungetc(int c, gzFile file) { - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* in case this was just opened, set up the input buffer */ - if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) - (void)gz_look(state); - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } - - /* can't push EOF */ - if (c < 0) - return -1; - - /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->x.have == 0) { - state->x.have = 1; - state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = (unsigned char)c; - state->x.pos--; - state->past = 0; - return c; - } - - /* if no room, give up (must have already done a gzungetc()) */ - if (state->x.have == (state->size << 1)) { - gz_error(state, Z_DATA_ERROR, "out of room to push characters"); - return -1; - } - - /* slide output data if needed and insert byte before existing data */ - if (state->x.next == state->out) { - unsigned char *src = state->out + state->x.have; - unsigned char *dest = state->out + (state->size << 1); - while (src > state->out) - *--dest = *--src; - state->x.next = dest; - } - state->x.have++; - state->x.next--; - state->x.next[0] = (unsigned char)c; - state->x.pos--; - state->past = 0; - return c; -} - -/* -- see zlib.h -- */ -char * ZEXPORT gzgets(gzFile file, char *buf, int len) { - unsigned left, n; - char *str; - unsigned char *eol; - gz_statep state; - - /* check parameters and get internal structure */ - if (file == NULL || buf == NULL || len < 1) - return NULL; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return NULL; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return NULL; - } - - /* copy output bytes up to new line or len - 1, whichever comes first -- - append a terminating zero to the string (we don't check for a zero in - the contents, let the user worry about that) */ - str = buf; - left = (unsigned)len - 1; - if (left) do { - /* assure that something is in the output buffer */ - if (state->x.have == 0 && gz_fetch(state) == -1) - return NULL; /* error */ - if (state->x.have == 0) { /* end of file */ - state->past = 1; /* read past end */ - break; /* return what we have */ - } - - /* look for end-of-line in current output buffer */ - n = state->x.have > left ? left : state->x.have; - eol = (unsigned char *)memchr(state->x.next, '\n', n); - if (eol != NULL) - n = (unsigned)(eol - state->x.next) + 1; - - /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->x.next, n); - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - left -= n; - buf += n; - } while (left && eol == NULL); - - /* return terminated string, or if nothing, end of file */ - if (buf == str) - return NULL; - buf[0] = 0; - return str; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzdirect(gzFile file) { - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* if the state is not known, but we can find out, then do so (this is - mainly for right after a gzopen() or gzdopen()) */ - if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) - (void)gz_look(state); - - /* return 1 if transparent, 0 if processing a gzip stream */ - return state->direct; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_r(gzFile file) { - int ret, err; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're reading */ - if (state->mode != GZ_READ) - return Z_STREAM_ERROR; - - /* free memory and close file */ - if (state->size) { - inflateEnd(&(state->strm)); - free(state->out); - free(state->in); - } - err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; - gz_error(state, Z_OK, NULL); - free(state->path); - ret = close(state->fd); - free(state); - return ret ? Z_ERRNO : err; -} diff --git a/thirdparty/zlib/gzwrite.c b/thirdparty/zlib/gzwrite.c deleted file mode 100644 index 435b4621b5..0000000000 --- a/thirdparty/zlib/gzwrite.c +++ /dev/null @@ -1,631 +0,0 @@ -/* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004-2019 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on a memory allocation failure, or 0 on - success. */ -local int gz_init(gz_statep state) { - int ret; - z_streamp strm = &(state->strm); - - /* allocate input buffer (double size for gzprintf) */ - state->in = (unsigned char *)malloc(state->want << 1); - if (state->in == NULL) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* only need output buffer and deflate state if compressing */ - if (!state->direct) { - /* allocate output buffer */ - state->out = (unsigned char *)malloc(state->want); - if (state->out == NULL) { - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = deflateInit2(strm, state->level, Z_DEFLATED, - MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); - if (ret != Z_OK) { - free(state->out); - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - strm->next_in = NULL; - } - - /* mark state as initialized */ - state->size = state->want; - - /* initialize write buffer if compressing */ - if (!state->direct) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = strm->next_out; - } - return 0; -} - -/* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file or if gz_init() - fails to allocate memory, otherwise 0. flush is assumed to be a valid - deflate() flush value. If flush is Z_FINISH, then the deflate() state is - reset to start a new gzip stream. If gz->direct is true, then simply write - to the output file without compressing, and ignore flush. */ -local int gz_comp(gz_statep state, int flush) { - int ret, writ; - unsigned have, put, max = ((unsigned)-1 >> 2) + 1; - z_streamp strm = &(state->strm); - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return -1; - - /* write directly if requested */ - if (state->direct) { - while (strm->avail_in) { - put = strm->avail_in > max ? max : strm->avail_in; - writ = write(state->fd, strm->next_in, put); - if (writ < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - strm->avail_in -= (unsigned)writ; - strm->next_in += writ; - } - return 0; - } - - /* check for a pending reset */ - if (state->reset) { - /* don't start a new gzip member unless there is data to write */ - if (strm->avail_in == 0) - return 0; - deflateReset(strm); - state->reset = 0; - } - - /* run deflate() on provided input until it produces no more output */ - ret = Z_OK; - do { - /* write out current buffer contents if full, or if flushing, but if - doing Z_FINISH then don't write until we get to Z_STREAM_END */ - if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && - (flush != Z_FINISH || ret == Z_STREAM_END))) { - while (strm->next_out > state->x.next) { - put = strm->next_out - state->x.next > (int)max ? max : - (unsigned)(strm->next_out - state->x.next); - writ = write(state->fd, state->x.next, put); - if (writ < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - state->x.next += writ; - } - if (strm->avail_out == 0) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = state->out; - } - } - - /* compress */ - have = strm->avail_out; - ret = deflate(strm, flush); - if (ret == Z_STREAM_ERROR) { - gz_error(state, Z_STREAM_ERROR, - "internal error: deflate stream corrupt"); - return -1; - } - have -= strm->avail_out; - } while (have); - - /* if that completed a deflate stream, allow another to start */ - if (flush == Z_FINISH) - state->reset = 1; - - /* all done, no errors */ - return 0; -} - -/* Compress len zeros to output. Return -1 on a write error or memory - allocation failure by gz_comp(), or 0 on success. */ -local int gz_zero(gz_statep state, z_off64_t len) { - int first; - unsigned n; - z_streamp strm = &(state->strm); - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - - /* compress len zeros (len guaranteed > 0) */ - first = 1; - while (len) { - n = GT_OFF(state->size) || (z_off64_t)state->size > len ? - (unsigned)len : state->size; - if (first) { - memset(state->in, 0, n); - first = 0; - } - strm->avail_in = n; - strm->next_in = state->in; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - len -= n; - } - return 0; -} - -/* Write len bytes from buf to file. Return the number of bytes written. If - the returned value is less than len, then there was an error. */ -local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { - z_size_t put = len; - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* for small len, copy to input buffer, otherwise compress directly */ - if (len < state->size) { - /* copy to input buffer, compress when full */ - do { - unsigned have, copy; - - if (state->strm.avail_in == 0) - state->strm.next_in = state->in; - have = (unsigned)((state->strm.next_in + state->strm.avail_in) - - state->in); - copy = state->size - have; - if (copy > len) - copy = (unsigned)len; - memcpy(state->in + have, buf, copy); - state->strm.avail_in += copy; - state->x.pos += copy; - buf = (const char *)buf + copy; - len -= copy; - if (len && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } while (len); - } - else { - /* consume whatever's left in the input buffer */ - if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* directly compress user buffer to file */ - state->strm.next_in = (z_const Bytef *)buf; - do { - unsigned n = (unsigned)-1; - if (n > len) - n = (unsigned)len; - state->strm.avail_in = n; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - len -= n; - } while (len); - } - - /* input was all buffered or compressed */ - return put; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) { - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids a flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } - - /* write len bytes from buf (the return value will fit in an int) */ - return (int)gz_write(state, buf, len); -} - -/* -- see zlib.h -- */ -z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, - gzFile file) { - z_size_t len; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* compute bytes to read -- error on overflow */ - len = nitems * size; - if (size && len / size != nitems) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); - return 0; - } - - /* write len bytes to buf, return the number of full items written */ - return len ? gz_write(state, buf, len) / size : 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputc(gzFile file, int c) { - unsigned have; - unsigned char buf[1]; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* try writing to input buffer for speed (state->size == 0 if buffer not - initialized) */ - if (state->size) { - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); - if (have < state->size) { - state->in[have] = (unsigned char)c; - strm->avail_in++; - state->x.pos++; - return c & 0xff; - } - } - - /* no room in buffer or not initialized, use gz_write() */ - buf[0] = (unsigned char)c; - if (gz_write(state, buf, 1) != 1) - return -1; - return c & 0xff; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputs(gzFile file, const char *s) { - z_size_t len, put; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* write string */ - len = strlen(s); - if ((int)len < 0 || (unsigned)len != len) { - gz_error(state, Z_STREAM_ERROR, "string length does not fit in int"); - return -1; - } - put = gz_write(state, s, len); - return put < len ? -1 : (int)len; -} - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -#include <stdarg.h> - -/* -- see zlib.h -- */ -int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { - int len; - unsigned left; - char *next; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return state->err; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* do the printf() into the input buffer, put length in len -- the input - buffer is double-sized just for this function, so there is guaranteed to - be state->size bytes available after the current contents */ - if (strm->avail_in == 0) - strm->next_in = state->in; - next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); - next[state->size - 1] = 0; -#ifdef NO_vsnprintf -# ifdef HAS_vsprintf_void - (void)vsprintf(next, format, va); - for (len = 0; len < state->size; len++) - if (next[len] == 0) break; -# else - len = vsprintf(next, format, va); -# endif -#else -# ifdef HAS_vsnprintf_void - (void)vsnprintf(next, state->size, format, va); - len = strlen(next); -# else - len = vsnprintf(next, state->size, format, va); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) - return 0; - - /* update buffer and position, compress first half if past that */ - strm->avail_in += (unsigned)len; - state->x.pos += len; - if (strm->avail_in >= state->size) { - left = strm->avail_in - state->size; - strm->avail_in = state->size; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return state->err; - memmove(state->in, state->in + state->size, left); - strm->next_in = state->in; - strm->avail_in = left; - } - return len; -} - -int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) { - va_list va; - int ret; - - va_start(va, format); - ret = gzvprintf(file, format, va); - va_end(va); - return ret; -} - -#else /* !STDC && !Z_HAVE_STDARG_H */ - -/* -- see zlib.h -- */ -int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3, - int a4, int a5, int a6, int a7, int a8, int a9, int a10, - int a11, int a12, int a13, int a14, int a15, int a16, - int a17, int a18, int a19, int a20) { - unsigned len, left; - char *next; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that can really pass pointer in ints */ - if (sizeof(int) != sizeof(void *)) - return Z_STREAM_ERROR; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return state->error; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->error; - } - - /* do the printf() into the input buffer, put length in len -- the input - buffer is double-sized just for this function, so there is guaranteed to - be state->size bytes available after the current contents */ - if (strm->avail_in == 0) - strm->next_in = state->in; - next = (char *)(strm->next_in + strm->avail_in); - next[state->size - 1] = 0; -#ifdef NO_snprintf -# ifdef HAS_sprintf_void - sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, - a13, a14, a15, a16, a17, a18, a19, a20); - for (len = 0; len < size; len++) - if (next[len] == 0) - break; -# else - len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, - a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#else -# ifdef HAS_snprintf_void - snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, - a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(next); -# else - len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len == 0 || len >= state->size || next[state->size - 1] != 0) - return 0; - - /* update buffer and position, compress first half if past that */ - strm->avail_in += len; - state->x.pos += len; - if (strm->avail_in >= state->size) { - left = strm->avail_in - state->size; - strm->avail_in = state->size; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return state->err; - memmove(state->in, state->in + state->size, left); - strm->next_in = state->in; - strm->avail_in = left; - } - return (int)len; -} - -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzflush(gzFile file, int flush) { - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* check flush parameter */ - if (flush < 0 || flush > Z_FINISH) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* compress remaining data with requested flush */ - (void)gz_comp(state, flush); - return state->err; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct) - return Z_STREAM_ERROR; - - /* if no change is requested, then do nothing */ - if (level == state->level && strategy == state->strategy) - return Z_OK; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* change compression parameters for subsequent input */ - if (state->size) { - /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) - return state->err; - deflateParams(strm, level, strategy); - } - state->level = level; - state->strategy = strategy; - return Z_OK; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_w(gzFile file) { - int ret = Z_OK; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're writing */ - if (state->mode != GZ_WRITE) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - ret = state->err; - } - - /* flush, free memory, and close file */ - if (gz_comp(state, Z_FINISH) == -1) - ret = state->err; - if (state->size) { - if (!state->direct) { - (void)deflateEnd(&(state->strm)); - free(state->out); - } - free(state->in); - } - gz_error(state, Z_OK, NULL); - free(state->path); - if (close(state->fd) == -1) - ret = Z_ERRNO; - free(state); - return ret; -} |